Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

agent-doc Functional Specification

  • Removing a claimed agent:queue row is authoritative cancellation (#queue-removal-cancels), not a best-effort request. Steering identifies the exact owner, bound harness worker, and claim generation. The binary first tombstones that exact identity+generation and retires any pending completion delivery so replay cannot resurrect or integrate it; a same-text re-add uses a fresh generation. The harness interrupts the old attempt only if still alive, at the nearest safe consistency boundary, preserves recoverable branch/worktree/commit artifacts, stops further implementation, tests, integration, publication, release, and external issue closure, then generation-fenced releases the claim. Best judgment controls only shutdown mechanics, never whether sunk-cost work continues. Irreversible effects already crossed are reported rather than undone. The binary emits this binary-to-harness contract without pretending it can kill a harness worker directly, and ambiguous edit or duplicate lineage does not cancel a worker. Deleting a durably terminal struck row is presentation-only cleanup; a strikethrough that conflicts with claim, receipt, or outbox evidence emits a degraded mismatch and preserves/fences the work instead of cancelling or integrating it.

  • Newly scaffolded and auto-created todo components use <!-- agent:todo priority -->; existing todo markers remain operator-owned and unchanged.

  • systemd-backed tmux-spawn-*.scope units are stewarded without assuming ownership (#tmuxscopesteward): Rust-test targets prevent new scope creation, scheduled and on-demand sweeps reset failed units, and a running orphan is stopped only with empty-cgroup or executable-plus-temp-fixture ownership proof. All ambiguous processes are reported and left running. See Session And Tmux Commands.

  • An exhausted replica-rebuild budget (state=editor_holds_unmerged_visible_text) is resolved in place, not by a controller recycle (#jetbrainsreplicaloops): the controller sends a hash-fenced editor_visible_roll_forward event, the JetBrains editor publishes its complete visible buffer onto that exact canonical as one bounded splice, and the retained transition re-applies the pending write on top of the operator’s text once. The remedy no longer forbids admin recycle; it is the fallback after the request. See Real-Time Workflow Authority.

  • Grok Build uses a native final-JSON backend and the existing managed supervisor lifecycle, with exact document-bound resume IDs and structural composer readiness. Passive hooks are not admission/continuation authority; the shared Grok skill uses connected admit/finalize. See the backend contract.

  • Cross-version supervisor recycle requests use a retained recycle-epoch high water mark, independent of compacted event counts. Settlement names the exact observed request epoch; a late settlement cannot consume a newer request. A fresh replacement acknowledges an uncleared legacy request only after successfully adopting its surviving child.

  • Supervisor freshness display is a process-scoped effect of binary freshness. Its pane-local marker is display output, never recycle authority; adoption refreshes the warning without clearing the surviving child’s turn title.

  • Automatic layout ownership is a retained receipt/actor Computed separate from structural reuse: tab switches and geometry drift cannot erase outgoing ownership, while actor rebinding invalidates obsolete pane proof.

  • A same-session document rename preserves its pane through the path-transition projection. Legacy sync may recover a missed editor transition only from one unambiguous registry row whose old path is absent and whose pane proves that old-path ownership; conflicting or still-live paths fail closed.

  • Editor-route readiness is semantic across pane-layout generations. A newer generation that still contains the routed document remains awaitable and may satisfy dispatch when it converges. Absence, operator ownership, or a newer layout that removes the routed document remains a refusal; RPC must not republish competing layout generations.

  • Retained-projection replica registration must preserve two independent facts: the bootstrap shape and causal frontier coverage. A durable canonical receipt may force a full bootstrap, but the controller must still compare the editor’s supplied retained state vector and return canonical_covers_retained_frontier as true, false, or unknown. The editor may replace a live buffer that still equals its settled projection only when coverage is explicitly true. False or unknown coverage remains an ambiguity hold, and retained editor state is never union-merged into a forced canonical bootstrap.

  • A selected-document focus that resolves a proven live-owner pane outside the active agent-doc window must surface that pane before selection. Promotion and selection share the editor focus-generation fence, and the controller re-observes pane/window co-visibility after promotion. A stale desktop focus, failed promotion, or pane that remains stashed must not select in place or report success.

  • Route startup must transport its resolved concrete harness through both provisional and child start_session publications. A missing or blank document agent: consults active actor authority for every admission mode, including a new route-created session; the literal default registry sentinel is absence, never a launchable harness identity. This prevents a Codex route from being overwritten and launched as Claude while editor metadata is temporarily unavailable.

  • Effective queue pause authority fences the dead-supervisor watchdog as well as normal dispatch. Killing a quarantined supervisor must leave it stopped until the operator resumes the queue; a live pane and stale non-closed actor are not sufficient authority to relaunch its prior harness generation.

  • The dead-supervisor watchdog restarts only a supervisor whose recorded pane is alive AND positively observed outside a stash window (#watchdogbindinglive, GH #133). A route-owned supervisor runs inside a shell pane, so a deliberate kill leaves the pane alive; a stashed pane holds no visible column and route re-provisions it on demand, so resurrecting it only undoes the kill. An unresolvable window fails closed. The skip is logged once per document and dead pid as controller_supervisor_watchdog_skip reason=binding_not_live.

  • A dead-supervisor cold start has no live process that can accept replacement work. Its controller receipt therefore remains pending until the editor-authoritative document validates and the successor start command is submitted. A malformed live document or other cold-start failure returns a synchronous failed replacement receipt; it must never appear first as an accepted restart followed only by background_failed.

  • A stale supervisor must validate the editor-authoritative frontmatter before replacing itself with a same-child execve. Transiently malformed document text defers the hot reload while the current supervisor continues serving the live harness; bounded retries may reload after the document becomes valid. It must not strand the preserved child at a bare shell by failing during reentry or poll editor authority on every idle-watch tick while the text stays invalid.

  • Ordinary startup may repair an unterminated leading frontmatter block only when its would-be closing fence has exactly one stray ASCII alphanumeric prefix, the preceding YAML already forms a valid typed frontmatter mapping, and removing that prefix makes the entire document parse. Longer or ambiguous prefixes remain fail-closed. The repair is persisted through document authority before route-owned resume admission continues, using the same live current text startup will parse rather than a stale disk projection.

  • A deliberately terminated supervisor is not a crash (#gh133sigterm, GH #133 follow-up). The supervisor’s SIGTERM handler (and a requested self-kill) records a durable supervisor_intentional_exit marker in state.db naming its exact pid and generation, then exits exactly as before (status 143). The watchdog never respawns that pid, even in a visible column, and logs controller_supervisor_watchdog_skip reason=intentional_exit. The marker is pid-scoped, so a later generation’s crash still restarts; the controller replacement path clears the marker its own kill produced before cold-starting the successor, and a newly registered supervisor clears any earlier one.

  • A controller replacement records its continue intent (a time-bounded controller_replacement_cold_start marker) before it requests the kill, and a supervisor’s own exit record never downgrades a fresh replacement marker for its pid and generation (#replacementintent). A replacement whose controller died before the cold start is therefore recovered by the watchdog once the grace ends, instead of being read as an operator stop. A promoted predecessor’s drain waits for in-flight replacement workers (#replacementdrain), and the dead-pane actor GC leaves alone a binding that the crash watchdog would recover (#gcdefercrash). A stale-binary continue replacement withdraws its pending kill once the supervisor has re-exec’d onto the installed binary in place (#replacementwithdraw). See specs/supervisor.md.

  • With agent_doc_per_component_convergence explicitly enabled, the commit candidate uses the same exact retained expected→target ownership set as the terminal convergence gate. Every owned component must already equal current Lazily/editor authority; the candidate is then rebased onto that current cut so all unowned operator bytes survive. An owned mismatch blocks commit, and a live editor never grants authority to merge an independent disk candidate. An empty/no-op ownership journal or drift in an unowned exchange falls back to the snapshot-selective commit guard. An already committed response cannot authorize absorbing a new unanswered prompt. Failed-launch recovery leaves that prompt uncommitted and actionable on repeated preflight attempts. Post-commit cleanup cannot use response-heading similarity as answer proof. Queue-echo repair requires an exact prompt from a missing committed queue proof; a prompt appended while that proof remains visible is preserved.

  • A capacity-paused or otherwise detached closeout must reconcile exact pending editor operations before treating an on-disk document equal to the cycle base as evidence that no concurrent edit occurred. The on-disk bytes remain the compare-and-swap expectation, while the replayed operator cut is the semantic current document used for response merge, snapshots, and queue reconciliation. Replayed operations are cleared only after the reconciled document is written successfully (#pauseddeletetombstone).

  • Compact Exchange derives its semantic input from the same exact base-keyed durable editor-op cut before parsing the exchange. It retains the originally observed authority bytes as its compare-and-swap base, atomically lands operator deletes with the compact rewrite, and consumes the op epoch only after the authoritative write and snapshot succeed (#compactcachedeletetombstone). A transient delivery ACK between operator bursts is not a stable cut: compaction waits outside the controller until the newest captured operator op has remained unchanged for the complete compact quiescence window, and every newer op resets that window.

  • Normal preflight publishes typed document observations to one controller-owned per-document Computed; short-lived preflight CLI processes consume that projection instead of independently rebuilding output state. It must establish the project-controller actor before its first authoritative current-document read, so a controller recycle cannot leave a live editor registration querying a removed socket before startup/model reconciliation can run. Probe mode remains actorless and side-effect free. Effects advance only through repair -> prior-cycle commit -> derived reads -> baseline checkpoint -> cycle-open; exhaustive effect identities and the terminal gate make skipped or newly inserted steps fail closed. Cycle-open remains a durable, exactly-once identity rather than computed state (#preflightreactive).

  • Hot-path authority is singular and named consistently across the binary and editor plugins: Lazily current owns the live document, and state.db owns intent/lifecycle coordination. Normal execution must not read, write, import, scan, or replay filesystem live-buffer, patch-inbox, queue-journal, queue-delete, continuation, capture, cycle, turn-scope, editor-op, transport-health, hook-session, or cooldown state. Snapshot/CRDT files are permitted only as cold recovery projections after the authority is unavailable; they never vote in a live merge. There is no compatibility fallback to retired sidecars.

  • The Zed integration is a supplemental language server for Zed’s existing Markdown language, not a second language that claims .md. It activates realtime replica behavior only while the live buffer has parseable frontmatter with a non-empty agent_doc_session; every other Markdown buffer is a strict no-op. Controller-to-Zed edits use workspace/applyEdit, and a delivery is acknowledged only after the matching visible-buffer hash returns through didChange. The LSP PID is registered with the controller’s process-exit watcher so a crash cannot strand editor authority.

  • The document write state machine is IntentCaptured -> CanonicalApplied -> ReplicaAccepted -> ReplicaVisible -> DiskProjected -> Committed. A transition may advance only one edge after its matching proof, duplicate/reordered events are idempotent, endpoint churn is a self-loop, and no recovery command may skip an edge or reconstruct intent from a projection. Queue deletion uses the same rule: the exact Lazily authority shape is the compare-and-swap base, so a missing historical queue item is deletion—not an input to union/replay.

  • A stale editor-delivery worker blocks new canonical mutations but not an already-satisfied projection (#staledeliverydurablenoop). When canonical authority already equals the target, delivery is converged, and disk exactly equals that same target, closeout accepts a no-write projected receipt and continues toward commit. Any missing or differing proof retains the target and fails closed without writing disk.

  • When a retained operation observes live editor authority that differs from disk, its recovery owner must request the editor’s typed save_document transition and prove that exact authority revision on disk before settlement or semantic replay continues. A changed revision retries from the new authority; an unavailable, rejected, or timed-out save remains retained. Recovery never projects those bytes directly to disk, and operator session-check remains a read-only observer rather than the save-effect owner.

  • A controller-derived retained-write settlement is a reactive effect receipt, not an imperative acknowledgment request. A short-lived observer may join a Satisfied receipt that differs from its turn-local semantic reconstruction only when the receipt names the same retained intent and its settled hash equals both the observer’s live editor authority and disk observations. A different intent, missing plane, or mismatched hash must not clear or unblock the local retained state.

  • A controller recycle invalidates relay membership even when an editor still holds a cached client. Forced editor refresh must retire that client and issue a fresh registration. When the replacement controller has neither a live hub nor a retained canonical projection and that registration carries a native-reload frontier, it must bootstrap from an empty canonical frontier and let the retained replica publish its missing CRDT operations; seeding from disk and forcing a full bootstrap would discard the only live copy and wedge the editor behind an ambiguous-generation hold. Existing controller state still wins, and an IDE restart without retained native state still uses the normal canonical bootstrap. Every deferred document write, including an explicitly authorized --force-disk projection, retains its full base and target in Lazily state so reconnect restores or component-merges the editor buffer without consulting Git HEAD. Compact Exchange must compose active captured/deferred response lineage before archiving.

  • Captured-response recovery must persist both the response and its complete editor-visible baseline in Lazily ResponseCaptured state; hashes alone are not replay authority. A partially materialized response may be reconciled only from added nonblank lines whose multiplicities are proven by the captured baseline and response, with at least two matching lines. The reconciled target must pass through document/editor authority, retain any unrelated operator text, and then replay and commit the complete response once. A legacy hash-only capture may consult a byte-hash-matching Git HEAD only as a historical baseline anchor and must fortify Lazily state with the recovered content; it must never restore the working tree to HEAD. Template-mode raw captures must become explicit exchange patches before strict replay. An open captured cycle may cross a recovered commit boundary only when the captured response is materially present in HEAD.

  • A recovery-capable operator session-check that applies a proven replay canonicalization must also close its exact binary-owned commit boundary before reporting OK. It may commit only the session document through a private index after proving normalize(HEAD) == authority == disk, must checkpoint and re-prove the committed bytes, and must recover that settlement across a process restart without consuming unrelated staged or working-tree content.

  • A canonical CRDT whose encoded state exceeds both a 1 MiB floor and the visible UTF-8 text by more than eight times plus 64 KiB must retain an automatic fresh-lineage request until every live editor has visibly projected the current delivery. Automatic history compaction never crosses an unacknowledged live-editor delivery, does not require a later editor update once that delivery settles, and records the unsatisfied gate when deferred. The compact frontier is projected back to each live editor so its persisted resume state, subsequent full bootstraps, and later controller-recycle suffixes remain bounded instead of retaining all prior insert/delete history.

Language-independent specification for the agent-doc interactive document session tool. This document captures the exact behavior a port must reproduce.

Individual specs are in specs/. This file is the index.

Notable invariants:

  • Terminal presentation and tmux session ownership are separate. The binary purely resolves document/project/global host policy against typed environment observations, and editor plugins consume its receipt. An attached client wins; auto prefers an available IDE over an external terminal; explicit unavailable hosts fail closed. Project tmux_session remains the only session-name setting; the optional tmux_sessions list (GH #17) is an allow-list for multi-session projects, not a second name. Every resolved target must be a member, and an empty list keeps the single-session behavior.

  • Prompt provenance normalization preserves Markdown quote structure: it never rewrites > ... as ❯ > .... Marker-only projection envelopes and restored quoted prompts already adjacent to their response are semantic diagnostics, not new operator intent; an unanswered quoted tail remains actionable.

  • Real-time document authority is operator-first. The editor-visible document state owns every operator-authored change, including ordinary non-prompt text, queue/backlog edits, frontmatter, comments, whitespace, and partial words. content_ours, snapshots, and legacy editor-content receipts are merge candidates only; they must never authorize a recovery, IPC patch, harness hook, or disk write that drops operator-visible text. Snapshots are durable backup/audit state, not hot-path authority; legacy snapshot-derived candidates must be narrowed and merged into the latest source-of-truth document. The document realtime state machine, source-authority projection, editor/disk epochs, owner leases, and in-flight apply facts belong to agent-doc-document-realtime and are lazily-rs-backed state, not turn-local sidecars. The realtime parse state projection is also lazily-backed: parse issues surface as realtime editor diagnostics and preflight repair is a crash/retry backstop, not the hot-path way to make live documents parse. agent-doc-document remains the pure document model/projection crate. CRDT merge and document realtime apply/verify do not commit; the document turn lifecycle owns commit decisions. An attached-document write waits for typing quiescence, rebases the agent target over the latest canonical CRDT cut, and applies backpressure while any prior delivery frontier lacks visible-replica acknowledgement. Repeated intent is coalesced to the latest target; an accepted CRDT replacement is never replayed through legacy editor IPC, and disk is only a post-acknowledgement projection of exact canonical text. Bounded convergence failure retains the change and fails closed instead of issuing a competing disk write. An editor-visible write acknowledgement is durable authority only when its Lazily event carries the full acknowledged content; hashes validate and index that content but cannot reconstruct it. A legacy hash-only already_applied receipt gets one bounded live-buffer publication attempt that upgrades the same patch fact. If no editor replica can publish, the full target is retained as a Lazily deferred-write intent and the cycle fails promptly without file IPC or a disk projection. An empty delivery target set is never convergence for an editor-owned write. Editor-selected tmux focus is likewise latest-wins per project. A stale or pruned actor projection cannot hide a still-running document owner when the latest open session log, live pane, and exact process-tree document binding all agree; incomplete or cross-document evidence fails closed without repairing the document or ownership projections. The normal preflight boundary also recognizes the narrowly provable legacy corruption shape where a structurally complete session document is repeated byte-for-byte two (or a power-of-two number of) times. It automatically coalesces that replay to one projection through the same CRDT/ACK path before parsing, diffing, or dispatch; the agent must never run a document-repair workflow for this transport artifact. Non-identical content is never eligible. Editor delivery must target the editor_id from the newest live reliable-sync registration when an owner lease exists; untargeted file-IPC fallback is not delivery proof for an editor-owned document. See Real-Time Workflow Authority and Turn Lifecycle Authority. Invariant: parse state projection drives editor diagnostics; preflight repair is not the live parse hot path.

  • Admission compares the recorded merge baseline, the registered live editor authority, and the durable disk file in the durable domain: transient agent-doc markers (<!-- agent:boundary:… -->, the (HEAD) heading suffix, ❯ 🚧, per-cycle guard comments, managed pipeline frontmatter) are normalized away before the planes are compared, so agent-doc’s own transport state can never manufacture a third revision and refuse admission permanently. Three durably distinct revisions are still resolvable when the live buffer preserves every durable disk line in order — the blocked-commit shape (NativeSaveRequired with disk_projection_ready=false, disk keeping the older commit, operator still typing) proceeds on the authority and adopts nothing. Before a genuine split merge, an exact-base captured editor-op epoch is replayed to the initial authority cut. A disk-only queue row that appears in an intermediate replay revision and disappears from that final operator cut is a superseded save of the same row, not an independent addition; admission removes only the lineage-proven excess occurrence from the disk branch while preserving every disk row without that proof. The initial operator cut and durable op epoch remain the proof across the bounded compare-and-swap retry even after the first projection advances authority. The merge baseline is content-addressed, so a commit that never landed leaves it at the last durably-projected revision: checkpoint_document_baseline compares the new content hash against the projected baseline and, when they match, logs document_baseline_checkpoint_unchanged instead of appending a fact or emitting a filesystem content copy. Re-asserting the same baseline is not a new revision, so a blocked commit and its retries cannot walk the generation forward and make the ledger read as though the baseline had advanced past the commit. Only an unchanged durable authority branch authorizes fast-forwarding a proven newer durable save. agent_doc_document::admission_divergence owns the classification for both preflight and session-check; every non-trivial observation logs admission_divergence … reason=<token> action=<token>, and refusals print both the raw and durable hashes. See Real-Time Workflow Authority.

  • agent-doc commit remains snapshot-selective. It may repair narrowly-classified missed agent-owned drift before staging, but it must not absorb free-form user prompts from the working tree. Already-committed historical response drift may repair the snapshot only when the working tree matches HEAD modulo transient boundary / (HEAD) markers. On an already-current no-op closeout, a stale agent-owned exchange collapse (committed ### Re: heading missing from the working exchange, with only committed exchange lines remaining and a duplicated queue-prompt blockquote proving the missing response id) is restored from HEAD; independent local queue/backlog/prompt drift outside agent:exchange remains visible and uncommitted.

  • When the snapshot already matches HEAD, post-commit local drift classification must reuse the canonical prompt-bearing diff classifier. Queue/backlog directive edits that preflight would surface as prompt targets are user_follow_up drift, not anomalous working_tree_edits; inline content corrections remain working-tree edits.

  • A same-marker, same-attribute nonempty-to-empty transition of an agent:done archive="..." body is a binary-owned staging projection only when the exact removed bytes are proven as the complete append to the configured archive target. That proven publication is not prompt-bearing drift and must not start a new response cycle. Body additions and revisions, attribute or marker edits, absent or mismatched archive publication, and inline agent:done changes remain visible so operator-authored changes fail open (#donearchive-stop-race). The same proof governs session-check’s active-session post-commit drift guard: while a Codex session is bound to the document, a proven drain is classified against a baseline that already shows the drained body, so a Codex Stop hook keeps the committed cycle closed whether or not a harness session is active (#stopreopenflake).

  • agent-doc prompt --all must normalize OpenCode horizontal permission prompts for any external prompt consumer. When the OpenCode pane exposes option controls but no explicit ← ... question line, the reported question is the neutral Permission required; earlier shell command text, including ANSI-literal printf prompt fixtures, must never become a user-facing prompt label. First-party JetBrains and VS Code plugins do not consume this polling surface.

  • agent-doc memory index/search must use the shared tsift-memory library crate to index/search agent-doc session surfaces (agent:backlog, agent:review, agent:done, agent:icebox, and live agent:exchange responses) in .tsift/memory.db. It must not invoke or embed the heavy tsift CLI codebase index on the per-cycle hot path. preflight and plan may reuse that shared library path to emit advisory semantic_completion_match candidates when open backlog/review items or free-text queue prompts are highly similar to done-state memory events; those advisories are proposals only and do not mark work done without a deterministic closeout path.

  • A status update accepts one value (embedded newlines carry multi-line content). Without sync, it replaces the complete agent:status body. The default additive sync policy updates only the managed status:sync block and preserves surrounding operator text; explicit sync-mode=replace may remove ordinary prose while retaining protected operational paragraphs. Lossless-tree parity must compare the exact authoritative projection for either policy, including an already-current second application, and lint must accept the documented status-owned sync, sync-mode, and interval attributes.

  • Managed supervisor sessions own both the child PTY and a terminal-state model for that PTY. Filtered child output must be fed into an alacritty_terminal viewport, and readiness/help/protected-prompt checks must prefer that current screen text before falling back to the raw byte ring, so cursor rewrites and line clears are not interpreted as append-only tmux scrollback. In managed OpenCode sessions, the supervisor stdin forwarder must translate legacy arrow-key escape sequences to Tab/BackTab only while the current child output is an OpenCode horizontal permission prompt (Allow once / Allow always / Reject). Normal OpenCode composer arrow editing must pass through unchanged, and permission-prompt arrows must not leak literal ^[[C / ^[[D text into the TUI.

  • When agent-doc commit sees a HEAD-current snapshot plus a later user follow-up prompt, it must leave that prompt uncommitted for the next response cycle and log post_commit_user_follow_up; that safe follow-up shape must not be reported as prior_patchback_without_response_body or out_of_band_write. If the persisted cycle is already terminal, this is a prompt handoff only: it must not re-emit commit_noop / commit_already_current, rewrite committed cycle state, or describe the prompt handoff as another closeout.

  • A headless run never resumes a live harness session (#runchildresumesowner). run (bare agent-doc <FILE> included) and stream refuse, before any diff, pre-commit, snapshot, or cycle effect, when the document’s resume id for the resolved harness equals the session the caller runs inside (CLAUDE_CODE_SESSION_ID / CODEX_THREAD_ID / GROK_SESSION_ID). The UnansweredEditPending refusal names the in-harness answer first (end the turn; the next /agent-doc <FILE> cycle answers it) and forbids the run path from inside a harness turn. A HEAD-current commit retry also proves compositions of the committed cycle’s own late projections (captured plan --status, reported-handoff count, answered-free-text strike) byte-for-byte and commits them forward instead of refusing them as an operator edit; see specs/07-core-commands.md and specs/07-closeout-commands.md.

  • Extreme snapshot/file drift does not relax that rule for tracked documents. Wholesale snapshot re-sync from the live file is reserved for bootstrap scaffold snapshots on files with no HEAD entry yet; tracked documents stay selective so unanswered prompts cannot be committed during preflight.

  • Post-commit cleanup keeps the committed blob, snapshot, and user-facing document state in the same clean boundary shape. Transient (HEAD) / boundary-only churn must be collapsed after commit instead of being left as post-success working-tree dirtiness, and that cleanup must preserve comment-only user notes that live outside the committed response.

  • If post-commit cleanup proves the working tree lost committed HEAD content and added no carry-forward user directive, agent-doc must restore the file to the committed HEAD blob and push that committed content to a live JetBrains editor buffer through a guarded refresh_content socket message. The editor may apply the refresh only when the live buffer still matches the stale content hash/length; any changed buffer must reject the refresh so legitimate carry-forward edits are not clobbered. With a live editor listener, the working-tree disk write may be skipped only after that editor refresh is acked; a no-ack/error refresh must fall back to the authoritative HEAD disk write and log transport=disk_after_failed_editor_refresh.

  • Post-commit cleanup must also fail closed against stale editor buffers that resurrect completed queue prompts. If HEAD contains a completed agent:queue row and the working/editor buffer contains an active row with the same prompt text, cleanup must restore the committed completed row before any generic editor-buffer flush can persist the stale active copy. This applies to pinned/id-backed queue heads and answered free-text rows, preserves unrelated new queue work, and is directional: a newly struck editor-owned row when HEAD still has it active remains editor-owned queue state.

  • An operator re-arm beats snapshot-struck dominance (#unstrikelost). Preflight queue convergence rewrites a live copy of a head the committed snapshot holds struck back to its struck form (#qeditdupguard) only when no operator edit produced that live copy. When the durable editor-op epoch (the active epoch, or the newest retained checkpoint when a non-operator projection already closed it) was captured against the committed snapshot and replays to a queue in which that identity is live, the operator un-struck or re-typed the head: it stays live and in the drain. No later maintenance pass, and no closeout that did not answer it, may re-strike it — #ftstrike strikes only heads the cycle’s response quotes, and the #qheadresidue/#qftbklgstrike catch-up strikes only heads the committed snapshot holds live. Without matching operator op evidence the live copy is indistinguishable from a stale editor re-emit and is re-struck. A head the operator typed again as a fresh line is a re-arm too (#retypestruck). The text the active epoch’s operator ops inserted is base-independent evidence: it needs no replay base, so it holds when the epoch was captured against a text other than the committed snapshot (an earlier operator edit or an agent projection advanced the base), which is exactly when the exact-base replay above has nothing to offer. A whole typed line whose queue identity the snapshot holds struck stays live, whether the operator deleted the old struck row first or appended the new line below it, because a stale editor flush is never recorded as operator keystrokes. Only the active epoch counts: it opens after the last non-operator projection, so its keystrokes postdate every strike the agent projected, while a retained checkpoint may hold the keystrokes that typed a head the agent has since answered. Typed strikethrough and partial lines are not evidence. Live repro (agent-doc-bugs.md, 2026-10-11): an operator re-typed release + publish behind claimed heads to run after them; with the epoch base one edit past the snapshot, maintenance rewrote it to a bare ~~release + publish~~ twice before any response quoted it.

  • The same operator re-arm evidence governs the per-item queue lifecycle merge (#unstrikelost). When a closeout write (a response-writing cycle’s tracked-work/queue mutation, a deferred-write composition, a retained controller delivery, or a queue-maintenance rebase) is merged over the operator’s editor cut, the Live < Struck join normally lets the struck side win so a stale buffer cannot resurrect a retired head. That join yields to the live side only when (a) the merge base holds the item struck, (b) the struck side still carries that same instruction (it did not re-answer a revised head), and (c) the operator’s own captured editor ops, replayed from that merge base, leave the item live. Every other strike the closeout makes still lands, and a merge with no matching op evidence keeps the anti-resurrection join unchanged.

  • Unreadable re-arm evidence is not absent evidence (#unstrikelost, unreadable evidence). Reading the operator’s editor-op epoch can fail: the controller this preflight launched died before the read (its socket file remains and refuses connections), it is wedged past the read deadline, or state.db cannot be read. Queue maintenance must not map that failure to “no evidence”, because no evidence re-strikes every contested head. A contested head is a live queue head whose identity the committed snapshot holds struck; only those heads’ outcome depends on the evidence. When there are none, maintenance does not read the evidence at all. When there are some, it retries the read a bounded number of times (AGENT_DOC_QUEUE_AUTHORITY_ATTEMPTS, default 3, re-ensuring the controller between attempts). If every attempt fails, it logs queue_rearm_evidence_unavailable … admission=refused and refuses with QueueAuthorityUnavailable. Preflight then refuses admission and persists nothing, so the contested head is neither re-struck nor resurrected. The queue-maintenance CAS rebase follows the same rule: when its merge base holds a struck queue item, unreadable evidence aborts the rebase instead of applying the Live < Struck join. The document write path follows the same rule at both of its re-arm evidence reads: rebasing an agent candidate over the live editor cut, and composing a new deferred write target over a retained one. When the merge base holds a struck queue item, the evidence is read up to 3 times (OPERATOR_REARM_EVIDENCE_ATTEMPTS, each read reconnecting to or relaunching the controller). If every read fails, the write path logs <source>_rearm_evidence_unavailable … outcome=refused and returns an error before it projects anything, and a refused composition leaves the prior retained intent unchanged. A base with no struck queue item cannot be re-armed, so its evidence is not read. Live repro (load flake, 2026-10-15): unstrike_then_a_closeout_with_no_quote_keeps_the_head_live failed with “queue maintenance re-struck the operator’s unstrike”. Killing the test project’s controller just before the evidence read reproduces it deterministically: Connection refused was swallowed and ~~release + publish~~ was persisted.

  • A blocking operator request is durable operator work (#packettodo, §2). A closeout response that presents a structurally parsed blocking [#subagent-operator-request-<unique-id>] packet records one deterministic agent:todo item per packet in the same replayable tracked-work transaction. The todo’s own id is the packet id; an explicit --todo-add suppresses derivation only when it supplies that same id. New briefs carry queue_item: <origin-queue-item> unchanged. While the same-id todo is open, the matching live queue row carries the orthogonal 🙋 [#request-id] annotation alongside any worker lifecycle marker and is not drainable. That annotation vetoes every queue completion path, including explicit tracked completion signals and the reactive answered-free-text auto-strike; a response that presents the request does not simultaneously complete its row. Completing the todo clears the annotation and restores ordinary completion eligibility. Thus exchange, todo, and queue share one stable request identity. Packet ids are unique within the closeout; duplicates fail before capture.

  • Operator todos carry ids and an operator check is final (#todoids, §2). Every --todo-add item gets an own [#id], and todo ids LAYER on tracked-work ids (#todoidlayer): a todo is the visibility layer for an operator decision on a tracked item, so it reuses the one open agent:review/agent:backlog/agent:icebox id its action cites (a second open todo for that id folds into the first; a caller-chosen id= naming no tracked work yields to that id and the receipt says so). Every explicit or implicit single tracked-work link is visibly component-qualified as (source: agent:<component> [#<id>]); neither the todo’s own id nor an unqualified #id citation is enough context. Preflight audits and authority-safely migrates legacy singly linked rows behind the typing gate, emits legacy_source_unqualified in todo_signals, and logs whether migration landed (#todocontextmigration). A surrogate id (minted, avoiding every document, tracked-work, and done-archive id, or a caller-chosen id= naming no tracked work) is written only when the action cites several open tracked items or none, or as a follow-up when a CHECKED todo already owns the one id. An explicit id naming resolved work is rejected. Checking the box (- [x]) in the editor is the operator’s done signal and needs no agent turn. No agent write unchecks it: a patch:todo carrying a checked item open keeps it checked, and only --todo-reopen reopens one. Preflight reports todo_signals (an unqualified legacy source; an operator-checked todo whose own id is an open review gate, backlog item, or icebox item; an open todo whose own or cited work is resolved). A closeout with tracked-work flags checks off only open todos whose OWN id is resolved and logs todo_auto_done; a todo that only cites resolved work is surfaced, never completed. A todo’s own id is its leading [#id] or bare #id (one letter at least; a leading #157 stays a citation), and rewrites keep the row’s spelling; a closeout --done <id> naming no tracked work but a todo’s own id checks that todo off in place and strikes its [#id]: ... queue head instead of failing with “id not found” (#sdktododone). A queue head drained without --done never completes a todo. Preflight gives every id-less todo row an own id by the --todo-add rules (reuse the one open review/backlog/icebox id an open row cites, else mint), behind the typing gate, never re-id’ing a row and inserting only the id token (#todoidbackfill). The same fail-closed rule applies: unreadable tracked-work or done-archive evidence yields no signal, migration, or completion (todo_auto_done_skipped reason=link_evidence_unreadable), never a verdict that nothing is open or resolved.

  • Queue-head closeout consumption must require proof for the exact active head. Id-backed queue heads require an explicit same-id closeout signal such as --done, --backlog-gate, --review-resolve, or --backlog-edit; free-text heads require an explicit current-response target such as the > **Queue prompt:** echo for that head. Registered prompt-preset references are a third class: preflight resolves every referenced preset (including multiple references and trailing context such as #gh-fix URL), and one shared admission/strike predicate accepts either the exact labeled head echo or response evidence against every expansion. Preflight must persist selected response-driven prompts in cycle state before response capture; the visible in-progress marker is transient UI, and its loss during convergence/recycle must not bypass strict closeout. A head selected into the live queue after the pre-turn baseline may still be consumed in that same atomic closeout only when durable cycle state proves preflight selected it and the current response contains its exact > **Queue prompt:** echo plus answer prose; a visible marker or a preset-expansion phrase alone is insufficient. Generic repair/no-op responses and unrelated exchange answers must keep the head runnable. An explicit id closeout must not be blocked by or consume an unrelated selected free-text head; exact prompt evidence remains mandatory when free text itself is the closeout target.

  • Before that cleanup runs, newly patchbacked ### Re: headings in append-mode exchange content must surface as transient (HEAD) markers in the working tree/editor buffer so the user can distinguish the fresh uncommitted response from already-committed transcript history. The write path, FFI/editor patch paths, and fallback patchers must all preserve that temporary marker until the post-commit cleanup removes it.

  • Final responses and their complete editor-visible baselines are durably captured as ResponseCaptured facts in state.db before canonical application. Interrupted-cycle replay uses only that ledger intent and rebases its semantic cell on Lazily current; recovery projections and Git history cannot synthesize or supersede the response. One narrow same-cycle replacement is permitted before materialization: when strict closeout proves that the retained response lacks mandatory evidence for a durably selected queue prompt, a later authoritative owner response may replace that response under the same capture id only when it satisfies the shared closeout evidence validator (an exact free-text quote or every resolved prompt-preset expansion). Another response that still lacks the evidence must not churn the retained hash. Replacement records a new response hash, fences workers holding the old hash, and leaves editor/disk authority unchanged until the normal exact-once replay path applies the repaired capture.

  • A Stop-hook repair that returns the shared retained-write refusal while durable ownership is Deferred remains an open closeout owned by the existing keyed retry; the hook subscribes to that exact cycle’s controller projection before deciding whether to surface a blocker. A terminal or superseded edge is re-inspected, and an owner-release edge permits one exact keyed resume before re-inspection; the live owner lease itself must not be rendered as Blocked by hook. Only a bounded wait with no progress, an observation failure, or an explicit needs_operator result remains fail-closed. The hook must not direct the agent to repair, reopen, recapture, or resubmit the retained intent. Validation/evidence failures are not retained-write deferrals. Recursive Stop invocations are status gates for that exact capture, while the controller remains responsible for delivery, the editor-native save receipt, and the terminal commit. A committed response cycle whose retained editor write has not settled must also gate auto-queue continuation before the hook observes or records the next head: no new prompt is selected, no later capture is created, and the same owner pane continues only after the retained write reaches terminal delivery (or explicitly reports needs_operator). If an older binary already created an empty preflight_started auto-queue child behind that retained predecessor, the replacement binary may quarantine the child metadata-only and roll back its session queue selection only when the retained intent names a different predecessor cycle and the empty child durably names that exact selected queue head. A child with a capture/response, same-cycle lineage, or mismatched prompt remains protected.

  • With queue auto-clear on (the default for an active agent:queue, explicitly declared by bare clear in generated templates; legacy disable-auto-clear turns it off) and a drain-ready supervisor with no overdue hand-off, the Codex Stop hook does not continue the queue in-pane: it allows the stop so the supervisor can restart Codex fresh and dispatch the next head (#bgclearpolicy, see specs/supervisor.md). The same receiver-first rule governs fresh queue or exchange steering that appears after a committed predecessor but before its first Stop: a ready supervisor owns that settled set through the reactive idle steering wake, so Stop allows exit without opening a successor or emitting Codex’s Blocked by hook continuation; the untouched committed predecessor remains the wake base (#postcommitpromptownership, #steeringwake). Only when no supervisor is provably ready does Stop open the empty successor and use the bounded in-pane continuation fallback. Direct queues hand off per completed turn; subagent queues wait for the next safe idle boundary after claims settle. Otherwise, a healthy Codex auto-queue handoff still uses Codex’s required Stop decision: "block" continuation shape, so the host renders Blocked by hook even though no agent-doc operation failed. Its reason must begin with Queue continuation, not an error: and immediately explain that host label before naming the next queue prompt and same-turn persistence instructions. That continuation belongs only to the exact Codex turn recorded by the session binding: a background subagent or other foreign turn sharing the session id must pass through without inheriting the coordinator’s Blocked by hook result (#codexsubagentstop). Codex prints the reason verbatim in the operator’s pane, so it is terse and agent-actionable only (#codexstopterse): the path- and prompt-independent instruction stays within PROMPT_CONTINUATION_INSTRUCTION_BUDGET, and a suppressed background context reset (accretion, compaction, or ctx% reason) neither changes the instruction path (an MCP-configured session keeps its MCP guidance) nor appears in the payload; it is recorded only by codex_background_context_clear_suppressed in ops.log. During the active turn, that Stop continuation is the exclusive owner of the next auto-queue transition: a concurrent dispatch-only plain trigger must coalesce without pane input, while ordinary active-turn plain triggers remain supported when no active auto queue exists (#codex-stop-continuation-label).

  • If a Codex Stop attempt fails before response capture and owner release abandons that exact empty preflight as cancel_preflight_cycle_abandoned, unresolved prompt-bearing operator steering still belongs to the active in-pane continuation (#stopsteeringafterabandon). The recursive Stop must atomically open one out-of-band successor cycle from committed HEAD and the current document authority, stamp it with the durable codex_stop_steering_continuation_started origin event, and block the turn so the steering can be answered. A later recursive Stop may auto-close only that marked successor. No manual agent-doc <FILE> re-entry is required, while abandoned cycles with a capture, a response, a different terminal event, or no pending steering retain the ordinary bounded-recursion behavior.

  • Under a queue-level subagents / fan-out attribute, every unclaimed dispatchable head and every head held by the concurrency cap is owned outside the attended in-session drain. The same derived exclusion set (active claims + dispatchable heads + capacity-held heads) must feed preflight drainability, continuation/session-check, supervisor fallback, and queue consume. Session-check identifies an unclaimed dispatch head as work to claim and dispatch, never as ordinary inline continuation; queue consume refuses it until a worker completion/report makes coordinator closeout authoritative. Subagent prompt preambles default to the worker’s own branch and fast-forward pushes, but verbatim operator authorization may explicitly name another branch or a force push; that exception overrides only the named scope and never constitutes a harness-native permission grant (#queuesubagents, GH #308).

  • A queue release records that the released claim’s worker reported (#reportedrelease); queue release --requeue records nothing. While that receipt governs a live, unclaimed line, the line is never offered to a new worker, steering routes it dispatch=persist_reported, and the Codex Stop hook blocks with the worker’s unpersisted result and the exact closeout that strikes the line (> **Queue prompt:** echo or --done <id>) instead of treating it as fresh work. Every Stop block for a fresh queue line names that same strike contract, because a heading-only answer leaves the line queued to be served (and dispatched) again. The striking closeout prunes the receipt.

  • Queue lifecycle is a durable-state projection, not decoration (#queueworkevidence). Every row visibly distinguishes pending 📥, dispatching 🟡, running 🚧, reported/outbox 📤, reconciliation 🔄, lost ⚠️, or degraded/unknown ❔; current attempts and receipts include the normal-bracket [#owner#N] identity, and 🙋 [#request-id] composes orthogonally for operator-choice blocking. Legacy ⟦owner#N⟧ and ⟦owner=…;generation=…⟧ input remains readable but is normalized to the normal-bracket form. Reported queue work also projects one aggregate 📤 Queue handoff: coordinator obligation into agent:status. Preflight and controller restart repair manual marker drift from exact identity/generation or show ❔; they never pair fuzzy rows or let stale-generation completion annotate a later same-text item. A Markdown strike is terminal only with durable integrated/retired backing; live durable evidence under a manual strike reopens as unknown. Deletion of live work is authoritative cancellation, while deletion of a durably terminal struck row is presentation-only cleanup.

  • Cycle-state lifecycle transitions append stable, idempotent state-backbone facts and advance the formal write phase only after matching proof. No JSON cycle/capture file participates in normal execution.

  • Git closeout appends a CommitObserved fact carrying the exact HEAD SHA after a successful real commit or already-current no-op closeout.

  • session-check and preflight read the state-backbone projection as the only open/terminal lifecycle authority. Projection-only open cycles fail closed; missing/corrupt ledger state is an explicit recovery condition, never permission to import a sidecar.

  • agent-doc preflight must surface warnings[].code = "stuck_captured_cycle" when persisted cycle state says committed but the matching durable capture’s materialized response body is absent from HEAD. Detection must match the active cycle/capture id and response hash, ignore discarded captures, tolerate template patch materialization and prompt-prefix stripping, and stay quiet when HEAD already contains the response.

  • Every recovery-capable document turn stage that can observe the LIVE controller/supervisor — preflight, generation, stream, finalize/write, commit, compact, and closeout evidence — must detect when its recorded launch controller_binary no longer matches current_binary_identity and write an idempotent per-document recycle request. The request is mandatory for proven staleness even when proactive auto-recycle is disabled, checkpoints CRDT state first, and is honored only at the supervisor’s safe idle boundary so it cannot sever an open closeout. Preflight emits warnings[].code = "supervisor_binary_stale"; operator session-check emits [session-check] WARNING: but remains status-only and does not request the recycle. No stage may insert an operator-facing stale marker into document content. Detection remains fail-open when status or identity evidence is unavailable.

  • Quiescent idle-queue and pass-scoped document observation must be lazily invalidated. With live editor authority, supervisors and short-lived CLI readers compare a compact canonical CRDT state vector plus replica liveness/convergence state from the running Project Controller before materializing canonical markdown; with disk authority or an intentionally suppressed controller probe, they compare file metadata. Full-text hashing, serialization, queue parsing, and agent-frontmatter inspection run only when that revision changes or the compact probe cannot establish an initial content identity. A bounded safety reconciliation re-observes the compact revision but must not bypass an unchanged identity and fan out full-document reads across idle supervisors. If the controller revision is unavailable, readers preserve the fail-closed uncached path. A process may fully hydrate a project’s durable reliable-sync liveness journal at most once: concurrent cold probes share one per-project restore, and subsequent unknown-document probes advance only through the rowid-bounded incremental journal query. Installed-binary staleness remains a prompt local probe outside this throttle.

  • A reliably-open editor authority with zero registered relay replicas is also stale at every observable turn stage, even when the supervisor binary inode is current. The complete write target remains in CRDT/Lazily state, agent-doc requests the same owner-scoped safe recycle automatically, and recovery retries the binary-owned finalize transaction after reconnect; it must not require response repair or an implicit force-disk write.

  • Stale-controller replacement must be directional. The caller stamps its full binary identity on controller RPC requests; a replacement shutdown is accepted only when that identity proves a newer release or a newer same-version build timestamp than the controller bootstrap identity. An older caller must adopt the newer live controller rather than tear it down. This proof applies before every stage-level recycle request so a stale controller cannot refuse a genuinely newer install merely because its own process-local executable still matches its bootstrap record.

  • Supervisor recycle in-flight state is a lazily-backed project-controller projection, not a .agent-doc/ marker authority. Recycle starts publish StateFact::SupervisorRecycleStarted and settle paths publish StateFact::SupervisorRecycleSettled; callers inspect SupervisorRecyclePhase::{InFlight,Settled} through controller RPC helpers. Route/direct/dispatch-only callers must wait through wait_for_supervisor_recycle_settle_for_file before injecting prompt text so triggers are not dropped across supervisor execve. A settle minted from a lagging read (epoch below the outstanding Started) is re-minted at the outstanding epoch by the controller so the recycle cannot stay InFlight after the supervisor has already re-entered its watch loop (#fixruninfra; see specs/13-state-backbone.md). The controller’s durable reload never swaps in a snapshot that predates a fact it has already applied, so that re-mint cannot be defeated by a regressed live projection (#runfrontenddispatch). A document already wedged InFlight self-heals at the dispatch-only gate: a supervisor ready registration (stamped in supervisor_leases.ready_registered_at, never by heartbeats) strictly after the recycle’s marked_secs is the settle observed directly, so the gate proceeds and the controller re-verifies and re-mints settled-<in-flight epoch> at exactly the observed epoch (#dispatchreadyselfheal). The old recycle-in-flight marker sidecar is retired.

  • Installing the cdylib must apply an explicit per-adapter reload policy after the versioned symlink swap and controller/supervisor auto-recycle. The controller enumerates Lazily registrations, deduplicates by project/PID/editor identity, and sends the shared reload_library intent through the PID-scoped endpoint only to adapters explicitly known to support safe hot reload. VS Code and Linux JetBrains are hot-reload capable; unknown or unproved host registrations are restart-required. JetBrains must marshal native calls onto a bounded generation-owned worker pool, keep document replica operations FIFO through per-document workers and per-replica native locks, distinguish queue-wait timeouts from running-call timeouts, stop and join every old-generation CRDT/listener worker, drain calls, join every IPC connect watchdog thread the generation spawned (a watchdog is joined as soon as its connect returns, and one still blocked after a connect timeout fails the quiesce until it exits, because a live thread keeps executing and holding TLS destructors against the generation being unloaded), quiesce native replicas, terminate every owner thread, close the old JNA handle, and prove the old mapping is absent before loading a replacement and re-registering open projects. A queued timeout retains the generation; only a call that actually runs beyond its lease poisons it. Controller launch from an embedded cdylib must use a short-lived external helper rather than a controller-lifetime reaper thread. The reloadable cdylib must not own the reliable-sync SQLite outbox; durable enqueue/replay belongs to the project controller. Any failed thread, mapping, or ABI proof must load no replacement and require restart. Native-library and restart-free plugin replacement must preserve the controller’s last acknowledged editor-surface and focus Sources throughout this local quiesce; the outgoing adapter must not send editor_surface_forget, and the replacement generation must publish successors before the handoff completes, so tmux pane auto-sync never enters a null interval. Only actual project/editor/plugin termination retires those Sources. On compatible JetBrains builds, the package is dynamically replaceable: unload must preserve enablement, prove that the prior descriptor and classloader are gone, initialize every surviving open project from the replacement classloader, and recreate every project listener/service under a generation-owned disposable. That initialization must republish each open document’s reliable-sync registration with the replacement plugin version before native-save targeting can treat the endpoint as current; an XML listener that IntelliJ does not reconstruct for an already-open project is insufficient. The replacement generation may race the retiring generation for the PID-scoped root socket; a failed bind or temporarily unavailable FFI must retain no false callback and retry once per root with bounded backoff until the current, non-quiesced watcher binds successfully. Retry callbacks are lifecycle-fenced so quiesced, disposed, retired, or replaced watchers cannot resurrect an endpoint. Builds with asynchronous classloader retirement cannot satisfy the synchronous retirement proof: agent-doc must stage every package upgrade and require an IDE restart there. The operation is best-effort and reports projects, endpoints, deliveries, restart requirements, and failures. No filesystem broadcast or compatibility watcher exists. Running controllers/supervisors still recycle onto the new binary at their idle boundary.

  • Every JetBrains split-package content module must carry the private runtime classes its isolated PluginClassLoader uses. In particular, agent.doc.backend.jar embeds io.github.lazily/**; the package must not place Lazily only in the root plugin lib/, because backend content-module loaders do not search that directory. Artifact and prepared-sandbox verification must prove the backend module JAR contains representative Lazily classes and no standalone root Lazily JAR is the runtime authority.

  • PyPI bootstrap target selection treats a non-empty platform.libc_ver() result as authoritative. The /lib/ld-musl-*.so.1 heuristic is permitted only when Python cannot identify libc, so a glibc host with the optional musl loader installed still receives the GNU cdylib.

  • Every successful binary, cdylib, or editor-plugin update is one ordered runtime handoff boundary: after the final artifact/package replacement, fan out safe idle-boundary recycle to every existing supervisor first and then to every existing project controller. The controller fanout must not skip idle roots or same-binary controllers, because either can still retain an endpoint or plugin generation replaced by the update. Multi-target plugin updates run the boundary once when at least one target changed, including partial-success runs. The explicit falsey AGENT_DOC_RECYCLE_ON_INSTALL opt-out is reserved for a supervisor-managed outer install that owns the single recycle wave.

  • After that recycle, a fresh controller’s authoritative NoRetainedIntent may retire a local durable intent only when the durable verdict is PayloadAbsentFromConvergedContent, both canonical authority and disk hashes are present and equal, and an exact intent-id compare immediately precedes the clear. A different intent, missing/divergent content cut, in-flight delivery, or controller-retained intent remains blocked; controller absence alone is never completion proof.

  • A stale controller endpoint or zero-replica observation retains the exact canonical revision in the per-document Lazily graph. Registration and canonical-projection delivery wake that same graph; no ACK-replay, force-refresh, full-state request, or editor text-adopt recovery event exists. JetBrains, VS Code, and Zed all open replicas from the controller bootstrap and project it downstream.

  • An editor adapter must not register a non-session Markdown buffer as a document replica. JetBrains derives eligibility from the current editor text at every open and local-edit ingress; when no replica is attached, a missing agent_doc_* frontmatter key and missing <!-- agent: component marker is a terminal classification for that text, cancels registration retry state, and consumes the local event without a controller round trip. The classification is re-evaluated on later text, so adding a marker enables registration without an invalidation side channel. (GH #282)

  • A document replica may register a carried agent_doc_session identity only when the durable session-identity owner is unclaimed or resolves to that document’s canonical path/hash. A second path containing a plain copy is refused as duplicate_session_identity before relay-authority lookup, even when a stale hub is already attached, so editor discovery cannot admit the copy or let retained queue effects rewrite it. Rename-compatible path/hash ownership remains accepted. This ownership check is a one-shot registration boundary over durable state.db observations with the legacy registry as compatibility bootstrap; edit, pull, projection, and awareness traffic do not poll it. (GH #349)

  • A retained Base → Target transition must pin the response continuation that produced it when durable events are projected. Recovery, its final effect fence, its supervisor wake projection, and the supervisor’s resumed operation key/body may not consult a later current-cycle capture after checkpoint, abandonment, or supervisor recycling; replay reconstructs the owning continuation from event order without a sidecar or imperative acknowledgement. The published-effect frontier advances only after successful transition publication, never after a failed attempt.

  • When exact retained convergence makes that pinned continuation runnable while its originating foreground finalize still owns the same open cycle, closeout ownership transitions atomically from the foreground owner to the exact captured continuation. The continuation must not wait for owner-process exit, lease expiry, an idle timer, polling, or an editor acknowledgement. An ordinary response-captured wake, a stale cycle/capture/response identity, or a different recovery role cannot authorize this transition.

  • The relay must retain recognized editor replica identity metadata with membership and, when a replacement registers, retire prior memberships only when their encoded editor process is provably dead. This pruning occurs on registration and update-driven reattachment rather than idle polling, precedes replacement bootstrap/convergence, and must never infer liveness or ownership for opaque identities. A crashed or restarted editor therefore cannot leave an unreachable pending-delivery member blocking write --commit, while independent live replicas remain protected.

  • Controller restart recovery must push one targeted rebuild signal to every registration missing from the process-local replica hub, even when the editor advertises peer-pull support. A handoff replacement hydrates durable registrations while private but defers rebuild effects until its exact pid and generation are observed as stable through the public controller socket; otherwise the editor can rebuild into the predecessor generation and promotion can discard the replica. Peer pull is a complementary startup/transport-recovery mechanism because a transparent controller restart may not trip an editor transport-loss hook. An idle watcher that observes an explicit attached-missing-replica or sync-pending state requests one bounded current observation before entering the existing 30-second backoff. High-frequency liveness predicates must not append success or uncertainty events on every controller reconciliation.

  • The binary must detect a stale editor plugin and warn (#stale-plugin-detect). Each plugin reports its release version in its live Lazily registration; preflight compares that registration against the build-time expected JetBrains/VS Code version and emits one non-blocking stale_plugin warning per distinct kind+version. For JetBrains, mapped root-JAR evidence selects the package generation for the live IDE’s proven platform line: builds 242–261 use the classic generation, 262 uses the modular generation, and 263 uses the modern generation. The exact-262 and 263 packages share the agent.doc-<version>.jar root-jar name, so the archive root classifies a staged ZIP and the target’s proven platform build classifies the canonical installed tree; the shared jar basename alone never selects between those lines. The classic and shared modular/modern layouts all participate in mapped-byte, activation, ownership, installed-version, and staged-restart diagnostics. Installed and staged evidence is scoped to that live IDE’s plugin tree, so another idle IDE cannot supply the remedy. No live-buffer file is written or consulted. Version comparison is dotted-numeric with leading v and prerelease/build suffixes ignored; unparseable versions and source-absent packaged builds fail open. When the live JetBrains IDE’s mapped plugin tree belongs to a platform build outside every published package range (GH #233, e.g. 264), the warning names that build, the supported ranges and the plugin left installed, and offers no install remedy, because no package can be installed there.

  • The exact-262 and exact-263 JetBrains artifacts are modular Plugin Model v2 package lines whose descriptor-only root JAR exposes no restart-free upgrade launcher (#jbmodulardynupgrade, GH #259, GH #290). Before that limitation can apply, release projection must compare each package’s recorded pluginSourceDigest: a new agent-doc release with byte-identical plugin sources retains that package’s existing pluginVersion, updates only its pluginReleaseVersion ownership metadata, leaves the binary’s expected plugin generation paired with the already-running generation, and reconciles it as Unchanged without replacing files or requiring a restart (GH #295). Only a changed source digest allocates a fresh, collision-free plugin version and reaches package replacement. The backend module already carries the upgrader classes, so the decline must not imply that adding a manifest entry restores the capability. Content modules are not treated as an independent platform prohibition: DynamicPlugins evaluates the main descriptor’s resolved module graph. The 2026-10-19 filtered attach probe on IU 263.7031.23 established the module-graph refusal only for that measured build; package classification does not repeat it during an install, diagnostics must not present it as a live measurement, and a different exact-263 build must be qualified separately (GH #333). The package-line safety blocker is that a backend attach cannot atomically replace the split-mode frontend running in another JetBrains Client JVM. Awaiting the platform’s later notification is a delayed failure observation after reconfiguration, not proof that retirement succeeded; a backend-only swap while the client keeps the old frontend is invalid. Moving the current Kotlin orchestration into a plugin-owned child loader is not a safe shortcut: the stable plugin would first have to own every IntelliJ registration/disposable, use a version-neutral boundary, prove complete callback/worker quiescence and state handoff, verify the replacement JAR, and coordinate both split-mode JVMs. When either package replaces files owned by a live IDE, the installer must classify the expected fallback as declined_by=modular_package, name those deepest blockers, explain that the installed files are current and the running IDE needs a restart, and preserve that explanation in the restart-required marker. It must never describe either current package as legacy, claim that the files were refused, recommend --local, or classify the package property as upgrader_failure. Because no safe whole-package swap exists for the package line, the loss is classified as permanent for that package line (GH #277): the decline reaches the same permanence accounting as agent-doc’s own asynchronous-classloader decline (GH #108, #114), while the operator text scopes the modular loss to the package line instead of claiming the dated probe measured the current build. plugin_upgrade_summary ... restart_free_unavailable=true remains true and attribution stays declined_by=modular_package; the restart-free path is not attempted. The NOTE and summary state only what the code guarantees between the binary upgrade and the restart: the restart can wait for a convenient moment, because editor routes to the running IDE stay admitted while its native endpoint answers with this binary’s build (GH #267) and native saves stay admitted while its plugin is at or above the JetBrains native-save protocol floor (GH #236); the new plugin’s own changes load only at the restart, preflight keeps its stale_plugin warning until then, and a route refused with plugin_bytes_superseded takes agent-doc admin reload-lib and then a restart if that native reload is refused. The summary omits that guidance when the NOTE already printed it in the same process.

  • JetBrains plugin upgrade verdicts are auditable effects: every dynamic-upgrade decision and non-empty reconciliation summary appends to the current project’s ops.log. Project-root discovery and append failures retain the complete verdict in an operator-visible WARNING:; they must never be discarded as a best-effort Option (GH #299).

  • Editor-plugin release resolution must prefer the latest stable GitHub Release and, when walking older releases for a matching asset, exclude entries marked prerelease or draft. GitHub API requests may authenticate from a non-empty GITHUB_TOKEN (preferred) or GH_TOKEN; unauthenticated requests remain valid. A 403 response with x-ratelimit-remaining: 0 must report rate-limit exhaustion, include x-ratelimit-reset when present, and advise token authentication instead of surfacing a generic network-fetch error (#plugin-release-stability, GH #56).

  • Supervisor generation replacement must not sever or duplicate an open agent-doc turn. An open cycle may cross the supervisor execve boundary only with one of two exact continuity proofs: a durable captured response that the typed recovery path can replay, or the same live harness child and PTY admitted for adopt-only transport reentry. The live-child path freezes supervisor IPC effects and complete PTY input/output transactions, requires the terminal filter to be between sequences, preserves the actor/session/cycle identity, and replaces only the supervisor process image; it must not kill the child, inject the document prompt, replay the turn, or transfer closeout ownership. If execve fails, the old image continues serving the child. If the child disappears before adopt-only reentry completes, the replacement may restore an empty harness transport but must not re-dispatch the interrupted turn. Without either continuity proof, or while IPC/PTY evidence is unsafe, stale auto-recycle, explicit admin recycle, and failed-reexec escalation defer with no timeout escape. Stalled-cycle abandonment may clear only old, no-IPC cycles at a true harness turn boundary, never a long active turn mid-closeout.

  • A managed supervisor owns one document and must never use a process-global harness-history selector to replace its child. Claude --continue, Codex resume --last, and OpenCode --continue can select another document’s most-recent conversation even while CP actor/registry ownership remains correct. Replacement launches therefore start fresh and re-submit the owning document’s trigger unless a future implementation has durable, exact document-to-harness-session proof.

  • Binary installation is an atomic promotion and ordered handoff boundary. Local install paths must build a complete executable, copy it to a same-directory staging path, preserve executable permissions, and rename it over the installed binary; they must never unlink the live path before the replacement is complete. Background supervisor auto-install must defer while the source checkout is dirty and suppress nested generic recycle-on-install fanout. A successful direct install must discover every live agent-doc start supervisor, resolve relative document arguments against each supervisor process CWD, durably mark all open supervisors before controllers, and issue exactly one fleet recycle wave. A controller predecessor whose self-handoff worker owns promotion/drain is ineligible for its stranded-controller self-watchdog, and after promotion it must relinquish the listener guard for the public pathname so predecessor exit cannot unlink the successor’s live controller.sock (#handoffsocketownership). Live child PTYs remain owned across the in-place supervisor exec, including a safe mid-turn swap: the outgoing image holds the child-reap, supervisor-IPC, and PTY-I/O handoff gates through execve, and the replacement adopts the inherited master FD under the same session identity. A failed handoff must keep the prior process/binary serving rather than reap the pane. A replacement supervisor adopting a preserved child is a transport reentry, not ordinary document admission: if controller/editor current-document authority is temporarily unavailable during the handoff, it must read disk only as observational launch metadata (without publishing disk authority), retain the existing actor/session lifecycle, and recheck the live model after registration instead of exiting and orphaning the child. If that reentry finds its actor closed or pane-less while the replacement still owns the preserved child in the current pane, it must re-register through the controller under the actor’s authoritative session at the next generation; only a different non-empty active pane is a fatal ownership conflict.

  • upgrade --auto captures the canonical install path and installer provenance before its first poll. Every later release targets that retained path rather than re-reading a replaced Linux /proc/self/exe; a standalone/tarball/Cargo install must never fall back to pip, while a PyPI bootstrap may use its recorded console entrypoint for pip verification.

  • Recycle-yield for self-driving queue loops uses the same controller projection, not a sidecar file. The supervisor idle watch records stale_binary_drain or state_flush_drain as a SupervisorRecycleStarted reason; preflight, session-check, and queue continuation detection suppress in-session looping while supervisor_recycle_yield_pending_for_file reports the projection in flight, and they surface queue_recycle_yield=true / RECYCLE_YIELD_GUIDANCE so the harness yields one boundary and restarts on the fresh supervisor. Clearing a recycle-yield settles only those yield reasons and must not clear real admin/auto-install in-flight recycle state.

  • Queue drain-stall continuation-pending state is a lazily-backed project-controller projection, not a .agent-doc/ marker authority. A clean closeout that still requires queue continuation publishes StateFact::QueueDrainStallContinuationRecorded; the next preflight classifies #qstallguard facts and publishes StateFact::QueueDrainStallContinuationCleared after every reconciliation outcome. Supervisor idle-watch drain progress also clears the same projection so an actively progressing supervisor drain cannot false-fire queue_stall_detected in the next agent preflight.

  • Streaming agent paths must also save durable partial-response checkpoints while generation is still in progress. The first non-empty partial response and then changed partial output at most once every 30 seconds are appended as cycle-scoped recovery facts in state.db for diagnostics/manual recovery, without advancing the cycle to response_captured. Once the persisted cycle changes, commits, or is abandoned, the writer must stop instead of updating the retired cycle’s ledger projection.

  • Partial model output must never be written into the authoritative session document. Streaming and orchestration buffer generation outside the document, may update only the state.db recovery ledger, and submit exactly one complete final response to the write+commit boundary. Bare/non-committing agent-doc write on a session document fails before stdin, capture creation, document mutation, queue consumption, or lifecycle advancement.

  • Outside fenced code examples, a session exchange may contain at most one agent:boundary marker and it must occupy a standalone line. Final placement removes every prior boundary before appending the singleton at exchange end; duplicate or inline markers fail the mandatory integrity gate. Explicit repair may normalize historical partial-patchback artifacts, but ordinary preflight/finalize/compact/session-check must never launder them into a new baseline.

  • Every repair mutation must compare-and-swap against the exact realtime authoritative document image from which the repair was computed. After the write, repair must prove both the realtime authority and the disk projection are byte-identical to the intended repaired image before it may save a snapshot, commit, or report success. A concurrent/stale projection mismatch fails closed and must never be merged back as operator content, because doing so can resurrect fragmented response bodies and duplicate boundaries. If the CAS target was durably retained but the editor owner has zero registered replicas, explicit repair may use the audited force-disk authority to project only that exact retained target; ordinary writes remain deferred, and repair must preserve force-disk reconnect lineage after exact disk proof so a stale editor buffer cannot overwrite the repair when it returns.

  • If a repair crosses a detached write boundary and an editor registers with the exact pre-repair authority after the repaired bytes reach disk, settlement must wait a bounded interval for that editor to acknowledge the target. If the interval expires, the original expected-to-target compare-and-swap lineage must remain durably resumable; the already-applied repair must not be reported as an unretained terminal failure. Any different/newer editor cut remains a concurrent-authority mismatch and fails closed.

  • Multi-stage repair must settle every superseded deferred target after exact authority/disk proof and retain at most the newest reconnect target, using the original editor cut as its content-bearing merge base. Settling the newest delivery must not reveal an older intermediate marker, boundary, or fragmented response image.

  • When a newer response target already equals live CP authority, it supersedes any older deferred response target instead of merging that stale assistant tail back into the document. Reconnect lineage rebases on the exact superseded target: an unchanged failed-ACK editor cut receives the newer target directly, while later operator prompt nodes are preserved through semantic response-tail reconciliation with one terminal boundary.

  • When recovery resumes a newer durable capture while the deferred journal still points at a prior-cycle reconnect target, that stale target must not block or overwrite the newer capture. If rebasing the retained target over exact current authority cannot materialize the newer captured response, recovery skips that stale rebase and CAS-replays only the newer response cell over the same authority cut; it clears the deferred lineage only after editor/canonical/disk convergence proves the resulting bytes.

  • Every deferred-write composition and settled-operator rebase must canonicalize boundary control state from the newest target branch: outside fenced examples the result retains exactly that branch’s singleton agent:boundary marker at exchange end. A forced editor refresh is not a reconnect merge or delivery operation: it captures the exact visible editor bytes, validates them, and register/swaps the replacement replica from that same baseline under a generation fence. It never preinstalls or saves a deferred target. Retained mutations replay afterward through the ordered document-cell/CRDT path, so a refresh cannot overwrite a prompt or resurrect deleted queue state.

  • Before the generic integrity gate, recovery may collapse a replica-refresh suffix only when the retained prefix is already structurally sound, the appended bytes are an exact suffix of that prefix beginning at any UTF-8 character boundary (including a mid-line or mid-token cut), and the suffix contains agent-doc component scaffolding. This repair removes one duplicated partial component tail without interpreting repeated operator prose as binary-owned state; non-exact or prose-only tails fail closed.

  • Session-check publishes that proof-bearing replica-refresh repair through an exact-current authority compare-and-swap. It must not route the repaired projection through the ordinary semantic component merge against the structurally invalid editor generation, because that merge can recreate the duplicate tail it is repairing.

  • Terminal session-check success additionally requires byte-for-byte equality between current canonical document authority and disk, except for an operator-edit lead (#operatorleadpendingsave): with no open cycle, retained capture, retained document write, or unlanded tracked-work mutation, an authority that holds uncommitted content while disk equals a committed plane (baseline or HEAD) or is preserved line-for-line by the authority is reported as pending-save (plus verbatim pending steering), never INTERRUPTED. A disk ahead of or conflicting with the authority, an authority equal to a committed plane, or no committed plane at all stays fail-closed. The operator-facing command is status-only: a mismatch fails closed and records both hashes without requesting recovery, replaying a capture, settling a retained write, or mutating document content. Finalize/write/preflight and the supervisor own those transitions. Its sole self-heal is metadata-only repair of an already-committed historical snapshot whose exact HEAD content is proven; substantive post-commit operator edits are never eligible.

  • An open preflight_started cycle whose exact registered owner pane has a fresh turn-active lease is reported as [session-check] IN PROGRESS, not as abandoned-closeout evidence (#sessioncheckliveturn). The command remains nonzero/fail-closed until a terminal boundary exists, but its guidance forbids concurrent recovery or owner restart and it does not raise the dogfood actionable-defect prompt. Liveness must correlate the document registry owner with that pane’s lease; a sibling document’s project-wide marker, expired lease, or unreadable ownership state is not proof.

  • Operator steering found after a committed cycle is a typed steering pending outcome, not an interruption (#steerinterruptexit): session-check prints [session-check] steering pending: … with every settled item verbatim and its dispatch, exits 0 (2 under --codex-final-gate), and the embedded respond / finalize / write --commit closeout succeeds. Genuine integrity failures and blocking retained writes still report INTERRUPTED. In a Codex session the active-harness-session drift guard reports the same outcome only for editor-op-proven operator steering (#codexsteerinterrupt); unproven drift, including console output replayed into the document, stays INTERRUPTED. A typed UnansweredEditPending refusal reached after Stop has committed the response ends the hook successfully (#stopnextedit): the newer typed-component edit remains live and uncommitted for the next cycle instead of being mislabeled as an unfinished closeout. See specs/07-closeout-commands.md.

  • Mid-turn steering observes the same authoritative document as turn admission (#steering-live-authority, GH #173). With a live editor, every PostToolUse observation compares the watermark against the controller-owned CRDT text; disk bytes, disk mtime, and a later native save may not synthesize a removal/re-addition pair. Because the relay currently exposes content identity but not editor edit time, live edits settle by per-item stability rather than stale disk mtime. An explicit-send receipt identifies the authoritative content hash it sent, so it cannot flush a later unsaved edit; detached documents may retain the file-stat fast path and legacy timestamp coverage.

  • When session-check collides with a foreground closeout owner for the same durable capture, it must subscribe to that exact cycle’s controller projection and continue as soon as the cycle becomes terminal or the request-scoped owner guard releases. A long-lived supervisor PID is not proof that an individual closeout request is still active. Recovery retries once after owner release, controller reconnect, or a bounded 30-second crashed-owner fallback; the foreground lease is a safety stopgap, never the normal wait mechanism. A timer may schedule a wake at the lease boundary, but it may only observe the resulting clock edge into controller-owned Lazily state; the shared Computed closeout gate, derived from cycle, owner, and observed-clock sources, owns the blocking/released decision.

  • Connected and managed clients must not run a second agent-invoked session check after strict finalize succeeds (#sessioncheckturnreactive). agent_doc_finalize returns the terminal binary-owned closeout report plus queue-continuation fields; managed orchestration consumes the same strict finalize boundary directly. The next turn’s admit/preflight resolves the current document and evaluates the open-cycle, prompt-only-tail, and bypassed-response guards before opening new work. A PreflightStarted fact for cycle N+1 clears cycle N’s closeout owner in the live projection immediately, so a superseded diagnostic cannot retain a lease. The explicit session-check command remains available for direct-exec harness distrust checks and debugging.

  • Response placement, answered queue-head removal, backlog/review/done mutations, snapshot publication, and commit form one final-response transaction. A validation or convergence failure leaves none of those effects authoritative. AlreadyApplied can advance that transaction only when the visible document contains the exact complete final payload expected by the same transaction; a response prefix, partial checkpoint, prior-cycle body, or heading-only match is insufficient.

  • Every appended response must cross a commit boundary in the document turn lifecycle unless the user explicitly asks to leave it uncommitted. The normal happy path is agent-doc finalize <file>; the documented repair path for an already-present prompt is agent-doc write --commit <file>. CRDT merge/realtime convergence may provide the verified document state for closeout, but it must not run the commit as a side effect.

  • Strict write --commit with empty stdin may only commit when it first recovers an agent-doc-owned visible response or applies explicit backlog/review/icebox mutations. A live editor/CRDT projection is harness-neutral authority for this recovery: even when cycle state is already Committed and the snapshot/HEAD image is compacted or stale, a response delta proven in the editor buffer must be adopted into the snapshot and carried through the normal commit/session-check boundary exactly once. The binary must never recommend restoring the editor buffer to HEAD for that state. Empty stdin with no recoverable response and no tracked-work mutation must fail before commit so live prompt drift remains unresolved for the next cycle.

  • Once a closeout cycle reaches Committed, a delayed editor intent for that cycle is rejected by its state-ledger phase and generation fence. No alternate delivery transport exists. Active delivery timeout retains the same intent in state.db, performs no direct write for an attached document, and resumes from the recorded phase. Terminal lifecycle updates are idempotent.

  • Explicit --force-disk closeout is the operator-controlled direct-write escape hatch for stale/wedged editor listeners. When used with strict write --commit / finalize, the force flag must apply to the whole binary-owned closeout path: response placement, pending-maintenance reap, queue consumption, done-id marking, and free-text queue strike. Ordinary preflight/route maintenance still fails closed under active listeners unless the caller explicitly selected this force-disk recovery path, and force-disk maintenance writes must remain attributable in ops.log. A live editor buffer that diverges from disk because the operator has unsaved edits is a valid state, not a wedge (#unsaved-buffer-divergence-valid): the retry after typing stops / visible_write_deferred_live_buffer_changed / live_prompt_drift deferral is the guard working as designed. Harnesses must not chain make install + agent-doc admin recycle + --force-disk to force a closeout through it, and must escalate to the stale-binary recycle path only when the drift is actually traced to a stale_install / recycle-yield projection; once the response already reached committed in HEAD with session-check OK, state-only leftovers left in the working tree reconcile on save and must not be force-disked. See runbooks/commit.md #unsaved-buffer-divergence-valid.

  • Every agent:exchange write emits exchange_write_diagnostic with the transaction id, writer identity, named intent, expected/current Lazily generations, affected semantic nodes, before/after canonical hashes, rebase/conflict result, and receipt phases. All template, queue, compact, normalization, and repair mutations use node/component-scoped socket intents; fullContent, file IPC, degraded attached-editor disk fallback, and compatibility payloads do not exist. The plugin validates target-node preconditions immediately before apply, and the state machine advances only from typed Lazily accepted/visible receipts. Duplicate-prompt repair is response-block aware and operates on the verified canonical result before disk projection; it never adopts post-preflight operator scratch text into an agent-owned snapshot candidate.

  • agent-doc route defaults to a bounded 500ms quiescence gate before it inserts a missing session id, scrubs duplicate prompt comments, or submits a managed/dispatch-only reopen. The route gate must observe both filesystem mtime idle and the shared editor typing indicator idle for the debounce window; if either remains active through the bounded wait, route fails closed before document mutation or pane input. Editor integrations may pass --debounce 0 only after they have saved the focused document themselves; the JetBrains Run Agent Doc path uses that focused-save fast path so dispatch is not delayed by a second debounce.

  • Direct-pane route submit acceptance must not treat a single empty pane capture as proof that the harness received the prompt. Empty captures must remain stable before acceptance, visible drafted triggers still get a bounded submit-key retry, and Codex accepted-without-dispatch-start proof must attempt one late Enter retry when the same routed prompt is visibly sitting in the input. Once the full trigger transport succeeds, absence of dispatch-start proof never authorizes another full-payload send; post-send recovery may send only a bare submit key while the exact routed draft remains visibly present.

  • When route --dispatch-only queues a prompt-bearing editor rerun behind a busy actor in agent:queue, the rerun must be inserted ahead of queued active-loop items (priority preempt, #jb-run-preempt-autoloop-priority): a manual Run Agent Doc preempts the loop instead of landing at the tail. Route-owned queue writes must never add auto; when they touch a legacy agent:queue auto tag they strip auto while preserving other attributes. A bare slash-command line such as /clear in an exchange diff is prompt-bearing even without a ❯ prefix, and route must short-circuit it into agent:queue for the idle supervisor instead of submitting it as a normal agent-doc turn. The priority insert lands after any leading queue directive (preset / start fence) and must not supersede a lone active-loop prompt, so the queued item is preserved (manual prompt first, then the queued item) rather than replaced. If an explicit editor run finds no new prompt-bearing diff but the document already has a startable inactive queue head (queue_active: true, a start fence, or legacy auto), route must promote that head to queue_active: true, sync the snapshot, and let the supervisor idle-queue watch drain it after the busy pane returns to idle. The idle-queue watch must treat the hook-owned turn-active marker as authoritative over renderer prompt heuristics: queued work, slash-command heads, and automatic context-reset clears may run only after the full turn reaches the Stop/idle boundary. Queued /clear / /new heads and context reset clears must use the supervisor’s clear submit path, not generic prompt dispatch, so they are recovery controls and remain gate-exempt while still submitting Enter to the owner pane. A non-interrupting session clear on a busy active auto-queue must publish exactly one deferred QueueContextClearDeferred projection for the supervisor’s next proven idle boundary; repeat clears while that deferred projection is pending must report “already deferred” and must not refresh the projection or inject another /clear into the active turn. After the idle-watch submits the deferred clear, it promotes the projection to QueueContextClearStarted until the cleared pane settles. A synthetic active queue head that consists only of a slash command, ignoring surrounding whitespace, is command-only for preflight, plan, and direct run: it must not open preflight_started, must not become prompt targets/repo actions, and must stay live in agent:queue for supervisor idle submission.

  • A managed owned pane must not remain indefinitely split between authoritative ready state and stale busy renderer state. When actor state, supervisor actor state, and controller lease are all ready but the live pane probe still reports alive-busy/prompt_ready=false from a recoverable stale queued-draft cue, route-owned completion and the idle-queue watch debounce that ready/busy conflict for the same four-poll window used by stale-busy idle repair, emit owned_pane_ready_busy_conflict, and then let queued work proceed. Genuine active-turn, permission, hook-review, shell-search, help, and clean-exit blockers remain protected. agent-doc session status must make the ready/busy conflict explicit and prefer bounded reconcile/clear guidance over pane restart.

  • A plain route --dispatch-only --plain-trigger reopen (the editor Run Agent Doc contract) submits the bare agent-doc <FILE> trigger to a live ready, busy, or waiting_input authoritative actor only after any prior open cycle reaches a terminal closeout. An unresolved response or retained component write blocks dispatch; route performs the existing controller-projected closeout drain and fails closed if it cannot settle. After admission, the trigger remains transport-only: it must not derive prompt-bearing queue work from the document diff, mutate agent:queue, or wait for pane-capture acceptance or dispatch-start proof. This is the single replacement/steering boundary: an interrupted turn whose actor projection still reads busy receives the same plain trigger as a fresh run, and a Run click made with selected text or a live document diff follows the same route instead of a separate supervisor-steering RPC. Legacy selected_text / steering_id payload fields are accepted only as compatibility metadata and are normalized onto this plain-trigger route. Protected interactive substates and non-turn surfaces such as the Claude artifact picker still fail closed, and a still-booting starting pane retains the bounded readiness guard.

  • Once route admission classifies managed_reopen or dispatch_only_reopen as an explicit operator reopen, a stale same-generation in-flight dispatch receipt must not coalesce that controller dispatch. Automatic/non-operator re-dispatches retain durable in-flight backpressure, and the JetBrains action layer may still coalesce duplicate clicks while the same bounded editor_route request is alive; those are separate dedupe boundaries.

  • Template write paths must fail closed when a response contains patch/replace markers outside code blocks but no closed patch blocks parse. Such malformed patchbacks must log template_patchback_parse_shape and template_patchback_malformed_rejected with response hash, marker count, patch count, exchange patch count, unmatched length, and source before returning an error; they must never be synthesized into agent:exchange as raw unmatched content. Strict template, stream, and IPC closeout routes share the same marker and response-heading validation before durable response capture, even when replacing a pending response. Binary-owned replay may transiently normalize the retired agent:patch:* wrapper only for an already-durable, complete, marker-only exchange response; it must not mutate the stored capture or session document during migration. Socket IPC attempts must also log ipc_socket_attempt plus lazily visible-write receipt hashes/lengths so corruption reports can distinguish malformed payload parsing, editor projection drift, and stale fallback writers.

  • When an agent-doc turn also includes ordinary repo commit + push, manual git commits must exclude the active session document. Agents may commit the non-session repo files first, but the session document still closes through agent-doc finalize <file> / write --commit <file>, and the push happens after that binary-owned closeout commit lands.

  • Narrowed/path-scoped manual repo commits must fail closed on staging drift. The agent must resolve the exact intended non-session path set first, run stage commands only for that set, stop immediately if any stage step fails, prove the staged diff still matches the intended set before git commit, and use an explicit pathspec commit or equivalent isolated-index strategy so unrelated pre-staged entries cannot leak into the commit.

  • session-check must warn on likely partial manual staging closeouts: if the latest repo commit (or dirty submodule repo surfaced by the owning worktree) changes relevant source/test paths and tracked dirty or staged companion changes remain with overlapping changed string literals, the closeout is suspect because local verification may have run against the dirty worktree while CI sees only the committed tree.

  • agent-doc finalize <file> is the binary-owned happy path for session responses: it must fail before mutating non-git documents, run the normal write pipeline, invoke commit, and refuse success unless the cycle closes in committed. If the active prompt is a synthesized active agent:queue head and the captured response heading targets that queue item or its #id, finalize consumes the queue head even when the visible document had no queue-head diff; unrelated baseline prompts must not consume it.

  • A semantic response-cell closeout must not commit ahead of visible convergence. ResponseCellAdded proves durable idempotence only; finalize must apply normal typing/ACK backpressure, materialize the acknowledged canonical cut to disk even when an attached authority currently has zero live relay members, and only then snapshot and commit. Materialization proof is semantic across transient (HEAD) and boundary annotations. Before adding the latest complete response, the operation anchors at the last unchanged committed response in HEAD, removes only later uncommitted assistant-response nodes, preserves all operator prompts, and emits one terminal boundary; interrupted partial/full variants must not accumulate or require repair. The committed blob and working-tree projection must therefore begin closeout byte-identical instead of relying on later repair.

  • Inter-queue-item dispatch is convergence-gated (#fullboundary): item N+1 must not dispatch until item N proves a quiescent close — cycle committed, the retained editor-delivery settlement no longer blocks a new cycle, this document’s editor-IPC inflight count drained to 0, and the authoritative actor idle (dispatch-ready prompt, no active turn). The delivery proof is purpose-scoped Lazily state, not whole-document equality with Git HEAD: queue control and newly appended operator queue rows are legitimate next-cycle input and must not retroactively make a completed response look unconverged. A genuinely Unsettled retained write blocks; NoRetainedIntent, Satisfied, and the new-cycle fail-open Unobserved verdicts do not. The decision core is the pure convergence_gate::convergence_gate_decision(ConvergenceFacts) returning Dispatch (all four proofs), Defer { unmet } (not yet quiescent, within the bounded timeout), or Blocked { unmet } (bounded timeout exceeded while unconverged). A blocked boundary is an ERROR condition and persists a replayable operation-playback artifact (convergence_playback::ConvergencePlayback) to .agent-doc/playback/<doc-hash>/<cycle-id>.json capturing the ordered IPC attempt sequence (patch_id/transport/receipt/inflight), snapshot/baseline/HEAD hashes, candidate vs content_ours lengths/hashes, cycle/run/actor/supervisor identity, and the closeout state-machine transitions, so a recovering agent can root-cause the wedge without guessing. The live supervisor inter-item dispatch (idle-queue watch / drain) is the consumer of this gate and composes with the drain-owner lease (#kp5z, dispatch ownership) and queue_continuation drainability.

  • A preflight mutation wait must not refuse a turn over replica delivery (#preflightsteeradmit). A delivery_pending observation carries the authoritative current text, so preflight admits on it immediately (with one best-effort urgent drain) and later operator edits reach the turn through mid-turn steering; never disk, never --force-disk. Only states with no authoritative text (missing_replica, current_pending, authority_unavailable) wait and fail closed, re-observing Lazily current authority exactly once at the defer boundary so already-visible convergence succeeds.

  • The live_prompt_drift editor-convergence recovery is component-merge-aware (#qpcwcmerge). After the editor applies the convergence patches, the recovered editor buffer is accepted even when it is NOT byte-identical to content_ours, provided every divergence lives strictly INSIDE a component OTHER than the agent’s response component (exchange) — the editor’s live queue/backlog/review/status and any plugin-defined component, while the response component, the document’s non-component regions (preamble/frontmatter/interstitial), and the component structure all match (normalized). In that case the editor buffer is the correct merged state (the operator’s live queue + same-cycle auto-strikes + the response), so committing it makes HEAD equal the editor buffer and eliminates the recurring #pcwc post-commit worktree drift instead of falling back to the content_ours disk write that drops the editor’s components (editor-wins, #queue-user-edit-overwrite). The discriminator is AST-structure-driven and component-name-agnostic (it keys off component::parse, never an allowlist), so a plugin that defines a new component is reconciled identically to the built-in queue. Conservative: any out-of-response divergence, a structural component add/remove, or a parse failure fails closed to the existing block/content_ours path.

  • preflight IPC-truncation recovery may ask the active editor to flush its visible buffer through typed save_document, but only through the matching PID-scoped editor socket and with a Lazily receipt. JetBrains and VS Code implement the same intent, record editor-surface outcomes through agent_doc_record_editor_surface_event, and never use a file signal or editor-local log formatter. If save proof is absent or the published buffer no longer preserves the committed exchange, recovery fails closed with the operator-visible Lazily cut authoritative.

  • Component patch and recovery writes may target an editor only when its live Lazily registration, editor identity, PID, and PID-scoped endpoint agree. With no live registration the document is detached and may project to disk; disagreement fails closed before payload delivery, leaving captured intent retryable.

  • The editor-sync barrier observes the retained Lazily projection and live replica frontier. Timeout is a bounded absence of convergence; it never sends a republish, re-registration, save, or ACK request to the editor.

  • A durable retained transition is one typed state machine over durable Base → Target facts, current editor/CRDT delivery, and controller generation. Its exhaustive states are no projection, idle, awaiting controller, awaiting delivery, awaiting live editor, awaiting convergence, apply target, target visible, reconcile materialized capture, and typed conflict. One derived optional Effect observes the current delivery projection, compare-and-projects Target, or resumes closeout; waiting and conflict states have no effect. The controller listener must be bound before restored liveness publishes missing-replica targets so the resulting full projection cannot be lost during controller startup. This is reactive Source propagation, not an editor request/ACK protocol.

  • When preflight/current-document resolution observes live editor membership but the relay model is missing, it schedules the controller-owned canonical projection and returns the typed retained/pending observation. It never asks the editor to publish its current buffer, never seeds authority from disk while attached, and never blocks the foreground command behind an editor recovery barrier.

  • The #yzer reconnect-reread is editor-agnostic and lives in the binary FFI (agent_doc_reconnect_buffer_decision, owning the disk==HEAD vs buffer==prior-commit staleness decision); both the JetBrains plugin (reconcileStaleBuffersOnReconnect) and the VS Code plugin (PatchWatcher.reconcileStaleBuffersOnReconnect, run on activation) are thin callers that only re-read disk into a buffer the FFI proves stale, so genuine unsynced user edits are never clobbered (editor wins, #editorbufwin). The two plugins must stay behavior-matched through that shared FFI.

  • Operator-authored queue prompt order is position-locked by stable identity, not by mutating visible prompt text. During preflight, queue prompts absent from the snapshot and not appended by backlog sync form an operator-authored identity set; priority and auto-DAG queue sorting anchors those identities like operator pins while leaving the line marker-free, including id-backed do [#id] heads. Binary-synced backlog mirrors still use append-stable ordering, explicit operator pins still anchor normally, and dependency edges may still outrank an anchor when holding the slot would violate the edge (#qauthorderpin).

  • Progressive edits to a newly-added id-less queue line must converge to the live operator wording, not accumulate each intermediate spelling as a separate queue item. When a stale merge base predates the text-derived identities, the live/editor free-text run is authoritative only within the same gap between shared durable anchors, including the subset case where the retained agent cut contains old + current spellings while the editor has deleted old and retained current; explicit #id items and id-less additions in different anchor gaps remain independent. The causally gated raced-projection repair also recognizes a non-prefix rewrite sequence only when its final spelling contains every earlier draft, plus a two-row fresh residue only when at least eight normalized words form a strict prefix pair; this converges high-evidence revisions without collapsing short, plausibly independent prompts. The recursive CRDT merge, default document-cell merge, and raced-projection repair share this operator-authoritative queue policy.

  • Free-text queue heads are struck when answered, regardless of position (#ftstrike). The normal leading-head consume only strikes a contiguous leading run and stops at an id-backed head, so a free-text report sitting BEHIND an unfinished do [#id] head was never struck even after the response addressed it. On closeout, after the leading-head consume, a position-independent pass (strike_answered_free_text_queue_heads) strikes every non-struck free-text head whose text the committed response answers — matched conservatively by requiring the head text (priority-markers stripped, normalized to lowercase alphanumeric words) to appear inside the response’s > quoted-prompt blockquote region, with a minimum four-significant-word guard. A head merely mentioned in prose (not quoted as a prompt) is NOT struck, so an unaddressed operator report is never silently dropped. A quoted head followed by a deferral (a **Deferred…** lead or deferral phrasing in the quote’s paragraph, #deferstrike) is NOT struck; the deferral veto is anchored to that head’s labeled echo (or a four-word quoted-head match), never an unrelated response block that happens to contain a short head word. A worker claim (#queueclaim) does not hold an answered head back (#claimstrike): an echoed, undeferred claimed head is struck and its claim released in the same closeout, so the strike set equals the session-check #qheadresidue set. If the supervisor abandons a cycle before its response is captured but closeout later materializes that exact same-cycle response, the capture retains its answered-head strike authority until terminal closeout proof or a later admission clears it (#ftstrike-abandoned-closeout, GH #313); closeout must not commit the answer while leaving the echoed head runnable. The pass is also conservative about in-flight operator edits (#qstrikeexplain): a free-text head is struck only when it was already present in the stable pre-turn baseline (the preflight baseline), or when durable cycle state proves preflight selected that exact head and the current response contains its exact labeled echo plus answer prose. A head that first appeared in the live buffer during this turn — a line the operator is still typing — is never same-cycle struck merely because it has a visible marker or fuzzy-matches a quote; it defers to the cycle that actually answers it (editor-wins, consistent with #queue-user-edit-overwrite). A missing baseline (rare; preflight writes it each cycle) skips the gate, preserving legacy strike behavior. The pass runs independent of the leading-head queue_consumption_allowed decision, strikes the document and snapshot in sync, and is best-effort (a missed strike never fails an otherwise-clean closeout). This mirrors how strike_done_queue_head_prompts strikes id-backed heads regardless of position. If the answered strike resolves the final live prompt and the remaining queue body is losslessly discardable residue, the same projection clears the body, removes marker-side activation tokens, and persists the stopped frontmatter state rather than waiting for a future preflight cleanup.

  • A deferral after an operator-note answer still defers its head (#annotateddeferstrike). An annotated head must answer its annotation as a > **Operator note:** <annotation> quote (#qheadannotation), and that quote sits between the > **Queue prompt:** echo and a **Deferred:** paragraph. The deferral scan (queue_response::deferral_scope_has_marker, shared by response_defers_free_text_head and latest_free_text_head_echo_is_deferral) skips the operator-note quote blocks that follow the echo, so the block after them states the deferral for do [#id]: note, [#id]: note, and plain free-text heads alike. Only operator-note blocks are skipped: the next head’s own > **Queue prompt:** echo and deferral are never borrowed. The deferral veto also covers id-backed heads: a deferred do [#id] head is not consumed by an implicit signal (its ### Re: #id heading, a synthetic heading-id match, or the prompt diff), and queue_targeted_completion_id_for_current_head returns no completion id for it, so the Codex Stop auto-close cannot turn its heading into one either. An explicit --done/--pending-gate/--review-resolve naming the head still consumes it, because that flag resolves the backlog item itself. A deferral never waives the annotation answer: the **Deferred:** paragraph is the answer prose that #qheadannotation requires after the operator-note quote.

  • Free-text queue-head removal proof is cycle-scoped (#ftstrike-cycle-proof): session-check may accept only the captured response payload belonging to the cycle that recorded the active head. It must never search older Exchange responses for proof, even when an older response shares a distinctive #id with the current prompt; missing same-cycle response evidence fails closed.

  • A claimed free-text queue head strikes only through an explicit exact > **Queue prompt:** echo authored by the agent (#ftstrikeclaimedmention); #claimstrike still holds, so that echo with no deferral strikes the claimed head and releases its claim in the same closeout. An active claim (agent-doc queue claim, a subagent or coordinator:* owner) means another worker owns the head, so every weaker completion proof is refused for it: a prose mention, a quote of the head’s shared prompt-preset body, a ### Re: identifier heading, and an unlabeled blockquote that merely starts with the head’s prose. The echo must not be a bare listing (#bareechodrop) or be followed by a deferral (#ftstrikedefer). Every site applies the same claimed-head proof, so the strike set equals the residue set: the finalize strike, the controller’s answered-free-text projection, the late-strike commit recovery, preflight’s residue strike, and the session-check #qheadresidue guard. The closeout’s leading free-text consume applies it too. It never consumes a claimed head unless the agent’s own captured response carries that exact, undeferred echo, so the binary never synthesizes a > **Queue prompt:** echo (#queue-prompt-echo-in-response) for a claimed head it was not asked to close. Separately, for any head (claimed or not), prompt-preset completion evidence requires the head’s own argument (its text without #tag tokens, such as the issue URL) to appear as whole words in the response beside the expanded preset body. A preset body is shared by every head that uses it, so the body alone cannot say which head was answered.

  • Queue-item preset resolution treats #preset tokens inside balanced inline-code spans as quoted evidence, not executable preset references (GH #331). The one shared resolver masks those spans before resolving item presets for subagent authorization, response evidence, write gates, steering, and skip diagnostics. Resolved item presets retain first textual occurrence order and repeated references are deduplicated, rather than inheriting frontmatter map order.

  • Short free-text heads such as deploy count as answered only when the response contains an explicit labeled > **Queue prompt:** echo for that exact head (#qheadresidue), never from a bare prose mention. session-check must fail closed when an active free-text queue row is still present even though exchange history contains that labeled echo, because the row is completed queue residue and would re-run stale work.

  • Free-text answer projection is queue-graph aware (#ftstrike-multiqueue): discovery, durable-node-key strike, lifecycle-marker cleanup, annotation, claim release, and observability inspect every agent:queue component occurrence. An empty earlier queue must not hide an answered head in the later queue selected by the graph; the component occurrence encoded in the node key determines the exact row mutated.

  • Completed queue residue never needs a model-run repair (#qresiduewedge, #qresiduecommittedhint). The session-check #qheadresidue INTERRUPT on a committed cycle names no command for the agent: agent-doc preflight is binary-owned (#preflightinbinary) and pane-authority bound, so a hint that prescribed “run preflight, then commit” was unreachable for every actor. The hint says the next agent-doc <FILE> admission strikes the answered head itself (preflight’s #qheadresidue catch-up strike), forbids running preflight, resubmitting the response, or striking the row by hand, and tells an agent whose admission was refused to report that refusal’s reason and stop. Admission must therefore reach that queue maintenance: a retained response whose ### Re: heading the document already holds (a committed-heading replay, replay_guard::committed_heading_replay_topic) is refused by the replay guard on every attempt, so repair parks it instead of failing closed. Parking preserves the payload under .agent-doc/repair-blocked/, discards the capture, and retires the captured response with reason committed_heading_replay_parked (which clears its pending response even when its cycle already committed), so no later admission replays it. In the same pass repair strikes each free-text head the parked replay answers (the #ftstrike predicate with claims, #deferstrike and the baseline gate) whose answer the exchange already holds under the head’s own title (### Re: <head first line>, attribution ignored; queue_consume::project_committed_heading_replay_free_text_strike_with_claims). The never-written replay alone never strikes a head, and its echo never makes a head completed residue in session-check. Live repro (haiven-dev docs.md, 2026-10-16): a cycle committed ### Re: <head> without an echo, the Codex Stop hook’s repeated-head recovery captured the closing chat summary as a second answer to that head, and every Run Agent Doc after it was refused with preflight response recovery failed closed.

  • A tracked-work transition’s #donequeuestrike queue strike never writes a > **Queue prompt:** echo into the response cell; only the cycle’s own prompt consumption echoes (#closeoutduplicatedcommit). Every response-identity comparison (the committed-text integrity guard, the live-prompt-drift recovery target, agent-doc dedupe) reads one shape, response_block_signature, which ignores binary-owned decoration: a labeled > **Queue prompt:** echo block, ❯ prompt prefixes, boundary / (HEAD) markers and blank lines (#dupemoduloecho). A visible extra copy of a committed response classifies as duplicate_committed_response, whose recovery is agent-doc dedupe <FILE> then agent-doc commit <FILE>, and write --commit refusing a response already in HEAD names the same remedies instead of “run preflight and retry” (#closeoutduplicatedcommit).

  • The preflight #qheadresidue catch-up strike counts only echoes written after the head last entered the queue (#qheadresiduescope). The exchange keeps every earlier answer, so an operator who types an already-answered report again (a repeated bug report), or un-strikes an answered head, would otherwise have the new copy struck by the old echo without any cycle answering it. The entry point comes from git history: the walk reads the document’s commits newest first while the head’s identity (priority markers stripped, whitespace-collapsed lowercase prose, any live Prompt row) is live in the queue, and stops at the first commit in which it is not (struck, deleted, or not yet typed). That commit’s exchange is the anchor, and only the exchange text after it (queue_response::exchange_text_newer_than: the lines between the longest common leading and trailing runs, so append and prepend exchanges both work, and a compaction of older history only widens the window) may answer and strike the head, including the claimed-head and #deferstrike checks. Git history is the source because it survives closed editor epochs, restarts and snapshot rewrites; the operator’s captured insert runs (#retypestruck) cover only the active epoch, which a non-operator projection closes before a later cycle’s catch-up runs. With no commit history, or a head live in every commit back to the document’s first, every echo counts (the earlier behavior). The walk reads at most 128 commits; a head still live at the limit is anchored at the oldest version read, which can only hide an echo an earlier pass would already have struck. A skipped strike logs preflight_freetext_residue_strike_skipped_echo_predates_head_entry. Recurring-imperative heads (#qimpstrike) stay exempt. Closeout is already scoped: finalize’s #ftstrike and the session-check residue guard judge a head only against the current cycle’s captured response, so a closeout that does not quote a re-typed report neither strikes it nor INTERRUPTs on it. The #syntheticstrike continuation-head skip uses the same scope: a free-text head the whole exchange would call answered is skipped from the continuation offer (queue_continuation_required / the next head) only when an echo written after its entry point answers it, so a re-typed report answered only before its re-entry is offered as the next head. Both sites share one implementation: the walk’s decisions (queue_head_entry::FreeTextHeadEntryWalk, the entry identity, the 128-commit limit) live in the pure agent-doc-queue crate and the git reads in agent_doc_git_io::revision::free_text_head_entry_anchor_exchange, which the preflight strike and the agent-doc-queue-io continuation adapter both call. The pure required_continuation_excluding_claimed keeps the whole-exchange behavior (no history); required_continuation_excluding_claimed_scoped takes the entry anchor. The anchor is read only for a head the whole exchange calls answered, so an unanswered head costs no history read. Claimed heads stay out of the continuation offer and recurring-imperative heads are never skipped. A live head of a loop queue is scoped further (GH #327 pass 4): the catch-up strike and the #syntheticstrike continuation-head skip count only an echo newer than both the commit at or before the current pass’s opening and any write that added an echo while retiring the same head in another queue, and neither strikes nor skips a loop head while no pass is open (see specs/02-document-format.md §2.5 Queue schedule). Both sites resolve the scope through one path: agent_doc_queue_io::queue_schedule::head_echo_window reads the queue’s queue_head_entry::HeadEchoWindow once (HeadEntry for a non-loop queue, LoopPass with the open pass’s opened_secs, LoopHeld otherwise), and agent_doc_git_io::revision::head_echo_scope resolves each head’s queue_head_entry::HeadEchoScope (whole exchange, newer than an anchor, or no open pass). The continuation adapter passes that resolver to required_continuation_excluding_claimed_scoped, so a loop head the residue strike keeps is never skipped from the continuation offer as answered; non-loop queues keep the entry scope only.

  • Preflight must not refuse Run Agent Doc over a self-healing missing replica (#runtypingadmit, GH #272). An attached-editor refusal whose recovery class is ReloadEditor or ReregisterEditor holds admission (observation-only, at most 20s, clamped to the admission deadline) and re-resolves through the editor tier when the replica answers; every other class refuses at once, and an expired hold names its cause (replica_hold_expired) ahead of the remedy. The hold never reads disk. A turn admitted after a hold, or while the #qheadcomposing wait hit its ceiling with the operator still typing, carries the admitted_after_replica_hold / operator_still_editing preflight warning.

  • Preflight must not admit a prompt the operator is still typing (#qheadcomposing). A converged Lazily current cut proves delivery, not a finished line: when the coherent current text differs from preflight’s initial read, preflight waits until it stays unchanged for the document debounce window (bounded by the progress ceiling and the admission deadline) before computing the diff; an unchanged document pays no wait. A recorded free-text head that the operator later extended (a strict prefix of a still-queued prompt) is still queued: closeout must neither count it as removed nor let a response that quoted only the fragment consume the finished item.

  • Queue convergence also auto-strikes a LIVE free-text queue head when it is already complete OR a backlog item already addresses it, even if no exchange answer echoes it (#qftbklgstrike). During preflight queue maintenance, after the #qheadresidue exchange-answer strike, a deterministic (no-LLM) lexical scorer (memory_cmd::semantic_queue_strike_matches, the strike sibling of the existing semantic_completion_match warning) scores every non-struck free-text head (no #id) against BOTH the completed agent:done archive and the active agent:backlog items. A head that clears the conservative QUEUE_STRIKE_THRESHOLD (1.6 — strictly above the warning’s 0.8 floor, set above the scorer’s +1.0 substring-contains bonus so only a near-restatement of a tracked item can reach it) is struck in place and annotated: a done match renders - ~~<original> — auto-struck: completed by #<id> (#qftbklgstrike)~~, a backlog match renders - ~~<original> — auto-struck: tracked by backlog #<id> (#qftbklgstrike)~~ (the reason is baked INSIDE the strikethrough so the line round-trips as a stable Completed entry). The head is struck, never deleted. The same committed-snapshot in-flight-edit gate as #qheadresidue applies, so an operator line convergence just added is never struck; id-backed heads are skipped (they have their own done-strike); the operator-authored position-lock (#qauthorder / #queue-operator-pin-position-lock) and existing #ftstrike exchange-answer strike are preserved. The conservative threshold is the false-strike safety margin: an unrelated operator prompt that is not a near restatement of a tracked item can never reach 1.6, so an unanswered operator prompt is never silently buried. A backlog match additionally requires exact lineage (#freetextqueue): the backlog item’s own text, with its leading #id stripped and normalized to lowercase alphanumeric words, must equal the head’s normalized text — the same identity free-text admission mints a backlog id from. Lexical score alone never proves tracking: the scorer’s +1.0 substring bonus let an unrelated backlog item whose prose merely QUOTED the head (inside a route error message) clear 1.6 and strike a head whose fix was still in flight under its own claim (2026-10-10, #runctrlclaude vs the supervisor-thrash head). Containment of a head’s text inside another item’s prose is never tracking; an exact-lineage backlog item clears the threshold regardless of cosmetic markdown/punctuation differences.

  • Free-text promotion carries claims by exact lineage (#freetextqueue). When preflight free-text admission promotes a queue head into a backlog id and replaces it with do [#id], admission records a promotion receipt (source head text, id) per removed line, and every live (unexpired) #queueclaim whose identity is exactly that source head’s claim identity is carried to the do [#id] head with the same owner and the same expiry. The source claim is kept and is pruned as closed once its head is gone, so a retried promotion write is idempotent. A different head (even one containing the claimed text), an expired claim, or an #id head another owner already claims is never transferred. Without this, a claimed head handed to a subagent re-surfaced after promotion as unclaimed dispatch work (2026-10-10, do [#runfrontendcrashed] under subagent:frontendcrash).

  • Queue parser/drainability must treat operator prose followed by a --- separator as one multiline free-text prompt (#qfreetext-sep). In a preset-bearing queue, a prose bug report followed by fenced diagnostics is drainable work: the preset supplies the directive and the prose lead is the object. Pure log/evidence blocks with no prose lead remain predicate-proven noise and may be removed by queue prune-noise; prose+diagnostic reports must instead be answered and then struck/consumed by closeout.

  • A column-zero prose paragraph at an agent:queue item boundary starts a distinct free-text head, including when it immediately follows a live free-text list item without a thematic break (#queuefreetextsplit). Indented lines remain continuations of the preceding list item; consecutive prose and directly following blockquote lines remain one bare head. A bare paragraph with an attached blockquote remains recognizable at the queue start after the preceding item is consumed. Thematic breaks (---, ***, ___) separate heads and are never silently absorbed as text; paired --- prompt fences remain supported for compatibility. Unexpected prose elsewhere stays inert Freeform and remains visible to queue-noise warnings instead of being silently dropped.

  • Queue parser and the Markdown-AST overlay must segment each operator-pasted multi-line block (a bullet-less title line plus a balanced code fence, introduced by a --- separator or pasted directly beneath another multi-line item) as its own head, never folded into the previous one, and the answered-head strike of such a head must leave a well-formed ~~~done fence with no annotation on its closing line (#multilinequeuehead; rule 9 of the queue parsing rules in specs/02-document-format.md).

  • Paused-queue supervisor fallback must not use a supervisor-owned drain-owner lease as proof that a self-driving in-session loop owns the drain (#qstallguard-failsafe-lease). The transactional drain-owner row gates only real /loop owners; owner=supervisor-failsafe rows are ignored by the pause gate, stale-recycle-yield gate, and stall classifier.

  • Done-id collection uses each item’s OWN id, never prose citations (#donemirrorreap). The preflight already-done-mirror reap removes an active agent:backlog/agent:review item whose id appears in agent:done (or the external archive= file). That done-id set must be collected per item via extract_done_item_own_ids — the FIRST [#id] on each list-item line — NOT via a whole-text scan that harvests every bracketed id. Otherwise a [#other] cited inside one done entry’s prose (e.g. “behind do [#fullboundary]” inside the #ftstrike entry) is wrongly treated as done and falsely reaps a still-open #other review/backlog mirror. An item’s identity is its leading id, never a citation in its description.

  • Derived tracked-work ids are minted against the full identity history (#archivedidreservation, GH #289): active tracked-work rows and prompt presets, completed rows still awaiting reap, inline agent:done own ids, and own ids in the configured external agent:done archive= file. Completed identities remain excluded from active dispatch lookup, but they are never considered free for minting; a collision receives assign_unique_id’s stable hash suffix. Only each done entry’s leading own id is reserved—ids cited in its prose remain references. If a configured archive exists but cannot be read, a minting path fails closed instead of silently reusing an unknown historical id.

  • Todo own ids participate in that same reservation set (#todoidreservation, GH #306). Free-text queue admission that mentions a todo, tracked-work, or done id mid-line must preserve the citation verbatim and coin a fresh backlog id; it must never reuse the cited id or strip it from the promoted text.

  • agent-doc mcp serve [--project-root DIR] is a stdio MCP transport into the same binary-owned document APIs. With no --project-root it walks up from its working directory to the nearest project root, so the installed Codex config carries no absolute install-machine path (#skillinstallconfigpath); outside any project it stays in the working directory. It exposes read/preflight/plan/session-check/finalize tools for Codex or other MCP clients, but finalize must still call the normal strict write/commit/session-check machinery instead of creating a harness-specific patchback path. Its result includes any queue continuation and is terminal for the managed turn; the session-check tool is an explicit diagnostic, not a required companion call.

  • agent-doc <file> and agent-doc run <file> are the same mode-aware entrypoint. Document mode comes from frontmatter via resolve_mode(), with template as the default when no explicit format is present.

  • After run pre-commits user edits and opens its response preflight_started cycle, the agent child wait is bounded by AGENT_DOC_RUN_AGENT_TIMEOUT_SECS (default 1800s). While waiting, run emits parent-visible heartbeat stderr every AGENT_DOC_RUN_HEARTBEAT_SECS (default 30s) and records the heartbeat as open-cycle progress by updating the cycle state’s updated_at and last_event; that gives Codex/direct harnesses phase/cycle evidence that a long child wait is still progressing. When run is invoked with terminal stderr inside a tmux pane owned by a Codex/OpenCode parent harness, routine run/diff/commit stderr is redirected to .agent-doc/logs/run-stderr.log unless verbose input diagnostics are enabled, so progress output cannot paint over the foreground TUI after a restart. If the child times out, or if a Codex harness tries to run agent-doc <file> from the same tmux pane that already owns that document, the command must fail closed, leave the cycle in preflight_started with a timeout/blocking last_event, and surface cycle id, phase, pane, actor generation/state, and retry/restart guidance.

  • If the pre-commit repair for run closes an already-committed missed patchback and the post-repair diff is empty, run must fail before child-agent dispatch. The diagnostic must say no new assistant response body was supplied and name agent-doc write --commit <FILE> as the missed-response repair path.

  • agent-doc start [<file>] defaults an omitted file to agent-doc.md in the current working directory, then uses the same admission and runtime path as an explicit file. It must preserve the one-live-pane-per-session invariant by failing closed when another alive pane is already bound to that document. Normal start may not reuse, restart, supersede, or silently replace that pane. The error must include concrete tmux inspect/capture/kill commands so the user can decide which pane to keep. --force remains the explicit escape hatch for deliberate repair work.

  • Route-created start panes carry an explicit lifecycle policy. Editor-origin Run Agent Doc requests and editor-layout/focus reconciliation create interactive keep-alive document sessions so a successful commit cannot be misclassified as a crash and later recreated solely because the selected document became unfocusable. Controller/watchdog recovery retains auto one-shot behavior: after a new cycle reaches committed, it may stop and reap only when the supervisor actor is in stable ready prompt state or direct live-pane evidence shows the child is back at an idle harness prompt, and the document has no liveness signals. Explicit blocking prompt states such as queued drafts, permission prompts, hook-review prompts, history search, and clean-exit restart prompts keep the pane alive. If a one-shot fresh trigger is accepted but no cycle starts, route must record startup-miss provenance and reap the just-created pane instead of preserving an idle registered owner indefinitely.

  • Effective queue pause/drain control fences every autonomous session resurrection boundary. Route auto-start must check it before reusing an existing dispatch target or allocating a pane; route-owned start must re-check it before admitting a new lifecycle so a pause racing an already-submitted tmux command still prevents harness spawn. The controller dead-supervisor watchdog must apply the same fence. Supervisor exec-reentry that preserves an already-running child is not a new lifecycle and remains allowed.

  • Route must re-check legacy associated-pane evidence immediately before normal-path auto-start. If stale registered-pane cleanup clears the old binding and only then a live associated pane becomes provable from session-log / registry_rebind / same-file evidence, the binary must fail closed with explicit claim/repair guidance instead of cold-starting around that ambiguity or silently promoting the legacy pane back to authority.

  • Startup-miss supersession follows the current registered file owner, not the stale marker’s original session_id. Once a later pane/session is registered for the same document, start, route, sync, and session-check may clear the old pane’s startup_miss marker only when the current owner’s session log proves a newer session_start on that registered pane.

  • agent-doc gc prunes stale operational artifacts without hiding fresh diagnostics: Codex blocked-stop payload records age out after seven days, and starting actor records older than one hour close unless a live supervisor PID still has a fresh supervisor heartbeat for that generation. A live but non-heartbeating agent-doc start process is not enough to pin starting indefinitely. Actor cleanup mutates the controller SQLite store transactionally. The lightweight stale-starting actor cleanup also runs every normal preflight, start, and sync cycle; the full orphan-file GC is bounded by a coordination throttle in .agent-doc/state.db.

  • Repeated state-database opens must keep document-version convergence proportional to the exceptional unversioned rows, not to the full event ledger. The every-open document_version = 0 guard is backed by a sparse partial index so idle controller RPCs perform an index seek after convergence; older binaries may still append default-zero rows, and those rows remain discoverable and repairable.

  • agent-doc run <file> must advance the cycle to write_applied once the final response (and any resume update) is on disk, before attempting the post-write commit. In git-backed runs, it must then pass through the same strict post-write closeout helper used by finalize, write --commit, repair, and the Codex Stop-hook: commit, prove the cycle is closed, retry once if the snapshot still differs from HEAD, and finish with session-check. Preflight/recover then finish from the recorded write_applied state instead of a stale response_captured phase.

  • Codex Stop-hook, direct template writes, and repair replay must validate captured assistant payload shape before writing whenever an exchange patch is mixed with unmatched text. Transcript-shaped or full-document component dumps fail closed into diagnostics, while known replay guard comments such as <!-- no-pending-capture --> may wrap an otherwise valid patch response. Safe plain progress commentary before the first patch is stripped, and the sanitized patch payload is what the write path applies.

  • The Codex Stop pending-work guard must use the shared queue eligibility predicate. Deferred review mirrors cannot create response debt after committed closeout; eligible manual prompts remain pending without opting into auto activation, and stop/time fences and inline operator verdicts retain their queue-policy meaning. A post-commit prompt-bearing diff must also reuse the typed mid-turn steering classification (#claimedstopforward): queue work already classified forward_to_owner for a live claim is not re-admitted as coordinator work. Stop may finish when every changed prompt is externally owned; a mixed diff still re-enters for the first genuinely unclaimed prompt.

  • The per-session log at .agent-doc/logs/<session>.log must capture document closeout boundaries in the same timeline as harness/supervisor events. When a session document crosses preflight_started, response_captured, write_applied, committed, or abandoned, the corresponding document_cycle phase=... cycle=... event=... entry must be appended to that session log so crash forensics do not have to infer the closeout boundary from separate state files.

  • agent-doc preflight treats preflight_started, response_captured, and write_applied as open cycle states. It auto-attempts recovery+commit for response_captured / write_applied; a stale preflight_started lock auto-clears when recover can prove the recorded snapshot/file hashes still match exactly, when safe historical HEAD proof shows the patchback is already committed, or when an otherwise-empty preflight_started cycle has no capture and has been stale past the bounded timeout. If the JetBrains File Cache Conflict Cancel branch leaves the response already visible in the working tree and snapshot while HEAD lacks it, preflight must classify both write_applied and already-marked committed variants as jb_cache_conflict_cancel and close the missing commit boundary instead of requiring manual agent-doc write --commit. If route --dispatch-only leaves a busy-actor queued dispatch in the snapshot (queue_active: true, agent:queue) while HEAD lacks it, preflight must commit that route-owned snapshot before diffing; any later visible prompt edit remains uncommitted for the fresh cycle. If that stale empty cycle still has unresolved prompt-bearing drift, recover marks the cycle abandoned instead of committing a placeholder response, leaving the prompt in the live document for the next fresh preflight cycle. Recent empty prompt-bearing cycles still fail closed so active concurrent work is not stolen. Outside those cases, preflight_started still only auto-closes when recover replays a pending/captured response first. If neither path applies, preflight fails closed before diffing. Pure agent-owned boundary churn ((HEAD) attribution and boundary-id-only diffs) is normalized back to no_changes / already-committed closeout instead of opening a new user-visible cycle, so transient post-commit markers do not leak a stale preflight_started lock. It emits non-blocking warnings[]; when frontmatter agent: is set and differs from the detected active harness after alias normalization, preflight emits code: "harness_mismatch" so the skill can surface the mismatch while still using active-harness attribution and closeout behavior. It also emits the tier/attribution contract the skill consumes: effective_tier, required_tier, suggested_tier, model_switch, model_switch_tier, agent_model, and session_accretion when local exchange/log heuristics detect churn-heavy growth or restart-heavy reopen patterns. Those heuristics are advisory only; preflight does not auto-compact the document. Each session_accretion reason must name the measure that actually crossed and that measure’s own warn limit, and must not name a measure that did not cross (#accretionthreshold): reporting both raw counts and no limit leaves the reader to pair one of them with the nearest number in the same report, which is clear_threshold — an unrelated /clear-cadence knob also counted in response sections — and read a warning session as under the limit.

  • Inline prompt-preset references are prompt-preset requests, not only standalone preset <name> directives. preflight.prompt_presets_requested, backlog-capture guards, and plan classification must recognize user prompt text such as Please analyze failed orders and bot traffic. #next-steps, while ignoring YAML prompt_presets: (alias presets:) definition lines. Stale empty preflight cycles and post-compact follow-up prompts that contain #next-steps must reopen a fresh actionable prompt_target cycle with backlog capture still required; step-2 commit recovery must classify that drift as post_commit_user_follow_up instead of absorbing it into the snapshot or HEAD. A preset reference is a live request only on a directive-bearing line (#quotedpreset): both the preset <name> directive form and the bare #preset hashtag form must be scoped over the WHOLE prompt text by one shared mask that suppresses fenced blocks, blockquotes, and quoted diff/report content, so a preset named inside a pasted terminal report, a quoted diff line, or a fenced task list is description rather than a directive. Quoted report content is indentation that is not markdown list nesting: an indented line whose nearest shallower non-blank line does not open a list item (or which has no shallower line at all) belongs to a paste. Scanning one line at a time is forbidden — it resets fence state on every line and leaves the hashtag form unscoped — and a caller that already holds the mask must not re-classify a single line without its surrounding context, or legitimately nested directives are suppressed.

  • Structured prompt presets may associate a project-local runbook with their prompt. The association is lazy: only an invoked preset emits a required-load instruction in preflight, and the runbook body is loaded through agent-doc runbook show, never copied into every cycle contract. The runbook list/show/create surface provides deterministic harness navigation and safe authoring; resolution is confined to Markdown under runbooks/ or .agent-doc/runbooks/ and rejects traversal, missing paths, overwrite collisions, and symlink escapes. See specs/07-orchestration-commands.md and runbooks/preset-runbooks.md.

  • Project-wide preset defaults live in the YAML frontmatter of optional .agent-doc/project.md (#projectpresets). Resolution starts at the established nearest .agent-doc/ root for the session file, walks through ancestor roots within AGENT_DOC_ROOT_CEILING_DIRECTORIES, and overlays presets at read time: farther project prompt_presets/presets provide defaults, nearer project declarations overlay them, and every document-local declaration wins on the same name, including a null/in-progress or malformed declaration that must shadow rather than revive inherited authorization. Missing project roots/files preserve legacy local-only behavior; a present but unreadable file or malformed project frontmatter is an error. Only presets are inherited: project-file bodies and other frontmatter fields do not affect session identity, routing, harness, or write policy. Effective presets are recomputed for each read so project changes apply to existing documents, while parse/write and closeout serialization remain local-only and never copy inherited values into those documents. Same-file alias precedence remains prompt_presets over presets, and inherited structured-preset runbooks remain relative to the effective nearest project root.

  • Effective project presets may recursively interpolate values from that overlaid map (#nestedpresetoverrides). A bare #name substitutes only when the exact key is declared, leaving unrelated hashtags literal; {{#name}} explicitly requires a definition. Missing explicit references, declared-but-unset or malformed referenced values, and cycles fail closed before prompt expansion or subagent authorization. Interpolation changes only the read-time prompt projection and never rewrites project/session frontmatter or transfers nested runbook metadata.

  • agent-doc plan may surface accretion guidance through normal prompt context. Exchange-size accretion and repeated commit_noop closeout churn remain advisory; the plan must not suppress normal repo work/finalize or require a compact/restart handoff unless the prompt or document explicitly requests compaction. Claude skill auto-update also defaults to restart, not /compact; compact reload requires explicit agent_doc_auto_compact opt-in in document frontmatter or project .agent-doc/config.toml. After a real Codex skill-version update, the installed Codex instructions must re-read the installed skill completely and continue the active turn in place; they must not request a supervisor restart or stop the turn (#codex-skill-reload-in-place).

  • A visible-write forward reconcile must distinguish a canonical read that is still exactly the pre-write cut from a newer settled buffer that dropped the acknowledged response. Two identical pre-write canonical reads are pending catch-up, not settled_buffer_dropped_response; the bounded receipt/canonical convergence path remains responsible for proving the acknowledged patch before closeout.

  • agent-doc plan must recognize both do #id and do [#id] directives as executable repo actions. When the id matches an open backlog or icebox item, the emitted normal finalize command must carry --done <id> so the binary-owned closeout records the resolved tracked-work item in the same cycle.

  • If an ancestor .tsift/graph.db is materialized, agent-doc plan and agent-doc orchestrate should try to collect graph evidence for queued do #id / do [#id] work before dispatch: graph-db status, graph-db refresh, per-target graph-db evidence, conflict-matrix, and dispatch-trace. Any tsift collection failure, including stale/fail-closed graph freshness, non-current status, missing evidence targets, command timeout, bad JSON, or missing graph orchestration contract fields, is advisory at the agent-doc turn boundary: plan must emit a soft warning plus manual_packet_only: true, orchestrate must warn and continue without graph evidence, and jobs create must still be able to write parent-reviewed manual packets. When graph evidence is successfully collected, evidence packets must be graph-db-evidence-v1 with packet_id, projection_hash, replay_commands, and repair_commands; conflict matrices must be conflict-matrix-v1; dispatch traces must be dispatch-trace-v1 with projection freshness/hashes, evidence packet ids, worker feedback, graph nodes/edges, replay commands, and repair commands; worker prompt packets must be worker-prompt-packet-v1 with packet_id, projection_hash, token_budget, and explicit fail-closed prompt text. A successfully collected conflict matrix can still block parallel dispatch when it explicitly reports unsafe ownership (can_parallel=false or fail_closed=true). Prompt targets and orchestration job prompts with available evidence must carry compact graph handles/evidence packet ids plus a normalized lower-agent job packet preserving owned files, read-only context, forbidden files, expected tests, expansion commands, token budgets, fail-closed instructions, and dispatch-trace audit context; child prompt context must not be injected into the session document itself. Successful graph-backed orchestrate child closeouts must append a tsift-projectable worker_result line with status, target id, touched files, tests, and follow-up ids before finalize so later graph projections can close the feedback loop without scraping CLI output.

  • agent-doc plan must also emit lower-agent routing fields for job-packet workflows: dispatch_candidate, task_class, risk, parallelizable, parent/model tier, context and job-packet token budgets, write_scope, required_proof, dispatch_mode, manual_packet_only, warnings, and tsift_context. agent_doc_dispatch: off disables the candidate flag; agent_doc_dispatch: auto records opt-in for future automatic dispatch. These fields are structural hints for packet generation and never replace parent review or verification. agent-doc jobs create <FILE> writes agent-doc-job-packet-v1 markdown packets under .agent-doc/jobs/<cycle>/, expands compound do [#a] [#b] directives into one packet per target, derives target-specific write_scope from explicit path references in backlog text, optionally writes an operation note, and records tsift context sidecars when tsift status --json / tsift context-pack --json succeed. When a tsift graph projection is usable, create dogfoods graph-db evidence, conflict-matrix, dispatch-trace, worker prompt packet, worker_result feedback, replay, and repair command contracts before attaching graph acceptance evidence; when manual_packet_only is true, the job index and packet body must preserve the warning and omit graph acceptance evidence so parent review remains explicit. agent-doc jobs list/status/collect inspect generated packets and agent-doc-worker-result-v1 result envelopes only; collection validates required changed path, command/test, touched-file, expected-test, follow-up, proof, and attention fields but does not apply patches, resolve backlog items, or bypass the normal parent-owned finalize closeout.

  • orchestrate --mode parallel owns the lifetime of every git worktree it creates (#orchworktreeleak). After results are collected — the timeout path breaks into collection rather than returning, so a killed task is disposed of exactly like a finished one — each worktree is removed together with its branch unless the task authored something: uncommitted tracked changes, an untracked path that is not orchestrate’s own scaffolding (.agent-doc-prompt.txt, .agent-doc-result.json, .agent-doc-result.log), or a commit on its branch since the recorded base commit. A retained worktree must be reported with its path, branch, and the specific reason it was kept; silently deleting a task’s only copy of its output is worse than the leak. A fan-out that aborts mid-spawn — worktree creation, prompt write, pane creation, or send-keys — must unwind every worktree it has already created instead of stranding them. The disposal rule is a pure predicate so it is testable without a repo.

  • agent-doc orchestrate <FILE> --mode dag --from-queue owns the auto-DAG queue path. It reads all active queue prompts plus queue-level presets, expands compound do [#a] [#b] items into per-target nodes, parses explicit dependency metadata and natural dependency phrases, computes deterministic antichain batches, persists agent-doc-auto-dag-schedule-v1 JSON under .agent-doc/schedules/, and writes schedule-backed job packets under .agent-doc/jobs/<schedule-id>/ before dispatch. --resume-schedule <ID> must reload the durable schedule, skip complete nodes, preserve attempt counts, and fail closed if a blocked/failed node would otherwise unblock downstream work. When graph evidence is present, auto-DAG treats stale graph status, missing target evidence, ambiguous ownership packets, or unsafe conflict-matrix antichain dispatch as blockers before launch. Recent ops-log/session-review families are scheduler input: prompt-budget/cache-resend gates to compact-first, restart-loop gates to restart/repair-first, and repeated noop-closeout gates to fixture-fix-first. The schedule record must preserve the guard action, replay commands, repair commands, node state, and attempt count for interrupted run recovery.

  • Repeated --backlog-add flags in a single write or finalize command must preserve caller order as a batch at the top of the backlog: the first backlog-add flag becomes the first new backlog item, followed by later backlog-add flags, followed by the pre-existing backlog. Legacy --pending-add remains an alias.

  • finalize / write --commit must expose --no-followups (with --no-pending-capture as an alias) as the first-class declaration that the response creates no actionable follow-up work. The runtime must encode the declaration into captured response evidence before pending-capture guards run, preserve it across idempotent closeout retries, and strip its transient marker from visible and committed document text.

  • A #next-steps closeout that captures multiple follow-up backlog items must preserve declaration/priority order through the same repeated --backlog-add path, and any generated Top backlog item: #id. status sentence must name the first inserted live backlog item.

  • In an explicit go-mode queue backed by an agent:backlog queue component, add and ungate mutations that make ids actionable must mirror those exact ids into agent:queue in the same closeout transaction (#backlogqueuepopulation). The binary records mutation-scoped actionable ids separately from new-add proof, performs an insert-only queue update after current-head consumption, and orders the new block by hard after=#id dependencies before priority. It must not sweep every open backlog id during closeout, because that would resurrect unrelated queue entries the operator intentionally deleted.

  • --backlog-add-to <file> <text> is the binary-owned path for explicit cross-document backlog capture. Legacy --pending-add-to remains an alias. It must fail when the target file is missing or lacks an agent:backlog/legacy agent:pending component, and agent-doc plan must expose explicit backlog target files so skills do not satisfy a target-specific prompt by adding to the current document. Closeout guards must still check explicit targets even when the current document recorded unrelated tracked-work mutations. When a prompt chain contains multiple #agent-doc-bug declarations, agent-doc plan must preserve declaration order in its expected add mutations and emitted placeholder flags; intentional priority overrides must be visible in response text or explicit mutation metadata, not produced by accidental LIFO insertion.

  • A cross-document tracked-work mutation is not complete merely because its target entered the controller canonical or the bounded replica-availability barrier released. Before the source response may commit, every attached destination must prove the exact target through the strict visible-projection receipt; a released silent/non-ACKing replica retains the destination write and withholds source snapshot/commit effects. The CLI must never report a successful --backlog-add-to closeout while the destination remains invisible in its editor.

  • An operator may move an existing open tracked-work item between documents by preserving its normalized id. The dropped-history guard accepts the move only when that id is open in exactly one other agent-doc document under the same project root. Plain prose/code mentions and nested projects do not count; multiple open destinations are ambiguous and fail closed; shared documents retain the cross-document security-review gate. Preflight and session-check consume the same destination evidence so admission and closeout cannot disagree.

  • --icebox-add, --icebox-add-after, --icebox-add-before, and --icebox-add-back are granular tracked-work mutations for parked work in agent:icebox. They use the same stable-id, checkbox, collision, same-cycle metadata, and operator-preserving writeback rules as backlog adds, but they must not mirror new items into runnable agent:queue.

  • agent-doc boundary prepares a transient working-tree insertion marker and may signal the editor, but it must not update the saved snapshot or create a git commit. A later preflight/commit may normalize marker-only working-tree churn as already-committed drift, but a standalone boundary marker is never the committed snapshot basis.

  • Full and partial exchange compact with a trailing unresolved prompt after the boundary must preserve that prompt in the live editor/working tree while leaving it out of the saved snapshot/commit. The compact closeout may archive old response sections and commit the compacted history, but the next agent-doc cycle must still see the prompt as live user drift. Compact therefore carries distinct live and committed targets through the transaction: editor save/relay convergence uses the live target, Git stages and verifies the committed target, and an already-converged live relay must never be reset to the committed-only projection. A stale zero-editor relay fallback may be repaired, but it must be repaired to the live target.

  • When warn/block session-accretion prompt packing is active, the bounded exchange context must anchor each prompt target to its actual exchange position: include the enclosing ### Re: block for inline prompt edits, or the immediately previous ### Re: block for tail follow-ups. The pack must also expose a lightweight live+archive response TOC plus a targeted retrieval surface (response-fetch) so agents can request exact neighboring sections on demand instead of relying only on a fixed recent-turn slice. If no clean anchor can be found, the pack may still fall back to the latest bounded recent-turn slice.

  • When sync discovers that a previously registered pane disappeared while the document’s cycle state is still response_captured or write_applied, it must attempt the same binary-owned recovery path immediately instead of only logging pane loss. response_captured must replay from durable capture through the normal write/commit closeout, and write_applied must finish the missing commit boundary if the live file/snapshot already prove the response landed. If either recovery attempt fails, the failure must be logged alongside the pane-loss provenance and the durable capture must remain available for later preflight / repair.

  • During tmux layout reconciliation, sync must not evict an unwanted pane whose owning document still has an open preflight_started, response_captured, or write_applied cycle. In that shape the binary warns and preserves the pane instead of stashing it mid-closeout.

  • finalize --done <id> is a tracked-work resolution and must satisfy pending-capture closeout requirements for do #id turns in the same way as adding new backlog work. If the item was already reaped into canonical agent:done, into the repo-relative external .done.md archive named by agent:done archive=..., or recorded as resolved in the active cycle, the flag is an idempotent no-op warning, not a fatal “id not found” error. Legacy agent:backlog-done and agent:pending-done markdown components are migration inputs only, not accepted completed archives at runtime; run agent-doc migrate to rewrite them.

  • During preflight maintenance, active agent:backlog or agent:review mirror items whose ids already appear in inline agent:done or the configured external agent:done archive=... are stale and must be removed from the active tracked-work surface without writing duplicate done archive entries. Active backlog/review items may also be auto-completed when their item text carries an explicit completion marker (DONE, SHIPPED, IMPLEMENTED, COMPLETE, or COMPLETED) plus deterministic commit or successful-CI proof, but blocker language such as partial, remaining, reopened, deferred, false-closeout, or follow-up work keeps the item active. That auto-completion must not fire on a false positive where the marker only describes already-landed dependency work: for an open (non-gated) item the completion marker must be the item’s own leading status verb (the status prefix before the first clause break), not a marker buried in a cited-dependency clause such as “the predicate already shipped in abc1234”; gated [/] items keep the marker-anywhere behavior because the agent deliberately code-completed them. Auto-completion must also never reap an item on the same cycle it is added — a brand-new add is absent from the cycle-start snapshot and must be closed explicitly rather than archived the moment it appears. Queue maintenance must also treat those ids as resolved: backlog-to-queue sync excludes them, and existing live queue prompts for them are struck before dispatch.

  • agent:review is the canonical review-pending tracked-work component. --backlog-gate <id> moves backlog work into review as [/]; --backlog-ungate <id> moves review work back to backlog as [ ]; legacy --pending-gate / --pending-ungate remain aliases. --done <id> accepts backlog, review, or icebox sources. review_done_guard defaults to off; with warn or strict/error, direct --done outside review is surfaced or blocked. agent-doc migrate moves legacy [/] backlog items into agent:review, and preflight warns with legacy_gated_in_backlog until that migration lands.

  • auto_done: true in frontmatter, or [guards] auto_done = true in .agent-doc/config.toml, opts a document into automatic tracked-work resolution for clear completion signals. Explicit inline prompts such as mark #id done, #id done, done #id, complete #id, and resolved #id must make agent-doc plan emit a ResolveExisting / --done <id> mutation even without auto_done; a bare done/complete/resolved prompt may auto-resolve only when auto_done is enabled and exactly one open agent:review item is the contextual target. When auto_done resolves a response-completion guard hit during finalize / write --commit, it must record the same cycle-state pending-done ids as an explicit --done. If the target still lives in agent:backlog, the auto path gates it into agent:review before marking it done.

  • Generated status text that includes Top backlog item: #id. must stay consistent with the live agent:backlog head. Pending maintenance, reap repair, explicit backlog reap, and exchange compaction must reconcile that sentence to the current open backlog head or clear it to No open backlog items. when the backlog is empty; unrelated free-form status text remains user-owned.

  • Editor-triggered sync serialization must be bounded. A stuck prior full sync may delay a later sync only up to the configured contention budget; safe-passive editor sync may wait only the sync_lock_wait latency budget. Immediate editor focus is handled by the separate Project Controller focus command; sync itself does not move focus before acquiring this lock. On safe-passive contention, the binary must emit a visible [sync] safe_passive_sync_lock_contention_retry ... phase=sync_lock_wait ... status=over_budget ... coalesced=skipped_stale marker and return without further auto-start, tmux reconciliation, or post-lock hidden-pane focus changes so the editor can retry the latest superseding selection instead of waiting the full lock budget. Lock acquisition blocks in the kernel on flock(2) with no userspace polling, and flock(2) is released automatically when the holding process exits (fd close), so a dead or orphaned owner can never wedge the lock — there is no /proc stale-orphan reap and no manual process cleanup.

  • Editor plugins must treat that safe-passive contention marker as deferred, not applied: the stale command must leave the last-applied selection state unchanged, and only the newest superseding tab/layout request may be retried. Editor-side guards must not self-contend by acquiring their local sync guard and then calling a helper that reacquires it before starting the CLI process.

  • Editor-selected document focus is operator-first while its latest-wins focus command crosses the Project Controller. The editor plugin must hold a short focus-intent lease that suppresses tmux-to-editor recall of the previously active pane, acknowledge the intended pane without reopening the editor, and restore normal tmux-to-editor following after a bounded expiry if the command never converges. This prevents the two directions from creating a self-sustaining cross-document focus loop.

  • Controller-owned safe-passive sync must use the live authoritative SQLite actor row as local ownership proof, allowing an exact-visible editor selection to swap an already-running hidden document pane into view. A standalone safe-passive CLI remains forbidden from issuing a nested Project Controller actor-binding RPC; it may proceed only from non-RPC ownership evidence.

  • Editor tab selection performs its immediate focus handoff through the separate latest-wins Project Controller focus_document_pane command, resolved from the focused document’s own project root rather than the one root chosen to span a mixed-root editor layout. The following safe-passive sync must not steal focus before acquiring its sync lock; it owns guarded exact-visible reconciliation, including the hidden-pane swap after controller-local actor proof.

  • A Remote Dev backend selection delivered by an admitted ClientType.CONTROLLER session is positive focus evidence for that selection generation. The focus-only projection must not additionally require a backend Swing activeWindow, because the visible window belongs to the thin client. Local and guest selections retain the project-window activity gate. Every scheduled focus-projection exit must report its named gate (superseded, inactive, disposed, or closed) or completed outcome at INFO, and the scheduled effect must catch and warn on any Throwable so failures before controller transport are observable.

  • One JetBrains editor surface may publish its authoritative layout snapshot through only one Project Controller root at a time. When a mixed-root editor selection successfully republishes that surface through a different root, the plugin must generation-fenced-forget the prior root; a failed forget remains retryable. Component-focus events are selection-only and must not republish unchanged structural layout. This prevents two healthy controllers from reconciling one tmux window from incompatible retained surfaces.

  • A JetBrains editor-surface publication is positive liveness evidence for its own endpoint. When the IDE’s detached-frame window enumeration lags, the plugin must union the current/published surface into the available live set and may retire only other retained endpoints absent from that set; it must never retire the endpoint that just published and thereby make the controller reject every later observation in the same generation. An empty backend window list remains unknown liveness for Remote Dev and retires nothing.

  • Plain agent-doc focus <FILE> without an explicit pane uses that same Project Controller command and its typed resume_latest missing-pane policy. A closed/missing actor projection with a known durable session must reach the resume transition rather than fail at the earlier focusability guard. The focus transition uses typed ProvisionOnly startup policy so pane creation/start/selection returns within the short focus RPC; harness readiness and layout reconciliation remain asynchronous. Before that automatic effect creates a pane, it must durably record the missing bound pane, then consume the same persisted recent-session-loss decision as normal editor routing and fail closed once the bounded crash window is exhausted; it must not consume an unpopulated ledger and keep rebinding a repeatedly vanishing document. Explicit --pane, --blocking, and operator-requested supervisor recovery retain their direct/operator behavior.

  • Safe passive sync must also fail safe before attach-first reconciliation would expand the visible agent-doc window around those protected panes. If a requested file is not currently visible and satisfying it would require attaching another pane while some already-visible unwanted pane is still protected by an open cycle, sync --no-autostart preserves the current visible layout and warns instead of creating a visible 3+/4+ pane mix it already knows cannot detach cleanly. That preserve-layout fast path must still reselect the requested pane when the focused file is already visible in the kept window.

  • Safe-passive exact-visible reconciliation is atomic across stale-supervisor admission. If the stale-column gate removes any requested editor column, sync --no-autostart must preserve the current tmux layout rather than realize a strict subset; the recycle-settled generation republishes and retries the complete surface. Full/manual sync retains its repair authority and may realize a non-empty admitted remainder, while every mode preserves if the gate leaves no requested columns.

  • Session-check must not treat plain content_edit drift as proof that an already-committed response bypassed closeout. Only new prompt targets, response patchback markers, hidden snapshot-vs-HEAD closeout drift, or open cycle states should force another closeout boundary.

  • Session-check must also fail closed when the live agent:exchange tail itself ends in a prompt-looking block with no later assistant response, even when that prompt already matches the committed snapshot. This catches direct/manual closeouts where implementation commits completed but the final response patchback never landed.

  • Explicit-baseline finalize / write --commit must classify concurrent live-file drift against the pre-response baseline. A prompt added after preflight but before write-back remains outside the committed closeout snapshot, and the required post-commit session-check must interrupt on that unresolved prompt_target.

  • For strict template/CRDT append-mode agent:exchange writes, an explicit baseline that is missing exchange content already committed in HEAD is stale for patch application. finalize / strict write --commit must apply the response on top of HEAD before producing content_ours, IPC snapshots, or commit-staged snapshots, while still leaving later live user drift for the next cycle. The repair path must log explicit_baseline_rebased_to_head.

  • Typed-baseline closeout must survive session-document path moves after preflight. Rename migration transactionally rekeys the ledger events and embedded fact hashes, so finalize / write --commit resolves the baseline under the current document identity without reading a baseline sidecar.

  • Mutable per-document recovery state lives only in typed state.db facts. No filesystem snapshot sidecar is written or consulted; legacy residue is inert cleanup input and cannot acquire document authority. reset --from-current rebuilds typed recovery state from Lazily current markdown; no CRDT, capture, pending, baseline, snapshot, or live-buffer file is imported.

  • Cross-process state exchange uses generic state_plane_publish/state_plane_subscribe transport RPC around canonical Lazily Snapshot/Delta messages. Producers publish keyed state projections; RPC handlers must not translate those publications into imperative plugin-owned effect retries. Covering snapshots may replace a prior producer, deltas require the exact producer/base epoch, duplicate delivery is idempotent, and subscribers resume from a monotonic controller plane version. Controller readiness probes use the lightweight handoff-status projection; operator status may include durable store diagnostics, but append-only ledger sizes are bounded high-water observations rather than full-table counts, so repeated readiness or health observation cannot rescan the state ledger.

  • Pane layout is the first state-plane domain. Editor plugins publish authoritative columns/window/focus, while the controller records the desired tmux target, actor bindings, observed receipt, and convergence status. A tmux attempt is keyed by the exact frontend snapshot generation plus actor-binding state. Convergence retires it; a retryable failure derives stable retry_pending while the same latest-wins effect worker retains ownership, waits with bounded backoff, and retries until convergence or supersession. A newer frontend snapshot or actor-authority fact interrupts that wait and wakes the retained worker immediately. The controller must not synchronously poll tmux from its IPC accept loop or create a detached periodic retry timer. Columns and focus are one effect target: convergence requires both matching observed columns and, when focus is requested, a typed receipt proving the final input-revision-fenced pane-selection consequence. The accepted frontend snapshot is committed to state.db before tmux effects, so controller restart recovery does not depend on controller-lifetime message history.

  • A pane-layout observation must independently compare the model-owned file-to-pane assignment in desired column order with tmux’s physical left-to-right pane order; matching document labels alone cannot prove convergence. A live same-window actor outside the desired surface is diagnostic, not terminal ownership: reconciliation may move its pane to stash without killing or interrupting the actor, and the generation remains retry_pending until the visible pane count and order converge. A missing requested surface document likewise remains retry_pending. Focus continues to resolve the requested document through the file-to-pane assignment and must never index directly into physical pane order. A column the layout effect acknowledges as deliberately gated out (gated_documents, a stale-supervisor column) is removed from both the expected surface and the focus requirement, so it converges rather than staying retry_pending; a stale stash pane is promoted only while its durable recycle request is not overdue and only when it replaces rather than adds a column (GH #136, specs/07-session-tmux-commands.md). Safety of the stale-column gate never depends on editor message order, delivery, or timing; the remote (Coder + JetBrains Remote Dev + Zscaler) path is the design point, and the one time budget involved (AGENT_DOC_STALE_RECYCLE_CONSUME_BOUND_SECS) is a configurable liveness bound only.

  • Pane-order invariant (#tmuxpanesreversed). After every layout operation, the panes of the wanted layout, read left to right by tmux geometry (pane_left, then pane_top inside a stacked column), are exactly the wanted column-major order. pane_index, list-panes line order, pane creation order, base-index, and pane-base-index are never ordering inputs. Panes outside the wanted set (for example a protected busy pane) neither satisfy nor break the invariant. Sync enforces it with one pure check and planner (agent_doc_tmux::pane_order): after tmux-router returns, it re-reads geometry past the observation cache, and when every wanted pane is present but misordered it applies the minimal swap-pane -d plan (at most n-1 swaps), restores the operator’s active pane, and re-reads. A violation that survives that one repair is reported as an error, never retried in a loop or accepted silently. Every layout pass writes one tmux_pane_order outcome=held|repaired|violated|incomplete|unobservable ops.log line carrying the tmux server version, base-index, pane-base-index, window size, the wanted pane order, and pane positions before the operation, after it, and after any repair.

  • Frontend layout authority; no structural guessing (#tmuxpanesreversed, GH #343). While an editor frontend is connected, its complete layout snapshot is the sole authority for column membership and left-to-right order. The backend does not own or derive a second editor layout: it retains the last accepted frontend snapshot with its generation, copies that column vector unchanged into the desired tmux effect target, and records observed tmux convergence. Selection-only, unknown, partial, stale, failed, or timing-ordered evidence may update focus intent only; it must preserve the last accepted structure or defer. It must never insert, replace, remove, regroup, fold, or reorder columns. Authenticated Remote Dev connection/lease establishment activates pending frontend authority before the first snapshot, including the 75 ms capture debounce, EDT capture, up-to-5-second schema negotiation, and Fleet RPC interval; backend fallback is suppressed throughout that window and after transport failure until explicit retire/release. Snapshot schema 3 carries the frontend-authored exact column vector directly; the backend validates paths but does not reconstruct columns from bounds. Between snapshots it may continue enforcing only the last accepted vector. Manual Sync Tmux Layout replaces stale structure only from a complete positive frontend capture; an incomplete/unknown capture preserves or defers, so retrying Sync cannot ratify stale backend structure or invent a column. Its refusal names flat_evidence_has_no_column_geometry for the Remote Dev case. When the frontend publisher stays unavailable, the backend and route failure prescribe the effective local/custom-install remedy: install the same modular plugin ZIP in JetBrains Client/Gateway and the Remote Dev backend, restart both, then retry. The sole cold-start exception is an explicit foreground Run Agent Doc ensure route: with no retained frontend vector, a positive live-tmux observation may prove that the target already has a pane (focus-only) or let the route’s complete named visible set replace the complete observed set at unchanged width. The one-column case remains valid and a two-column set may replace two live slots; partial replacement and widening remain forbidden. The replacement remains labelled column_order=unknown and cannot become editor-order authority.

  • A JetBrains Run Agent Doc route or Sync Tmux Layout command must name the authoritative editor surface snapshot the controller retains (surface_reference = { surface_id, min_sequence }, capability surface_layout_reference_v1 advertised in every editor_surface_observe reply) instead of sending --col arguments read at click time. The controller copies a complete snapshot’s columns and order unchanged into the tmux effect target and derives only non-structural routing metadata. Sync Tmux Layout fails closed (surface_reference_<reason>) on a missing, retired, incomplete, unknown, or older snapshot, or a foreground focus outside the columns. Run Agent Doc has only the typed, width-preserving live-tmux replacement exception above when its referenced Remote Dev surface has focus but no geometry. The plugin keeps the --col publication only as a logged compatibility fallback for a controller whose reply lacks the capability, a cross-root command, or a surface it could not publish. See specs/08-session-routing.md.

  • A foreground editor Run Agent Doc route must treat its complete frontend layout snapshot and focus as one exact-visible tmux target and await the corresponding convergence receipt before dispatching to the routed pane. Before publication, the controller canonicalizes editor-relative paths and requires the routed document in those columns; it never materializes a missing focus into a column. A focus absent from the authoritative columns fails closed before desired-state publication or dispatch.

  • Route focus is a typed authority effect: select-pane ⇔ authority = standalone_foreground ∧ target_placement = foreground. Background and controller-layout authorities never select a pane or window, and a stash or unproven target placement fails closed. A route re-entering from its document’s own parked pane is background exactly when current_pane_present ∧ owner_matches ∧ pane_is_stashed ∧ ¬controller_layout_owned; it may inject work into that proven existing pane, but must not rescue it, select its window, or mutate the foreground layout. An explicit operator/editor route remains able to focus only through the controller’s generation-sequenced layout authority.

  • Pane-layout status phase and reason_code are wire-stable enums; optional reason_detail is diagnostic only. Version 1 uses Lazily’s canonical JSON envelope and typed JSON node payloads. Protobuf may be added as a node payload codec for additional language runtimes, but it is not required by or embedded into the Lazily state-plane core.

  • Layout-owned startup stages a fresh pane in a detached window and returns its binding without changing visible geometry or focus. Only the current layout Effect places it; a superseded or concurrent startup cannot append a third visible pane after a two-column reconciliation. Standalone route placement and first-window bootstrap keep their existing behavior.

  • A pane-layout effect receipt is a source fact, while its applicability is a computed join of desired state, actor-binding state, and receipt state. The exact file-to-pane assignment returned by the effect remains attached to that desired-generation/actor-binding pair and takes precedence over actor-store or process-tree inference during observation. A receipt or observation from a superseded generation or actor binding cannot prove convergence or select a pane for newer editor navigation. This controller-owned rule is editor-neutral and therefore applies equally to JetBrains, VS Code, and Zed publishers.

  • install-full removes repository-owned compilation outputs only after the binary, native library, and editor plugins have been installed successfully. It preserves Cargo’s global dependency caches and supports AGENT_DOC_CLEAN_BUILD_ARTIFACTS=0 when an operator intentionally wants to retain incremental outputs.

  • Exchange prompt-prefix normalization must preserve exchange prompt-prefix state already committed in HEAD in both directions: previously prefixed user-prompt lines must keep ❯ , and previously unprefixed agent response lines must stay bare. A content_ours fallback may add ❯ to newly typed prompts, including every nonblank line in a blank-separated multi-line prompt run after a stale inserted response block, but it must not add that prefix to prior agent response lines simply because the snapshot/baseline pair is stale. Inserted assistant response blocks stay assistant-owned until an explicit ❯ line, component/boundary marker, or canonical prompt-target diff opens a new prompt run; prompt-shaped assistant prose such as questions is not enough by itself. When IPC sidecar verification rejects a plugin-side normalization result and computes a content_ours fallback, that fallback must first merge current disk edits against the explicit pre-response baseline, then deliver the normalized repair through narrow editor IPC. If editor delivery is skipped or unproven, the write must fail closed before saving a snapshot, CRDT state, commit, or direct working-tree repair. Concurrent user edits outside agent:exchange, including deletions of scratch HTML comments, must remain editor-owned and must not be restored by normalization retry. Post-commit prefix repair must not propagate historical bad prefixes from assistant evidence labels such as Commit / push: into later assistant responses, and patch/content prefix application must still refuse to prefix those assistant labels if a stale target list includes them, even when a historical stale target list contains Commit / push: and a later response has a fresh bare Commit / push: label. A temporarily prefixed response heading such as ❯ ### Re: is still an assistant response boundary; prefix repair must not treat matching response-body lines after that heading as prompt targets. Prompt-prefix overrun protection logs and passes through when more than MAX_NORMALIZE_USER_LINES prefixes would be applied; it must not force-commit from inside normalization now that typed repair decisions own disk/snapshot/editor recovery.

  • Binary-authored Markdown blockquotes, especially > **Queue prompt:** response scaffolds, are response envelopes rather than user-prompt normalization targets. Normalization removes a legacy ❯ prefix from those quote lines and collapses immediately repeated identical queue-prompt scaffold lines before captured-response materialization checks, making captured-finalize retries idempotent instead of appending one new scaffold per retry.

  • Sync live-owner recovery must rank file-specific evidence by freshness: path/supervisor provenance first, then the latest open session-log owner, and only then generic same-file process-tree matches. An older pane that still has a same-file harness process must not steal authority back from a newer pane that already recorded the latest session_start.

  • Sync must also treat the latest alive session_end origin=registry_rebind ... next_pane=... successor as authoritative live-owner evidence before generic same-file process-tree fallback. A pane handoff proven by tmux/session-log provenance must not fail just because the supervisor PID or foreground process tree changed afterward.

  • When route --dispatch-only reuses a live pane through direct tmux input, startup-window reroutes must first observe a harness-specific dispatch-ready prompt in that pane. A Codex status/footer line such as gpt-5.5 high · ... · Context ... is not a prompt by itself. OpenCode startup-window prompt probes must use the longer OpenCode redraw budget, including the same harness-specific recovery wait used for starting actors, because the idle splash can become dispatch-ready after the short Codex-style boot probe. During that startup prompt-ready wait, route owns the pane input window and must publish controller-backed RouteSubmitStarted / RouteSubmitSettled facts before any supervisor idle-queue context reset can enqueue or submit /clear / /new; pending QueueContextClearDeferred / QueueContextClearStarted projections and orphan visible clear drafts must wait while the route-submit projection is pending. Accepted-without-dispatch-start proof records RouteSubmitBlocked for the bounded blocked window. Dispatch proof must separate pane-input acceptance from dispatch-start evidence. Accepted shared text+Enter delivery is a successful dispatch-only result for Claude Code, Codex, and OpenCode, and logs proof=accepted proof_scope=accepted_only when dispatch-start proof is absent. Codex hook proof and OpenCode pane-state proof are still logged as stronger dispatch_start evidence when available, but missing stronger proof does not make the editor action fail. Editor-triggered JetBrains routes must propagate the durable Run Agent Doc attempt id into the binary process, and route/tmux diagnostics must include that id on the input-delivery and proof lines so a live click can be correlated across .agent-doc/state/editor-route-attempts/, ops.log, and preserved route-submit pane snapshots without replacing tmux-router reconciliation.

  • Claude readiness treats a bare ⧉ <label> line as an attached-artifact composer chip and continues scanning for the real idle ❯/permissions prompt; <label> is arbitrary session content and must never be hard-coded. Only the complete picker shape (Enter to open plus a claude.ai/code/artifact/... URL) is an operator-owned dispatch blocker.

  • Safe passive mixed-root sync must preserve the current visible agent-doc window layout whenever any visible file stays blocked under sync --no-autostart. In that shape the binary warns and skips tmux-router reconciliation instead of collapsing the remaining foreign pane set into a new authoritative layout, but it still reselects an already-visible requested focus pane inside the preserved window.

  • Full/manual agent-doc sync is the binary repair path behind editor Sync Tmux Layout: before applying the frontend-authored tmux target, it must invoke the same file-scoped doctor repair used by agent-doc session doctor <FILE> --repair when a focused/session document is available. That repair must close recoverable jb_cache_conflict_cancel commit-boundary drift (visible document and snapshot already contain the response while HEAD does not) before pane liveness can short-circuit, and must normalize the inferred tmux session to 0:agent-doc, 1:stash, and adjacent overflow N:stash windows, renaming stash-* aliases back to stash, even when the editor supplied a stale stash window target or sync starts while the active window is named stash. Passive sync --no-autostart remains non-destructive and does not run that repair step.

  • A full/manual sync that provisions a missing document pane owns one terminal create-and-route boundary: resolve the intended tmux session, create and register the pane there, wait for the harness to become dispatch-ready, and submit the document reopen before returning success. The Project Controller receipt records that this strict path was selected. Automatic/passive editor sync remains admission-oriented and must not wait on or claim this manual route boundary.

  • A foreground sync_tmux_layout command must name its focused document in the authoritative frontend columns after project-root canonicalization. A focus outside those columns is an impossible terminal target: the controller refuses it before durable snapshot memory or desired-target publication, rather than spending the effect retry budget. Passive automatic observations may omit an inactive focus and retain their existing focus-suppression behavior.

  • That manual controller command retains its frontend snapshot generation until the terminal tmux receipt is known. A passive editor-surface observation arriving after the command publication is deferred—even when its columns and focus are identical—so it cannot replace no_autostart=false with passive no_autostart=true before a missing local or cross-root pane is created. JetBrains must await the terminal command receipt and surface a refused, superseded, timed-out, pane-start, or route failure instead of reporting state-plane admission as successful completion.

  • Safe passive editor sync must optimize for the fast pane handoff path before it owns the bounded sync lock when a local projection or no-record provisioning miss is cheap, then converge through the existing locked path. Safe-passive prune may still remove stale registry rows and retained dead non-stash panes, but it must skip expensive stash-window and stash-pane cleanup before tmux-router reconciliation so extra visible panes are detached before orphaned stash scans spend the selection budget. If no live actor binding exists after the pre-lock handoff, reuse the latest matching pane when one is known, otherwise fall back to an alive exclusive registered pane rooted to the same document, and only then cold-start a new pane. The slower supervisor/process-tree recovery still applies to non-passive paths and non-happy-path recovery.

  • Automatic editor syncs that have a complete visible markdown snapshot must pass --exact-visible with --no-autostart; the binary must use the exact frontend column vector and skip remembered focus-only sibling expansion, so stale panes do not reappear after the editor switches away from a document.

  • resync --fix orphan-agent cleanup must prove a pane is unowned across project roots before killing it. A non-stash agent pane that is absent from the current registry but registered in its pane-local project root, still proves a live owner there, or hosts a live supervisor from that root is preserved instead of being reaped as a parent-project orphan.

  • Safe passive focus-only editor sync must not mutate pane membership or order. It may select a focused document only when that document already exists in the last accepted frontend snapshot. If it is absent, or no authoritative snapshot exists, the structural effect defers; tmux geometry, registered panes, retained focus, and event timing must never be used to invent or replace a column. A Run Agent Doc route whose structural effect defers may still dispatch focus-only when a positive live tmux observation proves that the routed document already has a pane; this publishes no layout generation and does not promote tmux state to editor-layout authority.

  • agent-doc preflight must also fail closed before diffing when the live snapshot/file pair already looks like an uncommitted assistant closeout with no open/recoverable cycle left to explain it. That includes a visible bypassed ### Re: block and the hidden snapshot != HEAD shape where the file now matches the snapshot but tracked side-effect edits are still only in the working tree. The failure must name agent-doc write --commit <FILE> as the repair path.

  • agent-doc commit <FILE> may close an already-committed historical response as a no-op while leaving later user follow-up prompt edits for the next turn only when an open/recoverable cycle still needs that terminal transition. If the most recent cycle is already terminal, a later user follow-up prompt is not a closeout at all; the command must return without lifecycle no-op bookkeeping and say to rerun agent-doc <FILE> or pipe the missing response through agent-doc write --commit <FILE>.

  • When the document diff is empty, direct harness prompt text or an active queue head item may still open a real cycle. The binary strips the leading agent-doc <file> invocation from the current harness prompt (Codex hook state or explicit AGENT_DOC_HARNESS_PROMPT) or reads the active agent:queue head prompt, synthesizes an in-memory added-lines diff from that body, and feeds it through the normal prompt-target / prompt-preset / backlog-contract classifiers. Bare agent-doc <file> with no trailing body and no active queue still remains no_changes. The synthesized queue head is the first selected head, else the first unclaimed live head drainable in the supervisor scope — the same derivation as the queue_supervisor_drainable gate (#regressionawaitingoperat). A claimed head, or an [operator-verify] / gated-review head awaiting the operator (⏳), is never synthesized, even when a drainable head sits below it.

  • A no_changes: true preflight carries no_changes_explanation (#noopnamefault): read_source (live_editor when preflight read an agent-doc editor buffer, disk otherwise), waiting_queue_items (items in an agent:queue that is neither active nor deferred), and guidance naming that fault. Harnesses relay the guidance instead of inventing a cause; a live_editor read never warrants “save the file” advice. It also carries claimed_queue_items (#explicitrunqueue): each live queue head an unexpired worker claim holds, as {item, owner, expires_at} (expires_at ISO-8601 UTC), and the guidance names each as `<item>` is claimed by <owner>, expires <t> with “nothing to dispatch; do not respond to, re-dispatch, re-claim, or release a claimed item” (the same classification mid-turn steering gives a claimed item, dispatch=forward_to_owner). This is a non-error outcome.

  • Consuming (striking) the active agent:queue head requires an explicit completion signal for do [#id] directive heads, never an inferred one (#queue-strike-on-halt); synthetic/preset heads have an exact-id exception (#queue-head-consume-on-topic-id-regression). On the CLI finalize / write --commit path, consuming a do [#id] head requires a closeout flag — --done <id>, --backlog-gate <id>, or --backlog-edit "<id>=..." — that names the head id, or a genuine fresh operator prompt-target / do queue trigger in the cycle diff. A ### Re: heading that merely names a do [#id] head is not a completion signal, because a halt/refusal response names the head to explain why it is not being done. For a synthetic/preset head (a natural-language prompt carrying a trailing #preset id, not a bare do [#id] directive), the CLI path additionally consumes when the response heading topic resolves to exactly the head id (### Re: #spec-test-build-install-commit-push). An operator-pinned bare id head ([#id] / #id, with or without a :pushpin: / :round_pushpin: priority pin) whose id names a tracked agent:backlog / agent:review item is an id-backed directive, not a synthetic/preset head: it follows the same explicit-flag rule and must not be struck by a ### Re: #id log-check/halt heading (#zwn5), so an operator-drive live-verify item the agent can only log-check stays pinned for an explicit close. A registered prompt-preset id is not a tracked backlog/review item, so it remains synthetic and still consumes on a matching heading. A bare [#id]: note is deliberately different: the immediate colon makes the whole head’s durable queue identity free text, even when the same id exists only in agent:todo; claim/dispatch/node selection and answer closeout must preserve that classification. Its exact > **Queue prompt:** [#id]: note echo is answer proof, and queue consume --id / --ack-id refusals direct the operator to bare agent-doc queue consume <FILE>. The explicit --done <id> todo-own-id lifecycle remains the documented exception that may atomically check the todo and strike its matching annotated queue row. Adding the explicit verb (do [#id]: note) keeps the annotated head id-backed. The Codex Stop-hook auto-close path, which has no closeout CLI flags, consumes from a response heading on an exact topic match to the head prompt (### Re: do [#id]) or a topic that resolves to exactly the head id (### Re: #id for head do #id) — never on a heading with trailing modifiers such as ### Re: #id halt / ### Re: #id deferred.

  • When recovery reopens a closeout from durable capture or Codex last_assistant_message, an AlreadyApplied dedup outcome is still allowed to advance the snapshot and write_applied phase when the live document already contains the response but the snapshot does not. That keeps the subsequent commit boundary binary-owned instead of downgrading the turn to post-commit local drift.

  • A Codex prompt first observed after the preceding cycle reached committed owns a fresh cycle. For a replayable Stop payload, the hook must open that cycle before capture and drive the normal write/commit path; a new capture must never be keyed to the terminal predecessor.

  • The same adopt-current closeout path must also work when no pending/capture artifact survives but the live document already contains a fresh visible response block absent from the snapshot. repair and the Codex Stop hook may synthesize that visible response back into the normal dedup/write-applied/commit pipeline, but they must not leave the response as plain working-tree drift that still needs a separate manual commit.

  • Explicit agent-doc repair must also fail closed when the no-pending recovery pass still leaves a session-check interruption behind. A committed historical patchback may self-heal the snapshot from HEAD, but if later prompt-bearing user drift remains after that repair, repair must surface the same interruption instead of reporting No pending response found.

  • Fresh route-triggered starts must not treat prompt detection or pane-input consumption as sufficient success. After the initial trigger injection, the route path must observe a new per-document cycle state for that file before considering the start successful; otherwise it fails closed as a missed startup rather than silently idling. Harness-readiness detection should key off the real harness prompt shapes, not a generic shell > echo.

  • When route has already created a fresh pane for a document, a concurrent same-session registry rebind is not authority by itself. Fresh-start dispatch must stay on the new pane unless the new pane is invalid for that file, so layout/sync churn cannot supersede the just-created pane out of the visible agent-doc window.

  • When a Codex child exits after a stdin-forwarded Ctrl-D/stdin EOF or a terminating stdin-forwarded Ctrl+C, the supervisor must always route that clean exit through the restart-or-quit prompt, even if the run already recorded a committed document_cycle. Operator quit keys must never auto-restart Codex directly.

  • When Restart Agent re-resolves the document to a different harness, the replacement iteration is an authorized fresh spawn of that new harness. It must bypass same-harness exact-resume admission, clear adoption of the old child, and re-submit the owning document after the new prompt appears.

  • Supervisor stdin forwarding has one runtime implementation (#af88): on Unix it reads the raw stdin fd only after poll() selects it and watches a sibling stop pipe, so child exit can interrupt and join the forwarder before any restart/quit prompt reads stdin. PtySession must not expose a second blocking stdin.lock() forwarding path. Editor IPC connections are likewise bounded at both edges: callers time out a wedged connect_sync, and listener handlers close half-open clients that never deliver a complete request line.

  • When Codex definitively reports No saved session found with ID <id>, the supervisor must remove resume only if the current document still names that exact ID, then immediately launch and trigger a fresh session. If the current editor cut contains safely provable replay duplication, cleanup must normalize that structure and remove the matching pointer in the same expected-current authority write so malformed scaffolding cannot retain the dead ID. Before retrying cached resume launch arguments, the supervisor must also honor an operator removal already visible in document authority and relaunch fresh. It must not repeatedly back off and retry the stale ID. The pointer removal is best-effort and bounded: a stalled document write must not block the fresh relaunch. A Codex launch must never resume an id that belongs to another harness: hook-ledger bindings carry the recording harness, Claude-tagged bindings are never Codex resume candidates, and an id with a Claude transcript degrades a Codex resume to fresh. Ctrl+C during any crash-backoff interval must stop the supervisor even though no child currently owns stdin and the terminal is raw.

  • When a fresh/fresh-restart Codex child clean-exits before it ever surfaces an idle prompt and no forwarded operator quit key was observed, the supervisor must restart fresh instead of prompting the user. That exit is failed startup provenance, not an intentional quit.

  • When a routed Codex fresh-restart retry never regains a dispatch-ready prompt after the supervisor bounce, the binary must keep the optimistic fallback explicit: record the resulting startup_miss on the original routed pane, preserve the canonical absolute document path for later recovery, and avoid silently redirecting that retry through a replacement pane that never proved ready.

  • Route dispatches into an already-running pane must enforce the same fail-closed contract whenever the document already has unresolved prompt-bearing drift on top of a closed cycle. A consumed routed trigger is not enough; route must observe a newer per-document cycle state for that file before returning success, or fail closed instead of silently re-entering the stale pane.

  • When the baseline cycle is already committed, route/fresh-start acknowledgment must require a genuinely newer cycle id for that document. Same-cycle commit_already_current / other committed-state mutations do not count as proof that a new closeout cycle started.

  • Template writes and compact exchange must keep conversation content inside agent:exchange: a safe escaped ## User / ## Assistant / ### Re: tail is repaired automatically before snapshot/write, and the same repair path must also pull prompt-target blocks back inside exchange when they were typed after <!-- /agent:exchange --> but before sibling markdown section breaks such as ### / ## Pending. Before compact’s integrity gate, one byte-identical copy of the latest complete queue-prompt/response turn may be removed from agent:review only when the same turn is already present in agent:exchange and deletion reconstructs exactly one ID-backed - [/] [#id] ... row; non-identical copies, repeated matches, code/comment examples, and invalid row reconstructions remain fail-closed. Ambiguous mixed trailing structure still fails closed instead of being committed malformed. Comment-only or scratch-note content without escaped conversation headings stays outside agent:exchange; ordinary multiline HTML comment bodies (<!-- ... -->), including transiently unterminated comment tails while the user is typing, are ignored by escaped-tail scanners and prompt-bearing drift checks even when the comment text looks like a prompt. During final template reconciliation, complete post-exchange HTML comments remain user-owned scratch containers; duplicate or near-duplicate prompt text inside those comments is scrubbed while preserving the shell only when the duplicate line was not already present in the pre-response baseline/snapshot. After that safe scrub, any remaining duplicate prompt residue in freeform post-exchange Markdown outside tracked components is an invalid closeout/route state and must fail closed instead of being silently committed or dispatched.

  • Template exchange appends must keep response headings block-separated from the previous response body. When the appended agent:exchange content starts with ### Re:, both boundary replacement and fallback append paths must insert a blank line after non-empty prior exchange content so Markdown renderers never join the new H3 heading to the previous paragraph.

  • Template/CRDT closeout must also clean up answered raw prompt-target lines that were typed inside agent:backlog / legacy agent:pending: after the response is merged into agent:exchange, only the newly-added prompt-target lines are removed from the backlog component. Normal tracked backlog additions and backlog/review state changes remain part of the closeout.

  • Queue cleanup must treat an indented Markdown continuation at or beyond a completed inline queue row’s content column as residue owned by that completed row, so the continuation drains with it. Unindented, shallow, or otherwise unowned freeform operator text must continue to block lossless cleanup (#queuemultilineclear).

  • A multiline tracked-work add must own its entire payload as one item: the first line is the item text and every later line is an indented continuation. Rendering an add may never create flush-left non-item residue inside agent:backlog / agent:icebox. Lazy backfill may remove a complete fenced terminal transcript only under the narrow agent-doc invocation signature (› agent-doc ... or an absolute .../agent-doc start ...), must preserve incomplete/ordinary fences, and must report removed text through the existing auditable drop path (#componentresidue).

  • That template-write repair path must also handle duplicated-close failure shapes: if a merged document still contains the real <!-- agent:exchange ... --> opener but later hits a second <!-- /agent:exchange --> after safe escaped response content, the binary must move that escaped content back inside the real exchange block and drop the stray duplicate close before the final guard/commit boundary. If the text between close markers is only a duplicated template scaffold, that scaffold is dropped. If the duplicated scaffold is mixed with live prompt text, closeout fails closed with a typed flow::document_mutation event, and editor-visible normalization also rejects the shape, instead of moving or deduplicating that live text automatically. Ambiguous duplicate-close suffixes still fail closed.

  • When the user-added diff explicitly requests compact exchange, template/CRDT write-back must force agent:exchange replacement semantics for that turn instead of inheriting the component’s normal append mode. A compaction checkpoint summary must replace the superseded exchange body, not layer on top of it.

  • agent-doc compact <file> --component exchange --commit computes against Lazily current state and submits one expected-current canonical intent. An attached document is updated only through its PID-scoped editor endpoint; a detached document may project directly to disk. If the editor-visible and disk projections lag, compact persists the exact live/committed targets as a durable continuation; the controller completes snapshot/commit after the matching authority+disk projection clears the retained write. The initiating request receives the typed accepted retained_pending result and exits successfully, which says its compact is in editor delivery, will commit automatically after delivery settles, and must not be rerun. A repeated request while that continuation exists instead returns the typed nonzero already_pending outcome without another write and keeps the bounded-timeout rerun guidance. Neither pending outcome may claim HEAD; only verified completion returns committed. A controller-owned 30-second deadline retires an unsettled continuation through an identity-fenced timeout receipt, allowing the operator to rerun compact without restarting the editor; a late timeout cannot retire a newer continuation. One plane, a stale or divergent projection, and replay of an already-consumed exact projection cannot commit or duplicate the identity-fenced completion Effect. The initiating command does not poll or request an editor save/ACK. Reposition is the shared reposition intent, never a queued file patch. VCS refresh is observational and cannot invalidate an already-durable compact commit.

  • Editor refresh and reload work is bounded by the affected document. The typed refresh_vcs payload includes its absolute file path; JetBrains dirties that file only and VS Code refreshes only its containing repository, with no workspace-wide VFS/VCS refresh fallback. JetBrains installs one split-tree-filtered AWT layout listener rather than recursively attaching container listeners, discovers nested native endpoints only when a Markdown file from that root is open, and stops inbound native callbacks before disposing CRDT managers. Callback threads must never block indefinitely waiting for an IntelliJ read permit: editor-owned objects are captured on the EDT without blocking the caller, then native/CRDT work continues on pooled executors.

  • Agent-doc filesystem-event consumers prefer the platform watcher but must preserve liveness when the shared account-level watch quota is exhausted: a native MaxFilesWatch result switches the watcher and every existing registration to bounded polling, while unrelated watcher errors remain visible. Moving JetBrains JNA bindings into another process is not an inotify remedy because Linux accounts watch capacity per user; the bindings allocate no filesystem watcher, and IDEA already runs its own native watcher process.

  • Reconciliation distinguishes operator edits from remote CRDT application using Lazily operation provenance in the same document lineage. There is no live-buffer digest sidecar and no older-plugin compatibility branch; a plugin lacking the required registration, intent, and receipt capabilities is rejected as incompatible.

  • A bare compact exchange directive in the current diff must not complete through the normal response write path. run, write, and finalize fail closed with a binary-compaction handoff (agent-doc compact <file> --commit) unless the turn is already using that compaction path.

  • The direct-exec Codex/OpenCode instruction path must run agent-doc session-check <file> after final response persistence (finalize or manual write --commit) and fail closed when the check reports an open cycle, unresolved prompt-bearing user edits with no newer cycle start, or a likely direct assistant patchback that bypassed the binary write path. The only self-heal exception is already-committed historical snapshot drift proven by HEAD. Connected clients use the terminal finalize report instead of invoking this companion command.

  • Closeout lifecycle, capture, prompt, and coordination state is read from state.db, not optional files. Logs are diagnostic and snapshot/CRDT files are recovery projections; their absence cannot create lifecycle proof. An unavailable ledger fails closed.

  • Harness-native agent-doc entrypoints (/agent-doc <FILE> in Claude Code, agent-doc <FILE> in Codex/OpenCode/direct-exec, and equivalent direct entry forms in other harnesses) must be treated as the start of the binary-owned response cycle rather than as a generic document-editing request. A turn started that way must not be reported successful until it crosses finalize or write --commit, and “not committed” is only valid when the user explicitly asked to leave it uncommitted.

  • When session-check fails on an uncommitted closeout (snapshot != HEAD, committed-cycle exchange drift with a newly appended assistant response marker, or a direct response patchback with no matching cycle), the diagnostic must include any tracked side-effect files and the explicit follow-through command agent-doc write --commit <FILE>.

  • Session-document closeout owns backlog consistency too: when a response clearly completes an existing #id backlog item, the same closeout cycle must record the matching --done <id> mutation or fail before commit. The done guard must scan the response body, including ### Re: do [#id] headings with later completion evidence, but it must exclude ids explicitly kept open by same-cycle backlog mutations such as --backlog-edit, --backlog-gate, --backlog-ungate, --backlog-reorder, or gate-type edits. Warn-only post-commit stale-backlog states are not acceptable as the default for real session docs.

  • When the active prompt contract requests backlog capture directly or through prompt-preset expansion (for example #code-review chaining into #follow-up-backlog), the same closeout cycle must either record backlog mutations, explicitly state that there were no actionable follow-up items to capture, or fail before commit. Findings-only review prose must not silently commit against an unchanged backlog. The backlog-request signals (tasks, todo, backlog, recommend, recommendations, next steps, action items, what's next, what's left, what remains, what else, what should we do, what do we need, add to backlog, add to pending, follow-up backlog, follow-up items, and the singular task only as a new item: a task, new task, another task) match whole prose words, never substrings: fenced code blocks and inline code spans are not prose; a whitespace-delimited chunk that is a path, URL, file name, hashtag id, mention, :: path or key=value pair is not prose and no phrase spans it; a word containing _ is an identifier; a hyphen joins a word, so a kebab-case token matches only a signal spelled the same way; and the last word of a signal may carry an inflection suffix (todos, recommended). So tasks/agent-doc/x.md, src/todo_list.rs, #todo-id and `tasks` do not arm the requirement, while “add a task for X”, “track this as a todo” and “add these to the backlog” do. The requirement is scoped to the queue heads the cycle actually drains (#capturegatedispatched): a queue line that rides in the cycle’s diff for a head the cycle does not drain — a completed (struck) head closed by an earlier cycle, a head an active worker claim or a queue subagents hold owns, or a head preflight lists in queue_subagent_dispatch for this cycle to dispatch — does not make the cycle require backlog capture, because that capture belongs to the cycle that closes the head. A worker’s report on such a head is scoped out the same way: the binary-authored subagent completion cell that queue report-complete appends to agent:exchange (heading, fixed body, keyed marker) quotes the queue item verbatim, but it is agent-doc bookkeeping, never an operator request, so none of its lines can make the cycle require backlog capture (the 0.35.529 cycle-1792527508436 regression: a reported head’s cell heading quoted … haiven-dev tasks/fpe.md …, and the bare tasks signal armed the gate). A dispatch-only coordinator cycle therefore needs neither a suppression marker nor a filler backlog item. The scoping is fail-closed: preflight evaluates both the admitted diff cut and the post-maintenance queue projection, and a line stays in scope when its normalized text also appears as a drainable live head, as any other line outside a queue component, or in the harness prompt, or when the queue cannot be parsed; a completion-shaped heading without the fixed body and keyed marker is ordinary text and stays in scope. Preflight logs preflight_backlog_capture_scoped_out when scoping removed the requirement. Follow-up heads the cycle inserts with agent-doc queue follow-up are tracked work: they record queue_followups_added_this_cycle on the cycle state and satisfy the generic requirement exactly like a --pending-add, at the pre-write, pre-commit, and post-commit gates. They do not satisfy an explicit backlog target, and they do not silence the strict uncaptured-recommendation heuristic, so a response that lists recommendations it never tracked is still refused. Preflight fixes the requirement, but the coordinator may claim a head preflight left drainable (not claimed, held, or listed in queue_subagent_dispatch) and start a worker for it mid-cycle; that head’s capture then belongs to the worker. Preflight therefore records the drainable heads the requirement rests on as backlog_capture_heads on the cycle state, named as the live head a claim holds (a free-text head queue maintenance promoted is recorded as its do [#id] head), and the pre-write, pre-commit, and post-commit gates release the generic requirement once every recorded head is worker-owned in the current document: an unexpired claim whose worker started (Running) or reported (Reported, awaiting integration), or a head with a binary-attested completion cell. A dispatch claim no worker acknowledged, a lost attempt, or a subagents hold is not worker ownership, and a part-claimed set keeps the requirement armed; the gates log closeout_backlog_capture_released on release. The recorded heads are only the ones that arm the requirement (a drainable head without a backlog signal is not behind it), and recording is fail-closed: when in-scope text that is not a drainable queue head also arms the requirement (an exchange prompt, a harness prompt line, or a head whose text also appears outside the queue), preflight records no heads and worker claims never release it. The release does not satisfy an explicit backlog target and does not silence the strict uncaptured-recommendation heuristic.

  • The pending-capture heuristic (heuristics.rs) must detect unconditional follow-up work — quantified remaining items (e.g., “18 remaining”), outstanding work, unfinished tasks, and unresolved current bugs/issues that the response frames as still needing follow-up — even when the response frames continuation as mutually exclusive options or blocked-with-choices. A single high-confidence unconditional follow-up indicator (confidence >= 0.7) is sufficient to trigger the guard at count=1; the count >= 2 threshold only applies to lower-confidence patterns.

  • The Codex install surface writes repo-local .codex/hooks.json and .codex/config.toml; UserPromptSubmit / Stop session tracking is stored in each relevant project state.db, never mirrored into ambient ancestor roots or filesystem session files. The single installed UserPromptSubmit command must durably track the session before running preflight for a valid harness-native agent-doc <FILE> invocation, despite injected preambles, and must emit the cycle contract plus its final success marker as Codex turn context. Ordinary prompts emit no context; tracking or preflight failures must not emit the success marker. Latest-prompt lookup skips malformed ledger rows. A refused preflight receipt fences Stop before capture, closeout recovery, or queue continuation; a new prompt clears it and late receipts are exact-turn fenced. Stop may finish an open cycle only from a validated single-assistant closeout; transcript-shaped or empty tool-only payloads remain diagnostic blockers and cannot count as response completion. Both installed lifecycle entries carry explicit outer timeouts. Stop must return a valid fail-closed response within its shorter binary budget, attempt captured-closeout resume at most once, and leave continued retry ownership with the route-owned supervisor. After strict repair replay, Stop and repair reuse the terminal closeout proof only for the same committed cycle/capture and unchanged live, snapshot, and Git content; later edits or missing proof require full closeout.

  • When Codex repeats the exact agent-doc <FILE> trigger as steering inside the same nonempty turn, an existing successful admission receipt may join the document’s still-uncaptured preflight_started cycle without rerunning preflight. Reuse requires exact session, turn, prompt text, and canonical document identity; a changed prompt, turn, document, refused receipt, captured response, or any other cycle phase follows normal fail-closed admission.

  • A controller-published retained-delivery convergence edge must re-arm captured-finalize recovery just like a closeout cycle-state edge. Delivery can become exact without changing cycle phase; the supervisor must therefore retry the same durable capture after that edge, retire any verdict derived from the prior delivery state, and keep timed effect retries separate.

  • Non-streaming Codex child runs must persist only the final assistant closeout for the active turn. If codex exec --json emits multiple item.completed agent_message events, agent-doc selects the last assistant message before turn.completed as the durable response body; if multiple assistant messages arrive without a turn.completed boundary, the run fails closed instead of committing progress/status chatter as a transcript-shaped patchback.

  • The shared instruction surface must treat MCP auth / OAuth tool flows as sub-steps inside the current agent-doc turn. A browser/authenticate step may pause the turn, but it does not satisfy the response boundary; the same turn still must finish through connected agent_doc_finalize or, on direct exec, finalize / write --commit plus session-check, or fail closed.

  • When that replayable Codex Stop payload contains a safe patch:backlog mutation, the backlog normalization must run before the payload is saved to the pending/capture ledger. Recovery must replay only the stripped exchange-safe payload, not the raw backlog patch, so later closeout recovery cannot fail just because the live backlog has interleaved section headers or other preserved non-item structure.

  • The atomic CRDT response-cell fast path is valid only when the entire exchange patch parses as canonical assistant-only response nodes. Template-compatible legacy heading depths such as ## Re: and mixed response/prompt patches must bypass that fast path and continue through compatibility patchback without issuing a controller response_cell_add; a deterministic response-cell parser rejection must not wedge a retained response_captured cycle into identical recovery retries.

  • The instruction surface must also preserve response-ordering: requested implementation / verification / build-install work completes before final response persistence, and once finalize / write --commit returns, only a required direct-exec distrust check, failure recovery, and final reporting remain for that turn.

  • The shared instruction surface must treat imperative user edits inside the document as executable directives for the underlying repo work. That includes explicit command-like lines (do #id, run tests, build + install, commit + push) and actionable pending-item prose that begins with an imperative verb (for example [#n8q4] Fix the cross-repo ...). For path-scoped commit + push work it must also require an explicit fail-closed staging contract: resolve the intended non-session path set, stop on any stage failure, verify the staged diff still matches that set, and commit only that validated set. It must not require the user to repeat those directives in chat, and it must not append “starting/continuing” status prose when the requested work has not actually happened. The binary run / write / finalize path must reject status-only or meta-only replies to those directive diffs unless the response contains either concrete execution evidence or a concrete blocker.

  • The project controller surface owns route/start/sync authority. agent-doc controller status --ensure lazily launches one project-local controller through .agent-doc/controller.sock, guarded by .agent-doc/locks/controller-launch.lock. Bootstrap epoch, launch mode, generation, handoff state, prior PID, and binary identity live transactionally in the .agent-doc/state.db controller_bootstrap row; there is no controller-state compatibility file. Controller launch skips a stale removed executable and falls back to the invoked command or agent-doc on PATH. RPC reads are bounded, an idle client cannot block unrelated clients, and stale-binary replacement promotes a private-socket generation before reaping verified same-project duplicates. Start, route, sync, and controller-backed admin operations use typed generation-CAS requests and receipts. Queue pause/drain and backpressure are durable SQLite state; explicit operator reopen bypasses a deliberate auto-drain pause once, while stale-supervisor churn-stop still forces recovery first.

  • A quiescent supervisor must not replay the full idle reconciliation pipeline on every 500 ms watch tick. Once queue state has been observed and the actor is ready, the tick retains only local installed-binary and historical-zombie liveness probes; pane inspection, full CRDT text/controller reads, and stable blocked-head retries are throttled to a five-second liveness pass. Busy work, in-flight clear settling, and installed-binary staleness bypass the throttle immediately. Binary freshness resolves the installed command independently of current_exe; when the running image began at a different launchable path (for example a PyPI versioned cache payload behind a stable bootstrap entrypoint), replacement is measured against the installed command’s launch-time identity/inode rather than treating the two unrelated paths as permanently stale. A stale supervisor must execve onto the installed binary at the first checkpoint with no supervisor IPC receipt handler in flight, regardless of harness turn/prompt stage or an open durable agent-doc cycle; the live harness child and cycle checkpoint survive the exec.

  • A detached controller is scoped to the exact project-root directory incarnation that requested it. On Unix, startup retains an open handle to the original directory for the controller lifetime so deletion cannot make that inode immediately reusable by a same-path replacement. If the directory disappears or is replaced during startup or while serving, the controller fails closed instead of recreating or attaching to a deleted temporary root. A serving controller also records the file identity (device, inode) of the socket it bound. A stable public controller with no self-handoff in flight or promoted exits when <root>/.agent-doc/controller.sock is unlinked or names another listener, because no client can reach it there (#detachedexitci). This covers a root that survives removal with its original inode: remove_dir_all unlinks the socket, a concurrent writer recreates .agent-doc/state.db, and the final rmdir fails. A promotion rename keeps the identity, so a promoted replacement still matches. Both checks run first in each idle tick, before maintenance can reopen state in the torn-down root. A controller that exits on either check leaves the pathname alone, since it may now name another controller’s socket. The OS process-exit watcher’s poller stops when its serve loop returns. Supervisors that survive an in-place execve must also reap already-exited historical agent-doc controller children without consuming the live harness child’s exit status.

  • Harness authority must be captured before destructive lifecycle transitions. In particular, when document agent: metadata is absent, manual new-session start reads the operator actor projection (including a closed recovery record) before closing stale actors; dispatch-ready filtering and cleanup cannot erase the only surviving Codex evidence and cause fallback to a configured Claude default. If both document and actor projections are damaged, start --harness <name> is explicit operator recovery authority: it is transported through tmux re-exec and actor publication without writing the document. Status display follows the same evidence order—explicit document authority, durable actor authority, then ambient detection—so ambient harness context cannot conceal a wrong durable actor. Supervisor hot-reload must resolve the installed command independently of current_exe; a launchable source-build image is a fallback candidate, never proof that the installed binary has been selected for a stale-inode recycle. A child-preserving hot-reload (execve_preserve_child) may hand over only a live child that nothing has condemned: it refuses while the published child has exited or been reaped, or while a stop or child-replacing restart (for example an operator clear’s fresh restart) is pending, and the host loop serializes reaping against the handoff so a reaped PID is never adopted by the replacement image (#reexecdeadchild).

  • The project controller actor store writes .agent-doc/state.db as the sole persistence boundary. The documents, actor_transitions, and registry tables carry session actor and pane-binding state; no actor or registry JSON projection participates in runtime resolution. A registry metadata save updates registry_entries only: omission from a caller’s partial registry projection is never lifecycle evidence and must not close, clear, or append a transition for a documents actor row. Sync column memory lives only in layout_states rows; there is no legacy layout import or compatibility file projection.

  • The project controller Phase C supervisor path is controller-owned: agent-doc start must lazy-launch/connect to the project controller, register the starting actor generation and supervisor lease, and report prompt-ready, busy dispatch, waiting-input, blocked, and closed lifecycle facts through controller IPC. Lifecycle reports include session id, pane id, and generation; stale reports fail closed before mutating the authoritative actor record. When session_id and pane_id both match the current actor record, a stale expected_generation is allowed through: the generation bump was from a same-owner rebinding (compact/restart/route), and the transition proceeds using the current generation rather than rejecting the legitimate owner. Supervisor state probes include the actor session id, pane id, and generation so session status / doctor can refresh the controller lease heartbeat and runtime_state from a live matching supervisor without adding a duplicate actor transition. Route readiness waits for a starting authoritative actor must stop immediately when the supervisor refreshes that actor to closed or blocked; those terminal states are the actionable diagnostic and must not be reported as a startup-ready timeout.

  • Operator Clear Session Context is a harness-context operation and must not wait on document convergence (#clearcapturedcycle). When it needs a fresh child (Codex, waiting_input, no live child) and the document’s cycle is open, the supervisor replaces the child at once only if the actor is Ready and the cycle’s response is durably captured, because the remaining closeout is the supervisor’s keyed captured-finalize resume and the retained write stays durable; any other open cycle latches the clear until it closes. A latched clear is reported as accepted but not applied (never “Cleared”), and a later supervisor-only continue recycle must not overwrite the latch. The relaunch after a clear that crossed such a captured cycle must not re-submit /agent-doc <file> (#clearsessioncontext): the closeout is the supervisor’s, so re-running the document would only make the fresh agent restate the retained-closeout blocker the old context already reported. Only an uncaptured open cycle re-triggers; queue heads and operator steering stay with the idle-queue watch, and Restart Agent keeps re-triggering. See specs/supervisor.md.

  • agent-doc session status <FILE> must include direct live-pane evidence beside projected actor/controller state: pane id, evidence source, pane current command, recent meaningful output tail, and an alive-idle / alive-busy / closed-clean / projection-stale classification. If direct evidence is alive-idle while actor, supervisor, or controller lease projection still says busy, the session operator path reconciles the actor/lease back to ready before printing status or clearing. For Codex operator status/clear, direct evidence that contains only Codex status/footer chrome, such as the model/cwd/context line, and no prompt input or busy cue is alive-idle; a bottom Codex model/cwd/context footer is also idle evidence even when older visible transcript text remains above it, as long as there is no protected composer state or busy cue. Codex idle placeholder prompts such as › Ask Codex to do anything, › Explain this codebase, and safe generated placeholders ending in in @filename, for @filename, or on my current changes are also prompt-ready evidence when the pane does not show an active Working (... esc to interrupt) cue. Dynamic Codex composer suggestions rendered with SGR-2 are likewise idle placeholders even when their text is not in the static phrase list, so supervisor readiness and auto-trigger verification must preserve ANSI until classification; the same undecorated text remains protected drafted input. Route dispatch still requires a real dispatch-ready prompt before injecting a reopen; a Codex footer alone never proves dispatch readiness. File-scoped session restart-supervisor <FILE> must fail closed when direct pane evidence is alive-busy or when the actor is still starting and the document changed after the last committed cycle; those refusals must point operators to --force. File-scoped session restart-supervisor <FILE> --force is the explicit discard path and may interrupt a busy live pane or bypass the starting-actor guard before requesting the supervisor restart. File-scoped session clear <FILE> is an explicit operator clear request and must not run the starting-actor readiness guard: it must not fail solely because a pane is classified alive-busy, because pane_current_command is an agent wrapper such as agent-doc, because the actor projection still says starting, or because the document has prompt-only drift after the last committed cycle. Clear may refuse protected prompt-input states such as a permission prompt, queued draft, shell search, drafted user input, or clean-exit restart prompt, and may block explicit busy cues such as an active Codex turn, hook-review prompt, or help/usage screen; those refusals must point operators to agent-doc session interrupt-clear <FILE> for the explicit discard path. Codex placeholder text rendered dim by the TUI is idle chrome, not drafted user input, even when the plain text is not in the built-in placeholder phrase allow-list. If session interrupt-clear times out after that explicit discard path, its ops event and user-facing error must report the final blocking live-pane state, evidence source, prompt-ready value, current command, and recent pane tail instead of collapsing to a generic timeout.

  • The project controller Phase D route path is controller-owned: before route submits a managed or dispatch-only reopen to an actor-owned pane, it must record a controller dispatch attempt for the current session id, pane id, generation, and command kind. Stale session, pane, or generation requests fail closed before tmux/supervisor input is submitted. A starting actor is not dispatchable until it refreshes to ready; route may promote a healthy starting actor to ready only after the current generation’s live pane shows a harness-specific dispatch-ready prompt, and if it remains starting after the bounded route wait, route must fail closed before tmux or supervisor input is submitted. If the same pane/generation later shows dispatch-ready prompt proof after route has marked it blocked for starting_actor_timeout, route may clear that timeout and promote the actor to ready before submitting. Reads of this per-document timeout projection must use the indexed (document_hash, fact_type, id) state-event path and must not replay the project-wide state-event ledger; editor focus polling may exercise route readiness while otherwise idle. Startup wait failures must persist a single typed diagnostic with elapsed time, pane id, generation, actor state, supervisor health/runtime state, prompt-ready status, and last lifecycle transition so the editor route error points at the exact failed phase. The current-generation ready-prompt barrier must also accept an idle_pane_reconcile transition as ready proof (#monster60stimeout): the supervisor’s idle-watch only records that reason after supervisor_pane_has_busy_cue returns Some(false) (direct pane evidence that the pane is not busy), so the route must not wait the full 60s timeout when the edge-triggered pty redraw missed re-emitting a recognized prompt shape but the supervisor already proved the pane idle.

  • When a document explicitly changes agent: to another harness, a healthy authoritative actor record for the old harness must not hard-fail future Run Agent Doc routes with “bound to harness X, not Y” (#actor-switch-rebind, #harnesshotrebind). Route treats that explicit frontmatter change as a typed boundary handoff: it accepts the operator request without dispatching any prompt bytes into the old harness, preserves an active old-harness turn, and lets the supervisor idle watch spawn the newly resolved harness at the first safe prompt_visible && !turn_active boundary and auto-trigger the owning document exactly once. Repeated routes coalesce with an in-flight handoff. A paused queue holds the accepted handoff until queue resume and must not require a supervisor restart. The supervisor IPC state payload reports current_harness; when the live runtime has already switched but the actor record is stale, route repairs that record and proceeds instead of starting another handoff. For an old-harness actor that is not a live authority (closed/blocked, or its pane is no longer dispatch-ready), route falls back to the normal create/rebind path. A healthy live authority is never cold-replaced (mismatched_authoritative_actor_can_be_replaced remains false), and agent_change_restart: false remains an explicit fail-closed policy. Without an explicit document harness change, a healthy ready actor from another harness also remains fail-closed.

  • Harness conversation identity is stored as a resume: map with explicit claude, codex, and opencode entries. Every launch, same-harness restart, controller cold recovery, direct run, and stream reads only the selected harness key; recording or clearing one harness id preserves the other harness histories. The producer harness is an explicit input to every mutation: managed paths use the running backend, and manual resume-id requires --harness; neither may infer the target key from the document’s possibly switched agent: value (#frontmatterintentmisclass). Ownership checks still inspect all entries so two documents cannot claim the same conversation. A legacy scalar remains readable only as the document’s active harness id and migrates into that harness’s map entry on the next managed resume write (#harnessresumemap).

  • Resumed agent prompts must restate the changed exchange tail as ordered user-authored prompt-bearing changes. The canonical subtypes are prompt_target, content_edit, recovery_artifact, and boundary_artifact. The turn-completeness contract is oldest-first: do not anchor only on the newest question, do not treat the turn as complete until each prompt_target item is answered or explicitly grouped into one response, and treat content_edit items as source-of-truth corrections while artifact items route to normalization/repair instead of ordinary conversation.

  • Prompt-cache replay metadata is part of direct-run prompt assembly. Only durable response contracts, harness-neutral instructions, turn-payload reading rules, cache-control metadata, and provider replay-key material may live above the cache boundary. File paths, queue heads, diffs, current document excerpts, status text, prompt-bearing change sections, compaction/accretion diagnostics, bounded context packs, session ids, and recovery markers must stay in the volatile suffix after the boundary. The provider cache key must include the agent-doc key version, routing-affinity hash, and stable-prefix SHA-256; the volatile suffix must never contribute to that key. The stable prefix SHA-256, provider cache key, cache-control policy, and routing affinity must remain identical across consecutive resumed agent-doc turns whose changes are only volatile session churn such as no-op closeout diagnostics, status edits, queue-head/list churn, boundary markers, diffs, or bounded context packs. Durable response-contract/instruction changes must change the stable-prefix fingerprint and provider cache key, even when the routing affinity is held constant.

  • Prompt-cache session-cost diagnostics must make cache misses explainable without raw JSON analysis. Given two cost samples, miss ranking compares stable-prefix fingerprint, adapter state, routing affinity, cached-input token delta, and creation-token spike, then reports ranked causes with the highest-impact invalidation cause first. When no prior sample is available, the diagnostic must still print the current fingerprint, adapter state, routing affinity, unknown token deltas, and an explicit baseline_required rank state so later history persistence can feed the same ranking path. The token/performance gate persists prompt-cache effectiveness samples as JSONL records keyed by provider, harness, and real transcript id (for example Codex/OpenAI and Claude/Anthropic transcripts). Trend checks must compare the current sample with the latest matching workload history and fail with an operator-readable summary that includes provider, harness, transcript id, previous observation time, cached-input delta, creation-token spike, thresholds, and the same ranked miss causes used by the session-cost diagnostic.

  • Prompt-prefix preservation is part of that same contract: append-mode exchange canonicalization must derive required ❯ transcript prefixes from the prompt-bearing classifier (not a separate ad hoc heuristic). That invariant still applies when repair dedups an already-present template response: AlreadyApplied is a canonicalization-capable outcome, not proof that transcript normalization can be skipped. Prefix repair must remain structurally scoped to prompt runs: once a ### Re: / ❯ ### Re: / ## Assistant response block starts, assistant prose and verification/list bullets must not become ❯ targets merely because their trimmed text matches a normalize_prefix_lines entry; targeted repair may leave the response block only when the line matches the explicit target set and also starts a prompt run, or when a boundary/component marker has already closed the response. session-check must fail closed when a bypassed response leaves bare prompt-target lines in the changed exchange tail, and when prompt-bearing user edits exist without any newer cycle start at all.

  • The prompt-bearing classifier itself must suppress stale-boundary prompt runs that are already visibly answered by a later response in the same changed tail, including raw assistant completion prose without a formal ### Re: heading. preflight, plan, routed admission projection gating, prompt-prefix normalization, and write-path snapshot decisions must all consume that same filtered actionable list instead of re-deriving their own stale-tail heuristics.

  • Unstarted exchange-prompt detection must not be snapshot-gated on a fresh session (#codex-exchange-prompt-no-dispatch). The queue path activates independently of any cycle snapshot, so a queue write dispatches Run Agent Doc even before the first snapshot exists; the exchange path keys off the snapshot↔file diff. When no snapshot exists yet, first_unstarted_prompt_bearing_change must fall back to the committed HEAD blob (then to an empty baseline for untracked docs) so a freshly typed exchange tail prompt is still detected and routed, instead of leaving exchange writes inert while the same text in agent:queue starts a turn. The HEAD fallback stays exchange-scoped — queue components remain stripped from this diff and keep their own activation path.

  • Component/comment parsing must never panic on valid UTF-8 document content. Ordinary HTML comments near multibyte glyphs such as ❯ must either parse normally or be ignored as prose; malformed agent markers still surface as structured parse errors instead of byte-boundary crashes.

  • The state backbone is the Cycle State Machine plus typed event-sourced projections, not one global FSM for every subsystem. The cycle FSM owns only turn closeout phases. Queue, document, transport, supervisor, route, and proof state must be represented as typed append-only facts reduced into deterministic projections, with live mutation guarded by owner actors, epochs, and leases. Local FSMs are allowed for small closed subdomains, coroutines may express linear protocols, and behavior-tree-style logic may be used only as policy over projections; GOAP/MPC-style planning is not the durable state model for correctness-critical closeout.

  • FlowCore is the typed ownership layer for the direct session cycle, routed reopen, closeout, document mutation, operator clear, and orchestration batch hot paths. The first phase is mirror-mode: existing commands still execute behavior, but high-risk branches emit flow_event ops lines with flow, stage, outcome, and tokenized reason, and agent-doc ops summary groups failures by flow stage. The same summary must also emit ranked bug clusters that correlate closeout/captured-response drift, route/start replay gaps, Codex warning storms, SQLite counts, cross-harness markers, session-review guardrails, and working-tree drift by file/session/cycle/thread keys. Closeout/document-mutation guard reasons, including pre-write/pre-commit pending capture blocks, patchback parse shapes, repair recovery boundaries, committed-cycle late fallback rejection, and disabled full-content decisions, must use FlowCore enums or document-mutation decision helpers instead of adding more free-form proof strings. New tactical fixes in these hot paths should prefer FlowCore enums and pure decision helpers over adding more free-form proof strings.

  • The FlowCore regression gate must remain executable, not only documented. Routed-reopen prompt-ready and dispatch-start failure reasons are represented by RoutedReopenGuardReason, and the hot-path source-token budget test must fail when route/write/preflight/session-check/orchestrate/git/repair add unaudited guard_, proof=, proof_scope=, reason=, flow_reason=, or accepted_only tokens. A failing budget is resolved by promoting the new branch into the owning FlowCore enum/event or by updating the budget with the FlowCore audit complete.

  • Agent harnesses, not git hooks, own full-suite verification after changes. The shared instruction surface must require explicit full-project verification before final response persistence whenever code, tests, build logic, or instruction surfaces changed.

  • Test-bearing harness turns must review the live tmux CI leg with gh run list --workflow CI --limit 1. The expected local reproduction command is make tmux-ci when the CI leg fails after runner startup; any failure fix should include deterministic SimWorld coverage for the regression class when feasible, so the default suite can catch modeled failures before relying on live tmux. Queued or in-progress CI runs are recorded but do not block turn closeout unless the user explicitly asks the agent to wait. Empty-step Actions jobs with no logs because GitHub never allocated a runner, such as billing/spending-limit exhaustion, are external CI-start blockers rather than tmux/code regressions; closeout should record the CI annotation and the local verification evidence.

  • Live tmux test launch helpers must prove that the shell executed their readiness probe through an external side effect. A shell-shaped foreground process or probe text in capture-pane is insufficient because terminal echo can precede command acceptance.

  • A failing full-suite verification run must not be waived off as “unrelated” or “flaky”. If the suite is red, the turn must either fix the failing tests or report a concrete blocker and capture the follow-up work in backlog before closeout.

  • make test should use a parallel test runner when available. cargo-nextest is preferred because it runs test binaries concurrently while preserving Cargo’s integration-test environment, with a doctest pass afterward. Plain cargo test --all-targets remains the fallback when the parallel runner is unavailable.

  • A failing test step is never lost to a deleted log (#flakyintegrate0494). Every step make test/check runs (nextest, the batched cargo-test packages, doctests, the plain cargo-test fallback, sim-medium, sim-net) runs through scripts/test-run-record, which keeps its combined output, exit status, command line, a snapshot of other test runs alive at its start (pid, working directory, load average), and, for nextest, a copy of that run’s JUnit report (nextest’s junit.xml, which stores each failing test’s stdout/stderr) in one per-invocation, per-checkout directory tmp/test-runs/<UTC start>-<make pid>/ (TEST_RUN_ARTIFACT_ROOT), outside target/ so cargo clean and disk sweeps cannot remove it. A JUnit report left by an earlier run is deleted before the step starts, so a run is never filed with another run’s report. A failing step prints the directory it kept. Pruning keeps the newest AGENT_DOC_TEST_RUN_KEEP (default 20) runs and any run with a failing step among the newest AGENT_DOC_TEST_RUN_KEEP_FAILED (default 100). An intermittent failure is diagnosed from that record and its nondeterminism fixed; it is never rerun to green.

  • Tests never mutate the process-global CODEX_THREAD_ID to bind an active Codex session; they pin it per test thread through agent_doc_codex_hook_io::override_codex_session_id_for_current_thread, and the Codex Stop-hook test fixture pins “no session” by default. A parallel test’s binding, or a test run launched from a Codex pane, must not change another test’s active-session drift classification (#stopreopenflake).

  • The full local gate is hermetic with respect to checked-in editor locks and build-path selection (#check-hermetic-target). make check bootstraps the locked VS Code dependencies when node_modules is absent or stale, honors CARGO_TARGET_DIR for both AGENT_DOC_BIN and native-plugin library discovery, and defaults test scratch files to a short writable non-project directory (preferring /var/tmp) while preserving an explicit TMPDIR override.

  • Tests never adopt a real project as their root (#testisolationtests). .agent-doc project-root discovery honors AGENT_DOC_ROOT_CEILING_DIRECTORIES, a PATH-style list of absolute directories with GIT_CEILING_DIRECTORIES semantics: the walk examines its starting directory, then each parent, and never climbs into a ceiling directory or above it; relative and empty entries are ignored. Unset, production discovery is unchanged (including users whose $HOME/.agent-doc serves as a lazy root for scratch files). A cargo test binary with no explicit ceiling bounds its own in-process discovery at its temp root. make test/check and the other test targets, and the nextest test-isolation setup script, run scripts/check-test-tmpdir, which refuses a TMPDIR that has an .agent-doc ancestor and exports the ceiling <TMPDIR>:<workspace> to every test process (an inherited ceiling is kept, but the guard appends this checkout’s own <TMPDIR> and workspace when it lacks them, so a list another checkout’s make exported never leaves this workspace unbounded; #checktmpdirleak) and the binaries and controllers they spawn, so a test tempdir under $HOME cannot write the operator’s ~/.agent-doc state.db, ops.log, proof ledger, or snapshots, or start a controller with --project-root $HOME.

  • Tests are never handed a live project either (#testisolationleaks). Discovery ceilings stop a test from walking up into a real root, but the /proc walks behind the install fan-out (controller_project_roots, controller_serve_pids, open_supervisor_processes) used to return every controller and supervisor on the machine. recycle_supervisors_all_projects_force_enumerates_without_error ran the real fan-out from inside each lib-test run. Each concurrent make check then checkpointed the operator’s live documents, so the test binary connected to the live editor sockets with a bare 0.35.509 hello (lib-test binaries carry no AGENT_DOC_BUILD_ID) and the editors rejected it as an IPC build mismatch. It also appended an install_fanout recycle request to every live project’s state.db, so open supervisors recycled with nothing installed (19:40, 19:56 and 20:27Z on 2026-10-15). A test process now has a runtime scope (agent_doc_fs::test_runtime_scope): std::env::temp_dir() for a cargo test binary (an executable in a deps/ directory), or the explicit AGENT_DOC_TEST_RUNTIME_SCOPE list. make test/check and the nextest test-isolation setup script export that list, so the agent-doc binaries an integration test spawns are scoped too. Cross-root discovery returns only roots and documents inside the scope. Driving a runtime outside it panics with #testisolationleaks: an existing controller socket connect, a controller recycle request, a supervisor recycle over IPC, a route-owned document CRDT checkpoint, an install recycle request, or a state.db open. A panic, not an error, so a fail-open fan-out cannot swallow the escape. A production process has no scope, sees every runtime, and never reaches a guard. The working directory is ambient too. A test’s working directory is its crate checkout, and the CWD session registry (agent_doc_session_registry_io::load/registry_path) used to open and create that checkout’s .agent-doc/state.db and state.db.lock; in the main checkout that is a live project’s ledger. agent-doc route pruned that registry against the configured tmux server before it checked the file, and prepare_editor_session ran a CWD project init. A test process whose working directory is outside its scope therefore has no CWD registry (cwd_registry_in_test_scope): load answers empty, CWD prune and claim validation are skipped, and an explicit load_in/save_in or a CWD project init outside the scope fails the test. Production, whose working directory is the operator’s project, is unchanged. process::tests pins the confinement with a positive control: a fake agent-doc start/controller serve process under the temp root stays discoverable, and one naming a root outside it does not.

  • Developer verification is two-tiered. make check-fast derives changed workspace packages and their transitive reverse dependents from Cargo metadata and validates only that affected scope plus relevant non-Rust surfaces. It never creates release proof. Release validation runs cheap version synchronization and editor-parity manifest checks before expensive suites, then independently reuses matching make check and make tmux-ci receipts. Receipt identity covers repository paths/bytes and toolchain versions, not index, commit, or tag metadata. Cargo targets remain worktree-local, make install-full honors an explicit CARGO_TARGET_DIR, and an available sccache may share only content-addressed compiler results across worktrees.

  • make check lints the whole workspace (#clippyworkspacegap): its clippy step runs cargo clippy --workspace --all-targets --all-features -- -D warnings. The workspace declares no default-members, so a bare cargo clippy selects only the root agent-doc package and leaves the other members’ tests, examples, benches, and every member the root does not depend on unlinted except by check-fast when affected. check-fast keeps linting only the affected packages; the authoritative gate never narrows its lint scope to the root package.

  • make check turnaround is measured, not guessed. Every Rust step shares one cargo build --workspace --all-targets (the feature resolution nextest’s workspace test build uses, which also uplifts target/debug/agent-doc and libagent_doc.so); steps select test executables from it (--workspace --bin agent-doc, --workspace --test …, nextest filtersets, scripts/run-batched-tests) rather than re-resolving features with -p or root-only invocations, which had compiled ~479 units per core-crate edit instead of ~256. The controller-heavy batched packages keep one libtest process per test binary at --test-threads=$(TEST_THREADS), but the binaries run concurrently (BATCHED_TEST_JOBS), and any failing binary fails the step. [profile.dev] keeps debug = "line-tables-only" (backtraces resolve to file:line; CARGO_PROFILE_DEV_DEBUG=2 restores full debuginfo). make tla runs TLC checks concurrently with per-job isolation and skips only on a content receipt over the model files, runner, and JVM. No check is dropped and no timeout is raised by these optimizations.

  • A release assembled from claimed queue workers has one explicit batch boundary before version projection. Every completed claim ready at that boundary is integrated into the same version/check/install train; later-ready claims wait for the next release. make release performs the batch’s only install-full after pushing main and the version tag. It emits elapsed time and separate terminal outcomes for the tag/publish handoff and local full-profile install, so a post-push local install failure cannot be mistaken for a failed publication or trigger a duplicate tag.

  • A cold launch waits on the child it spawned, not only on the socket path (launch exit masked as a timeout). connect_or_launch keeps the detached controller’s exit observer. As soon as the child exits before publishing the public socket, the wait makes one last connect to adopt a peer that won the race. If no peer answers, it fails with the child’s exit status and the tail of .agent-doc/logs/controller-stderr.log. It does not poll out the launch budget and then report “timed out waiting for project controller”. The timeout is left for a child that is alive but has not yet bound. Live repro (load flake, 2026-10-15): every captured instance of timed out waiting for project controller in agent-doc-preflight-io was a controller that had exited with status 1 within the same second. It exited on state db is corrupt … first16=2026-10-15T17:…, a state.db header overwritten by a log timestamp (the state.db fd-clobber bug, fixed on fix/statedb-fd-clobber).

  • A unit fixture whose assertion needs a controller RPC hosts a warm in-process controller (start_state_actor_for_tests) instead of letting its first timed RPC connect_or_launch a detached agent-doc controller serve (#visiblewriteloadflake). The detached launch charges exec, runtime hydration, and first-touch state.db convergence to the 2s test-mode connect/RPC deadlines, so a busy runner, not the code under test, decides the outcome. The in-process actor hydrates before it binds its socket and serves each client on its own thread like production, so one client’s long-poll cannot starve another client’s RPC. The same holds for the already-applied receipt fixtures in agent-doc-write-runtime-io (#flakyintegrate0494): their receipt is recorded strictly against a warm actor and each asserts no detached controller was cold-launched, because a receipt RPC that timed out was silently discarded and sent the code under test down the missing-receipt branch.

  • A fixture that simulates an editor socket uses agent_doc_test_support::SimulatedEditorListener (#flakyreceipthelpers), never a hand-rolled ipc_io::start_listener that records receipts and discards the result. The fixture ensures the process’s shared warm in-process controller (ensure_state_actor_for_tests, the same actor a closeout owner claim uses, so the two never steal each other’s socket) before it binds; records every visible-write receipt strictly, answering a failed record with a rejected receipt instead of a false applied, printing it, and failing the test when it drops; asserts on drop that no detached controller was cold-launched; and blocks until its socket serves and joins its listener on drop. It also registers its root in agent_doc_ipc_io::known_live_test_editors (feature test-support), which makes the client’s 6s editor receipt deadline a 30s hang ceiling for that root only: a slow receipt from an always-answering in-process editor is host load, not absence (the #remainingwallclock rule for editor IPC). With its core shared with 64 spinners the receipt record’s CPU stayed ~50ms while every thread handoff waited a scheduling round, so its wall time reached 3-4s; a fixture that must exercise the receipt timeout keeps an unregistered listener.

  • A workspace lib test never cold-launches a detached agent-doc controller serve (#coldlaunchflakes). When a lib-test harness (target/<profile>/deps/agent_doc*-<hash>) reaches connect_or_launch for a root with no controller, the process’s shared warm in-process state actor (ensure_state_actor_for_tests) serves the root instead. The actor binds its socket before it returns, so the connect has no startup race and no launch deadline. Every real spawn goes through launch_detached_at, which panics in a lib test that did not opt in with allow_cold_controller_launch_for_tests. A new launch path (handoff, recycle, helper) therefore fails the test that takes it instead of reintroducing the race, and cold_launch_test_policy::tests pins this guard. An opted-in launch waits only until the child publishes its socket or exits. Its budget is a 150s hang ceiling, below nextest’s per-test kill, not the 2s test-mode launch budget. The agent-doc binary (a launched controller, or the CLI an integration test spawns) is never classified as a lib test, so it launches exactly as production does. A lib test that routes a document’s relay in-process (seed_embedded_relay_for_file, a replica registration) models the controller-hosted topology: reliable_sync_editor_live_for_file answers from this process’s plane, like the controller itself, and does not ask the in-process actor, which shares this process’s relay registry. Measured 2026-10-15: one workspace nextest run had 498 cold launches from 17 lib-test binaries before this change and 0 after. Under load these launches produced the timed out waiting for launched controller pid N failures in agent-doc-preflight-io and agent-doc-queue-io, and the empty warning list in #staleplugwarnflake.

  • The cold-launch guard covers integration-test targets too (#integrationtesttargets). The policy keys on who launches. (1) A workspace test harness is any target/<profile>/deps/<name>-<16-hex-hash> executable, which covers lib tests and integration tests (tests/*.rs, e.g. session_check-<hash>). It is served in-process exactly like a lib test: connect_or_launch uses ensure_state_actor_for_tests, and an unopted spawn panics. (2) A process a test harness spawned is any process with a harness among its first 8 ancestors (Linux /proc), such as the agent-doc CLI an integration test drives. Its controller launch is production behavior. It is admitted only when the test sets AGENT_DOC_TEST_CONTROLLER_LAUNCH_REASON (exported as project_controller::TEST_CONTROLLER_LAUNCH_REASON_ENV) to a non-empty reason on the spawned command. Without a reason, launch_detached_at panics before any spawn side effect, so a target that newly starts launching controllers fails instead of adding unbounded cold launches. Each CLI-driving target sets its reason once in its command helper. A controller that a harness launched after allow_cold_controller_launch_for_tests inherits the opt-in through that env var, so its handoff replacement stays admitted. Every admitted launch waits only for the child to publish its socket or exit, with the 150s hang ceiling instead of the 2s test-mode budget. The test-support CLI no longer serves closeout-owner claims from its own short-lived in-process actor. That path sent test_shutdown to the test project’s launched controller and died with the CLI, so the project’s next command cold-launched again. The CLI now adopts the project’s controller as production does, and one launched controller serves every command of a test project. A CLI started inside a tmux pane (parent: the tmux server) or on a non-Linux host finds no harness ancestor and is unguarded. Measured 2026-10-15 on the integration-test targets (nextest -E 'kind(test)', 1234 tests): 546 launches before this change (403 from harnesses calling library code in-process, 143 from the CLI, up to 12 per test) and 237 after (0 from harnesses, 237 from the CLI, at most 2 per test, 1 per test project). The CLI count rose because the roughly 90 tests whose closeout used to run in a CLI-hosted actor now launch the production controller once. Summed test time fell from 2071s to 1877s. With a shim delaying each controller serve by 3s under stress -c 64, the targets went from 14 failures (19 timed out waiting for launched controller) to 0. Without the shutdown-and-relaunch per command, a CLI closeout on tmpfs finishes in well under a second, which exposed a whole-second tie in the #chatprompt ledger prune. A committed cycle now prunes a chat prompt only when the cycle opened strictly after the prompt was noted. A prompt noted in the same second as the cycle start is kept: dropping it would lose an unanswered prompt, while keeping it at worst carries an answered prompt into one more contract.

  • A unit test whose writer runs concurrently with the code under test synchronizes on the writer’s completion signal, not on a wall-clock deadline (#visiblewritewallclock). A poll that returns empty is a defect only if the writer had already recorded its receipt when the poll began; otherwise the test waits for the writer’s receipt event and re-polls with a zero budget, so the predicate alone decides. Production poll helpers keep their timeout APIs; only the test’s waiter changes. Raising a test timeout is not a fix.

  • Reactive controller tests await the matching state-plane publication instead of treating any frame as proof and then polling a replaceable map (#state-receipt-test). Wake-map mutation and its covering Snapshot share one publication order, and a same-capture retained-settled wake cannot be downgraded by a later generic wake before closeout consumes it.

  • An agent-doc self-development install schedules its own idle-boundary handoff. An active response cycle must close with respond before an explicit project recycle; recycling before closeout competes with the editor projection and manufactures retained-convergence churn (#closeout-before-explicit-recycle).

  • CycleContext/ActorContext are the lazily-backed read cache boundary for per-run global configuration and transactional document/project registry snapshots. Long-lived actors must explicitly invalidate those slots on controller events. Read-only route/sync/resync/gc lookups may reuse those snapshots for a single logical operation, but every registry read-modify-write path must still execute through the state-store transaction boundary.

  • Harness-specific launch controls are explicit: agent_args is generic, claude_args applies only to Claude, codex_args applies only to Codex, opencode_args applies only to OpenCode, and codex_network_access controls whether agent-doc preserves, removes, or forces CODEX_SANDBOX_NETWORK_DISABLED for Codex child sessions. claude_model: opus, /model opus, and the built-in Claude Code high tier are deferred to Claude Code: agent-doc emits --model opus so Claude Code resolves its current latest opus, and attribution is self-stamped by the running agent instead of a pinned version (agent-doc stores no concrete opus version, so launch and attribution can never lag a release). Explicit non-alias model ids (e.g. claude-opus-4-8) pass through unchanged. opencode_model / opencode_args allow managed OpenCode panes to launch as opencode --model <provider/model> with OpenCode-specific flags, while direct agent-doc run --agent opencode uses opencode run. Managed Codex capability proof is off unless document frontmatter sets managed_proof: true. When opted in, codex_network_access: enabled must prove host DNS plus a bounded codex exec --json child DNS/HTTPS command under the same launch args before route may trust the pane as network-capable; managed OpenCode startup uses a bounded opencode run --format json child probe for network checks. Opted-in Codex proof children use --ephemeral, --ignore-rules, and low reasoning effort, and combine network plus writable-root checks in one child when both are required. Managed OpenCode startup also records opencode_capability_proof for documents with required_ssh_targets, and that proof must run an isolated SSH check inside the OpenCode child before auto-trigger, supervisor injection, managed route, or dispatch-only route may submit prompt work. Successful proof events must include per-phase timings_ms for network, SSH, writable-root, and total proof time. Successful and failed managed proof summaries must be surfaced as tmux status messages through display-message on the owned pane, not written into the child pane transcript; the full proof event remains in the session log. For OpenCode, an otherwise chrome-only context ... % used status footer counts as an idle composer even when no standalone > prompt line is captured after proof completion. When Codex writable roots are required, successful proof events must also include a normalized writable_root_contract fingerprint, and route/session-status may treat a Codex proof as current only when that fingerprint matches the active document’s resolved --add-dir set after the latest session_start. When a Claude/Codex document lives in a submodule, harness launches must also auto-add any writable roots outside the submodule that the session lifecycle may need: the superproject working tree for parent-repo document patchbacks plus the external git metadata directories (.git/modules/... for the submodule and the superproject .git for pointer updates). If a resumed Codex exec resume <id> turn reports the local-browser/CDP EPERM signature (Operation not permitted on 127.0.0.1:9222 / localhost:9222), agent-doc must treat that as stale resumed-session capability drift, retry once with a fresh codex exec, and let the successful fresh thread replace the saved resume id instead of trusting the poisoned resume state again. Because codex exec resume cannot accept new --add-dir roots, a direct resumed Codex backend turn whose current launch args require writable roots must fresh-start with the full root set instead of attempting resume. Required SSH metadata may come from document frontmatter (required_ssh_targets or required_ssh_profile) or from project-local .agent-doc/config.toml mappings for known ops docs. If a configured SSH-dependent document cannot resolve any targets, preflight/startup must fail closed before launch. Those pre-launch SSH capability probes must run in isolated mode (ControlMaster=no, ControlPath=none, ClearAllForwardings=yes, PermitLocalCommand=no) so they cannot create or reuse shared SSH multiplexing state that would affect later operator shells. When a document resolves required SSH targets, that same resumed-session recovery must also treat bare socket: Operation not permitted command output as required-SSH capability drift when the command_execution event proves SSH command context for one of the required targets, while still excluding the localhost/CDP drift family and historical capture/log grep output from the SSH path. For resumed required-SSH streaming turns, early assistant chunks from the resumed session must stay buffered until required SSH is proven safe or the turn completes successfully, so a fresh retry can discard stale prelude text instead of leaking it into the final response. A transient capability-proof failure must not permanently disable the session: the proof retries with bounded exponential back-off (configurable via managed_proof_max_attempts, managed_proof_retry_backoff_secs, and managed_proof_probe_timeout_secs in frontmatter or .agent-doc/config.toml; defaults 3 / 2s / 45s), keeping the gate Pending between attempts and only committing to Failed after the budget is exhausted. Operator recovery is gate-exempt: only real prompt dispatch (Inject, auto-trigger, auto-queue) is gated, while the supervisor control methods (Clear, Stop, Restart) and read-only methods (State, Pid) bypass the gate, so agent-doc session clear / session interrupt-clear can stop or clear a proof-Failed session without kill -9 (#codex-capability-proof-unrecoverable).

  • ### Re: response headers must use the resolved model short name for attribution (for example gpt-5, opus-4-7), never the harness label (codex, claude). The agent authors the model and local timestamp from the preflight contract; strict closeout canonicalization preserves an already-valid attributed/timestamped heading byte-for-byte through the production write path.

  • Bundled skill/install content is part of the external contract: Claude/Codex/OpenCode hot-path instructions must render from one shared source surface, with differences limited to harness-specific invocation wording and frontmatter description. Harness installs must write trigger-scoped managed skill files (.claude/skills/agent-doc/SKILL.md, .codex/skills/agent-doc/SKILL.md, .opencode/skills/agent-doc/SKILL.md) and must retire old generated root AGENTS.md / .codex/AGENTS.md copies instead of refreshing them as always-on mirrors. audit-docs must fail generated managed skill surfaces that carry agent-doc managed frontmatter but no longer match the running binary, and must fail retired generated AGENTS.md surfaces until agent-doc skill install migrates them away. audit-docs must also compare every installed runbook bundle to the running binary: a stale runbook, a missing runbook, unbundled Markdown in a managed harness runbook directory, a surviving retired .codex/runbooks/ mirror, and drift in a directory listed under skill_runbook_mirrors are all release-blocking. make check runs audit-docs, because the release process runs make check and an audit only reachable from precommit cannot gate a release. Without an explicit --root, submodule-local audits check both the git superproject install root used by normal release installs and the submodule checkout itself — skill install resolves to the superproject, so submodule-local copies are otherwise touched only by release-version and never content-checked; explicit --root DIR checks generated surfaces under DIR exactly. release-version projects the version into bundled skill sources only; installed copies are the installer’s output, refreshed by skill install (--root DIR targets an explicit root). Custom root instruction files that do not look agent-doc-managed remain user-owned. Filesystem mtime freshness is advisory for agent-doc audits; source-only timestamp changes may be reported, but generated instruction surfaces are release-blocking only when the rendered content differs. The shared Claude/Codex/OpenCode manual-repair instructions must distinguish adding a missing user prompt from repairing a missed assistant response, use agent-doc write --commit <file> for the missed-response path, and not stop after bare agent-doc write. The repo-local Codex plugin manifest must stay schema-valid: it must not point skills at Claude install paths such as .claude/skills; if it exposes Codex skills, the manifest path must resolve to a real plugin-root ./skills/ tree.

  • The optional skill-harness integration is owned by the focused agent-doc-skill-harness crate, never by agent-doc-core or by skill-harness itself. Its AgentDocSkillHarnessPlugin detects the supervised AGENT_DOC_SESSION marker at priority 100, resolves <name> to .agent-doc/plugins/<name>/SKILL.md, and is installed into a consumer registry through register_agent_doc_plugin (or registry_with_agent_doc). This path is distinct from Agent Doc’s own harness bootstrap skill paths.

  • Reusable authoring runbooks and OKF concept bundles shipped by skill install are part of that same contract. If runbooks/split-spec-files.md or okf/index.md is referenced from the shared instruction surfaces, it must be bundled into installed harness resources and its ownership rule must stay harness-agnostic across agent-doc-managed surfaces while leaving custom root instruction files opt-in unless they still match the generated baseline.

  • Route readiness/trigger acceptance is a binary responsibility: pane prompt detection must be robust to shell startup noise and must wait for actual prompt state rather than treating echoed command text as readiness.

  • A route refused because a live editor maps superseded JetBrains plugin bytes must use the same recorded-verdict recovery ladder as preflight and attached-editor admission. Mappings moved by the atomic installer into <plugins>/.agent-doc-jetbrains-install/backup-*/lib/ still resolve their restart verdict from <plugins>/.agent-doc-jetbrains-restart-required; when that marker is newer than a live owner, both route admission and an otherwise byte-unchanged plugin install must prescribe the restart immediately and must not claim that no restart is required. (#pluginbyteidentity, GH #257) The owner’s start time is the kernel’s own record, /proc/<pid>/stat field 22 (starttime, clock ticks since boot, parsed after the last ) of comm) divided by sysconf(_SC_CLK_TCK) plus btime from /proc/stat; it must never be the /proc/<pid> directory mtime, which procfs stamps when it instantiates the inode (seconds before the read) and which made every recorded verdict look older than its process. When the start time cannot be read, the verdict is withheld and the restart-free ladder applies. Every process-age read in the workspace (this verdict, the controller reapers’ freshly-launched keep window, and duplicate-supervisor retirement’s pid-reuse fence) uses one shared reader, agent_doc_fs::process_start. (GH #263)

  • Route progress/status diagnostics must also be binary-safe: when route.rs trims captured tmux lines for stderr/status output, it must preserve UTF-8 char boundaries so multibyte glyphs in prompt/status lines cannot panic the reroute path.

  • Route trigger commands must use absolute file paths (resolved against the invoker’s CWD) to prevent submodule CWD-dependent misrouting. That invariant applies to every routed reopen attempt, including post-restart retries after an admission projection stays unchanged; once route has resolved the canonical path, later retries must not fall back to file.display() or other caller-relative renderings. When a tmux pane’s CWD is narrowed to a submodule root and the same relative path exists in both the main repo and the submodule, a relative path would resolve to the wrong file.

  • A stale JetBrains plugin warning must resolve package generation and install state from the live IDE’s mapped JAR. A mapping under the installer’s deleted .agent-doc-jetbrains-install/backup-*/lib/ swap tree retains the same IDE data-root identity as the replaced canonical plugin tree, so the warning must inspect the replacement package now on disk and prescribe restart-only guidance when that package is current.

#FileDescription
1OverviewWhat agent-doc does and how sessions work
2Document FormatFrontmatter fields, components, turn roles, and template structure
3Snapshot SystemSnapshot storage, lifecycle, and diff baseline
4Diff ComputationUnified diff, comment stripping, and informational-component filtering
5Agent BackendAgent trait, resolution order, Claude backend
6ConfigGlobal/project config, IPC, document state model
7CommandsCommand-spec index with split sibling specs for core, tmux/session, closeout, and orchestration behavior
8Session RoutingRegistry, claim semantics, stash routing, binding invariant
9Git IntegrationCommit/branch/squash and hook system
10SecurityThreat model, known risks, recommendations
11DebounceDebounce system gaps, limitations, and improvements
12Deterministic Simulation TestingFast seeded workflow simulation for closeout edge cases
13State BackboneCycle FSM boundary, typed event ledger, projections, and actor ownership
14Real-Time Workflow AuthorityOperator-first source-of-truth and live mutation invariants
15Turn Lifecycle AuthorityTurn/closeout state machine, realtime handoff, and commit ownership
16Codex SupportHarness-specific differences for Codex vs Claude Code

Command sub-specs:

  • Installed Claude/Codex/OpenCode SKILL.md files are one shared, compaction-resistant table of contents. runbooks/session-cycle.md owns the ordered binary-owned cycle spine; focused bundled runbooks own branch detail; generated-surface tests prove the former hot-path invariants remain reachable through the table. Harness differences are limited to trigger/frontmatter, invocation wording, and a short harness-specific route.
  • Core Commands
  • Focused Document Extract
  • Session And Tmux Commands
  • Closeout Commands
  • Orchestration Commands

Queue-worker Git provenance is durable (#queue-lineage): one exact queue work identity and monotonic claim generation maps to its worker, repository/worktree, branch, base SHA, source SHA and pushed ref, explicit source-to-integration edge and method, integration SHA, and release tag/state. queue claim and queue start establish the attempt and worker automatically without adding routine console or document noise; external coordinators append later lifecycle receipts with queue lineage-record. Operators query current plus historical attempts with queue lineage: its default text is one compact row per attempt, --verbose exposes full evidence and diagnostics, and --json is machine-readable. Integration is never inferred from branch names or patch equivalence: the edge must be explicitly recorded, after which Git ancestry/patch/tag facts validate it and later queries surface deleted worktrees, missing refs, or drift without deleting history. Active-row cancellation terminalizes only its exact generation. Removing an already struck row is presentation-only. Markdown may show a compact lineage hint only when explicitly requested, but state.db remains authoritative.

Session-routing supplements: