style: use 2-space indentation for Rust - #6
Merged
Merged
Conversation
Add rustfmt.toml with tab_spaces=2 and reformat all Rust files. Also add `nix run github:juspay/vira ci` as first step in `just ci`. Closes #3
srid
marked this pull request as ready for review
March 20, 2026 00:58
This was referenced Apr 22, 2026
This was referenced Apr 29, 2026
This was referenced May 14, 2026
srid
added a commit
that referenced
this pull request
May 19, 2026
Reviewer #6 on PR #929. Two related correctness gaps: 1. `sendRequest` had no per-request deadline — a hung helper left pending Promises forever. Add a 60s ceiling (covers cold nix-run builds; live RPCs return in ms) that rejects the pending entry, logs at `warn`, and cleans the timer on both resolve and reject paths. 2. The `readyTimeout` rejected the connect Promise but left `child` bound to the unready ssh process. The next `ensureConnected` then treated the half-open child as connected and hung again behind the same broken pipe. On timeout: kill the ssh child, null `child` + `connectPromise` so the next call starts a fresh connect attempt.
srid
added a commit
that referenced
this pull request
May 27, 2026
`SystemSchema` carried a `state: "copying"|"connecting"|"connected"|"disconnected"` field that the agent hardcoded to "connected" and the parent unconditionally overrode on every write — two independent volatility axes (OS reporting, parent↔agent link lifecycle) sharing one schema. Extract `ConnectionSchema` into its own cell on the shared surface; the agent serves the default value (it has no visibility into the link from the inside, lesson #6) and the parent owns the live `connection` updates from its `HostSession.onState`. Browser's overlay reads `connection.state` instead of `system.state`. Hickey F-3; Lowy Finding 3.
srid
added a commit
that referenced
this pull request
May 27, 2026
Codex review findings #6 and #7: - `build:agent` in `package.json` pointed at `tsconfig.agent.json` which doesn't exist (and the agent runs through `tsx`, no `tsc` emit step anywhere in the flow). Removed. - `packages/surface/README.md` said to pass `implementSurface(...).router` directly to `serveOverStdio` — that's the exact double-prefix footgun the regression test pins against. Updated the snippet's comment and added a "Router wrapping (footgun)" paragraph explaining why `implement(contract).router({...fragment.router})` is required. - `packages/surface/example/remote-process-monitor/README.md` still described the old v1 closure-copy model (`AGENT_PATH`, `nix copy --to ssh://`). Replaced with the `.drv`-copy + remote realise flow that the code actually does (`KOLU_AGENT_DRV` env, `nix copy --derivation`, `nix-store --realise` on the remote), including the single-binary `nix run .#process-monitor-monitor` entrypoint and the `trusted-users` requirement on the remote.
This was referenced May 27, 2026
Closed
srid
added a commit
that referenced
this pull request
May 30, 2026
…nary (R4c #6) `currentBuildId()` keyed on the `/nix/store/<hash>-kolu-stamped` path — the entire kolu build — so every deploy (even pty-host-untouched, server/client- only ones) flipped `outdated` and fired the "update pending" nudge, whose only action is a terminal-losing restart that gains nothing. Now keyed on a build-time content hash of just the @kolu/pty-host source, baked by nix as KOLU_PTY_HOST_BUILD_ID and inherited identically by server and daemon. Precedence: KOLU_BUILD_ID_OVERRIDE (test seam) → KOLU_PTY_HOST_BUILD_ID (prod) → deriveBuildId(argv[1]) (dev fallback, unset in dev so no spurious nudge). The separate wire-incompatible contract path (PTY_HOST_CONTRACT_VERSION) is untouched — a breaking change still force-restarts. - default.nix: hash pty-host src (*.ts minus tests + package.json), inject env - buildId.ts: pure resolveBuildId() + new precedence; +unit tests - client copy reframed "kolu build" → "terminal host" (chip, command, confirm) - surface.ts / ptyHostSurface.ts / supervisor.ts: doc corrections - daemon-update.feature/steps: narrative only (override seam still highest) See docs/plans/remote-terminals.pty-daemon.html.
srid
added a commit
that referenced
this pull request
May 30, 2026
…1047 Deployed #1034 to the production box and exercised it live: the deploy reattached 3 terminals from the surviving daemon and correctly flagged the pre-#6 daemon stale (the one-time staleness-regime cutover); the user restart then cleared it (outdated:false) in ~600ms with no kill-then-pray hang, and restore brought the session back — no empty-canvas lie. Scorecard, phase table, and decision note updated to prod-verified; flagged the open noImportCycles fix as pre-merge. Filed #1047 (always-visible build-id readout).
This was referenced May 30, 2026
This was referenced May 31, 2026
Merged
srid
added a commit
that referenced
this pull request
Jun 2, 2026
Paulg-method rewrite of the 14 panel-flagged passages. 11 applied after an adversarial skeptic confirmed each cleared the reader's stumble while preserving meaning, facts, the physics metaphors, and voice. 4 of the 11 are the skeptic's own endorsed fix (the rewriter's version was rejected and replaced). Headline fixes: - #1 "the invariant" now named ("the code's analogue of that frame-invariant interval") — was undefined-on-a-definite-article. - #6 "structural review has." -> "has become that." — elliptical gapping after a negative had inverted the meaning. - #4 lede "volatilities that got bound" -> "fast-moving and slow-moving parts coupled" — one reader had read "bound" as the opposite (good) meaning. - #12 moved "space-like" off the observer onto the slice/reading. - #3, #7, #8, #9, #10, #11, #14: see optimization log. 3 deliberate keeps (over-fix guard): #5 (the physics is fine as-is), #13 (gloss would steal the next paragraph's reveal), #2 (deferred to pass 2 — pass-1 rewrite contradicted the post's thesis). Behaviour gate: `just website::build` PASS.
srid
added a commit
that referenced
this pull request
Jun 6, 2026
Coherent axis (escape-sequences→typed events) fused into pty-host's process lifecycle. Inert since extraction, no external consumer, one entanglement (OSC 633 drives foreground sampling). Defer — a Löwy axis whose volatility hasn't fired yet.
srid
added a commit
that referenced
this pull request
Jun 13, 2026
Address both codex findings on the shell-carried commit stamp branch. F1 (fixed) — injectShellCommit's `/<head[^>]*>/i` also matched `<header>`, so a shell with no real <head> but a body <header> would build and inject the commit script at the wrong place, defeating the fail-loud contract. Tighten to `/<head(?:\s[^>]*)?>/i` (tag-name boundary) and add regression tests: a `<header>`-only shell now throws, and a `<head lang="en">` still matches. F2 (partial) — refresh the Atlas note to the shell-global model. Updated the current-looking invariants (#2 build identity rides the no-store shell via window.__SURFACE_APP_COMMIT__, read by shellCommit(), never a hashed-asset define; #6 commit propagation) and the pieces table; rebuilt docs/atlas/dist. Left the `clientCommit={__SURFACE_APP_COMMIT__}` snippet at line ~245 as-is: it lives inside the "## The API — historical (merge era)" section, which is explicitly banner-flagged as a removed/superseded API (composeSurfaces / implementSurfaceApp), so rewriting just its commit line would misrepresent design history rather than current contract. Also folded in `just fmt`'s reformat of two sibling test files on this branch.
srid
added a commit
that referenced
this pull request
Jun 15, 2026
Address codex's review of the P2.7 warm fast-path. F1 (minor, agreed/fixed): the speculative warm probe forwarded all its stderr through the user-visible onProgress ring. On a cold host the probe is *expected* to fail (the .drv isn't there yet) and nix emits a real `error: …` line, so a clean first-time provision read as if it had errored. Add a probe-specific callback `onProbeProgress` that still scans each line for the network classification (a transport failure on the probe must keep flipping `sawNetworkError` so the fall-through's `causeFor` calls an unreachable host "network" — deliberate decision #6) but does NOT echo the line to `opts.onProgress`. The real copy/realise path still reports its own errors verbatim if provisioning ultimately fails. Two tests lock both halves in: a cold probe-miss `error:` line is swallowed from the progress lines; a network-looking probe line still yields `cause: "network"`. No other findings — codex approved the core Nix semantics (realises the drv, returns the realised out-path, skips `nix copy` only on a realisable remote closure) and the unchanged cold path.
srid
added a commit
that referenced
this pull request
Jun 30, 2026
…view gauntlet) Hardens the S1+S2 cutover against the 4-reviewer architecture-first-principles + perfection-review debate (debates/pr1626-review). Every residual was in the shell around the fold; the fold spine was credited sound. - #2/#7 — the restore target is now a fold-produced discriminated value: `RestoreTarget = none | { exact, command, agent } | { legacyMostRecent, command }` (`restoreTargetOf`, consumed by `resumeFormFor`), replacing the bare optional `resumeAgent` identity. Absence can no longer be read as "resume most-recent": quit-to-shell → `none` → bare shell by construction (#1492) for new records; migrated pre-1.29 records keep most-recent as a NAMED `legacyMostRecent`. The derivation moved out of the emit shell into the fold (closes #7). The client restore card + dormant tile require an actual `exact`/`legacyMostRecent` target. - #5 — the authored collection no longer re-publishes on the ~150 ms observation firehose: the emit loop computes deltas once and gates each arm by its own (observed publish on an observed change, authored publish on an authored-fact change, disk autosave on a restore-relevant change). - #1 — the recency frame phase is decided BY VALUE (compare the re-resolved agent identity to the saved restore target), deleting the 1.5 s wall-clock window and its restamp race. - #8 — the schema-module docstring is rewritten to the Observation/AgentMemory/ KoluAwareness world; the deleted AwarenessValue/AwarenessSink paragraphs are gone. Deferral caveats made honest (not implemented): #3 the sleep drain stays deferred, and the docs stop claiming the freeze "holds by construction" (a sub-second launch-then-sleep now yields a false BARE shell under model B — fail-safe); #6 adds a fold.test.ts pin that a structurally-equal-but-new-ref git/pr still compares equal at the autosave fence. AgentIdentity + RestoreTarget move down to anyagent/schemas (the resume vocabulary layer), re-exported through terminal-workspace. SCHEMA_VERSION migration reshaped to synthesize the discriminated target. Docs (README, 5 Atlas notes, changelog) reconciled to the shipped behavior.
srid
added a commit
that referenced
this pull request
Jun 30, 2026
## Awareness — the producer observes, kolu remembers (S1 + S2 → R9.0) Implements the merged plan [`awareness-derive-store.mdx`](docs/atlas/src/content/atlas/awareness-derive-store.mdx) (#1621) as **one coordinated change** — S1 (the memoryless producer) and S2 (kolu's fold) are coupled, so they ship together — then **hardened across two rounds of a 4-reviewer architecture-first-principles + perfection-review gauntlet** (`debates/pr1626-review`, `debates/pr1626-rereview`). The reviewers credited the fold spine **sound**; every residual was in the shell around it — the first round's four must-fixes (below), then two relocations codex caught on re-review (F1/F2). ### The cut The per-terminal awareness engine used to **derive** awareness by **mutating a host record it also read back as memory**, through an `AwarenessSink` two homes (kolu + `pulam`) each had to wire. This splits it: - **S1 — memoryless producer.** `startAwareness` → `startSensors`: it *emits* per-field `TerminalEvent`s and takes no seed, no sink, no record. Deleted: the `AwarenessSink` interface, **both** `makeAwarenessSink` impls (kolu's + pulam's `hooks.ts`), `AwarenessRecord`, the apply-and-publish read-back. - **S2 — kolu's fold.** A pure `fold(cur, o, ctx) → TerminalState` (`{snapshot: TerminalSnapshot, memory: AgentMemory}`). The producer's emit type **cannot spell** a memory fact, so the old "two narrowed mutators" write-fence is now the **type**. - **R9.0 — local cutover.** kolu runs the producer in-process and folds the stream, publishing the snapshot half to `snapshots` and the memory half to `kolu.authored`. ### Review-gauntlet hardening (the four must-fixes) | # | Finding | Fix | | --- | --- | --- | | **#2 / #7** | The restore target was a bare optional `resumeAgent` identity read alongside `lastAgentCommand`, so `(command set, identity absent)` meant **both** "quit, restore nothing" *and* "no id captured, resume most-recent" — and the derivation lived in the emit shell, not the fold. | The fold now produces a **discriminated `RestoreTarget`** — `none \| { exact, command, agent } \| { legacyMostRecent, command }` (`restoreTargetOf`, consumed by `resumeFormFor`). Absence can no longer be read as most-recent: **quit-to-shell → `none` → bare shell by construction** (#1492) for new records; a migrated pre-1.29 record keeps most-recent as a *named* `legacyMostRecent`. The client restore card + dormant tile require an `exact`/`legacyMostRecent` target. | | **#5** | The authored *collection* re-published on **every** observation tick (~150 ms) — only the disk arm was fenced. | The emit loop computes deltas once and gates each arm by **its own** delta: snapshot publish on a snapshot change, **authored publish on an authored-fact change**, disk autosave on a restore-relevant change. | | **#1** | Recency leaned on a 1.5 s wall-clock window; a slow agent resolution crossing it could restamp saved recency on restore. | The frame phase is decided **by value** — compare the re-resolved agent identity to the saved restore target. The timer is deleted. | | **#8** | The schema module's docstring still taught the deleted `AwarenessValue` / `AwarenessSink` world. | Rewritten to `TerminalSnapshot` / `AgentMemory` / `TerminalState` / the emit type. | `AgentIdentity` + `RestoreTarget` moved down to `anyagent/schemas` (the resume-vocabulary layer), re-exported through `terminal-workspace` — the fold *produces* the target, `resumeFormFor` *consumes* it, one owned type. The serial lens → codex → simplify → code-police pass then collapsed the vestigial `AgentSessionRef` into `AgentIdentity`, shared one `resumableCommand` projection across the client surfaces, value-gated the emit fences, and hardened the migration against corrupt input. ### Second re-review — two relocations codex caught (the panel earned its keep again) A second 4-reviewer pass on the hardened HEAD credited the four must-fixes **closed by construction** — but codex (1 of 4) found two real defects relocated *inside* the new shapes, both verified against the diff: | # | Finding | Fix | | --- | --- | --- | | **F1** | `restoreTargetOf` paired `lastAgentCommand` with `snapshot.agent` **without checking they agree on agent kind**, so a stale-command/new-agent race could build `exact{ command:"opencode …", agent:{kind:"claude-code"} }` — which `resumeAgentCommand` silently downgrades to opencode's most-recent: the wrong-agent resume #2 makes unspellable, re-expressed in the `exact` arm. | One constructor, **`exactRestoreTarget(command, agent)`** (anyagent), builds `exact` *only when* `agentKindFromCommand(command) === agent.kind`, else `null`. **Both** production sites go through it — the fold (→ `none` on mismatch) and the migration (→ `legacyMostRecent` on mismatch) — so `resumeFormFor` always takes the same-agent path (exact-by-id, or refuse), never the downgrade. | | **F2** | The funnel `guardedEmit` swallowed a thrown emit **after** the producer advanced its dedup baseline, so "emitted" ≠ "accepted": the fold never got the value while the baseline advanced → a later equal value deduped → silent permanent divergence. The guard sat at the wrong seam. | Error handling moved to where the fallible work is — the host's **publish boundary**. `commitSnapshot`/`updateMemory`/`emitTerminalsDirty` (kolu) and pulam's snapshots `upsert` each **fold-accept first, then guard their own publish** (logged, self-heals on the next change). With the publishes infallible, `emit` is infallible — and the wrong-seam funnel guard is **removed**. | ### Type-naming cleanup A follow-up **mechanical, compiler-checked rename** gives the awareness types **one root per shape** — `TerminalSnapshot` (the whole value a host emits) · `TerminalEvent` (a per-field delta) · `TerminalState` (the `{ snapshot, memory }` composite kolu folds) · `Known<T>` (resolution status). The `Terminal` prefix scopes the wire-facing family, and a field repeats its type's root (`entry.observed` → `entry.snapshot`). The served collection key bumps `awareness` → `snapshots` (`TERMINAL_WORKSPACE_CONTRACT_VERSION` `2.0` → `3.0` — breaking, the wire path changed). "Observation"/"awareness" survive only as feature-word prose; the deleted `AwarenessSink`/`AwarenessValue` keep their old names where the text describes what was removed. The schema-module docstring, the [design note](docs/atlas/src/content/atlas/awareness-derive-store.mdx) (types, prose, and the foldflow/homes diagrams), and the unit-test fixtures all move with the code. ### Honoring the design philosophy - **Fail-fast / no knobs** — the write-fence is the emit type; the restore decision is a discriminated value, not a runtime fallback. No override path. - **Volatility boundary** — producer/fold/`RestoreTarget` stay in the `@kolu/*` packages; kolu and pulam are consumers, the dependency arrow points out. - **Reuse the source of truth** — `foldSnapshot` is shared by kolu's fold and pulam's accumulator; `restoreTargetOf` / `exactRestoreTarget` are the *one* place a restore target is decided; the migration composes the existing backfill ladder. ### Deferred refinements (documented honestly, with pins) - **Active drain-at-sleep (#3).** `beginSleep` freezes the last fold-written target and does **not** drain a final settle, so a sub-second launch-then-sleep freezes a stale `none` and wakes to a **false bare shell**. The docs no longer claim the freeze "holds by construction"; under model B the consequence is fail-*safe* (a bare shell, never the wrong conversation). The active drain is an async-`beginSleep` follow-up. - **`git`/`pr` reference equality (#6).** `restoreRelevantEqual` compares `git`/`pr` by reference (correct today — upstream `gitInfoEqual`/`prResultEqual` dedup before emit). A `fold.test.ts` pin asserts a structurally-equal-but-new-ref `git`/`pr` still compares equal at the fence, so a future fold copy can't silently break it. - **R9.3 scope** — the framed `TerminalFrame` *wire* stream and cross-host keying stay R9.3; R9.0 keys by `TerminalId` and folds in-process. ### Migration `SCHEMA_VERSION` 1.28.0 → 1.29.0: `backfillSnapshotCutover` backfills `pr: { kind: "absent" }` and **synthesizes the discriminated `restoreTarget`** from what a pre-cutover record remembered — a valid `agentSession` whose kind matches the command → `exact`, a command alone (or a kind mismatch) → `legacyMostRecent`, neither → absent (`none`); corrupt `agentSession` value-types fall through safely rather than producing a parse-rejecting record. ### Tests & CI The pure `fold` / `restoreTargetOf` / `exactRestoreTarget` / `resumeFormFor` are unit-tested (the discriminated switch, the kind-mismatch refusal, the ref-stability pin, the publish-boundary infallibility). The sleep/wake, adopt, reconcile, metadata, session-transfer, and restore-card tests track the reshaped persistence; the e2e session-restore + sleeping-terminals fixtures were fixed to stamp the now-required `pr`. All **unit tests** green across the touched packages, `just check` (tsc + biome) clean, and the **Atlas sync gate idempotent** — re-confirmed after the type-naming cleanup. **Full CI green on both `x86_64-linux` and `aarch64-darwin`** (every recipe × both platforms) on the naming commit, including `ci::e2e` on each. _Generated by [`/be`](https://github.com/srid/agency) on Claude Code (model `claude-opus-4-8`)._
srid
added a commit
that referenced
this pull request
Jul 7, 2026
…the known class's last consumers) Re-sweep #6's 3 confirmed defects (single-editor). No new classes — the last consumers of the host-scoping theme (a leg reading a LOCAL/host-independent fact against a REMOTE active host). MAJOR — the LOCAL padiLink leg false-warmed a REMOTE active host. `padiLink` is kolu-server's binding to its OWN local padi (host-independent), but downState()/daemonWarming() folded it UNCONDITIONALLY, so a local-padi drop (spontaneous reconnect, or daemon.restart → drainBoundPadi → renew — host-independent) while a REMOTE host was active replaced the remote's LIVE terminals with "Restarting kaval…", locked ⌘T, MASKED a genuine remote-kaval death, and read the remote inventory "unavailable" — a cross-host honesty regression, wrong in exactly the direction W4 sought. Fix: `activePadiLink()` = `localPadiLinkOnly(activeHost(), padiLinkState(), LOCAL_HOST)` (extracted pure) collapses the local leg to the "connected" no-op sentinel for a REMOTE active host, so the decision falls through to the host-scoped kaval state + activeEntryConnected (which cover a real remote drain via the remote's OWN daemonStatus); routed into downState, daemonWarming, and boundHostInventoryLive. LOCAL_HOST keeps the #1034 local-restart-drain fold verbatim. Pin (both directions): local drop + local active ⇒ warm (drain UI survives); local drop + remote active ⇒ NOT warm + the remote's own death still surfaces. MINOR — kaval memory tooltip floored on the ws leg only (useMemoryUsage). The kaval RSS renders on the HOST-SCOPED Kaval chip (dot/state/uptime floor on daemonChannelLive), so its display folds the SAME entry leg: a dead active REMOTE entry hides the stale RSS instead of a figure beside an "unknown" dot. The a340322 rationale (processMemory is a host-independent local-stack diagnostic) stands for the VALUE; the DISPLAY floors on the host-scoped channel like every other rail consumer. MINOR — the reattach-toast dedup used ONE shared localStorage high-water mark over RAW foreign adoptedAt epochs (per-host clocks, deliberately unreprojected — a monotonic dedup key). Cross-host clocks are not mutually monotonic, so a remote ahead-clock toast suppressed a genuine later LOCAL re-adoption (the foreign-clock class, storage edition; shipped #1365). Fix (shape per ruling): keep ONE key, make the VALUE a per-host record {[host]: mark} — the honest per-host-clock model, no persistedPref-name-at-init friction. Pin: remote ahead-clock toast, switch-back local re-adoption still fires. Green: client 583 (+4 pins), tsc, biome. (#6 convergence: no new classes.)
srid
added a commit
that referenced
this pull request
Jul 8, 2026
…panel bit Move UI state that parameterizes a VIEW OF a host's content into the per-host `scopedByEntry` owner (`hostScope/createViewState`) — per-host by construction, the "maximized pattern": fact born in the owner, facade re-points at `activeScope()?.view.<fact>`, removal race floors to the default. THE RULE now lives in `canvasBoundaryGuard.test.ts`: state that parameterizes a VIEW OF per-host content is per-host; state that parameterizes the VIEWER (density taste) is per-tab. 1. canvasMaximized — dropped the `kolu-canvas-maximized` boolPref; now a plain per-host in-memory signal in `createViewState` (default false; reload → tiled, matching the camera tier). `useViewState` re-points + floors to false. 2. activityWindow — was one global localStorage singleton; now a per-host persisted signal in the owner, keyed `kolu-activityWindow:<encodeHostKey(host)>` so each host's dock filter survives reload without colliding. `activityWindow.ts` became the facade (consumers unchanged). 3. showSleeping — same shape as (2), keyed `kolu-showSleeping:<encodeHostKey(host)>`. `showSleeping.ts` became the facade. 4. right-panel collapsed bit — was the global server pref `preferences.rightPanel.collapsed`. CHOICE: in-memory per-host signal in the owner, SEEDED from the existing global pref (`?? preferences().rightPanel.collapsed`), NOT a per-host field on the server schema — the lower-risk option (no schema widening; reload re-inherits the global). The right-panel ACTIVE TAB was already per-TERMINAL (server session via chrome.setRightPanel), i.e. strictly finer than per-host, so it is already host-scoped and needs no change. `panelSize`/ `codeTabTreeSize` stay global (viewer density taste, per-tab by THE RULE). 5. minimap-expanded — NO SUCH STATE EXISTS. Exhaustive search found no `minimapExpanded` / minimap open-collapse toggle; `CanvasMinimap` is simply shown in tiled posture and hidden when maximized. "minimap-expanded" appears only as an ILLUSTRATIVE example in `docs/atlas/.../padi.mdx` (alongside canvas-maximized), never built. The one real sibling posture is the dock's rail↔cards `dockMode` (`kolu-dock-mode`), which is density taste → correctly per-TAB by THE RULE, so it is deliberately NOT moved. Nothing to implement. 6. reattachAnnouncedAt — already correct: the dedup high-water mark is a `Record<encodeHostKey(host), ts>` keyed by the canonical host string, committed per active host; cross-host announcements are independent. Verified against the existing `reattachAnnounce.test.ts` "re-run #6" cross-host case. No change. Note: `terminal/activityWindow.ts`'s facade reads the owner via `activeScope`, and the owner reads that module's `DEFAULT_ACTIVITY_WINDOW`/`isActivityWindow` — a benign import cycle (call-time only on both sides; documented inline). Tests: new `perHostViewState.test.ts` — one acceptance per moved item over the REAL owner (set on A → B sees default → back to A restored), plus the per-host storage-key assertion for the two persisted filters (real `persistedPref` over happy-dom localStorage). perHostCanvas.test.ts's 3 pinned it() blocks are byte-identical; only its `./persistedPref` mock grew a `persistedPref` stub.
srid
added a commit
that referenced
this pull request
Jul 14, 2026
…1812) ## What The `/kolu` skill warns that a paste can fold into a `[Pasted text +N lines]` placeholder and fail to submit — but it frames that limit as **"multi-KB" / "large"** and calls anything smaller a **"normal-size"** prompt safe for the three-step submit. That mental model is wrong, and it bit the driving agent repeatedly. The fold is triggered by **line count, not byte size**. A multi-line status report folds well under 1 KB. This PR reframes the callout around line count and makes the file-pointer workaround the *default* for any multi-line message, not a special case for a "big brief." ## Why — the evidence Mined from the XKIT-PR2 `/be` run (session `fdc62b24`), where this session drove a coordinator terminal over `kaval-tui send`. Its reports kept folding into placeholders that would not submit, each forcing a *clear + short-pointer resend* cycle: | Observed fold | Size | The agent's own note | | --- | --- | --- | | `[Pasted text #13 +15 lines]` | 1807 B / 15 lines | "the known large-paste limitation" | | `[Pasted text #6]` | ~2414 B | "an Enter now would leave it staged" | | `[Pasted text #12]` | ~909 B | "clear it and send a tight venue question" | | (another) | ~1011 B | **"Folded again (the fold threshold is low)."** | Two of these folded at **under 1.1 KB** — nowhere near "multi-KB." The agent had to *discover empirically* that "the fold threshold is low" and switch to the file-pointer workaround, which the skill had already documented but mis-scoped as a big-brief-only path. ## The fix (per-edit ledger) `agents/.apm/skills/kolu/SKILL.md` (the source; generated `.claude/` + `.agents/` copies + `apm.lock.yaml` regenerated via `just ai::apm`, same commit): 1. **Callout framing** — "LARGE pastes (multi-KB) ... normal-size prompts" → "MULTI-LINE pastes ... a short prompt (a line or two)", stating the trigger is **line count, not byte size**, folding **well under 1 KB** (~900 B / ~a dozen lines), and that *any* multi-line message (report, ruling, verdict) is fold-prone. 2. **Workaround scope** — "Workaround for a big brief" → "for any multi-line message", with an explicit steer to reach for the file-pointer **by default** past a couple of lines rather than after getting bitten by a fold-and-resend cycle. ## Not shipped (observations only — did not meet the durability bar) - **Browser pointer/hover media emulation** (the e2e-gate took three escalations to learn Chromium welds `(hover)` to touch capability): a one-time domain discovery, self-corrected by the review gauntlet + `/perfection-review`, and already encoded in the shipped code comments. Not a recurring skill gap. - **`ci/pu/lease.sh` granting the quarantined `kolu-ci-1`** (forcing a two-lease dance): a transient infra quarantine; the real fix is a lease-script exclusion flag, which is out of `/self-improve`'s `.apm/skills/*` scope. Single incident. ## Verification - `just fmt` — clean (no reformats). - `just check` — green (exit 0): all typechecks + biome lint pass. - `just ai::apm` regen confirmed to land in `.claude/` and `.agents/` (hashes match in `apm.lock.yaml`); no unrelated skill drifted. Provenance: `/self-improve` micro-loop over session `fdc62b24-b5c8-4c0b-ad4c-577f8ab87b08`. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
srid
added a commit
that referenced
this pull request
Jul 28, 2026
…cet vocabulary `OsfactsReading` stood for both `Snapshot` and `HostSnapshot`, so eleven of its eighteen fields were structurally always-empty at every call site and the parser accepted either grammar in either output. It splits along the split Rust already has. - lowy F3 ≡ hickey #6 — one type for two verbs; now `SnapshotReading` / `HostReading` with `parseSnapshotOutput` / `parseHostOutput`, each refusing the other's row tags loudly instead of returning a silently empty field. `HostReading.memory` can finally be named `memory`, matching the JSON face - lowy F4 ≡ hickey #7 — `mem` meant process RSS and host RAM in one flat union; the verb split takes the facet unions with it - lowy F5 ≡ hickey #9 — the flag→wire-name map is not mechanical (`procs` names `proc`; `ports` names three), so every consumer re-derived tool knowledge by hand; `snapshotFacetNames` exports it. It states fact, not policy: which named facet counts as blindness stays with the consumer - lowy F8 — `processIdentity` put the daemon supervisor's identity-gate policy inside the explicitly policy-free client, with zero consumers (verified by grep) and shaped for the OSF8 consumer this PR deliberately parked. Deleted, with the sync spawn that existed only to serve it - lowy F1 ≡ hickey #1 — `facets.test.ts` pins the three unions to `osfacts/facets.json`, out of `describeDaemon` so the fast local loop catches the drift too - lowy F10 — the zero-value reading was written out twice with nothing requiring the copies to agree - lowy F12 — `isTcpPort` is no longer exported; it is the parser's own guard Raised by the lowy ∥ hickey lens review. Not pushed or merged.
srid
added a commit
that referenced
this pull request
Aug 1, 2026
- hickey #2 — rule 2's `seen` membership test now covers every entry reaching `overlay`, not just the top-level filter: a duplicated path makes `pathDiffOperations` emit two adds for one row, Pierre throws, and the recovery discards every hand-expanded folder. - hickey #6 — the rule-4 queue walk becomes one self-contained recursive `emit`. Fixes `lazyDirs.push` sitting above the visited check (a directory reached twice was listed twice) and `queue.unshift(...children)`, a `RangeError` on the six-figure flat level this feature targets. The loaded-but-empty directory keeps its own row exactly as before. - hickey #5 — `ignored` now names a loaded directory's own key as well. Pierre still paints that row from its children's prefixes, so dropping it un-dimmed the folder at the moment the user opened it, children dimmed below. - hickey #10 — `diffInventory` is the one constructor for the no-overlay case, so a new `BrowseInventory` field can't be forgotten at CodeTab's literal. Raised by the lowy ∥ hickey lens review. Not pushed or merged.
srid
added a commit
that referenced
this pull request
Aug 1, 2026
- hickey #3 — `openLazyDirs` carried three facts and two broke. A row that has no node right now (a search projection hid it) no longer retires the record, so a filter keystroke stops erasing the user's expansion; and a key the host no longer declares lazy is pruned, so an eye-toggle round trip reports afresh instead of showing an arbitrarily old cached level with no refetch path. - lowy #2 — a `lazyEpoch` prop clears the record when the host's loaded levels stop describing this tree (a repo / host switch), the wrapper's half of the invalidation the host already performs on its children cache. - lowy #6 — `onExpandLazyDirectory` may return a promise; on rejection the wrapper forgets the expansion, so a transient read failure no longer wedges the folder open-and-empty for the mount. - hickey #7 — the `tree.subscribe` callback runs under `safeApply`, so a throw can't escape into Pierre's emit loop and take other subscribers with it. - hickey #9 — "which directories should be open" is spelled once (`desiredExpandedPaths`) and used at both the constructor and `toOpen`. - hickey #8 — `expandPaths`' JSDoc no longer asserts an invariant `openLazyDirs` has made false. Raised by the lowy ∥ hickey lens review. Not pushed or merged.
srid
added a commit
that referenced
this pull request
Aug 1, 2026
- hickey #4 — one `AbortController` per directory replaces the hand-rolled `loadGeneration` + captured-`issuedSlot` pair, so "is this response still wanted" is ONE fact both callbacks read rather than two conditions each has to repeat. Fixes the real asymmetry where `.catch` checked only the slot and could toast a failure over a folder showing correct contents, and stops the superseded readdir server-side instead of racing it. - lowy #2 — pass `lazyEpoch={slotKey()}` beside the existing clear, so the tree's record of open lazy directories is invalidated by the same signal. - lowy #6 — the handler returns its promise and re-throws after toasting, so the tree drops its record and a retry costs one re-expand. Raised by the lowy ∥ hickey lens review. Not pushed or merged.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
rustfmt.tomlwithtab_spaces = 2and reformat all Rust filesnix run github:juspay/vira cias first step injust ciCloses #3