← the Atlas

Electricity — identified, and their progress

analysis · evergreen ·

A tracker for kolu's electricities — infrastructure pulled out from beneath the app into its own thing — and where each stands.

“Decompose based on volatility.” Functional decomposition splits a system by what it does; volatility-based decomposition isolates each area likely to change behind a stable interface — the way a body keeps blood-pressure, pulse, and salinity volatility “encapsulated behind the service called the heart.” An electricity, here, is one such volatility pulled out into its own package. — Juval Löwy, Volatility-Based Decomposition (excerpt from Righting Software).

The electricities

ElectricityOwns (volatility)PRProgress
@kolu/surfaceLive client↔server state — Cell/Collection/Stream/Event over oRPC, reconnect, fine-grained reconcile. #805 done · 2nd consumer: drishti
@kolu/surface-appThe app shell for surface apps — fresh delivery + server/build identity + the connection/update lifecycle model + desktop-install. Owns the stale-tab handshake gate ( #1231 ) and now the connection plumbing ( #1234 ) — the pid-echo, the partysocket construction, and the upgrade gate, lifted from both consumers into three composable primitives (surface-connection). The restart axis already lived here, so each leak plugs into a receptacle the package had. #1154 · #1231 · #1234 done · 2nd consumer: drishti
@kolu/surface-nix-hostHostSessionnix copy a closure to a host, realise, run --stdio over ssh. #984 done · also in drishti
@kolu/artifact-sdkTwo volatilities under one roof — the agnostic anchoring core (W3C quote re-find; speaks only Range/Document/ShadowRoot) and the sandboxed-iframe parent↔frame bridge (opaque-origin postMessage, now carrying comments + in-frame navigation + back/forward input). See the re-eval note below. #922 done re-eval
@kolu/transcript-core + transcript-htmlTranscript model + rendering. #744 done
@kolu/solid-pierreSolidJS adapters for Pierre tree/diff. #823 done
persistedPrefValidated localStorage (validate-on-read; closed the zoom-NaN + maximize bugs). #1089 done
@kolu/log · @kolu/html-escapeZero-dep leaf types every package can import without dragging the domain tree. #1089 done
dom/ + injectable isMacwalkShadowRoots relocated to a neutral wall; keybind core no longer reads the UA singleton. #1089 done
createSharedRootLazy app-scoped reactive singleton (7 consumers). 100% agnostic SolidJS. #974 done publish?
@kolu/serve-dirFetch-native file serving from an absolute root — streaming byte-range (206/416), content-type, lexical traversal guard; a pure (root, relPath, request) → Response. Its own package, zero workspace deps (node:fs/path/stream + the focused mrmime MIME table) — the dependency arrow points out (kolu-server → @kolu/serve-dir). Agnostic of terminals/git/kolu; the consumer injects the root and composes the artifact-sdk <script> decorator downstream. A 20-agent prior-art survey found no static-serve library fits the serving shape (all pipe to a Node res, breaking the Fetch-Response + decorator composition; none takes a per-request absolute root or does a realpath guard), so the serving is owned here — but the MIME table leans on mrmime (the separable commodity the survey explicitly didn’t cover). That’s load-bearing for decomposition: a complete table means adding a format to kolu’s *_EXTENSIONS classifier needs no edit here (mrmime already types it), so the ext↔MIME shared-volatility the lens debated is dissolved for every mrmime-known format. For the mrmime gap set (.m4v/.ico, and any future classifier entry mrmime doesn’t know) the coupling is instead contained-by-test: a 2-entry OVERRIDES in serve-dir supplies the MIME, and the coverage invariant in iframePreviewRoute.test.ts is load-bearing, not a thin sanity check — delete an OVERRIDES row and the classifier still routes the file to a <video>/<img> appliance while serve-dir answers application/octet-stream, so only that test catches the silent download regression. Path safety is two-stage by volatility: the lexical guard (decode-then-split + path.relative containment) is built in (pure, universal), while the realpath/symlink guard is an injected realpathGuard the consumer supplies (fs-touching, threat-model-specific) — kolu-server wires kolu-git’s assertRealpathUnder, so the package stays agnostic without dropping the security boundary. A leaf (bounded algorithm, not a transport-grade volatility). #1225 done ②/③ proof-pending
@kolu/terminal-protocolThe VT/device-query protocol policy both terminal clients and the server must agree on — the query-reply suppression grammars (whole-payload predicate for the browser’s onData, streaming boundary-aware stripper for kolu-tui’s raw tty), the headless forward/drop rule, the answered/silent device-query matrix as data (executed against a real headless by @kolu/pty-host’s contract tests, so policy and implementation can’t drift), the bracketed-paste delimiters, and the snapshot-reciprocal TTY reset. Born when the second terminal client (kolu-tui attach, #1255 ) made the fragmentation visible: the same concept lived in kolu-common, pty-host, and pty-tui, held in lockstep by prose — and the browser may not depend on @kolu/pty-host, so a leaf both sides import is the only receptacle that dissolves the cross-references. Hashed into the pty-host staleKey (a protocol change is observable daemon behaviour; pinned by buildId.closure.test.ts). A leaf (bounded protocol tables, not a transport-grade volatility) — the serve-dir tier, not the surface tier. #1255 done
@kolu/solid-xterm (createSolidXterm)xterm.js lifecycle — 8-addon orchestration, WebGL single-owner + context-loss recovery, FitAddon resize, owner-correct async dispose across await. #1116 (plan)to build
@kolu/solid-browserThe Code tab is a browser — location/address model, back-forward history, cross-content-type link interception, GitHub-relative resolution, sandboxed-iframe lifecycle. git is an injected resolver; the renderer packages plug in. Plan. #1191 phases 1+2 primitives + createBrowser history shipped · <Browser>/gitResolver deferred, ③ proof-pending

Plus external electricity correctly leaned on instead of hand-rolled: Corvu (dialog/drawer/focus-trap/scroll-lock), @solid-primitives/* (resize-observer, media). Origin: a 41-agent Hickey/Lowy audit (16 candidates) → its “ship now” tier landed in #1089 ; a framework-scale re-test + adversarial skeptic surfaced the missed solid-xterm.

Next: extract @kolu/solid-xterm

// one primitive (not a topic-bundle, per §6.5):
createSolidXterm({ container, theme, fontSize, canUseWebgl?, enabledAddons?,
  onData?, onResize?, onLinkActivate?, onCustomKeyEvent?, plugins? })
  -> { terminal, searchAddon, hasWebgl, renderer, dispose }

Owns the agnostic core; kolu bits (link provider, soft-keyboard, diagnostics probes, the PTY terminal.attach stream) stay consumer-injected via callbacks. Dissolves ~240–314 lines of Terminal.tsx. Survived the skeptic (“the domain braid runs too deep”) on the interface — those are orchestration concerns, not xterm-lifecycle concerns. Graduates the way surface did: any SolidJS app embedding xterm can plug in.

Considered — not electricity

Looked framework-sized (the audit’s biggest braids), but fail the bar — recorded so they don’t get re-proposed.

CandidateVerdictWhy
defineMutation (optimisticOverlay)helperOne module, one domain (canvas layouts); the write echo is already owned by surface’s metadata subscription. Pending is a UI cache, not a transport axis.
@kolu/fs-watchhelperOwns a refcount/debounce lifecycle, not a streaming transport — no wire contract, Node-bound. A @kolu/shared helper, not a socket.
@kolu/geometrydomain-coupledTileLayout binds it to a server-persisted domain type; a Rect package re-adapts at every boundary — moves the braid, doesn’t dissolve it.
@kolu/surface-publishalready-coveredSurface’s cellHandlers/collectionHandlers/pollOnEvent already own server snapshot+delta. Only terminal.attach is a raw escape hatch.
@kolu/commands (palette)domain-coupledPalette engine is already agnostic; all coupling is isolated in createCommands, which must stay in the app. Extracting deletes ~0 kolu lines.
God-procedure splitrefactorIts biggest dissolvable chunk is solid-xterm (above); the rest is kolu orchestration — a refactor, not a receptacle.

Bar from Juval Löwy, Righting Software (receptacle/volatility) + Rich Hickey, Simple Made Easy (complecting); one-socket-not-a-topic-bundle is .agency/lowy.md §6.5. file:line verified against the codebase; ③ demonstrated by drishti — a second consumer (kolu is the first) that vendors @kolu/surface via npins.