commits on main

2026-09-01

bee1dc82 dawn feat(coding-agent): add loss-bounded compaction projection

feat(coding-agent): add loss-bounded compaction projection

open commit browse files
f49ba1ee dawn fix(coding-agent): drain bash completion before RLM follow-up

fix(coding-agent): drain bash completion before RLM follow-up

open commit browse files
94f25d4f dawn feat(coding-agent): add root session controls

feat(coding-agent): add root session controls

open commit browse files
b0023ef6 dawn feat(coding-agent): add dot continuation shortcut

feat(coding-agent): add dot continuation shortcut

open commit browse files

2026-08-31

ca7ba908 dawn fix(coding-agent): avoid subagent finalization deadlock

fix(coding-agent): avoid subagent finalization deadlock

open commit browse files
bd35d3a8 dawn fix(update): preserve client reconnect across supervisor shutdown

fix(update): preserve client reconnect across supervisor shutdown

open commit browse files
6d3e2609 dawn fix(update): restart prepared daemon when coordination fails

fix(update): restart prepared daemon when coordination fails

open commit browse files
186ed0c5 dawn chore(models): refresh final live catalog changes

chore(models): refresh final live catalog changes

open commit browse files
992bc7c2 dawn fix(update): freeze daemon workers before package mutation

fix(update): freeze daemon workers before package mutation

open commit browse files
5a3bce07 dawn test(rlm): initialize hosted child runtime fixture

test(rlm): initialize hosted child runtime fixture

open commit browse files
81707659 dawn chore(models): refresh generated catalog

chore(models): refresh generated catalog

open commit browse files
2afe65a0 dawn fix(daemon): reclaim dead worker tombstones before updates

fix(daemon): reclaim dead worker tombstones before updates

open commit browse files
72bc988e dawn fix(runtime): survive SystemExit in persistent REPL

fix(runtime): survive SystemExit in persistent REPL

open commit browse files
d167f61c dawn fix(rlm): persist failed children without false result readiness

fix(rlm): persist failed children without false result readiness

open commit browse files
aa476e6f dawn fix(daemon): freeze snapshot messages at capture

fix(daemon): freeze snapshot messages at capture

open commit browse files
7e70aea0 dawn complete guarded RLM results and background completion wakeups

complete guarded RLM results and background completion wakeups

open commit browse files
78a0e05d dawn reject cd prefixes in bash(): teach repo.cd()/os.chdir instead

reject cd prefixes in bash(): teach repo.cd()/os.chdir instead

open commit browse files
7f881a4b dawn docs(rlm): reflect fail-closed spawn boundary in runtime architecture

docs(rlm): reflect fail-closed spawn boundary in runtime architecture

open commit browse files
4a770d65 dawn make rlm spawns fail-closed: schema-bound results by default, guarded context, explicit unguarded opt-out

make rlm spawns fail-closed: schema-bound results by default, guarded context, explicit unguarded opt-out

open commit browse files
63b9e269 dawn fix(ai): stop forcing disabled thinking on models that cannot disable it

fix(ai): stop forcing disabled thinking on models that cannot disable it

- GLM 5.3 rejects an explicit thinking disable ("use low, high, or max"); the zai/qwen/qwen-chat-template/deepseek wire formats treated unspecified thinking as an explicit disable, so /refine, compaction summaries, and other completeSimple callers failed with a 400 - unspecified or unsupported thinking now leaves thinking enabled for models whose thinkingLevelMap marks off as null - generate-models marks off/minimal/medium/xhigh unsupported for openai-completions GLM 5.3 entries (matching the OpenRouter-derived map), so clampThinkingLevel resolves off to low and getSupportedThinkingLevels stops advertising off - regenerated the model catalog

open commit browse files
878bf913 dawn feat(coding-agent): unify RLM subagent lifecycle, messaging, and observation on rlm

feat(coding-agent): unify RLM subagent lifecycle, messaging, and observation on rlm

