[{"name":"agent-session-controls.md","kind":"file","size":118,"lastCommitHash":"94f25d4f34f31f4b5a096834097edd9ccb1a2992","lastCommitWhen":"2026-09-01T22:32:33+09:00","lastCommitMessage":"feat(coding-agent): add root session controls\n"},{"name":"avoid-rlm-parent-followup-deadlock.md","kind":"file","size":91,"lastCommitHash":"ca7ba908b123006ce43d4c2942aa2f7720464edc","lastCommitWhen":"2026-09-01T01:36:56+09:00","lastCommitMessage":"fix(coding-agent): avoid subagent finalization deadlock\n"},{"name":"await-daemon-bash-end.md","kind":"file","size":65,"lastCommitHash":"6322b7bb977c46b522ef5b07c4f68f5deacfdc61","lastCommitWhen":"2026-08-29T11:10:28+02:00","lastCommitMessage":"refactor(coding-agent): await in-flight bash completion during daemon close (#1858)"},{"name":"bash-output-sentinel.md","kind":"file","size":288,"lastCommitHash":"809027134a1fb2064fe152507abffcfc5610e486","lastCommitWhen":"2026-08-28T17:08:43+02:00","lastCommitMessage":"fix(runtime): ordered bash output completion sentinel (#1838)\n\n* fix(runtime): fence bash output completion\n\n* docs(runtime): document post-fence output visibility in bash() docstring\n\n* fix(runtime): emit bash completion fence via absolute printf path\n\nA shell function named `command` shadows `\\command -p printf` (the\nbackslash only defeats aliases), swallowing both fence frames and\nwedging the await behind background jobs until shell death. A\nslash-qualified printf resolved on the system default utility PATH\nbypasses function and alias lookup in every POSIX shell.\n\nAlso scope the changelog claim: EXIT-trap/background output lands after\nthe completion marker by design and stays visible via handle.output().\n\n* docs(runtime): soften the fence-printf comment per review"},{"name":"daemon-agent-message-admission.md","kind":"file","size":86,"lastCommitHash":"ceb418049dd929676beb13f77a6d697bcd52f854","lastCommitWhen":"2026-08-28T17:09:00+02:00","lastCommitMessage":"refactor(coding-agent): centralize agent-message admission in AgentSession (#1861)\n\n* refactor(coding-agent): query agent peers on demand instead of broadcasting mirrors\n\n* refactor(coding-agent): centralize agent-message admission in AgentSession\n\n* fix(coding-agent): respond to unknown worker commands instead of dropping them\n\nLegacy worker_sync_agent_peers commands from an older supervisor fell\nthrough handleWorkerCommand without a response, forcing the requester\nto wait out its full 5s timeout on every peer sync. A default case now\nwrites an immediate failure for any unhandled worker command.\n\n* fix(daemon): re-check cron job runnability after prompt admission fence\n\nrunCronJob snapshotted the runnable job before promptHeartbeat/\npromptUntilAccepted, which can wait on the session admission fence. A job\ncancelled or completed during that wait was still delivered. Re-check via\nthe admissionCommitted hook and skip when the job is no longer runnable.\n\n* fix(daemon): skip cron delivery when the job content changed during admission\n\nupdateRlmHeartbeat mutates prompt/deliveryMode in place under the same job\nid, so the existence-only admissionCommitted re-check still delivered the\nstale snapshot captured before the admission fence wait. Compare the\nrefreshed job's prompt and deliveryMode and skip on mismatch; the skip\nreschedules nextRunAt so the updated instruction is delivered next cycle.\n\n* fix(coding-agent): re-check prompt admission after async input normalization\n\n_prompt ran admissionCommitted before _normalizeSubmission, but async\nextension input handlers are awaited between that check and\n_admitSessionInput, so a cron job cancelled or updated during the await\nstill delivered its stale prompt. Re-run the callback after the awaited\nnormalization so invalidated content is not admitted."},{"name":"derive-connection-models.md","kind":"file","size":88,"lastCommitHash":"d90062b608009db4b7062201417ea50481a1cd73","lastCommitWhen":"2026-08-28T14:15:34+02:00","lastCommitMessage":"refactor(coding-agent): derive available connection models on read (#1853)"},{"name":"derive-scoped-heartbeats.md","kind":"file","size":71,"lastCommitHash":"85c236d5fc5b0255addaa74026fbcfbf3e490b19","lastCommitWhen":"2026-08-29T10:54:05+02:00","lastCommitMessage":"refactor(coding-agent): derive scoped heartbeats at render time (#1857)\n\n* refactor(coding-agent): derive scoped heartbeats at render time\n\n* fix(coding-agent): keep the earliest heartbeat manager refresh deadline\n\nscheduleHeartbeatManagerRefresh now runs on every subagent snapshot\nupdate, and each call cleared and re-armed the refresh timer. An overdue\nheartbeat uses a relative 5s fallback delay, so children updating more\noften than every 5s postponed the open manager's refresh indefinitely.\nTrack the scheduled deadline and keep the pending timer unless the newly\nderived deadline is earlier.\n\n* test(coding-agent): cover re-arming the heartbeat refresh to an earlier deadline\n\nThe keep-timer-always mutant (returning whenever a timer is armed)\nsurvived the touched suites: nothing proved a sooner heartbeat pulls the\npending refresh forward past the capped 60s poll."},{"name":"dot-continuation.md","kind":"file","size":68,"lastCommitHash":"b0023ef6c0a260b08f9c00d08e81f4106da7430e","lastCommitWhen":"2026-09-01T21:18:22+09:00","lastCommitMessage":"feat(coding-agent): add dot continuation shortcut\n"},{"name":"drain-bash-before-rlm-followup.md","kind":"file","size":105,"lastCommitHash":"f49ba1ee03d67d742f4ab9d05b2d978482a9c064","lastCommitWhen":"2026-09-01T22:33:29+09:00","lastCommitMessage":"fix(coding-agent): drain bash completion before RLM follow-up\n"},{"name":"eng-5533-worker-recovery.md","kind":"file","size":98,"lastCommitHash":"ee8fd699617e8b66cb4bf36c97872c8fe52192e3","lastCommitWhen":"2026-08-29T10:51:07+02:00","lastCommitMessage":"fix(coding-agent): wait for worker recovery before session reuse (#1756)\n\n* fix(coding-agent): wait for worker recovery before session reuse\n\n* fix(coding-agent): join overlapping worker starts"},{"name":"execute-bash-abort-controller.md","kind":"file","size":273,"lastCommitHash":"853041ec88f550f4e8d07e523cad82fbbb7e44f9","lastCommitWhen":"2026-08-29T11:08:24+02:00","lastCommitMessage":"fix(coding-agent): abort every in-flight bash command with its own controller (#1882)\n\n* fix(coding-agent): give each executeBash invocation its own abort controller\n\nConcurrent execute_bash_and_wait daemon commands shared the single _bashAbortController field: the first finisher cleared the second command's controller and abortBash could only target the most recent command, leaving earlier still-running commands unabortable. Track per-invocation controllers in a set; abortBash aborts all in-flight commands. Fixes ENG-5752.\n\n* fix(coding-agent): flag pending user bash abort while other bash commands run\n\nabortBash only set _userBashAbortRequested when no abort controllers were registered, so an abort arriving during user_bash extension dispatch was lost when a concurrent executeBash occupied the controller set and the user bash still started. Set the flag whenever a user bash is running; runUserBash clears it at each start. Also reword the per-invocation controller comments to present-tense behavior.\n\n* test(coding-agent): update fake REPLs to protocol 3\n\n---------\n\nCo-authored-by: Xeophon <46377542+xeophon@users.noreply.github.com>"},{"name":"host-reply-envelope.md","kind":"file","size":106,"lastCommitHash":"af14f066c3e2b1dfec94672b78a3fd35a2acbe5a","lastCommitWhen":"2026-08-28T17:39:44+02:00","lastCommitMessage":"fix(coding-agent): dispatcher-owned host-reply envelope (#1836)\n\n* fix host reply result envelope\n\n* docs(coding-agent): drop a stale handler-contract sentence from the merge"},{"name":"inline-mermaid-diagrams.md","kind":"file","size":155,"lastCommitHash":"c382f09856d4a8c8d2b765179657047d58691f25","lastCommitWhen":"2026-08-30T17:18:36+02:00","lastCommitMessage":"feat(coding-agent): render Mermaid diagrams inline in the terminal (#1893)\n\n* feat(coding-agent): render Mermaid code blocks as inline Unicode diagrams\n\nPorts pi-mono's Mermaid rendering (grok-mermaid) into prime-agent:\n- pi-tui Markdown gains an options.transform hook that rewrites source\n  Markdown with the exact content width before parsing (ported from\n  upstream pi-tui).\n- New mermaid.ts transform replaces top-level mermaid code blocks with\n  themed Unicode diagrams, falls back to the raw block when the diagram\n  is wider than the message, and appends a themed warning line for\n  partially rendered final diagrams.\n- AssistantMessageComponent applies the transform to text blocks only\n  (never thinking blocks) and tracks streaming state so the\n  streaming-to-final transition re-renders.\n- New markdown.mermaid setting (off/final/streaming, default streaming)\n  with a settings-selector entry.\n\nLinear: ENG-5673\n\n* test(coding-agent): kill mermaid mutation survivors\n\nAdversarial review mutation testing found three surviving mutants:\n- width guard flipped to >= (exact-fit diagrams would fall back)\n- codeSpan fence reduced to a single backtick (backtick labels break)\n- isStreaming inverted at the message_end call site (final mode never renders)\n\nAdds an exact-width boundary test, a backtick-label test, and a\nhandleEvent-level final-mode transition test that kill them.\n\n* build(coding-agent): pin grok-mermaid exactly for renderer-output stability\n\n* test(coding-agent): collapse redundant mermaid coverage\n\n* docs(coding-agent): tighten mermaid comments\n\n* fix(coding-agent): tolerate non-object markdown settings values\n\nNormalize a malformed markdown settings value at the migration boundary\n(mirroring the telemetry handling) so changing the Mermaid mode cannot\nthrow, and add the missing tui changelog fragment.\n\n* test(coding-agent): drop mermaid.test.ts\n\n* chore(coding-agent): one-line mermaid codeSpan comments"},{"name":"kernel-snapshot-dispose-timeout.md","kind":"file","size":100,"lastCommitHash":"d60fab8a76d9c169f945341f0ee3bde21903bb55","lastCommitWhen":"2026-08-28T17:40:01+02:00","lastCommitMessage":"fix(coding-agent): repair corrupt REPL protocol frames (#1839)\n\n* refactor(coding-agent): unify kernel shutdown\n\n* docs(coding-agent): carry over shutdown rationale comments\n\n* fix(coding-agent): repair corrupt REPL protocol\n\n* fix(coding-agent): cancel the final kernel snapshot before disposal cleanup\n\n* fix(coding-agent): block new executions from splicing ahead of the final dispose snapshot\n\nflushSnapshotForDispose captured the execution queue while the kernel\nstate was still 'running', so a concurrent execute() (which has no\nper-cell timeout) could enqueue after the capture; captureSnapshot then\nqueued behind it and its timeout never started, hanging dispose() and\nshutdown({snapshot:true}) forever. Claim the flush before capturing the\nqueue: non-internal requests are rejected while the final snapshot is\nflushing, keeping every wait on the dispose path bounded.\n\n* fix(coding-agent): close protocol-repair races and bound the repair\n\n- Gate queued requests behind an in-flight repair: a request whose queue\n  slot opens during a repair releases the slot and requeues after the\n  repair, so queued executes/snapshots can no longer run on the empty\n  replacement kernel ahead of restoreState (and overwrite its result or\n  clobber the last good snapshot).\n- Race the repair wait in execute() with opts.signal so an aborted call\n  returns its aborted result promptly instead of pending through repair.\n- Bound the repair's restore with REPAIR_RESTORE_TIMEOUT_MS so a stalled\n  replacement cannot wedge protocolRepairPromise (and every later\n  execute) forever; a timed-out restore discards the replacement and\n  returns to clean idle.\n- Stop respawn-looping when the replacement kernel itself emits a corrupt\n  frame during repair: discard it and settle at clean idle instead of\n  superseding into an unbounded chain of repairs.\n\n* fix(coding-agent): re-bootstrap repaired kernels and gate busy-waiting cells\n\n- A protocol-repaired kernel restored only the user namespace, so live\n  handles (rlm, bash, skills) were missing and the next cell failed with\n  NameErrors. KernelManagerOptions gains bootstrapCode (the provisioner\n  passes its buildRlmBootstrapCode output); the repair re-runs it after\n  restore, bounded like the restore, and discards the replacement to\n  clean idle when it fails.\n- The repair requeue gate only ran right after taking the queue slot, so\n  a cell busy-waiting on an interrupted execution when corruption arrived\n  could proceed onto the unrestored replacement while blocking the\n  repair's restore behind its slot. The gate now sits after the busy-wait\n  (still exempting the repair's own requests), covering both windows.\n- Fold the repeated kill-to-clean-idle teardown into killChildToIdle and\n  rename REPAIR_RESTORE_TIMEOUT_MS to REPAIR_STEP_TIMEOUT_MS since it now\n  bounds restore and bootstrap.\n\n* fix(coding-agent): join concurrent teardowns into one final snapshot flush\n\nConcurrent dispose() and shutdown({ snapshot: true }) (e.g. a session\ndispose racing the SIGINT handler) each ran flushSnapshotForDispose: the\nfirst finisher's finally cleared flushingSnapshotForDispose while the\nsecond was still flushing, dropping the execution guard early and\nenqueueing a duplicate final snapshot behind the first. Memoize the\nin-flight flush so every teardown joins the same bounded flush.\n\n* fix(coding-agent): close protocol repair gaps for schema-invalid frames, startup chunks, and rebootstrap\n\n- Fail the protocol on JSON object frames that violate the frame schema\n  (unknown event kind; done/host_request without a string id) instead of\n  silently dropping them, which left the active request unsettled forever.\n  The protocol version handshake is exact, so unknown kinds are corruption,\n  not forward compatibility.\n- A corrupt frame sharing one stdout chunk with ready no longer lets the\n  startup mark the corrupt child running: failProtocolFrame records the\n  error while starting and doStart fails the start.\n- A fresh kernel started lazily after a discarded repair re-runs the\n  configured runtime bootstrap before serving user code, so rlm/bash/skills\n  handles are never silently missing.\n\n* test(coding-agent): reconcile chain-collapse suites and cover teardown racing the lazy re-bootstrap\n\n- Point the graceful-shutdown flush spies at captureSnapshot: the merged\n  final flush (kernel-snapshot-dispose-timeout) snapshots through the\n  bounded captureSnapshot path, not snapshotState, so the old spies let\n  real snapshot requests hit the mocked wire and leaked fake timers.\n- The superseded repair's booting replacement is now hard-killed without\n  a protocol shutdown (single-kernel-shutdown only drains running\n  kernels), so it may die before journaling its spawn; assert spawn-count\n  stability after teardown instead of an exact boot count.\n- New composition test: a teardown racing an in-flight lazy re-bootstrap\n  stays bounded, spawns nothing new, and settles the raced cell.\n\n* fix(coding-agent): re-check the final-flush guard after the re-bootstrap wait\n\n- An external execute admitted before the final dispose flush could park on\n  the lazy re-bootstrap, then take its queue slot after the flush captured\n  pendingExecutions - splicing between the captured queue and the final\n  snapshot and unbounding the teardown. Re-check the flush guard right\n  after the ensure await; unit test proves the re-check is load-bearing.\n- Deflake the teardown-vs-re-bootstrap composition test: the fake runtime\n  journals its spawn before ready, so poll isRunning before the teardown to\n  race the re-bootstrap deterministically instead of the boot.\n\n* fix(coding-agent): close bot-review gaps in protocol repair and teardown seams\n\n- Terminal frames (done/host_request) with an EMPTY string id now fail the\n  protocol like id-less ones: the runtime mints uuid hex ids and echoes the\n  host's uuids, so an empty id is corruption that previously slipped past\n  the validator into the silent-drop hang.\n- An execution aborted while waiting on the lazy re-bootstrap settles\n  promptly: the wait races the abort signal (same pattern as\n  waitForProtocolRepair) and the aborted request returns before parking on\n  the queue slot behind the still-running bootstrap.\n- A failed kernel startup awaits its own teardown (final snapshot flush\n  included) before surfacing the error, so a replacement provisioner gated\n  on this dispose can no longer race the still-flushing kernel over the\n  same snapshot files.\n- restart() during the final dispose flush is rejected instead of taking a\n  queue slot and joining the owning shutdown, which could deadlock the\n  flush's snapshot behind the held slot.\n\n* test(coding-agent): cover empty-string host_request ids in the frame validator\n\nKills the surviving mutant that relaxed the host_request half of the\nnon-empty-id requirement back to typeof-only: an empty-id host_request now\nhas a corruption test mirroring the empty-id done one (protocol fails and\nthe kernel is repaired instead of the awaiting cell hanging).\n\n* fix(coding-agent): restore the saved namespace on lazily reprovisioned kernels\n\nAfter a discarded repair whose failure never implicated the snapshot (the\nrepair start died, or only its bootstrap failed), the lazily started fresh\nkernel re-ran the bootstrap but silently abandoned the user's saved\nnamespace forever. Track restore separately: killChildToIdle marks both\npending; the two snapshot-culprit discard paths (clean restore failure,\nreplacement corrupted mid-repair) clear the restore flag so a poisoned\nsnapshot is never retried; the lazy path restores one-shot best-effort\n(ordinary startup semantics) before bootstrapping, and a teardown's final\nsnapshot never triggers reprovisioning. Restore-attempt journaling in the\nfake runtime pins the no-retry and no-double-restore semantics.\n\n* fix(coding-agent): protect the saved snapshot from unrestored kernels; phase-aware corruption attribution\n\n- The final dispose flush skips its snapshot while pendingRestore is set:\n  a kernel that never restored the saved namespace must not overwrite it\n  (the on-disk snapshot is strictly fresher). One interleaving-independent\n  condition instead of joining the reprovision promise, which would\n  reintroduce the 30-60s teardown stall the teardown guard prevents. The\n  lazy one-shot clear moves after the corruption check so the flag also\n  covers a flush racing an in-flight lazy restore.\n- The repair give-up path attributes corruption by phase: performRestore\n  clears pendingRestore on success, so the flag still being set means the\n  corruption struck at or before the restore (snapshot stays the prime\n  suspect, loop-safe); corruption strictly after a successful restore\n  keeps the namespace restorable at the cost of at most one bounded\n  restore per later attempt."},{"name":"legacy-rlm-parser.md","kind":"file","size":96,"lastCommitHash":"dfffea27181c5cf509fb76088ea3b0e1746afdbc","lastCommitWhen":"2026-08-29T10:53:00+02:00","lastCommitMessage":"fix(coding-agent): unify legacy RLM registry parsing (#1847)\n\n* fix(coding-agent): unify legacy RLM registry parsing\n\n* fix(coding-agent): drop damaged rlmMaxDepth instead of rejecting the entry\n\nThe unified parser hard-rejected a legacy registry entry when the optional\nrlmMaxDepth field was malformed, so a valid child edge vanished from ledger\nseeding and passive discovery. Normalize the field to absent instead; the\nrequired topology fields still gate the entry."},{"name":"loss-bounded-compaction-projection.md","kind":"file","size":413,"lastCommitHash":"bee1dc826360b82ca9d943ca856cd2863f597297","lastCommitWhen":"2026-09-01T22:34:13+09:00","lastCommitMessage":"feat(coding-agent): add loss-bounded compaction projection\n"},{"name":"on-demand-agent-peers.md","kind":"file","size":85,"lastCommitHash":"ceb418049dd929676beb13f77a6d697bcd52f854","lastCommitWhen":"2026-08-28T17:09:00+02:00","lastCommitMessage":"refactor(coding-agent): centralize agent-message admission in AgentSession (#1861)\n\n* refactor(coding-agent): query agent peers on demand instead of broadcasting mirrors\n\n* refactor(coding-agent): centralize agent-message admission in AgentSession\n\n* fix(coding-agent): respond to unknown worker commands instead of dropping them\n\nLegacy worker_sync_agent_peers commands from an older supervisor fell\nthrough handleWorkerCommand without a response, forcing the requester\nto wait out its full 5s timeout on every peer sync. A default case now\nwrites an immediate failure for any unhandled worker command.\n\n* fix(daemon): re-check cron job runnability after prompt admission fence\n\nrunCronJob snapshotted the runnable job before promptHeartbeat/\npromptUntilAccepted, which can wait on the session admission fence. A job\ncancelled or completed during that wait was still delivered. Re-check via\nthe admissionCommitted hook and skip when the job is no longer runnable.\n\n* fix(daemon): skip cron delivery when the job content changed during admission\n\nupdateRlmHeartbeat mutates prompt/deliveryMode in place under the same job\nid, so the existence-only admissionCommitted re-check still delivered the\nstale snapshot captured before the admission fence wait. Compare the\nrefreshed job's prompt and deliveryMode and skip on mismatch; the skip\nreschedules nextRunAt so the updated instruction is delivered next cycle.\n\n* fix(coding-agent): re-check prompt admission after async input normalization\n\n_prompt ran admissionCommitted before _normalizeSubmission, but async\nextension input handlers are awaited between that check and\n_admitSessionInput, so a cron job cancelled or updated during the await\nstill delivered its stale prompt. Re-run the callback after the awaited\nnormalization so invalidated content is not admitted."},{"name":"pending-open-ownership.md","kind":"file","size":176,"lastCommitHash":"5b6c0e94e11a97fcfdd7a9fc9dc4f7acbda9c853","lastCommitWhen":"2026-08-29T11:34:20+02:00","lastCommitMessage":"fix(coding-agent): enforce session ownership when joining an in-flight open (#1864)\n\n* fix(coding-agent): wait for worker recovery before session reuse\n\n* fix(coding-agent): join overlapping worker starts\n\n* fix(coding-agent): enforce session ownership when joining an in-flight open\n\nJoining an opening worker via openingWorkers returned the pending worker\nto any client with the same session path, bypassing the ownership check\nthat the settled path applies in reuseWorkerForCreate. Await the pending\nopen and apply the shared owner check before returning; a rejected open\nstill propagates its original error to joiners.\n\n* fix(coding-agent): rejoin an open registered during stale-worker reclaim\n\nThe reclaimStaleWorkerRegistration await sits between the pending-open\ncheck and openingWorkers.set, so a concurrent opener registered during\nthat await was overwritten and a second worker launched for the same\nsaved session (regression from the #1756 reordering). Re-check the map\nafter the reclaim await and join through the shared owner-checked path.\n\n* test(coding-agent): cover foreign-owner join at the post-reclaim re-check\n\nAn intruder client joining the open registered during stale-worker\nreclaim must get SessionAlreadyActiveError; kills the mutant that\nreturns the pending promise without the owner check."},{"name":"post-compaction-idle.md","kind":"file","size":65,"lastCommitHash":"dab03c00c45e474186a3c6d6d654adb33c848fb3","lastCommitWhen":"2026-08-29T10:54:41+02:00","lastCommitMessage":"refactor(coding-agent): wake RLM quiescence on activity changes instead of polling (#1859)\n\n* fix(coding-agent): serialize post-compaction continuation on run settlement\n\n* refactor(coding-agent): wake RLM quiescence on activity changes instead of polling\n\n* fix(coding-agent): guard post-compaction continue against auto-compaction and stale runners\n\n- Publish _compactionOperation from _runAutoCompaction so the\n  post-compaction continuation runner (and other waiters) serialize\n  against auto/threshold/overflow/requested compaction, not just\n  manual compact().\n- Identity-guard the success path of the continuation runner so a\n  cancelled runner cannot forget continuation messages that a\n  replacement settlement still owns (busy/error paths already did).\n\n* fix(coding-agent): recheck refine apply before dispatching post-compaction continue\n\nA refine() call could enter its apply phase (which disconnects the agent\nevent listener) between the runner's top-of-loop _waitForRefineIdle() and\nagent.continue(), losing the continuation's messages. Recheck\n_refineInFlight under the commit fence like pauses/_compactionOperation;\nthe path from that recheck to agent.continue() is synchronous, mirroring\nthe final refine barrier used by normal turn dispatch.\n\n* fix(coding-agent): release the continuation runner's idle wait on cancel\n\nA cancelled post-compaction continuation left its runner parked inside\nwaitForIdle when the pump was suspended with queued actions: the wait\nwas not raced against the settlement like its neighbors, so the runner\nre-registered a session-input checkpoint waiter on every notify. The\nleaked waiter kept hasPendingAdmissionWaiters true and blocked daemon\npassivation until an unrelated resume.\n\nwaitForIdle's loop now takes an optional settlement: the suspended-queue\npark races the settlement promise, deregisters its waiter on loss, and\nthe loop exits once the settlement is superseded. The runner uses the\nsettlement-scoped variant; public waitForIdle is unchanged."},{"name":"prefer-bash-skill.md","kind":"file","size":104,"lastCommitHash":"c718bf3c30fd8da206ed551837cbb54f7ad15948","lastCommitWhen":"2026-08-31T10:15:07+02:00","lastCommitMessage":"fix(coding-agent): steer the model away from subprocess.run toward bash() (#1910)"},{"name":"protocol-frame-repair.md","kind":"file","size":147,"lastCommitHash":"d60fab8a76d9c169f945341f0ee3bde21903bb55","lastCommitWhen":"2026-08-28T17:40:01+02:00","lastCommitMessage":"fix(coding-agent): repair corrupt REPL protocol frames (#1839)\n\n* refactor(coding-agent): unify kernel shutdown\n\n* docs(coding-agent): carry over shutdown rationale comments\n\n* fix(coding-agent): repair corrupt REPL protocol\n\n* fix(coding-agent): cancel the final kernel snapshot before disposal cleanup\n\n* fix(coding-agent): block new executions from splicing ahead of the final dispose snapshot\n\nflushSnapshotForDispose captured the execution queue while the kernel\nstate was still 'running', so a concurrent execute() (which has no\nper-cell timeout) could enqueue after the capture; captureSnapshot then\nqueued behind it and its timeout never started, hanging dispose() and\nshutdown({snapshot:true}) forever. Claim the flush before capturing the\nqueue: non-internal requests are rejected while the final snapshot is\nflushing, keeping every wait on the dispose path bounded.\n\n* fix(coding-agent): close protocol-repair races and bound the repair\n\n- Gate queued requests behind an in-flight repair: a request whose queue\n  slot opens during a repair releases the slot and requeues after the\n  repair, so queued executes/snapshots can no longer run on the empty\n  replacement kernel ahead of restoreState (and overwrite its result or\n  clobber the last good snapshot).\n- Race the repair wait in execute() with opts.signal so an aborted call\n  returns its aborted result promptly instead of pending through repair.\n- Bound the repair's restore with REPAIR_RESTORE_TIMEOUT_MS so a stalled\n  replacement cannot wedge protocolRepairPromise (and every later\n  execute) forever; a timed-out restore discards the replacement and\n  returns to clean idle.\n- Stop respawn-looping when the replacement kernel itself emits a corrupt\n  frame during repair: discard it and settle at clean idle instead of\n  superseding into an unbounded chain of repairs.\n\n* fix(coding-agent): re-bootstrap repaired kernels and gate busy-waiting cells\n\n- A protocol-repaired kernel restored only the user namespace, so live\n  handles (rlm, bash, skills) were missing and the next cell failed with\n  NameErrors. KernelManagerOptions gains bootstrapCode (the provisioner\n  passes its buildRlmBootstrapCode output); the repair re-runs it after\n  restore, bounded like the restore, and discards the replacement to\n  clean idle when it fails.\n- The repair requeue gate only ran right after taking the queue slot, so\n  a cell busy-waiting on an interrupted execution when corruption arrived\n  could proceed onto the unrestored replacement while blocking the\n  repair's restore behind its slot. The gate now sits after the busy-wait\n  (still exempting the repair's own requests), covering both windows.\n- Fold the repeated kill-to-clean-idle teardown into killChildToIdle and\n  rename REPAIR_RESTORE_TIMEOUT_MS to REPAIR_STEP_TIMEOUT_MS since it now\n  bounds restore and bootstrap.\n\n* fix(coding-agent): join concurrent teardowns into one final snapshot flush\n\nConcurrent dispose() and shutdown({ snapshot: true }) (e.g. a session\ndispose racing the SIGINT handler) each ran flushSnapshotForDispose: the\nfirst finisher's finally cleared flushingSnapshotForDispose while the\nsecond was still flushing, dropping the execution guard early and\nenqueueing a duplicate final snapshot behind the first. Memoize the\nin-flight flush so every teardown joins the same bounded flush.\n\n* fix(coding-agent): close protocol repair gaps for schema-invalid frames, startup chunks, and rebootstrap\n\n- Fail the protocol on JSON object frames that violate the frame schema\n  (unknown event kind; done/host_request without a string id) instead of\n  silently dropping them, which left the active request unsettled forever.\n  The protocol version handshake is exact, so unknown kinds are corruption,\n  not forward compatibility.\n- A corrupt frame sharing one stdout chunk with ready no longer lets the\n  startup mark the corrupt child running: failProtocolFrame records the\n  error while starting and doStart fails the start.\n- A fresh kernel started lazily after a discarded repair re-runs the\n  configured runtime bootstrap before serving user code, so rlm/bash/skills\n  handles are never silently missing.\n\n* test(coding-agent): reconcile chain-collapse suites and cover teardown racing the lazy re-bootstrap\n\n- Point the graceful-shutdown flush spies at captureSnapshot: the merged\n  final flush (kernel-snapshot-dispose-timeout) snapshots through the\n  bounded captureSnapshot path, not snapshotState, so the old spies let\n  real snapshot requests hit the mocked wire and leaked fake timers.\n- The superseded repair's booting replacement is now hard-killed without\n  a protocol shutdown (single-kernel-shutdown only drains running\n  kernels), so it may die before journaling its spawn; assert spawn-count\n  stability after teardown instead of an exact boot count.\n- New composition test: a teardown racing an in-flight lazy re-bootstrap\n  stays bounded, spawns nothing new, and settles the raced cell.\n\n* fix(coding-agent): re-check the final-flush guard after the re-bootstrap wait\n\n- An external execute admitted before the final dispose flush could park on\n  the lazy re-bootstrap, then take its queue slot after the flush captured\n  pendingExecutions - splicing between the captured queue and the final\n  snapshot and unbounding the teardown. Re-check the flush guard right\n  after the ensure await; unit test proves the re-check is load-bearing.\n- Deflake the teardown-vs-re-bootstrap composition test: the fake runtime\n  journals its spawn before ready, so poll isRunning before the teardown to\n  race the re-bootstrap deterministically instead of the boot.\n\n* fix(coding-agent): close bot-review gaps in protocol repair and teardown seams\n\n- Terminal frames (done/host_request) with an EMPTY string id now fail the\n  protocol like id-less ones: the runtime mints uuid hex ids and echoes the\n  host's uuids, so an empty id is corruption that previously slipped past\n  the validator into the silent-drop hang.\n- An execution aborted while waiting on the lazy re-bootstrap settles\n  promptly: the wait races the abort signal (same pattern as\n  waitForProtocolRepair) and the aborted request returns before parking on\n  the queue slot behind the still-running bootstrap.\n- A failed kernel startup awaits its own teardown (final snapshot flush\n  included) before surfacing the error, so a replacement provisioner gated\n  on this dispose can no longer race the still-flushing kernel over the\n  same snapshot files.\n- restart() during the final dispose flush is rejected instead of taking a\n  queue slot and joining the owning shutdown, which could deadlock the\n  flush's snapshot behind the held slot.\n\n* test(coding-agent): cover empty-string host_request ids in the frame validator\n\nKills the surviving mutant that relaxed the host_request half of the\nnon-empty-id requirement back to typeof-only: an empty-id host_request now\nhas a corruption test mirroring the empty-id done one (protocol fails and\nthe kernel is repaired instead of the awaiting cell hanging).\n\n* fix(coding-agent): restore the saved namespace on lazily reprovisioned kernels\n\nAfter a discarded repair whose failure never implicated the snapshot (the\nrepair start died, or only its bootstrap failed), the lazily started fresh\nkernel re-ran the bootstrap but silently abandoned the user's saved\nnamespace forever. Track restore separately: killChildToIdle marks both\npending; the two snapshot-culprit discard paths (clean restore failure,\nreplacement corrupted mid-repair) clear the restore flag so a poisoned\nsnapshot is never retried; the lazy path restores one-shot best-effort\n(ordinary startup semantics) before bootstrapping, and a teardown's final\nsnapshot never triggers reprovisioning. Restore-attempt journaling in the\nfake runtime pins the no-retry and no-double-restore semantics.\n\n* fix(coding-agent): protect the saved snapshot from unrestored kernels; phase-aware corruption attribution\n\n- The final dispose flush skips its snapshot while pendingRestore is set:\n  a kernel that never restored the saved namespace must not overwrite it\n  (the on-disk snapshot is strictly fresher). One interleaving-independent\n  condition instead of joining the reprovision promise, which would\n  reintroduce the 30-60s teardown stall the teardown guard prevents. The\n  lazy one-shot clear moves after the corruption check so the flag also\n  covers a flush racing an in-flight lazy restore.\n- The repair give-up path attributes corruption by phase: performRestore\n  clears pendingRestore on success, so the flag still being set means the\n  corruption struck at or before the restore (snapshot stays the prime\n  suspect, loop-safe); corruption strictly after a successful restore\n  keeps the namespace restorable at the cost of at most one bounded\n  restore per later attempt."},{"name":"README.md","kind":"file","size":254,"lastCommitHash":"b5807b6f932ae3b208bc190176bc04a72126ff23","lastCommitWhen":"2026-08-20T10:01:49-07:00","lastCommitMessage":"Changelog fragments: conflict-free changelog entries (#1589)\n\n* feat(coding-agent): add changelog fragments with CI check and release-time aggregation (ENG-5408)\n\n* refactor: flag-day cutover — remove [Unreleased] sections entirely\n\nPer review: drop the transition machinery. All four changelogs lose their\n[Unreleased] header; coding-agent's pending entries move into a fragment.\nrelease.mjs no longer re-adds the header; the CI check accepts only\nfragments (or the no-changelog label). The stray-[Unreleased] absorption\nstays in buildReleaseSection so an accidentally merged old-style entry is\nfolded into the release instead of stranded. Test file removed.\n\n* fix: address bot findings — escape version in dry-run regex, refuse empty fragments\n\nCodeQL: the dry-run preview regex embedded the CLI version argument\nunescaped. Macroscope: empty fragments were git rm'd without appearing in\nthe changelog; the release now aborts on them and the CI check requires\nthe added fragment to have content. Cursor: normalizeFragment unexported.\n\n* fix(ci): verify fragment content, not just line additions\n\nA whitespace-only fragment passed the additions>0 guard but aborts the\nrelease. The check now reads each candidate fragment's content via its\ncontents_url (head-repo scoped, so fork PRs work) and requires non-blank\ntext.\n\n* refactor: decouple CI from release semantics for empty fragments\n\nThe fail-closed release abort forced CI to predict exactly what release\nwould reject, which pulled content fetching and fork-ref handling into\nthe workflow. Empty fragments have nothing to lose, so the release now\nwarns and leaves them unconsumed instead of aborting; CI goes back to a\nplain added-file presence check. Also trims comments and doc blocks.\n\n* fix(ci): fail closed when a PR exceeds the listFiles cap\n\nAbove 3000 changed files the API cannot return the full list, so the\ncheck could miss a src change. The no-changelog label remains the\nexplicit escape hatch."},{"name":"remote-message-single-send.md","kind":"file","size":232,"lastCommitHash":"80bf72c8855cacd0e299159682f11fcecc4f2924","lastCommitWhen":"2026-08-29T00:37:16-04:00","lastCommitMessage":"fix(coding-agent): avoid retrying delivered remote agent messages (#1700)\n\n* fix(coding-agent): avoid retrying delivered agent messages\n\n* Add the changelog fragment"},{"name":"remove-config-cache-reset.md","kind":"file","size":62,"lastCommitHash":"378e32d5813087768ec3f34ed32901813a36744c","lastCommitWhen":"2026-08-28T14:15:16+02:00","lastCommitMessage":"refactor(coding-agent): remove test-only config cache reset APIs (#1849)"},{"name":"remove-daemon-lookup-fake.md","kind":"file","size":63,"lastCommitHash":"bcf69db501da0227ecadb1de9dc78340f3e9ac2e","lastCommitWhen":"2026-08-29T11:10:24+02:00","lastCommitMessage":"refactor(coding-agent): remove the test-only daemon-lookup seam from main.ts (#1851)"},{"name":"remove-empty-selector-timers.md","kind":"file","size":75,"lastCommitHash":"18fe5d5b6d133f2b4a490cfe98dd0ae21cd2a30e","lastCommitWhen":"2026-08-29T10:53:50+02:00","lastCommitMessage":"refactor(coding-agent): delete unreachable empty-selector auto-cancel timers (#1855)"},{"name":"remove-test-telemetry-branch.md","kind":"file","size":69,"lastCommitHash":"9db2722ed48bcf5c2576176a463cd23d3e59eec9","lastCommitWhen":"2026-08-29T10:53:35+02:00","lastCommitMessage":"refactor(coding-agent): remove the NODE_ENV=test telemetry branch (#1848)"},{"name":"remove-unused-kernel-seams.md","kind":"file","size":110,"lastCommitHash":"5e0e288a883f1e375de1f93af5730848cc45c1dc","lastCommitWhen":"2026-08-28T17:07:52+02:00","lastCommitMessage":"Remove unused kernel seams (#1835)"},{"name":"repl-01-bash-tool.md","kind":"file","size":542,"lastCommitHash":"0940833b771fbaf5144451988604b310a96722fd","lastCommitWhen":"2026-08-26T14:41:46-07:00","lastCommitMessage":"Async bash() tool for the kernel runtime (#1684)\n\n* feat(coding-agent): add async-by-default bash() to the kernel runtime\n\n* chore(coding-agent): tighten bash() comments and changelog fragment\n\n* fix(coding-agent): address bash() review findings — exact tail retention, foreground-status lifecycle with group anchoring, post-kill forkserver reap, Windows start-id parity, executor-free await\n\n* fix(coding-agent): tree-kill bash() process trees on Windows and make running reflect group liveness\n\n* fix(coding-agent): carry bash() status pipe as stdin so strict-POSIX shells accept single-digit fd redirections\n\n* fix(coding-agent): close status fds when wake-pipe creation fails and gate bash() commands on orphan-journal registration\n\n* fix(coding-agent): kill full process trees in the Windows orphan reaper via taskkill /T\n\n* fix(coding-agent): kill one-shot await bash() on cancel, resolve Windows helpers via System32, retry taskkill after reap, and fail closed on orphan-journal enrollment\n\n* fix(coding-agent): confirm group exit before a cancelled one-shot bash() await propagates and complete-write orphan-journal records\n\n* fix(coding-agent): shield the cancelled-await bash() confirm-exit from re-cancellation, fail clearly without bash on Windows, and fence slow pumps out of result assembly\n\n* fix(coding-agent): flag the pump's read-to-commit window so the bash() drain fence cannot miss an in-flight chunk\n\n* fix(coding-agent): resolve taskkill via absolute System32 path in the host orphan reaper\n\n* fix(coding-agent): write the inactive orphan-journal record only after a delivered kill so undelivered signals leave the host reaper in charge\n\n* fix(coding-agent): count an already-exited leader as delivered in the Windows bash() reap so clean exits still journal inactive\n\n* fix(coding-agent): resolve trusted absolute shell host-side and close Windows journal/reap gaps\n\n* fix(coding-agent): best-effort-kill pid-only orphan records in daemon force-stop and recovery reaps\n\n* fix(coding-agent): resolve the kernel bash shell only from trusted absolute paths on Windows\n\n* fix(coding-agent): contain Windows bash children with kill-on-close job objects\n\n* fix(coding-agent): fall back to taskkill when job termination fails\n\n* fix(coding-agent): start Windows bash children suspended and fail closed when job containment cannot be established\n\n* fix(coding-agent): kill the whole tree for enriched orphan records on Windows force-stop\n\nstopTrackedProcess signals only the shell pid on Windows; use killOrphanProcess (taskkill /T) after the identity check, matching the owned-session-worker and daemon-supervisor reapers.\n\n* fix(coding-agent): skip the liveness check when the orphan identity is stale\n\nA reused pid looked like a failed kill after the identity re-check skipped taskkill, blocking worker cleanup with a spurious failure.\n\n* fix(coding-agent): journal Windows bash() children before job assignment so a kernel kill mid-spawn cannot leak an unjournaled suspended process\n\n* fix(coding-agent): pre-create the Windows bash() job before spawn and contain the child before the journal start-id query\n\n* fix(coding-agent): create Windows bash() children atomically inside the kill-on-close job via PROC_THREAD_ATTRIBUTE_JOB_LIST, closing the Popen-to-assignment leak window\n\n* chore(coding-agent): compress the atomic-job-association comments to one-line rationale\n\n* fix(coding-agent): retain the Windows bash() process handle through job cleanup and taskkill fallbacks so a recycled pid can never be killed\n\n* fix(coding-agent): serialize Windows bash() abort cleanup under the kill lock so shutdown taskkill can never race the process-handle close"},{"name":"repl-03-host-swap.md","kind":"file","size":94,"lastCommitHash":"61eb64748eb077e2a084432db92d101a2a83e146","lastCommitWhen":"2026-08-26T15:24:10-07:00","lastCommitMessage":"Minimal CPython REPL runtime (rlm.repl) (#1685)\n\n* feat(coding-agent): add async-by-default bash() to the kernel runtime\n\n* chore(coding-agent): tighten bash() comments and changelog fragment\n\n* feat(coding-agent): add a standalone CPython REPL runtime speaking JSON lines over stdio\n\n* chore(coding-agent): tighten REPL runtime comments\n\n* feat(coding-agent): run the kernel on the REPL runtime over stdio\n\n* fix(coding-agent): reject pending host requests on kernel teardown\n\nThe runtime now fails pending host_request futures when stdin hits EOF or\na shutdown request arrives, so a cell awaiting a host reply can no longer\nblock _serve from consuming the shutdown and wedge the process. Startup\nand busy-kernel messages plus the ipython tool description now say Python\nkernel, matching the default REPL runtime client.\n\n* chore(coding-agent): describe the kernel-heavy test tag client-neutrally\n\n* feat(coding-agent): make the REPL runtime the only kernel\n\nRemoves the Jupyter/ipykernel/ZMQ kernel client, the fork server, the\nPRIME_AGENT_KERNEL escape hatch, and the %%bash/%cd/%env cell rewriting.\nMagic-style cells (%/%%/!) return a one-line error naming the Python or\nbash() replacement. The kernel venv no longer installs ipykernel;\nexisting venvs are rebuilt once via the bootstrap schema bump. Old\nsnapshot artifacts still restore through the runtime's pickle compat.\n\n* fix(coding-agent): close MCP transports in REPL shutdown\n\n* fix(coding-agent): address bash() review findings — exact tail retention, foreground-status lifecycle with group anchoring, post-kill forkserver reap, Windows start-id parity, executor-free await\n\n* fix(coding-agent): tree-kill bash() process trees on Windows and make running reflect group liveness\n\n* fix(runtime): address repl runtime review findings\n\n- revalidate targeted interrupts through SIGINT delivery so a stale signal\n  cannot cancel a later request\n- preserve a parked untargeted interrupt while another request is inflight\n- reject non-string interrupt ids and validate snapshot options\n  (prune_oversized bool, max_bytes/max_variable_bytes present => int)\n- guard str(exc) in error/skip/fail reasons so a broken __str__ cannot\n  kill the runtime\n- fail the snapshot when the manifest write fails (before any pruning)\n- report 'snapshot not found' reason on restore of a missing path\n- wait unbounded for the output-pump drain marker so done never precedes\n  captured output and marker bytes never leak\n- document that aggregate-cap skips are not pruned\n\n* fix(coding-agent): carry bash() status pipe as stdin so strict-POSIX shells accept single-digit fd redirections\n\n* fix(coding-agent): address host-swap review findings — runtime-neutral kernel wording, %cd/%env rewrite fidelity, linear-time magic regexes, restart supersession guard\n\n* fix(coding-agent): reject stale column-0 line magics on any cell line, not just the first\n\n* fix(coding-agent): close status fds when wake-pipe creation fails and gate bash() commands on orphan-journal registration\n\n* fix(coding-agent): strip quoted %cd targets, use UTF-16-safe %env parsing, and expand $var/${var} values PEP-215-style\n\n* fix(coding-agent): fail rlm.run fast outside a live kernel so vitest workers cannot hang on a comm that never replies\n\n* fix(coding-agent): clear the active cell id before terminal events so late background output is never tagged with a finished cell\n\n* fix(coding-agent): update legacy IPython-era tests to assert cutover behavior\n\n* fix(coding-agent): describe the column-0 magic scan without referencing the removed rewrite backend\n\n* fix(coding-agent): consume parked interrupts on compile failures and survive user-closed stdio in the drain path\n\n* fix(coding-agent): redact bare %env listings, prefer '=' in %env parsing, echo %cd targets, and keep graceful shutdowns owning their cleanup\n\n* fix(coding-agent): reject kernel startup promptly on spawn errors and commit %cd previous-dir tracking only after chdir succeeds\n\n* fix(coding-agent): trim ParsedIpythonBashCell to the body field its callers use\n\n* fix(coding-agent): kill full process trees in the Windows orphan reaper via taskkill /T\n\n* fix(coding-agent): survive compile-phase crashes and fd-reuse drain hangs in the REPL runtime\n\n* fix(coding-agent): shield snapshot prune deletions from interrupts and pin the host comm probe to its real seam\n\n* fix(coding-agent): route list_names through the per-request backstop and skip non-string namespace keys\n\n* fix(coding-agent): reject snapshot requests whose manifest path aliases the payload path\n\n* fix(coding-agent): reject negative snapshot size caps that would prune every user variable\n\n* fix(coding-agent): kill one-shot await bash() on cancel, resolve Windows helpers via System32, retry taskkill after reap, and fail closed on orphan-journal enrollment\n\n* fix(coding-agent): attribute REPL stream output at write time so raw fd and user-thread bytes never carry another cell's id\n\n* fix(coding-agent): surface unattributed REPL stream output as separate background output instead of dropping or merging it\n\n* fix(coding-agent): confirm group exit before a cancelled one-shot bash() await propagates and complete-write orphan-journal records\n\n* fix(coding-agent): expose a working sys.stdout.buffer on the tagged REPL writer routing bytes through the null-attributed raw channel\n\n* fix(coding-agent): mark between-cell background output truncated when the pending buffer cap is hit\n\n* fix(coding-agent): shield the cancelled-await bash() confirm-exit from re-cancellation, fail clearly without bash on Windows, and fence slow pumps out of result assembly\n\n* fix(coding-agent): survive hostile protocol lines in the REPL reader thread and interrupt without pthread_kill on Windows\n\n* fix(coding-agent): send the protocol shutdown from dispose() so the runtime closes MCP servers and kills live bash groups before the hard kill\n\n* fix(coding-agent): flag the pump's read-to-commit window so the bash() drain fence cannot miss an in-flight chunk\n\n* fix(coding-agent): guard the whole REPL request line against hostile input, reject duplicate in-flight ids, complete short buffer-pipe writes, and clean the snapshot temp file on KeyboardInterrupt\n\n* fix(coding-agent): drop stale between-cell background output on kernel teardown so it cannot surface after a restart\n\n* fix(coding-agent): assert the tagged channel only in the large buffer-write REPL test since cross-channel ordering is not guaranteed\n\n* fix(coding-agent): resolve taskkill via absolute System32 path in the host orphan reaper\n\n* fix(coding-agent): write the inactive orphan-journal record only after a delivered kill so undelivered signals leave the host reaper in charge\n\n* fix(coding-agent): keep a REPL request interrupt-targetable through its trailing-expression repr and output drain until done is emitted\n\n* fix(coding-agent): count an already-exited leader as delivered in the Windows bash() reap so clean exits still journal inactive\n\n* fix(coding-agent): reject NaN and Infinity in emit() payloads before they corrupt REPL protocol framing\n\n* chore(coding-agent): correct the stale ipykernel requirement on the python override doc\n\n* chore(coding-agent): drop migration-era wording from kernel comments\n\n* fix(coding-agent): resolve trusted absolute shell host-side and close Windows journal/reap gaps\n\n* fix(coding-agent): best-effort-kill pid-only orphan records in daemon force-stop and recovery reaps\n\n* refactor(coding-agent): drop the magic-cell rejection gate\n\n%-prefixed and !-prefixed cells now reach CPython and fail with its own\nSyntaxError, which names the offending line. The rejection layer guarded\nagainst model-produced IPython syntax, but with the shipped prompt fresh\nsessions do not produce it, and the plain SyntaxError is protection enough.\nparseIpythonBashCell stays: transcripts from ipykernel-era sessions render\n%%bash cells with shell highlighting forever.\n\n* fix(coding-agent): report a committed destructive snapshot as success even when an interrupt was parked\n\n* chore(ai): drop stray live-regen drift in models.generated.ts\n\nad657d7ec accidentally committed generate-models output produced by a local\nbuild; the catalog belongs to its own regen PRs.\n\n* test(coding-agent): expect a plain SyntaxError for legacy %%bash cells after the magic-rejection gate removal\n\n* fix(coding-agent): consume a finishing-targeted interrupt after a completed state request instead of failing the done\n\n* fix(coding-agent): exit the REPL runtime when its owner dies even during a busy cell\n\n* fix(coding-agent): resolve the kernel bash shell only from trusted absolute paths on Windows\n\n* fix(coding-agent): contain Windows bash children with kill-on-close job objects\n\n* test(coding-agent): cover owner death during a non-yielding REPL cell\n\n* fix(coding-agent): skip concurrently deleted names during snapshot instead of aborting\n\n* fix(coding-agent): fall back to taskkill when job termination fails\n\n* fix(coding-agent): stop telling REPL-default users they need ipykernel\n\n* fix(coding-agent): clear the SIGINT target when its request finishes\n\n* test(coding-agent): drop migration-era wording from the %%bash rejection comment\n\n* fix(coding-agent): start Windows bash children suspended and fail closed when job containment cannot be established\n\n* fix(coding-agent): re-assert the kernel SIGINT handler between cells so a cell rebinding SIGINT cannot break interrupts\n\n* fix(coding-agent): kill the whole tree for enriched orphan records on Windows force-stop\n\nstopTrackedProcess signals only the shell pid on Windows; use killOrphanProcess (taskkill /T) after the identity check, matching the owned-session-worker and daemon-supervisor reapers.\n\n* docs(coding-agent): describe current magic-cell behavior in release notes\n\nMagic-style cells fail with a plain SyntaxError; the migration error and %cd/%env rewrites were removed, so the notes stop claiming them.\n\n* fix(coding-agent): skip the liveness check when the orphan identity is stale\n\nA reused pid looked like a failed kill after the identity re-check skipped taskkill, blocking worker cleanup with a spurious failure.\n\n* fix(coding-agent): journal Windows bash() children before job assignment so a kernel kill mid-spawn cannot leak an unjournaled suspended process\n\n* fix(coding-agent): pre-create the Windows bash() job before spawn and contain the child before the journal start-id query\n\n* fix(coding-agent): create Windows bash() children atomically inside the kill-on-close job via PROC_THREAD_ATTRIBUTE_JOB_LIST, closing the Popen-to-assignment leak window\n\n* chore(coding-agent): compress the atomic-job-association comments to one-line rationale\n\n* fix(coding-agent): send duplicate-id protocol errors outside the interrupt lock and reject int payloads in the captured stdout buffer\n\n* docs(coding-agent): update the kernel provisioner docstring for the REPL/IPython split\n\n* fix(coding-agent): retain the Windows bash() process handle through job cleanup and taskkill fallbacks so a recycled pid can never be killed\n\n* fix(coding-agent): serialize Windows bash() abort cleanup under the kill lock so shutdown taskkill can never race the process-handle close\n\n* fix(coding-agent): commit REPL snapshot payload and manifest atomically via unique temp files with guaranteed cleanup and parked-SIGINT restore\n\n* fix(coding-agent): stage REPL restore before an interrupt-parked apply and recover committed snapshot/restore results from protocol interrupts so a committed operation is never misreported as failed\n\n* chore(coding-agent): compress restore-shield rationale comments to one line each\n\n* fix(coding-agent): surface unattributed background output in IPython cell details and render it after the traceback in the expanded cell view\n\n* docs(coding-agent): replace stale Jupyter comm vocabulary in rlm-runtime failure modes and focused validation with stdio-transport equivalents\n\n* docs(coding-agent): describe the REPL trust boundary and runtime-bootstrap failure in stdio terms and drop the removed TokenUsage export\n\n* fix(runtime): address REPL review findings\n\n* fix(runtime): preserve near-cap snapshots\n\n---------\n\nCo-authored-by: Seth <seth@primeintellect.ai>"},{"name":"repl-04-cutover.md","kind":"file","size":391,"lastCommitHash":"61eb64748eb077e2a084432db92d101a2a83e146","lastCommitWhen":"2026-08-26T15:24:10-07:00","lastCommitMessage":"Minimal CPython REPL runtime (rlm.repl) (#1685)\n\n* feat(coding-agent): add async-by-default bash() to the kernel runtime\n\n* chore(coding-agent): tighten bash() comments and changelog fragment\n\n* feat(coding-agent): add a standalone CPython REPL runtime speaking JSON lines over stdio\n\n* chore(coding-agent): tighten REPL runtime comments\n\n* feat(coding-agent): run the kernel on the REPL runtime over stdio\n\n* fix(coding-agent): reject pending host requests on kernel teardown\n\nThe runtime now fails pending host_request futures when stdin hits EOF or\na shutdown request arrives, so a cell awaiting a host reply can no longer\nblock _serve from consuming the shutdown and wedge the process. Startup\nand busy-kernel messages plus the ipython tool description now say Python\nkernel, matching the default REPL runtime client.\n\n* chore(coding-agent): describe the kernel-heavy test tag client-neutrally\n\n* feat(coding-agent): make the REPL runtime the only kernel\n\nRemoves the Jupyter/ipykernel/ZMQ kernel client, the fork server, the\nPRIME_AGENT_KERNEL escape hatch, and the %%bash/%cd/%env cell rewriting.\nMagic-style cells (%/%%/!) return a one-line error naming the Python or\nbash() replacement. The kernel venv no longer installs ipykernel;\nexisting venvs are rebuilt once via the bootstrap schema bump. Old\nsnapshot artifacts still restore through the runtime's pickle compat.\n\n* fix(coding-agent): close MCP transports in REPL shutdown\n\n* fix(coding-agent): address bash() review findings — exact tail retention, foreground-status lifecycle with group anchoring, post-kill forkserver reap, Windows start-id parity, executor-free await\n\n* fix(coding-agent): tree-kill bash() process trees on Windows and make running reflect group liveness\n\n* fix(runtime): address repl runtime review findings\n\n- revalidate targeted interrupts through SIGINT delivery so a stale signal\n  cannot cancel a later request\n- preserve a parked untargeted interrupt while another request is inflight\n- reject non-string interrupt ids and validate snapshot options\n  (prune_oversized bool, max_bytes/max_variable_bytes present => int)\n- guard str(exc) in error/skip/fail reasons so a broken __str__ cannot\n  kill the runtime\n- fail the snapshot when the manifest write fails (before any pruning)\n- report 'snapshot not found' reason on restore of a missing path\n- wait unbounded for the output-pump drain marker so done never precedes\n  captured output and marker bytes never leak\n- document that aggregate-cap skips are not pruned\n\n* fix(coding-agent): carry bash() status pipe as stdin so strict-POSIX shells accept single-digit fd redirections\n\n* fix(coding-agent): address host-swap review findings — runtime-neutral kernel wording, %cd/%env rewrite fidelity, linear-time magic regexes, restart supersession guard\n\n* fix(coding-agent): reject stale column-0 line magics on any cell line, not just the first\n\n* fix(coding-agent): close status fds when wake-pipe creation fails and gate bash() commands on orphan-journal registration\n\n* fix(coding-agent): strip quoted %cd targets, use UTF-16-safe %env parsing, and expand $var/${var} values PEP-215-style\n\n* fix(coding-agent): fail rlm.run fast outside a live kernel so vitest workers cannot hang on a comm that never replies\n\n* fix(coding-agent): clear the active cell id before terminal events so late background output is never tagged with a finished cell\n\n* fix(coding-agent): update legacy IPython-era tests to assert cutover behavior\n\n* fix(coding-agent): describe the column-0 magic scan without referencing the removed rewrite backend\n\n* fix(coding-agent): consume parked interrupts on compile failures and survive user-closed stdio in the drain path\n\n* fix(coding-agent): redact bare %env listings, prefer '=' in %env parsing, echo %cd targets, and keep graceful shutdowns owning their cleanup\n\n* fix(coding-agent): reject kernel startup promptly on spawn errors and commit %cd previous-dir tracking only after chdir succeeds\n\n* fix(coding-agent): trim ParsedIpythonBashCell to the body field its callers use\n\n* fix(coding-agent): kill full process trees in the Windows orphan reaper via taskkill /T\n\n* fix(coding-agent): survive compile-phase crashes and fd-reuse drain hangs in the REPL runtime\n\n* fix(coding-agent): shield snapshot prune deletions from interrupts and pin the host comm probe to its real seam\n\n* fix(coding-agent): route list_names through the per-request backstop and skip non-string namespace keys\n\n* fix(coding-agent): reject snapshot requests whose manifest path aliases the payload path\n\n* fix(coding-agent): reject negative snapshot size caps that would prune every user variable\n\n* fix(coding-agent): kill one-shot await bash() on cancel, resolve Windows helpers via System32, retry taskkill after reap, and fail closed on orphan-journal enrollment\n\n* fix(coding-agent): attribute REPL stream output at write time so raw fd and user-thread bytes never carry another cell's id\n\n* fix(coding-agent): surface unattributed REPL stream output as separate background output instead of dropping or merging it\n\n* fix(coding-agent): confirm group exit before a cancelled one-shot bash() await propagates and complete-write orphan-journal records\n\n* fix(coding-agent): expose a working sys.stdout.buffer on the tagged REPL writer routing bytes through the null-attributed raw channel\n\n* fix(coding-agent): mark between-cell background output truncated when the pending buffer cap is hit\n\n* fix(coding-agent): shield the cancelled-await bash() confirm-exit from re-cancellation, fail clearly without bash on Windows, and fence slow pumps out of result assembly\n\n* fix(coding-agent): survive hostile protocol lines in the REPL reader thread and interrupt without pthread_kill on Windows\n\n* fix(coding-agent): send the protocol shutdown from dispose() so the runtime closes MCP servers and kills live bash groups before the hard kill\n\n* fix(coding-agent): flag the pump's read-to-commit window so the bash() drain fence cannot miss an in-flight chunk\n\n* fix(coding-agent): guard the whole REPL request line against hostile input, reject duplicate in-flight ids, complete short buffer-pipe writes, and clean the snapshot temp file on KeyboardInterrupt\n\n* fix(coding-agent): drop stale between-cell background output on kernel teardown so it cannot surface after a restart\n\n* fix(coding-agent): assert the tagged channel only in the large buffer-write REPL test since cross-channel ordering is not guaranteed\n\n* fix(coding-agent): resolve taskkill via absolute System32 path in the host orphan reaper\n\n* fix(coding-agent): write the inactive orphan-journal record only after a delivered kill so undelivered signals leave the host reaper in charge\n\n* fix(coding-agent): keep a REPL request interrupt-targetable through its trailing-expression repr and output drain until done is emitted\n\n* fix(coding-agent): count an already-exited leader as delivered in the Windows bash() reap so clean exits still journal inactive\n\n* fix(coding-agent): reject NaN and Infinity in emit() payloads before they corrupt REPL protocol framing\n\n* chore(coding-agent): correct the stale ipykernel requirement on the python override doc\n\n* chore(coding-agent): drop migration-era wording from kernel comments\n\n* fix(coding-agent): resolve trusted absolute shell host-side and close Windows journal/reap gaps\n\n* fix(coding-agent): best-effort-kill pid-only orphan records in daemon force-stop and recovery reaps\n\n* refactor(coding-agent): drop the magic-cell rejection gate\n\n%-prefixed and !-prefixed cells now reach CPython and fail with its own\nSyntaxError, which names the offending line. The rejection layer guarded\nagainst model-produced IPython syntax, but with the shipped prompt fresh\nsessions do not produce it, and the plain SyntaxError is protection enough.\nparseIpythonBashCell stays: transcripts from ipykernel-era sessions render\n%%bash cells with shell highlighting forever.\n\n* fix(coding-agent): report a committed destructive snapshot as success even when an interrupt was parked\n\n* chore(ai): drop stray live-regen drift in models.generated.ts\n\nad657d7ec accidentally committed generate-models output produced by a local\nbuild; the catalog belongs to its own regen PRs.\n\n* test(coding-agent): expect a plain SyntaxError for legacy %%bash cells after the magic-rejection gate removal\n\n* fix(coding-agent): consume a finishing-targeted interrupt after a completed state request instead of failing the done\n\n* fix(coding-agent): exit the REPL runtime when its owner dies even during a busy cell\n\n* fix(coding-agent): resolve the kernel bash shell only from trusted absolute paths on Windows\n\n* fix(coding-agent): contain Windows bash children with kill-on-close job objects\n\n* test(coding-agent): cover owner death during a non-yielding REPL cell\n\n* fix(coding-agent): skip concurrently deleted names during snapshot instead of aborting\n\n* fix(coding-agent): fall back to taskkill when job termination fails\n\n* fix(coding-agent): stop telling REPL-default users they need ipykernel\n\n* fix(coding-agent): clear the SIGINT target when its request finishes\n\n* test(coding-agent): drop migration-era wording from the %%bash rejection comment\n\n* fix(coding-agent): start Windows bash children suspended and fail closed when job containment cannot be established\n\n* fix(coding-agent): re-assert the kernel SIGINT handler between cells so a cell rebinding SIGINT cannot break interrupts\n\n* fix(coding-agent): kill the whole tree for enriched orphan records on Windows force-stop\n\nstopTrackedProcess signals only the shell pid on Windows; use killOrphanProcess (taskkill /T) after the identity check, matching the owned-session-worker and daemon-supervisor reapers.\n\n* docs(coding-agent): describe current magic-cell behavior in release notes\n\nMagic-style cells fail with a plain SyntaxError; the migration error and %cd/%env rewrites were removed, so the notes stop claiming them.\n\n* fix(coding-agent): skip the liveness check when the orphan identity is stale\n\nA reused pid looked like a failed kill after the identity re-check skipped taskkill, blocking worker cleanup with a spurious failure.\n\n* fix(coding-agent): journal Windows bash() children before job assignment so a kernel kill mid-spawn cannot leak an unjournaled suspended process\n\n* fix(coding-agent): pre-create the Windows bash() job before spawn and contain the child before the journal start-id query\n\n* fix(coding-agent): create Windows bash() children atomically inside the kill-on-close job via PROC_THREAD_ATTRIBUTE_JOB_LIST, closing the Popen-to-assignment leak window\n\n* chore(coding-agent): compress the atomic-job-association comments to one-line rationale\n\n* fix(coding-agent): send duplicate-id protocol errors outside the interrupt lock and reject int payloads in the captured stdout buffer\n\n* docs(coding-agent): update the kernel provisioner docstring for the REPL/IPython split\n\n* fix(coding-agent): retain the Windows bash() process handle through job cleanup and taskkill fallbacks so a recycled pid can never be killed\n\n* fix(coding-agent): serialize Windows bash() abort cleanup under the kill lock so shutdown taskkill can never race the process-handle close\n\n* fix(coding-agent): commit REPL snapshot payload and manifest atomically via unique temp files with guaranteed cleanup and parked-SIGINT restore\n\n* fix(coding-agent): stage REPL restore before an interrupt-parked apply and recover committed snapshot/restore results from protocol interrupts so a committed operation is never misreported as failed\n\n* chore(coding-agent): compress restore-shield rationale comments to one line each\n\n* fix(coding-agent): surface unattributed background output in IPython cell details and render it after the traceback in the expanded cell view\n\n* docs(coding-agent): replace stale Jupyter comm vocabulary in rlm-runtime failure modes and focused validation with stdio-transport equivalents\n\n* docs(coding-agent): describe the REPL trust boundary and runtime-bootstrap failure in stdio terms and drop the removed TokenUsage export\n\n* fix(runtime): address REPL review findings\n\n* fix(runtime): preserve near-cap snapshots\n\n---------\n\nCo-authored-by: Seth <seth@primeintellect.ai>"},{"name":"rlm-activity-change-waiter.md","kind":"file","size":68,"lastCommitHash":"dab03c00c45e474186a3c6d6d654adb33c848fb3","lastCommitWhen":"2026-08-29T10:54:41+02:00","lastCommitMessage":"refactor(coding-agent): wake RLM quiescence on activity changes instead of polling (#1859)\n\n* fix(coding-agent): serialize post-compaction continuation on run settlement\n\n* refactor(coding-agent): wake RLM quiescence on activity changes instead of polling\n\n* fix(coding-agent): guard post-compaction continue against auto-compaction and stale runners\n\n- Publish _compactionOperation from _runAutoCompaction so the\n  post-compaction continuation runner (and other waiters) serialize\n  against auto/threshold/overflow/requested compaction, not just\n  manual compact().\n- Identity-guard the success path of the continuation runner so a\n  cancelled runner cannot forget continuation messages that a\n  replacement settlement still owns (busy/error paths already did).\n\n* fix(coding-agent): recheck refine apply before dispatching post-compaction continue\n\nA refine() call could enter its apply phase (which disconnects the agent\nevent listener) between the runner's top-of-loop _waitForRefineIdle() and\nagent.continue(), losing the continuation's messages. Recheck\n_refineInFlight under the commit fence like pauses/_compactionOperation;\nthe path from that recheck to agent.continue() is synchronous, mirroring\nthe final refine barrier used by normal turn dispatch.\n\n* fix(coding-agent): release the continuation runner's idle wait on cancel\n\nA cancelled post-compaction continuation left its runner parked inside\nwaitForIdle when the pump was suspended with queued actions: the wait\nwas not raced against the settlement like its neighbors, so the runner\nre-registered a session-input checkpoint waiter on every notify. The\nleaked waiter kept hasPendingAdmissionWaiters true and blocked daemon\npassivation until an unrelated resume.\n\nwaitForIdle's loop now takes an optional settlement: the suspended-queue\npark races the settlement promise, deregisters its waiter on loss, and\nthe loop exits once the settlement is superseded. The runner uses the\nsettlement-scoped variant; public waitForIdle is unchanged."},{"name":"rlm-child-snapshot.md","kind":"file","size":94,"lastCommitHash":"c0334a176fb8f78b8c37327a6c76865792b03b52","lastCommitWhen":"2026-08-29T10:52:45+02:00","lastCommitMessage":"fix(coding-agent): single projection for RLM child snapshots (#1845)\n\n* fix(coding-agent): single projection for RLM child snapshots\n\n* fix(coding-agent): project live follow-up activity for session-only children\n\nA rehydrated child registered without an RlmChildRun always snapshotted as\nstatus done with no activity, so an attach mid-follow-up showed it idle.\nDerive activity from live session state, mirroring the run projection's\ndone-plus-activity convention for follow-ups."},{"name":"rlm-guarded-by-default.md","kind":"file","size":579,"lastCommitHash":"4a770d657c741044a547b490f2059c1aafb7f7a7","lastCommitWhen":"2026-08-31T21:52:03+09:00","lastCommitMessage":"make rlm spawns fail-closed: schema-bound results by default, guarded context, explicit unguarded opt-out\n"},{"name":"rlm-result-contracts.md","kind":"file","size":94,"lastCommitHash":"878bf91309c9dfa8030245019a17cf411920fd4b","lastCommitWhen":"2026-08-31T21:52:03+09:00","lastCommitMessage":"feat(coding-agent): unify RLM subagent lifecycle, messaging, and observation on rlm\n\n- rlm() and rlm.list_subagents() return one mutable RLMSubagent handle owning refresh, send, observe, info, result, and delete; RLMSpawnHandle is removed\n- agent messaging and observation move into rlm (send_parent, send_sibling, send_child, family, observe, info); agent_message.* and agent_observe.* host routes register whenever their controllers exist, independent of skill visibility\n- bundled agent-message and agent-observe skills are no longer model-visible; prompts document the rlm-native surface only\n- composable schema-validated result and context-admission contracts for RLM subagents\n- docs and changelog fragments updated for the unified surface\n"},{"name":"rlm-unified-surface.md","kind":"file","size":564,"lastCommitHash":"878bf91309c9dfa8030245019a17cf411920fd4b","lastCommitWhen":"2026-08-31T21:52:03+09:00","lastCommitMessage":"feat(coding-agent): unify RLM subagent lifecycle, messaging, and observation on rlm\n\n- rlm() and rlm.list_subagents() return one mutable RLMSubagent handle owning refresh, send, observe, info, result, and delete; RLMSpawnHandle is removed\n- agent messaging and observation move into rlm (send_parent, send_sibling, send_child, family, observe, info); agent_message.* and agent_observe.* host routes register whenever their controllers exist, independent of skill visibility\n- bundled agent-message and agent-observe skills are no longer model-visible; prompts document the rlm-native surface only\n- composable schema-validated result and context-admission contracts for RLM subagents\n- docs and changelog fragments updated for the unified surface\n"},{"name":"session-path-predicate.md","kind":"file","size":76,"lastCommitHash":"8c4ab8f5d63790c660b89d356310852aecfaacba","lastCommitWhen":"2026-08-28T14:15:06+02:00","lastCommitMessage":"refactor(coding-agent): centralize the session-path predicate (#1846)"},{"name":"single-kernel-shutdown.md","kind":"file","size":105,"lastCommitHash":"d60fab8a76d9c169f945341f0ee3bde21903bb55","lastCommitWhen":"2026-08-28T17:40:01+02:00","lastCommitMessage":"fix(coding-agent): repair corrupt REPL protocol frames (#1839)\n\n* refactor(coding-agent): unify kernel shutdown\n\n* docs(coding-agent): carry over shutdown rationale comments\n\n* fix(coding-agent): repair corrupt REPL protocol\n\n* fix(coding-agent): cancel the final kernel snapshot before disposal cleanup\n\n* fix(coding-agent): block new executions from splicing ahead of the final dispose snapshot\n\nflushSnapshotForDispose captured the execution queue while the kernel\nstate was still 'running', so a concurrent execute() (which has no\nper-cell timeout) could enqueue after the capture; captureSnapshot then\nqueued behind it and its timeout never started, hanging dispose() and\nshutdown({snapshot:true}) forever. Claim the flush before capturing the\nqueue: non-internal requests are rejected while the final snapshot is\nflushing, keeping every wait on the dispose path bounded.\n\n* fix(coding-agent): close protocol-repair races and bound the repair\n\n- Gate queued requests behind an in-flight repair: a request whose queue\n  slot opens during a repair releases the slot and requeues after the\n  repair, so queued executes/snapshots can no longer run on the empty\n  replacement kernel ahead of restoreState (and overwrite its result or\n  clobber the last good snapshot).\n- Race the repair wait in execute() with opts.signal so an aborted call\n  returns its aborted result promptly instead of pending through repair.\n- Bound the repair's restore with REPAIR_RESTORE_TIMEOUT_MS so a stalled\n  replacement cannot wedge protocolRepairPromise (and every later\n  execute) forever; a timed-out restore discards the replacement and\n  returns to clean idle.\n- Stop respawn-looping when the replacement kernel itself emits a corrupt\n  frame during repair: discard it and settle at clean idle instead of\n  superseding into an unbounded chain of repairs.\n\n* fix(coding-agent): re-bootstrap repaired kernels and gate busy-waiting cells\n\n- A protocol-repaired kernel restored only the user namespace, so live\n  handles (rlm, bash, skills) were missing and the next cell failed with\n  NameErrors. KernelManagerOptions gains bootstrapCode (the provisioner\n  passes its buildRlmBootstrapCode output); the repair re-runs it after\n  restore, bounded like the restore, and discards the replacement to\n  clean idle when it fails.\n- The repair requeue gate only ran right after taking the queue slot, so\n  a cell busy-waiting on an interrupted execution when corruption arrived\n  could proceed onto the unrestored replacement while blocking the\n  repair's restore behind its slot. The gate now sits after the busy-wait\n  (still exempting the repair's own requests), covering both windows.\n- Fold the repeated kill-to-clean-idle teardown into killChildToIdle and\n  rename REPAIR_RESTORE_TIMEOUT_MS to REPAIR_STEP_TIMEOUT_MS since it now\n  bounds restore and bootstrap.\n\n* fix(coding-agent): join concurrent teardowns into one final snapshot flush\n\nConcurrent dispose() and shutdown({ snapshot: true }) (e.g. a session\ndispose racing the SIGINT handler) each ran flushSnapshotForDispose: the\nfirst finisher's finally cleared flushingSnapshotForDispose while the\nsecond was still flushing, dropping the execution guard early and\nenqueueing a duplicate final snapshot behind the first. Memoize the\nin-flight flush so every teardown joins the same bounded flush.\n\n* fix(coding-agent): close protocol repair gaps for schema-invalid frames, startup chunks, and rebootstrap\n\n- Fail the protocol on JSON object frames that violate the frame schema\n  (unknown event kind; done/host_request without a string id) instead of\n  silently dropping them, which left the active request unsettled forever.\n  The protocol version handshake is exact, so unknown kinds are corruption,\n  not forward compatibility.\n- A corrupt frame sharing one stdout chunk with ready no longer lets the\n  startup mark the corrupt child running: failProtocolFrame records the\n  error while starting and doStart fails the start.\n- A fresh kernel started lazily after a discarded repair re-runs the\n  configured runtime bootstrap before serving user code, so rlm/bash/skills\n  handles are never silently missing.\n\n* test(coding-agent): reconcile chain-collapse suites and cover teardown racing the lazy re-bootstrap\n\n- Point the graceful-shutdown flush spies at captureSnapshot: the merged\n  final flush (kernel-snapshot-dispose-timeout) snapshots through the\n  bounded captureSnapshot path, not snapshotState, so the old spies let\n  real snapshot requests hit the mocked wire and leaked fake timers.\n- The superseded repair's booting replacement is now hard-killed without\n  a protocol shutdown (single-kernel-shutdown only drains running\n  kernels), so it may die before journaling its spawn; assert spawn-count\n  stability after teardown instead of an exact boot count.\n- New composition test: a teardown racing an in-flight lazy re-bootstrap\n  stays bounded, spawns nothing new, and settles the raced cell.\n\n* fix(coding-agent): re-check the final-flush guard after the re-bootstrap wait\n\n- An external execute admitted before the final dispose flush could park on\n  the lazy re-bootstrap, then take its queue slot after the flush captured\n  pendingExecutions - splicing between the captured queue and the final\n  snapshot and unbounding the teardown. Re-check the flush guard right\n  after the ensure await; unit test proves the re-check is load-bearing.\n- Deflake the teardown-vs-re-bootstrap composition test: the fake runtime\n  journals its spawn before ready, so poll isRunning before the teardown to\n  race the re-bootstrap deterministically instead of the boot.\n\n* fix(coding-agent): close bot-review gaps in protocol repair and teardown seams\n\n- Terminal frames (done/host_request) with an EMPTY string id now fail the\n  protocol like id-less ones: the runtime mints uuid hex ids and echoes the\n  host's uuids, so an empty id is corruption that previously slipped past\n  the validator into the silent-drop hang.\n- An execution aborted while waiting on the lazy re-bootstrap settles\n  promptly: the wait races the abort signal (same pattern as\n  waitForProtocolRepair) and the aborted request returns before parking on\n  the queue slot behind the still-running bootstrap.\n- A failed kernel startup awaits its own teardown (final snapshot flush\n  included) before surfacing the error, so a replacement provisioner gated\n  on this dispose can no longer race the still-flushing kernel over the\n  same snapshot files.\n- restart() during the final dispose flush is rejected instead of taking a\n  queue slot and joining the owning shutdown, which could deadlock the\n  flush's snapshot behind the held slot.\n\n* test(coding-agent): cover empty-string host_request ids in the frame validator\n\nKills the surviving mutant that relaxed the host_request half of the\nnon-empty-id requirement back to typeof-only: an empty-id host_request now\nhas a corruption test mirroring the empty-id done one (protocol fails and\nthe kernel is repaired instead of the awaiting cell hanging).\n\n* fix(coding-agent): restore the saved namespace on lazily reprovisioned kernels\n\nAfter a discarded repair whose failure never implicated the snapshot (the\nrepair start died, or only its bootstrap failed), the lazily started fresh\nkernel re-ran the bootstrap but silently abandoned the user's saved\nnamespace forever. Track restore separately: killChildToIdle marks both\npending; the two snapshot-culprit discard paths (clean restore failure,\nreplacement corrupted mid-repair) clear the restore flag so a poisoned\nsnapshot is never retried; the lazy path restores one-shot best-effort\n(ordinary startup semantics) before bootstrapping, and a teardown's final\nsnapshot never triggers reprovisioning. Restore-attempt journaling in the\nfake runtime pins the no-retry and no-double-restore semantics.\n\n* fix(coding-agent): protect the saved snapshot from unrestored kernels; phase-aware corruption attribution\n\n- The final dispose flush skips its snapshot while pendingRestore is set:\n  a kernel that never restored the saved namespace must not overwrite it\n  (the on-disk snapshot is strictly fresher). One interleaving-independent\n  condition instead of joining the reprovision promise, which would\n  reintroduce the 30-60s teardown stall the teardown guard prevents. The\n  lazy one-shot clear moves after the corruption check so the flag also\n  covers a flush racing an in-flight lazy restore.\n- The repair give-up path attributes corruption by phase: performRestore\n  clears pendingRestore on success, so the flag still being set means the\n  corruption struck at or before the restore (snapshot stays the prime\n  suspect, loop-safe); corruption strictly after a successful restore\n  keeps the namespace restorable at the cost of at most one bounded\n  restore per later attempt."},{"name":"snimu-tui-queue-single-source.md","kind":"file","size":92,"lastCommitHash":"bab124212fd5451beb071a884b5771ac7c1a8e1a","lastCommitWhen":"2026-08-29T10:52:17+02:00","lastCommitMessage":"fix(coding-agent): single-source the interactive queue state (#1842)\n\n* fix(coding-agent): single-source the interactive queue state\n\n* fix(coding-agent): close queue-state races around rebind, moves, and failed edits\n\n- rebindCurrentSession: re-sync sessionActions after resubscribing; a\n  session_action_update fired in the unsubscribed gap was lost forever.\n- browseQueueSelection: block browsing while a queue move RPC is pending,\n  matching the pendingQueueEdit guard, so the move response cannot reselect\n  the original item under newly browsed editor text.\n- moveQueueSelection: when the applied move's session_action_update has not\n  landed yet (sessionActions reference unchanged), mirror the swap locally so\n  the moved selection is not dropped against the pre-move snapshot; reconcile\n  the selection in the error path.\n- applyQueueSelection: reconcile the selection after the pending-edit flag\n  clears, so a rejected/failed edit no longer leaves Enter targeting a row\n  that was removed while events were suppressed."},{"name":"supervised-rename-authority.md","kind":"file","size":92,"lastCommitHash":"90343dca053de853555b5d0697fa36e8687894fb","lastCommitWhen":"2026-08-28T14:14:55+02:00","lastCommitMessage":"fix(coding-agent): trust supervisor-approved session renames in worker mode (#1841)"},{"name":"test-only-parser-hints.md","kind":"file","size":68,"lastCommitHash":"056014620853010778e478396b76ac04b3341864","lastCommitWhen":"2026-08-29T10:12:24+02:00","lastCommitMessage":"refactor(coding-agent): remove test-only parser and feature-hint seams (#1860)\n\n* refactor(coding-agent): remove test-only parser and feature-hint seams\n\n* test(coding-agent): restore provider-overlap and invalid-suffix warning coverage via public resolver API"},{"name":"use-message-count.md","kind":"file","size":57,"lastCommitHash":"0f6a388544df538d6b31ec54e53d1455f7b5a9de","lastCommitWhen":"2026-08-28T14:15:25+02:00","lastCommitMessage":"refactor(coding-agent): read messageCount instead of a shadow flag (#1852)"},{"name":"vouch-sirouk.md","kind":"file","size":70,"lastCommitHash":"a903d4b6768f484bd6d459b7b0aa7dee38e461e2","lastCommitWhen":"2026-08-29T20:06:21-04:00","lastCommitMessage":"chore: vouch sirouk as an external contributor (#1899)"}]