- rlm() and rlm.list_subagents() return one mutable RLMSubagent handle owning refresh, send, observe, info, result, and delete; RLMSpawnHandle is removed - 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 - bundled agent-message and agent-observe skills are no longer model-visible; prompts document the rlm-native surface only - composable schema-validated result and context-admission contracts for RLM subagents - docs and changelog fragments updated for the unified surface

open commit browse files
d9c54e19 dawn fix(ai): preload provider modules at process startup

fix(ai): preload provider modules at process startup

Upgrading a global install rotates the hashed bundle chunk files under a still-running process. Provider adapters load lazily via dynamic import, so the first request for a not-yet-loaded adapter after an upgrade resolves against the mutated install and fails with "Cannot find module". preloadApiProviderModules() warms every provider module at boot in every process that enters main() (interactive client, daemon worker, daemon supervisor), so a running process never resolves provider chunks from disk again. Load failures still surface per-stream through the lazy wrappers.

open commit browse files
c718bf3c Sebastian Müller fix(coding-agent): steer the model away from subprocess.run toward bash() (#1910)

fix(coding-agent): steer the model away from subprocess.run toward bash() (#1910)

open commit browse files

2026-08-30

c382f098 Sebastian Müller feat(coding-agent): render Mermaid diagrams inline in the terminal (#1893)

feat(coding-agent): render Mermaid diagrams inline in the terminal (#1893)

* feat(coding-agent): render Mermaid code blocks as inline Unicode diagrams Ports pi-mono's Mermaid rendering (grok-mermaid) into prime-agent: - pi-tui Markdown gains an options.transform hook that rewrites source Markdown with the exact content width before parsing (ported from upstream pi-tui). - New mermaid.ts transform replaces top-level mermaid code blocks with themed Unicode diagrams, falls back to the raw block when the diagram is wider than the message, and appends a themed warning line for partially rendered final diagrams. - AssistantMessageComponent applies the transform to text blocks only (never thinking blocks) and tracks streaming state so the streaming-to-final transition re-renders. - New markdown.mermaid setting (off/final/streaming, default streaming) with a settings-selector entry. Linear: ENG-5673 * test(coding-agent): kill mermaid mutation survivors Adversarial review mutation testing found three surviving mutants: - width guard flipped to >= (exact-fit diagrams would fall back) - codeSpan fence reduced to a single backtick (backtick labels break) - isStreaming inverted at the message_end call site (final mode never renders) Adds an exact-width boundary test, a backtick-label test, and a handleEvent-level final-mode transition test that kill them. * build(coding-agent): pin grok-mermaid exactly for renderer-output stability * test(coding-agent): collapse redundant mermaid coverage * docs(coding-agent): tighten mermaid comments * fix(coding-agent): tolerate non-object markdown settings values Normalize a malformed markdown settings value at the migration boundary (mirroring the telemetry handling) so changing the Mermaid mode cannot throw, and add the missing tui changelog fragment. * test(coding-agent): drop mermaid.test.ts * chore(coding-agent): one-line mermaid codeSpan comments

open commit browse files
a903d4b6 Sebastian Müller chore: vouch sirouk as an external contributor (#1899)

chore: vouch sirouk as an external contributor (#1899)

open commit browse files

2026-08-29

5b6c0e94 Sebastian Müller fix(coding-agent): enforce session ownership when joining an in-flight open (#1864)

fix(coding-agent): enforce session ownership when joining an in-flight open (#1864)

* fix(coding-agent): wait for worker recovery before session reuse * fix(coding-agent): join overlapping worker starts * fix(coding-agent): enforce session ownership when joining an in-flight open Joining an opening worker via openingWorkers returned the pending worker to any client with the same session path, bypassing the ownership check that the settled path applies in reuseWorkerForCreate. Await the pending open and apply the shared owner check before returning; a rejected open still propagates its original error to joiners. * fix(coding-agent): rejoin an open registered during stale-worker reclaim The reclaimStaleWorkerRegistration await sits between the pending-open check and openingWorkers.set, so a concurrent opener registered during that await was overwritten and a second worker launched for the same saved session (regression from the #1756 reordering). Re-check the map after the reclaim await and join through the shared owner-checked path. * test(coding-agent): cover foreign-owner join at the post-reclaim re-check An intruder client joining the open registered during stale-worker reclaim must get SessionAlreadyActiveError; kills the mutant that returns the pending promise without the owner check.

open commit browse files
6322b7bb Sebastian Müller refactor(coding-agent): await in-flight bash completion during daemon close (#1858)

refactor(coding-agent): await in-flight bash completion during daemon close (#1858)

open commit browse files
bcf69db5 Sebastian Müller refactor(coding-agent): remove the test-only daemon-lookup seam from main.ts (#1851)

refactor(coding-agent): remove the test-only daemon-lookup seam from main.ts (#1851)

open commit browse files
8ca52555 Sebastian Müller refactor(ai): delete the unused getOverflowPatterns export (#1850)

refactor(ai): delete the unused getOverflowPatterns export (#1850)

* refactor(ai): delete the unused getOverflowPatterns export * docs(ai): fix changelog fragment placement for getOverflowPatterns removal The removed API belongs to @earendil-works/pi-ai, not the coding-agent package (whose root export never included it), so drop the misplaced coding-agent fragment and name the removed export explicitly in the ai fragment.

open commit browse files
853041ec Sebastian Müller fix(coding-agent): abort every in-flight bash command with its own controller (#1882)

fix(coding-agent): abort every in-flight bash command with its own controller (#1882)

* fix(coding-agent): give each executeBash invocation its own abort controller Concurrent 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. * fix(coding-agent): flag pending user bash abort while other bash commands run abortBash 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. * test(coding-agent): update fake REPLs to protocol 3 --------- Co-authored-by: Xeophon <46377542+xeophon@users.noreply.github.com>

open commit browse files
dab03c00 Sebastian Müller refactor(coding-agent): wake RLM quiescence on activity changes instead of polling (#1859)

refactor(coding-agent): wake RLM quiescence on activity changes instead of polling (#1859)

* fix(coding-agent): serialize post-compaction continuation on run settlement * refactor(coding-agent): wake RLM quiescence on activity changes instead of polling * fix(coding-agent): guard post-compaction continue against auto-compaction and stale runners - Publish _compactionOperation from _runAutoCompaction so the post-compaction continuation runner (and other waiters) serialize against auto/threshold/overflow/requested compaction, not just manual compact(). - Identity-guard the success path of the continuation runner so a cancelled runner cannot forget continuation messages that a replacement settlement still owns (busy/error paths already did). * fix(coding-agent): recheck refine apply before dispatching post-compaction continue A refine() call could enter its apply phase (which disconnects the agent event listener) between the runner's top-of-loop _waitForRefineIdle() and agent.continue(), losing the continuation's messages. Recheck _refineInFlight under the commit fence like pauses/_compactionOperation; the path from that recheck to agent.continue() is synchronous, mirroring the final refine barrier used by normal turn dispatch. * fix(coding-agent): release the continuation runner's idle wait on cancel A cancelled post-compaction continuation left its runner parked inside waitForIdle when the pump was suspended with queued actions: the wait was not raced against the settlement like its neighbors, so the runner re-registered a session-input checkpoint waiter on every notify. The leaked waiter kept hasPendingAdmissionWaiters true and blocked daemon passivation until an unrelated resume. waitForIdle's loop now takes an optional settlement: the suspended-queue park races the settlement promise, deregisters its waiter on loss, and the loop exits once the settlement is superseded. The runner uses the settlement-scoped variant; public waitForIdle is unchanged.

open commit browse files
85c236d5 Sebastian Müller refactor(coding-agent): derive scoped heartbeats at render time (#1857)

refactor(coding-agent): derive scoped heartbeats at render time (#1857)

* refactor(coding-agent): derive scoped heartbeats at render time * fix(coding-agent): keep the earliest heartbeat manager refresh deadline scheduleHeartbeatManagerRefresh now runs on every subagent snapshot update, and each call cleared and re-armed the refresh timer. An overdue heartbeat uses a relative 5s fallback delay, so children updating more often than every 5s postponed the open manager's refresh indefinitely. Track the scheduled deadline and keep the pending timer unless the newly derived deadline is earlier. * test(coding-agent): cover re-arming the heartbeat refresh to an earlier deadline The keep-timer-always mutant (returning whenever a timer is armed) survived the touched suites: nothing proved a sooner heartbeat pulls the pending refresh forward past the capped 60s poll.

open commit browse files
18fe5d5b Sebastian Müller refactor(coding-agent): delete unreachable empty-selector auto-cancel timers (#1855)

refactor(coding-agent): delete unreachable empty-selector auto-cancel timers (#1855)

open commit browse files
9db2722e Sebastian Müller refactor(coding-agent): remove the NODE_ENV=test telemetry branch (#1848)

refactor(coding-agent): remove the NODE_ENV=test telemetry branch (#1848)

open commit browse files
dfffea27 Sebastian Müller fix(coding-agent): unify legacy RLM registry parsing (#1847)

fix(coding-agent): unify legacy RLM registry parsing (#1847)

* fix(coding-agent): unify legacy RLM registry parsing * fix(coding-agent): drop damaged rlmMaxDepth instead of rejecting the entry The unified parser hard-rejected a legacy registry entry when the optional rlmMaxDepth field was malformed, so a valid child edge vanished from ledger seeding and passive discovery. Normalize the field to absent instead; the required topology fields still gate the entry.

open commit browse files
c0334a17 Sebastian Müller fix(coding-agent): single projection for RLM child snapshots (#1845)

fix(coding-agent): single projection for RLM child snapshots (#1845)

* fix(coding-agent): single projection for RLM child snapshots * fix(coding-agent): project live follow-up activity for session-only children A rehydrated child registered without an RlmChildRun always snapshotted as status done with no activity, so an attach mid-follow-up showed it idle. Derive activity from live session state, mirroring the run projection's done-plus-activity convention for follow-ups.

open commit browse files
bab12421 Sebastian Müller fix(coding-agent): single-source the interactive queue state (#1842)

fix(coding-agent): single-source the interactive queue state (#1842)

* fix(coding-agent): single-source the interactive queue state * fix(coding-agent): close queue-state races around rebind, moves, and failed edits - rebindCurrentSession: re-sync sessionActions after resubscribing; a session_action_update fired in the unsubscribed gap was lost forever. - browseQueueSelection: block browsing while a queue move RPC is pending, matching the pendingQueueEdit guard, so the move response cannot reselect the original item under newly browsed editor text. - moveQueueSelection: when the applied move's session_action_update has not landed yet (sessionActions reference unchanged), mirror the swap locally so the moved selection is not dropped against the pre-move snapshot; reconcile the selection in the error path. - applyQueueSelection: reconcile the selection after the pending-edit flag clears, so a rejected/failed edit no longer leaves Enter targeting a row that was removed while events were suppressed.

open commit browse files
ee8fd699 Sebastian Müller fix(coding-agent): wait for worker recovery before session reuse (#1756)

fix(coding-agent): wait for worker recovery before session reuse (#1756)

* fix(coding-agent): wait for worker recovery before session reuse * fix(coding-agent): join overlapping worker starts

open commit browse files
05601462 Sebastian Müller refactor(coding-agent): remove test-only parser and feature-hint seams (#1860)

refactor(coding-agent): remove test-only parser and feature-hint seams (#1860)

* refactor(coding-agent): remove test-only parser and feature-hint seams * test(coding-agent): restore provider-overlap and invalid-suffix warning coverage via public resolver API

open commit browse files
80bf72c8 Sebastian Müller fix(coding-agent): avoid retrying delivered remote agent messages (#1700)

fix(coding-agent): avoid retrying delivered remote agent messages (#1700)

* fix(coding-agent): avoid retrying delivered agent messages * Add the changelog fragment

open commit browse files

2026-08-28

d60fab8a Sebastian Müller fix(coding-agent): repair corrupt REPL protocol frames (#1839)

fix(coding-agent): repair corrupt REPL protocol frames (#1839)

* refactor(coding-agent): unify kernel shutdown * docs(coding-agent): carry over shutdown rationale comments * fix(coding-agent): repair corrupt REPL protocol * fix(coding-agent): cancel the final kernel snapshot before disposal cleanup * fix(coding-agent): block new executions from splicing ahead of the final dispose snapshot flushSnapshotForDispose captured the execution queue while the kernel state was still 'running', so a concurrent execute() (which has no per-cell timeout) could enqueue after the capture; captureSnapshot then queued behind it and its timeout never started, hanging dispose() and shutdown({snapshot:true}) forever. Claim the flush before capturing the queue: non-internal requests are rejected while the final snapshot is flushing, keeping every wait on the dispose path bounded. * fix(coding-agent): close protocol-repair races and bound the repair - Gate queued requests behind an in-flight repair: a request whose queue slot opens during a repair releases the slot and requeues after the repair, so queued executes/snapshots can no longer run on the empty replacement kernel ahead of restoreState (and overwrite its result or clobber the last good snapshot). - Race the repair wait in execute() with opts.signal so an aborted call returns its aborted result promptly instead of pending through repair. - Bound the repair's restore with REPAIR_RESTORE_TIMEOUT_MS so a stalled replacement cannot wedge protocolRepairPromise (and every later execute) forever; a timed-out restore discards the replacement and returns to clean idle. - Stop respawn-looping when the replacement kernel itself emits a corrupt frame during repair: discard it and settle at clean idle instead of superseding into an unbounded chain of repairs. * fix(coding-agent): re-bootstrap repaired kernels and gate busy-waiting cells - A protocol-repaired kernel restored only the user namespace, so live handles (rlm, bash, skills) were missing and the next cell failed with NameErrors. KernelManagerOptions gains bootstrapCode (the provisioner passes its buildRlmBootstrapCode output); the repair re-runs it after restore, bounded like the restore, and discards the replacement to clean idle when it fails. - The repair requeue gate only ran right after taking the queue slot, so a cell busy-waiting on an interrupted execution when corruption arrived could proceed onto the unrestored replacement while blocking the repair's restore behind its slot. The gate now sits after the busy-wait (still exempting the repair's own requests), covering both windows. - Fold the repeated kill-to-clean-idle teardown into killChildToIdle and rename REPAIR_RESTORE_TIMEOUT_MS to REPAIR_STEP_TIMEOUT_MS since it now bounds restore and bootstrap. * fix(coding-agent): join concurrent teardowns into one final snapshot flush Concurrent dispose() and shutdown({ snapshot: true }) (e.g. a session dispose racing the SIGINT handler) each ran flushSnapshotForDispose: the first finisher's finally cleared flushingSnapshotForDispose while the second was still flushing, dropping the execution guard early and enqueueing a duplicate final snapshot behind the first. Memoize the in-flight flush so every teardown joins the same bounded flush. * fix(coding-agent): close protocol repair gaps for schema-invalid frames, startup chunks, and rebootstrap - Fail the protocol on JSON object frames that violate the frame schema (unknown event kind; done/host_request without a string id) instead of silently dropping them, which left the active request unsettled forever. The protocol version handshake is exact, so unknown kinds are corruption, not forward compatibility. - A corrupt frame sharing one stdout chunk with ready no longer lets the startup mark the corrupt child running: failProtocolFrame records the error while starting and doStart fails the start. - A fresh kernel started lazily after a discarded repair re-runs the configured runtime bootstrap before serving user code, so rlm/bash/skills handles are never silently missing. * test(coding-agent): reconcile chain-collapse suites and cover teardown racing the lazy re-bootstrap - Point the graceful-shutdown flush spies at captureSnapshot: the merged final flush (kernel-snapshot-dispose-timeout) snapshots through the bounded captureSnapshot path, not snapshotState, so the old spies let real snapshot requests hit the mocked wire and leaked fake timers. - The superseded repair's booting replacement is now hard-killed without a protocol shutdown (single-kernel-shutdown only drains running kernels), so it may die before journaling its spawn; assert spawn-count stability after teardown instead of an exact boot count. - New composition test: a teardown racing an in-flight lazy re-bootstrap stays bounded, spawns nothing new, and settles the raced cell. * fix(coding-agent): re-check the final-flush guard after the re-bootstrap wait - An external execute admitted before the final dispose flush could park on the lazy re-bootstrap, then take its queue slot after the flush captured pendingExecutions - splicing between the captured queue and the final snapshot and unbounding the teardown. Re-check the flush guard right after the ensure await; unit test proves the re-check is load-bearing. - Deflake the teardown-vs-re-bootstrap composition test: the fake runtime journals its spawn before ready, so poll isRunning before the teardown to race the re-bootstrap deterministically instead of the boot. * fix(coding-agent): close bot-review gaps in protocol repair and teardown seams - Terminal frames (done/host_request) with an EMPTY string id now fail the protocol like id-less ones: the runtime mints uuid hex ids and echoes the host's uuids, so an empty id is corruption that previously slipped past the validator into the silent-drop hang. - An execution aborted while waiting on the lazy re-bootstrap settles promptly: the wait races the abort signal (same pattern as waitForProtocolRepair) and the aborted request returns before parking on the queue slot behind the still-running bootstrap. - A failed kernel startup awaits its own teardown (final snapshot flush included) before surfacing the error, so a replacement provisioner gated on this dispose can no longer race the still-flushing kernel over the same snapshot files. - restart() during the final dispose flush is rejected instead of taking a queue slot and joining the owning shutdown, which could deadlock the flush's snapshot behind the held slot. * test(coding-agent): cover empty-string host_request ids in the frame validator Kills the surviving mutant that relaxed the host_request half of the non-empty-id requirement back to typeof-only: an empty-id host_request now has a corruption test mirroring the empty-id done one (protocol fails and the kernel is repaired instead of the awaiting cell hanging). * fix(coding-agent): restore the saved namespace on lazily reprovisioned kernels After a discarded repair whose failure never implicated the snapshot (the repair start died, or only its bootstrap failed), the lazily started fresh kernel re-ran the bootstrap but silently abandoned the user's saved namespace forever. Track restore separately: killChildToIdle marks both pending; the two snapshot-culprit discard paths (clean restore failure, replacement corrupted mid-repair) clear the restore flag so a poisoned snapshot is never retried; the lazy path restores one-shot best-effort (ordinary startup semantics) before bootstrapping, and a teardown's final snapshot never triggers reprovisioning. Restore-attempt journaling in the fake runtime pins the no-retry and no-double-restore semantics. * fix(coding-agent): protect the saved snapshot from unrestored kernels; phase-aware corruption attribution - The final dispose flush skips its snapshot while pendingRestore is set: a kernel that never restored the saved namespace must not overwrite it (the on-disk snapshot is strictly fresher). One interleaving-independent condition instead of joining the reprovision promise, which would reintroduce the 30-60s teardown stall the teardown guard prevents. The lazy one-shot clear moves after the corruption check so the flag also covers a flush racing an in-flight lazy restore. - The repair give-up path attributes corruption by phase: performRestore clears pendingRestore on success, so the flag still being set means the corruption struck at or before the restore (snapshot stays the prime suspect, loop-safe); corruption strictly after a successful restore keeps the namespace restorable at the cost of at most one bounded restore per later attempt.

open commit browse files
af14f066 Sebastian Müller fix(coding-agent): dispatcher-owned host-reply envelope (#1836)

fix(coding-agent): dispatcher-owned host-reply envelope (#1836)

* fix host reply result envelope * docs(coding-agent): drop a stale handler-contract sentence from the merge

open commit browse files
ceb41804 Sebastian Müller refactor(coding-agent): centralize agent-message admission in AgentSession (#1861)

refactor(coding-agent): centralize agent-message admission in AgentSession (#1861)

* refactor(coding-agent): query agent peers on demand instead of broadcasting mirrors * refactor(coding-agent): centralize agent-message admission in AgentSession * fix(coding-agent): respond to unknown worker commands instead of dropping them Legacy worker_sync_agent_peers commands from an older supervisor fell through handleWorkerCommand without a response, forcing the requester to wait out its full 5s timeout on every peer sync. A default case now writes an immediate failure for any unhandled worker command. * fix(daemon): re-check cron job runnability after prompt admission fence runCronJob snapshotted the runnable job before promptHeartbeat/ promptUntilAccepted, which can wait on the session admission fence. A job cancelled or completed during that wait was still delivered. Re-check via the admissionCommitted hook and skip when the job is no longer runnable. * fix(daemon): skip cron delivery when the job content changed during admission updateRlmHeartbeat mutates prompt/deliveryMode in place under the same job id, so the existence-only admissionCommitted re-check still delivered the stale snapshot captured before the admission fence wait. Compare the refreshed job's prompt and deliveryMode and skip on mismatch; the skip reschedules nextRunAt so the updated instruction is delivered next cycle. * fix(coding-agent): re-check prompt admission after async input normalization _prompt ran admissionCommitted before _normalizeSubmission, but async extension input handlers are awaited between that check and _admitSessionInput, so a cron job cancelled or updated during the await still delivered its stale prompt. Re-run the callback after the awaited normalization so invalidated content is not admitted.

open commit browse files
80902713 Sebastian Müller fix(runtime): ordered bash output completion sentinel (#1838)

fix(runtime): ordered bash output completion sentinel (#1838)

* fix(runtime): fence bash output completion * docs(runtime): document post-fence output visibility in bash() docstring * fix(runtime): emit bash completion fence via absolute printf path A shell function named `command` shadows `\command -p printf` (the backslash only defeats aliases), swallowing both fence frames and wedging the await behind background jobs until shell death. A slash-qualified printf resolved on the system default utility PATH bypasses function and alias lookup in every POSIX shell. Also scope the changelog claim: EXIT-trap/background output lands after the completion marker by design and stays visible via handle.output(). * docs(runtime): soften the fence-printf comment per review

open commit browse files
5e0e288a Sebastian Müller Remove unused kernel seams (#1835)

Remove unused kernel seams (#1835)

open commit browse files
d90062b6 Sebastian Müller refactor(coding-agent): derive available connection models on read (#1853)

refactor(coding-agent): derive available connection models on read (#1853)

open commit browse files
0f6a3885 Sebastian Müller refactor(coding-agent): read messageCount instead of a shadow flag (#1852)

refactor(coding-agent): read messageCount instead of a shadow flag (#1852)

open commit browse files
378e32d5 Sebastian Müller refactor(coding-agent): remove test-only config cache reset APIs (#1849)

refactor(coding-agent): remove test-only config cache reset APIs (#1849)

open commit browse files
8c4ab8f5 Sebastian Müller refactor(coding-agent): centralize the session-path predicate (#1846)

refactor(coding-agent): centralize the session-path predicate (#1846)

open commit browse files
90343dca Sebastian Müller fix(coding-agent): trust supervisor-approved session renames in worker mode (#1841)

fix(coding-agent): trust supervisor-approved session renames in worker mode (#1841)

open commit browse files
older commits →