Interactive document sessions with AI agents
Project description
agent-doc
Interactive document sessions with AI agents.
Edit a markdown file, press a hotkey, and the tool diffs your changes, sends them to an AI agent, and writes the response back into the document. The document is the UI.
Alpha Software — actively developed; APIs and frontmatter format may change between versions.
Single-user only. agent-doc operates on the local filesystem with no access control. Use a private git repository. See the Security section for details.
Install
curl -fsSL https://raw.githubusercontent.com/btakita/agent-doc/main/install.sh | sh
Alternatives:
# From PyPI
pip install agent-doc
# From a local source checkout
cargo install --path src/agent-doc --force
# Or from inside src/agent-doc
cargo install --path . --force
The Rust workspace is an implementation detail: every agent-doc Cargo package is
marked publish = false. New releases ship through GitHub Releases and PyPI;
older crates.io uploads remain as immutable historical artifacts.
Quick Start
# 1. Initialize project (creates .agent-doc/ and installs SKILL.md)
agent-doc init
# 2. Scaffold a session document
agent-doc init session.md "My Topic"
# 3. Claim the document to the current tmux pane
agent-doc claim session.md
# 4. Route hotkey triggers to the correct tmux pane
agent-doc route --dispatch-only --plain-trigger --wait-for-ready 60 session.md
# 5. Run: diff, send to agent, write response back
agent-doc run session.md
The typical edit cycle: write in your editor, trigger agent-doc route --dispatch-only --plain-trigger --wait-for-ready 60 <file> via a hotkey, and agent-doc dispatches the plain agent-doc <file> reopen into the right pane. Route waits for the file mtime and shared editor typing indicator to settle before it mutates the document or submits the reopen, and editor-triggered routing gives slow-starting supervisors a longer readiness window before surfacing a startup error. During that readiness window, route owns the pane input window, so supervisor queue drains and context-reset /clear / /new recovery wait instead of interleaving into the composer. That editor path always stays a bounded reopen send; it does not restart Codex just because the previous prompt was /clear.
Feature Taxonomy
agent-doc has a broad feature surface because the README doubles as a user guide and capability ledger. The reader-facing overview is grouped by workflow layer here; the exhaustive feature catalog is kept near the bottom so installation, architecture, editor setup, and security stay easy to scan.
- Document model — template components, backlog archival, exchange boundaries, snapshots, durable captures, and component-aware baseline guards.
- Write and merge pipeline — IPC-first editor writes, CRDT/3-way merge, template patching, response replay, strict finalize/write closeout, and selective git commits.
- Agent orchestration — harness-specific routing for Claude, Codex, and OpenCode, prompt contracts, model attribution, direct-run dispatch, sequential/parallel/DAG orchestration, per-item enqueue markers, and lower-agent job packets with target write scopes plus tsift context/graph acceptance sidecars.
- Session memory —
agent-doc memory index/searchrecords backlog, review, done, icebox, and exchange history in.tsift/memory.dbthrough the sharedtsift-memorylibrary for local dedupe and resolved-before checks. - Tmux and editor coordination — route/sync/start/claim, project-controller actor state, session drift repair, startup-miss handling, passive sync, stash/rescue, and editor plugins.
- Operational safety — preflight recovery, session-check guards, hooks, Codex stop-hook recovery, required-SSH/network capability proofs, accretion context, and explicit manual-repair rules.
Architecture
flowchart LR
user["User edits session document"]
editor["Editor plugin or CLI"]
route["route / sync / start / claim"]
controller["Project controller\nactor + lease state"]
tmux["tmux supervisor pane"]
harness["Agent harness\nClaude / Codex / OpenCode"]
preflight["preflight / plan\nrecover, diff, classify"]
response["Agent response\npatch blocks"]
finalize["finalize / write --commit\nstrict closeout"]
sessionCheck["session-check\npost-write guard"]
subgraph DocumentState["Document state"]
doc["Markdown session document\nfrontmatter + components"]
baseline["Snapshots + baselines"]
capture["Durable captures"]
cycle["Cycle state"]
end
subgraph BinaryCore["Rust binary core"]
diff["diff + prompt contract"]
template["template patch engine"]
merge["CRDT / 3-way merge"]
ipc["IPC-first editor patches"]
git["selective git commit"]
hooks["hooks + ops log"]
end
user --> editor --> route --> controller --> tmux --> harness
editor --> preflight
preflight --> diff --> harness
harness --> response --> finalize
finalize --> template --> merge --> ipc --> doc
finalize --> git --> sessionCheck
sessionCheck --> hooks
doc <--> baseline
preflight --> cycle
response --> capture
diff --> doc
template --> doc
git --> baseline
The binary owns all deterministic behavior: component parsing, patch application, CRDT merge, snapshot management, git operations, tmux routing, and IPC writes. The bundled skill / AGENTS instructions are the non-deterministic orchestrator layer — they read the diff, generate responses, and decide what to write.
For how concurrent agent writes and live editor keystrokes merge without splicing content across unrelated regions of the document, see Document Node-Merge Architecture.
Binary vs. Agent Responsibility:
| Responsibility | Owner | Why |
|---|---|---|
| Component parsing, patch application, mode resolution | Binary (Rust) | Deterministic, testable, consistent across agents |
| CRDT merge, snapshot management, atomic writes | Binary (Rust) | Concurrency safety requires flock + atomic rename |
| Diff computation, comment stripping, truncation detection | Binary (Rust) | Reproducible baseline comparison |
| Git operations (commit, history, clean) | Binary (Rust) | Direct std::process::Command calls; selective commit can self-heal narrow missed agent-owned drift and normalize boundary cleanup without absorbing free-form user prompts |
| Tmux routing, session registry, pane management | Binary (Rust) | Process-level coordination |
| Pre-response snapshots, undo, extract, transfer | Binary (Rust) | File-level atomicity |
| Boundary marker lifecycle (insert, reposition, cleanup) | Binary (Rust) | Deterministic, all write paths need it |
| Reading diff, interpreting user intent | Skill (SKILL.md) | Requires LLM reasoning, including treating imperative document edits as executable directives rather than meta-only discussion topics |
| Generating response content | Skill (SKILL.md) | Non-deterministic |
| Deciding what to write to which component | Skill (SKILL.md) | Context-dependent, including the shared Claude/Codex/OpenCode manual-repair rule to use agent-doc write --commit <file> when the prompt already exists |
| Enforcing response-cycle completion for the normal happy path | Binary (Rust) | agent-doc finalize fails closed unless the write reaches a terminal committed cycle state |
| Console progress, final-response timing | Skill (SKILL.md) | Partial output stays outside the document |
| Pending item management (parse, populate, process) | Skill (SKILL.md) | Semantic understanding of prompts |
See CLAUDE.md for the full module layout, stream mode details, and release process.
Large specs now split behind stable entrypoint files instead of growing indefinitely. For command behavior, start at specs/07-commands.md, which indexes the focused sibling specs for core commands, tmux/session behavior, closeout, and orchestration. For the authoring rule behind that split, see runbooks/split-spec-files.md. That runbook applies across agent-doc-managed harness instruction surfaces, while custom root instruction files stay opt-in unless they still match the generated baseline.
Supported Editors
JetBrains (IntelliJ, PyCharm, etc.)
agent-doc plugin install jetbrains
When multiple JetBrains IDE data roots exist, select the target explicitly for automation:
agent-doc plugin install jetbrains --plugins-dir ~/.local/share/JetBrains/IdeaIC2026.1/plugins
Or install from JetBrains Marketplace. Configure an External Tool: Program=agent-doc, Args=run $FilePath$, Working dir=$ProjectFileDir$. Assign a keyboard shortcut.
VS Code
agent-doc plugin install vscode
Or install from the VS Code Marketplace. Add a task with "command": "agent-doc run ${file}" and bind it to a keybinding.
Vim/Neovim
nnoremap <leader>as :!agent-doc run %<CR>:e<CR>
Domain Ontology
agent-doc extends the existence kernel vocabulary with domain-specific terms.
Document Lifecycle
| Term | Definition |
|---|---|
| Session | A persistent conversation between a user and an agent, identified by UUID. Stored in frontmatter as agent_doc_session. |
| Document | A markdown file that serves as the UI for a session. Contains frontmatter, components, and user/agent content. |
| Snapshot | A baseline copy of the document at a known state. Used for diff computation and CRDT merge. |
| Component | A named region in a template document (<!-- agent:name -->...<!-- /agent:name -->). Targeted by patch blocks. |
| Boundary | A marker (<!-- agent:boundary:hash -->) that separates committed content from uncommitted user edits. |
| Exchange | The shared conversation surface where user and agent write inline. A component with patch=append. |
Pane Lifecycle
| Term | Definition |
|---|---|
| Binding | The document→pane association stored in sessions.json and the actor store. Created by claim (explicit) or auto_start (automatic). One active document owns a pane; if a stale cross-document alias exists, the incoming owner closes and clears the displaced binding. |
| Reconciliation | The process of matching editor layout to tmux layout. Performed by sync. Stashes unwanted panes, provisions missing ones. |
| Provisioning | Creating a new tmux pane and starting the configured agent harness for a document. Performed by route::auto_start. The normal path for new documents — sync triggers provisioning when it finds a session UUID with no registered pane. |
| Initialization | Assigning a session UUID, creating a snapshot, and committing to git. Performed by ensure_initialized(). Called from claim, preflight, and sync's resolve_file. |
Integration Layer
| Term | Definition |
|---|---|
| Route | Resolve which tmux pane handles a file. Creates panes if needed (provisioning). |
| Sync | Reconcile editor layout with tmux layout. The primary entrypoint from the JB plugin on every tab switch. |
| Claim | Bind a document to a specific existing pane. Used for manual pane assignment; not needed in normal editor workflow (sync + auto_start handles it). |
Interaction Model
| Term | Definition |
|---|---|
| Directive | A signal that authorizes and requests action. User inputs like "do", "go", "yes" are directives. Classified as DiffType::Approval in preflight. The directive's brevity is independent of the expected execution thoroughness — quality processes always apply in full. |
| Cycle | One round-trip: user edits -> preflight -> agent response -> write-back -> commit. Logged in .agent-doc/logs/cycles.jsonl with git state references for reproducibility, with the current per-document phase tracked in .agent-doc/state/cycles/<doc-hash>.json and the exact response body durably captured in .agent-doc/captures/<doc-hash>/<cycle-id>.json so interrupted cycles can be replayed or blocked exactly. |
| Layout check | Pre-agent tmux health inspection (check_layout()). Detects: missing window 0, non-idle stash panes, and session drift (registered panes spanning multiple tmux sessions). Preflight immediately attempts the narrow base-index repair when window 0 is missing, then reports remaining issues as layout_issues[] in preflight JSON. Full manual sync also repairs window order to 0:agent-doc, 1:stash, then overflow N:stash before reconciliation. |
| Session drift | Condition where registered document panes span more than one tmux session. Detected by preflight's check_layout(). Fixed by agent-doc session set <N> to consolidate panes into the target session. |
| Diff | The user's changes since the last snapshot. Classified by classify_diff() into a DiffType for skill routing. Comment-stripped before comparison. |
| Annotation | A user edit to agent-written content (inline modification, colon-append). Classified as DiffType::Annotation. |
Security
agent-doc is designed for single-user, local operation. All session data (documents, snapshots, exchange history) is stored on the local filesystem and committed to a git repository.
Current security model:
- Single user only. There is no multi-user access control, authentication, or session isolation.
- Private repo recommended. Session documents may contain sensitive content (correspondence, research, credentials in context). Use a private git repository.
- Prompt injection risk. Content pasted into documents from external sources (emails, web pages, chat logs) could contain prompt injection attempts. The agent processes all document content as user input with no injection scanning.
--dangerously-skip-permissionsexposure. When running with this flag (common in agent-doc sessions), the agent has full filesystem access. Injected prompts could read files or execute commands if not sandboxed.- Shared-doc guard is explicit, not full auth. Documents may opt into
agent_doc_collaboration: shared; in that mode, cross-documentextract/transferand plan-backeddo #idwork that references another.mdfile fail closed unless the document also carriesagent_doc_security_review: <review-id>. This is an audit marker for cross-document access, not a replacement for real authentication or session isolation.
Planned: Collaborative security for web/networked deployments (multi-user access control, session isolation, content scanning, compartmented access patterns).
Key Features
This catalog is intentionally detailed. It records user-visible capabilities and workflow invariants that are useful for operators, release notes, and implementation audits, but it is no longer part of the first-screen README overview.
- Template mode — named component regions (
<!-- agent:name -->) updated independently; inline attrs (patch=,max_lines=) >components.toml> built-in defaults - Completed backlog archive — reaped tracked work is stored in canonical
agent:done, or in an explicit repo-relative.done.mdfile viaagent:done archive=...;agent-doc migraterewrites oldagent:backlog-doneandagent:pending-donetags - Review-pending tracked work —
agent:reviewholds code-complete[/]items awaiting human review.--pending-gatemoves backlog items into review,--pending-ungatemoves them back,--doneaccepts review items, and optionalreview_done_guardcan warn or fail when a project requires review before done. - Session memory retrieval —
agent-doc memory index/searchstores current backlog/review/done/icebox items and exchange response summaries in.tsift/memory.db, enabling deterministic local checks for already-tracked or already-resolved work without embedding tsift's heavy codebase index. - CRDT merge — yrs-based conflict-free merge for concurrent edits between agent writes and user edits; the markdown AST layer also defines a structured
.yrsoverlay schema and node-keyed component mutations so queue/backlog items can be consumed, deduped, reordered, and enqueued by semantic node identity instead of text lines - IPC-first writes — socket IPC (Unix domain sockets); editor plugin receives JSON patches instead of file overwrites; component patches carry explicit
op/node_idmetadata and payloads include receipt-gatednode_patchesfor item-level insert/strike/move/replace operations with target-node source proof, so unrelated editor drift can remain in the live buffer; preserves cursor position, undo history, and avoids "externally modified" dialogs - Tmux routing — persistent per-document agent sessions;
routedispatches to the correct pane or auto-starts one using the active harness's trigger shape (/agent-docfor Claude Code, plainagent-docfor Codex); reconciler always runs (no early exits) handling 0/1/2+ panes uniformly - Controller-backed admin controls —
agent-doc admin inspect,admin queue pause|resume|drain,admin reap,admin handoff, andadmin repair-projectionrun through the project controller instead of editing sidecars directly. Document-scoped mutations require the observed actor generation; stale requests produce typed rejected receipts. Queue pause/drain state is stored in.agent-doc/state.db, and dispatch reports durablequeue_pausedoractor_busy_drainingbackpressure receipts before any tmux/supervisor input is sent. An acceptedadmin queue pausesuppresses the unattended supervisor idle-queue watch auto-injection on ago-mode queue (#qpausego): the idle-watch stops injecting triggers while the pause is active, andpreflightsurfacesqueue_paused: true,queue_pause_reason, and pause-awarequeue_continuation_guidance. It does NOT stop the attended in-session/loop(which keeps draining real queue work) — usequeue: stopfrontmatter /--- stopfences for that;admin queue resumeclears the pause flag and reason. - Route-owned panes close after successful idle cycles — fresh panes created by
routerunagent-doc start --route-owned, so the supervisor stops and reaps the pane after the first new document cycle commits once the supervisor has stablereadyprompt state or direct pane output shows the harness is back at an idle prompt, and the document has no live backlog, queue, dirty edits, or unresolved exchange-tail prompt. Explicit blocking prompt states still keep the pane alive. If the fresh route never starts a cycle, the startup-miss marker is still recorded, but the just-created idle pane is killed instead of becoming a stranded registered owner. - Ready/busy owned panes reconcile instead of stalling forever — when the actor record, supervisor actor state, and controller lease all say
readybut a stale Codex renderer cue still reports the pane asalive-busy/prompt_ready=falsefrom a queued-draft footer, route-owned completion and the idle-queue watch debounce the conflict for the same short window used by stale-busy idle repair, logowned_pane_ready_busy_conflict, and let queued work continue. Genuine active turns, permission prompts, shell search, hook-review prompts, help screens, and clean-exit prompts remain protected.agent-doc session statusprints the conflict and points to bounded reconcile/clear recovery rather than pane restart. - Managed reroutes keep one tmux submit boundary — once a Claude/Codex session is running under
agent-doc start, route keeps the managed acceptance/queue paths on supervisor IPC, but dispatch-only editor reroutes and file-scoped/clearnow submit through the live pane's tmux input path instead of mixing direct PTY writes and supervisor-only reopen delivery. Tmux-bound command injects are normalized once and submitted once through the centralized submit profile: Codex, Claude, OpenCode, and default harnesses use normalized text plus a namedEnterkey in one tmuxsend-keys -t <pane> <text> Enteroperation. Literal\r/\nsubmit bytes are reserved for raw child-PTY fallback writes, not tmux. - Queued editor reruns preempt the auto-loop — a dispatch-only editor rerun queued behind a busy actor in
agent:queueis inserted ahead of pending active-loop items (priority preempt,#jb-run-preempt-autoloop-priority): a manualRun Agent Docjumps the queue rather than landing at the tail. Route-owned queue writes are canonical plainagent:queuewrites: they never addauto, and they strip a legacyautoattribute from any queue tag they touch. The priority insert lands after any leading queue directive (preset / start fence) and never supersedes a lone active-loop prompt, so the pending item is preserved (the manual prompt runs first, then the pending item) instead of being replaced. If an explicitRun Agent Docfinds a busy authoritative actor and the document already has an explicitly startable inactive queue head (marker-sidego/start, a start fence, or legacyauto), route promotes that head toqueue_active: trueand syncs the snapshot instead of failing as a silent no-op; unattended continuation after closeout still requiresgomode, neverqueue_active: truealone. Slash-only queue heads such as/clear, ignoring surrounding whitespace, are treated as command handoffs for the supervisor rather than assistant prompts, so preflight/plan/run do not open an exchange response cycle for them. A non-interruptingsession clearon a busy active auto-loop records one deferred queue context-clear projection for the next proven idle boundary; repeated clears before delivery report the existing deferred clear and do not inject another/clear. - Owned PTY output has a real screen model — managed supervisors feed filtered child output into an
alacritty_terminalviewport, and prompt/help/protected-input checks prefer that owned screen state before falling back to the raw byte ring. Cursor rewrites and line clears are interpreted like a terminal instead of tmux scrollback text. - Fresh reroutes keep the new pane authoritative — after route creates a fresh pane for a document, later same-session registry churn cannot hand the reopen back to an older pane and make the new pane disappear from the
agent-docwindow - Late associated-pane proof still fails closed before auto-start — if stale registered-pane cleanup exposes a live legacy associated pane later in the same route pass, the normal route path now stops with explicit inspect/claim guidance instead of silently cold-starting around ambiguous ownership
- Codex forwarded
Ctrl+Cand EOF/Ctrl-D now always hand control back to the operator — after a stdin-forwardedCtrl+Cthat terminates the child, or a forwarded stdin EOF/Ctrl-D, agent-doc returns to an explicit canonicalEnter/qprompt mode so the operator can intentionally restart fresh or exit the supervisor cleanly even when the parent harness keeps stdin in raw-ish mode, including immediately after a successfully committed turn - Only genuinely promptless clean exits auto-recover — if a fresh/fresh-restart Codex child clean-exits before it ever surfaces an idle prompt and no operator
Ctrl+Dwas forwarded, agent-doc still treats that as failed startup provenance and restarts fresh automatically instead of stopping for the quit prompt - Starting actor reroutes promote only dispatch-ready panes — when the controller still reports the authoritative actor as
starting, route polls the current actor generation until the live pane shows a harness-specific dispatch-ready prompt, promotes that same actor toready, and then uses the normal managed or dispatch-only send path. If the pane never becomes dispatch-ready, both route modes fail closed before sending tmux or supervisor input and persist one typed diagnostic with elapsed time, pane id, generation, actor state, supervisor health/runtime state, prompt-ready status, and last lifecycle transition. Repeated reroutes for the same stuck pane/generation coalesce behind that saved timeout instead of writing duplicateroute_authoritative_actor_starting_not_readyrecords. Because that saved timeout is sticky, a reroute that finds a blocked-by-starting-timeout actor polls that same pane/generation for a dispatch-ready prompt up to the harness recovery budget before failing closed — so a healthy but slow-starting harness (for example a heavy Codex model that takes seconds to present its idle composer after a supervisor restart) recovers within the same reroute instead of dead-ending on a single capture. A busy pane never satisfies that proof, so the bounded poll preserves the promote-only-proven-idle rule; when the proof appears, route clears the saved timeout, promotes the actor toready, and continues through the prompt-gated submit path. If the supervisor refreshes the actor toclosedorblockedduring that wait, route stops immediately and reports that terminal state instead of timing out against stalestartingstate. - Dispatch-only reroutes keep editor runs on proven live sessions — after
agent-doc session clear <file>or when a Codex session lacks a fresh capability-proof log event, the next editor-triggeredagent-doc route --dispatch-only --plain-trigger <file>still sends the plainagent-doc <FILE>reopen through that same live pane's tmux input path when supervisor/runtime state remains healthy. If the authoritative actor's supervisor is unreachable or missing runtime actor state but the actor pane is still the current registered/live owner, dispatch-only keeps that pane as the recovery target, logsroute_dispatch_only_authoritative_degraded_direct_pane, and only submits after the normal direct-pane readiness checks pass. - Dispatch-only reroutes trust shared Enter delivery across harnesses — if a live Claude Code, Codex, or OpenCode pane accepts
agent-doc route --dispatch-only <file>through the shared tmux text+Enterpath but no stronger dispatch-start proof arrives inside the proof window, route completes withproof=accepted proof_scope=accepted_onlyinstead of returning a hard IDE failure. Codex hook proof and OpenCode pane-state proof are still logged as strongerdispatch_startevidence when available. - Direct pane submit telemetry separates input acceptance from dispatch proof —
route_latency phase=direct_pane_submitrecords whether tmux input acceptance was observed, whileroute_latency phase=dispatch_start_proofrecords harness proof. Empty first captures must stay stable before acceptance so a delayed Codex composer draft can still be seen. If Codex hook tracking later proves the prompt was consumed or submitted, an unobserved direct-pane acceptance is labeledacceptance_unobserved_dispatch_provenand uses the tmux/control-mode acceptance budget instead of reporting a false submit timeout. If Codex later has only accepted-without-dispatch-start proof but the same prompt is visibly drafted, route sends one lateEnterretry and logsroute_submit_late_resubmit. Before appending a new direct-pane trigger, route also detects the same trigger already drafted in a Codex/Claude composer and sends bounded bareEnterretries instead of stacking another copy; stale scrollback is ignored when an idle prompt appears below the trigger. - Plain dispatch-only reopens fail closed on a busy actor instead of silently focusing — an editor
Run Agent Docreopen (no prompt-bearing work) against abusyauthoritative actor focuses the pane but must not return focus-only success, which would report a routed run even though nothing was submitted (#jb-run-agent-doc-command-route-miss). Route fails closed with the busy-not-ready diagnostic (route_dispatch_only_authoritative_actor_busy_focus_only_not_dispatched) carrying thethe authoritative actor is busy did not return to a dispatch-ready promptmessage, and the JetBrains plugin surfaces that as a "session still running" notification immediately rather than after silently re-waiting the ready timeout once per retry. The narrow exception is an explicitly startable inactive queue head; route may activate it, but unattended continuation after closeout still requiresgomode. Only a still-bootingstartingpane is silently retried. - Dispatch-only proof scope is explicit — route ops logs include both
proofandproof_scope; Claude Code dispatch-only routes remainaccepted_only, hook-backed Codex can report consumed/submitteddispatch_startproof, and OpenCode can reportproof=pane_state_changed proof_scope=dispatch_startafter its pane leaves idle chrome - Dispatch-only reroutes now absorb same-file restart handoffs before surfacing a boot-window refusal — if the first starting-pane ready probe times out but the supervisor immediately restarts the same session in-place or hands it to a new pane for the same file, route follows that newer run instead of pinning the stale pane and surfacing a false
still bootingerror to the editor. OpenCode uses a longer harness-specific redraw budget for this startup-window prompt gate so JetBrains reruns do not fail just after the idle splash becomes visible. - Dispatch-only reroutes now fail closed on cross-file pane reuse before any rebind lands — if the candidate pane is still registered to another document, route refuses the reopen instead of transiently superseding that other file's pane and then repairing the registry afterward
- Optimistic fresh-restart retries stay traceable — if a routed Codex fresh restart never gets back to a dispatch-ready prompt, agent-doc records a
startup_misson the original routed pane with the canonical absolute document path instead of silently redirecting the retry through a replacement pane - Stale startup-miss markers clear from the document's current owner — if a later pane/session is now the registered owner for the same file,
start,route,sync, andsession-checktreat the older pane'sstartup_missmarker as stale once the current owner logs a newersession_start, even if that handoff rolled the session id - Managed Codex and OpenCode panes prove requested capabilities asynchronously before dispatch — when a Codex document requests network access, required SSH targets, or extra writable roots through
--add-dir,startrecordscodex_capability_proof status=pending, launches the pane, and runs live network/SSH/write probes in the background. OpenCode documents withrequired_ssh_targetsnow recordopencode_capability_proof status=pendingand run a boundedopencode run --format jsonchild SSH probe, so sandbox errors such assocket: Operation not permittedfail closed before prompt dispatch. Forcodex_network_access: enabled, Codex uses host DNS plus a boundedcodex exec --jsonchild probe, while OpenCode uses the same child-probe gate throughopencode run --format json. Proof events includetimings_msfor host DNS, child network, SSH, launcher writable-root, child writable-root, and total proof time so slow starts identify the expensive phase; Codex writable-root proofs also record a normalizedwritable_root_contractfingerprint. Supervisor injection, auto-trigger, managed route, and dispatch-only route gate prompt dispatch until the current proof succeeds; failed proof blocks the actor and disables dispatch but leaves the live hosted child running (#tsiftmdcrash) — the gate alone blocks unsafe auto-dispatch, so a flaky background probe no longer SIGTERMs a healthy interactive session out from under the operator. Successful or failed proof summaries are surfaced as tmux status messages withdisplay-messageon the owned pane and kept out of the child pane transcript; the full event remains in the session log. Codex and OpenCode readiness accept an otherwise idlecontext ... % usedfooter as the composer-ready state after busy/protected prompt checks pass.agent-doc session statusreports the proof aspending,proven,failed,missing, ornot_required. - OpenCode prompt labels stay user-facing —
agent-doc prompt --allreportsPermission requiredfor horizontal OpenCode permission controls when no explicit← ...question line is present, so external prompt consumers never display earlier shell command text or ANSI-literal prompt fixtures as the question. First-party JetBrains and VS Code plugins no longer poll this surface. - Codex hook-review startup chrome blocks dispatch — if Codex starts with a
hook needs review/Open /hooks to review itwarning, route/start readiness treats that as an operator-action blocker and refuses to inject routed input, even when a later managed capability-proof line saysstatus=proven. - Required SSH preflight probes no longer touch shared multiplexing state — when a document declares
required_ssh_targets, the pre-launchssh ... truecapability checks now force isolated probe flags (ControlMaster=no,ControlPath=none,ClearAllForwardings=yes,PermitLocalCommand=no) so proving SSH for a managed session cannot create or reuse shared control sockets that might affect later operator shells - Required SSH drift detection now covers bare socket EPERM too — when a document declares
required_ssh_targets, resumed Codex recovery treatscommand_executionoutput likesocket: Operation not permittedas required-SSH capability drift when the same event proves SSH command context for one of those targets; localhost/CDP EPERM remains on the separate browser-capability retry path - Resumed required-SSH streams now drop stale prelude text before fresh retry — when a resumed Codex turn for an SSH-gated document emits assistant prelude text before the failing SSH command, agent-doc buffers those early resumed-session chunks until required SSH is proven safe or the turn completes, so a required-SSH fresh retry can discard the poisoned prelude instead of leaking it into the committed response
- Passive mixed-root sync stays fail-safe — when
sync --no-autostartleaves any visible file blocked, agent-doc preserves the current visibleagent-docwindow layout and warns instead of collapsing the remaining foreign pane set into a new authoritative layout; if the newly focused file is already visible in that preserved window, sync still reselects its pane - Manual Sync Tmux Layout uses the doctor repair path first — full
agent-doc syncdelegates focused session-document repair tosession doctor --repairlogic before reconciling editor panes, so it can close recoverable crash-left commit boundaries where the visible document and snapshot already contain a response thatHEADlacks, recreate0:agent-docfrom a currently selected or explicitly suppliedstashwindow, and normalize adjacentN:stashoverflow; passive--no-autostarteditor sync keeps that repair step explicit - Dispatch-only startup submits are prompt-gated — editor reroutes no longer type a bare reopen into a startup-window pane until it shows harness-specific idle evidence; a Codex/OpenCode model/context footer is dispatch-ready only when busy cues and protected prompt input are absent. While route owns that pane-input window, it records
RouteSubmitStarted/RouteSubmitSettled/RouteSubmitBlockedthrough the project-controller route projection instead of marker files, so supervisor idle-queue context resets and visible/clear//newdrafts yield until the submit window settles. - Queue context-clear gates are controller projections — explicit operator clears and queued slash-command clears publish
QueueContextClearStarted/QueueContextClearSettledfacts instead of.agent-doc/context-clear-in-flightmarker files. Busy-loop operator clears publishQueueContextClearDeferredinstead of.agent-doc/deferred-clearsmarker files until idle-watch can submit the clear and promote the projection toStarted. Plain manual clear cooldowns use the same context-clear projection source instead of.agent-doc/queue-cooldownsmarker files. The supervisor idle watch reads the lazily-backed queue projection to avoid stacking another clear or draining an agent-doc trigger into the same composer, and it settles that projection after the cleared pane has been idle for the cooldown window. - Queue drain-stall detection uses controller projections — clean closeouts that still require queue continuation publish
QueueDrainStallContinuationRecordedthrough the project controller instead of writing.agent-doc/drain-stallmarker files. The next preflight reconciles and clears that lazily-backed projection, while supervisor-driven drain progress clears it before it can false-firequeue_stall_detected. - Preflight ensures the live document model before surfacing editor-authority failures — when a live editor owns a document but the CRDT relay model is absent or not converged, current-document resolution asks the editor to republish/register through the read-only
publish_live_bufferpath and rechecks the relay before failing. A bounded failure is reported as document-model startup/reconciliation guidance while disk remains non-authoritative, instead of exposing the raw missing-replica relay state as the prompt contract. - Editor document switches focus immediately, then reconcile in the background — automatic editor sync first issues a best-effort
agent-doc focus <file>that uses the local actor projection orsessions.jsonwithout waiting on controller RPC, debounce, sync-lock acquisition, prune cleanup, or tmux-router reconciliation; a real selection event still runs the guardedsync --no-autostartpass afterward, even when the visible/focused signature was already marked synchronized, so a missing actor/supervisor can be safely cold-started instead of leaving later session commands atstage=missing_actor - Safe-passive sync has a pre-lock pane handoff —
sync --no-autostart --focus <file>selects a live local actor projection before waiting on.agent-doc/sync.lock; when no local actor record exists it tries skip-wait pane provisioning with nonblocking startup locks, then leaves prune, ownership proof, and tmux-router convergence to the normal locked path - Exact visible editor snapshots do not resurrect stale siblings — automatic editor syncs pass
--exact-visiblewith--no-autostartwhen they have the full visible markdown projection, so a one-file editor state remains a one-pane tmux projection instead of expanding from remembered column memory - Passive editor sync skips stash scans before reconcile —
sync --no-autostartstill prunes stale registry rows and retained dead non-stash panes, but it skips stash-window and stash-pane cleanup so tmux-router can detach extra visible panes immediately after a document switch instead of waiting on orphaned stash scans - Passive sync proceeds around open closeouts — when
sync --no-autostartneeds to attach a newly requested pane while an already-visible unwanted pane owns an openpreflight_started/response_captured/write_appliedcycle, agent-doc keeps that closeout pane alive but still allows DETACH to stash it, so the requested document can attach/focus without temporary visible pane growth - Editor sync lock contention is bounded and self-healing — if an older sync process is stuck or orphaned, later selection/layout sync commands wait only for the contention budget. Safe-passive sync may already have applied the pre-lock pane handoff, then logs the retry marker and returns without further auto-start, tmux reconciliation, or post-lock hidden-pane focus changes; editor plugins treat that marker as deferred and retry only the newest superseding selection instead of marking stale state applied. If the contended lock is held by stale orphaned
agent-doc syncprocesses, sync reaps those lock owners and retries acquisition so autosync/manual layout sync can recover without operator cleanup - Open closeout panes stay alive during sync reconcile — if an unwanted pane still owns a document with an open
preflight_started,response_captured, orwrite_appliedcycle, sync logs that state but lets tmux-router stash the pane; stashing is non-destructive, so closeout can continue without forcing a third visible pane into a two-document editor projection - Closeout drift noise is narrower — session-check no longer treats plain content-edit drift as an unstarted response cycle, and
content_oursprompt-prefix fallback preserves unprefixed agent response lines already committed inHEADinstead of creating a follow-up normalize commit - Sync now refuses editor-provided non-
agent-doctmux windows — if the editor passes a tmux window target that is not actually anagent-docwindow and the target session has no discoverableagent-docwindow by name, sync fails closed and preserves layout instead of reconciling remembered docs onto the wrong window - Current tmux session resolution is pane-owned — route, sync, preflight, and parallel dispatch resolve the current session from
TMUX_PANEwhen available, so another attached client's selected session cannot pull the active agent-doc window into the wrong tmux session - Normal route/start/sync no longer re-elect owners from legacy pane heuristics — the normal path now asks the project controller for the authoritative actor binding before using supervisor-backed registry compatibility evidence.
session-actors.json, session-log owners,registry_rebindsuccessors, and generic same-file process-tree matches remain projections or repair diagnostics, not owner-election inputs. - Project controller IPC is bounded against stalled clients — controller clients time out instead of blocking forever waiting for a response, the server handles accepted clients independently so one idle socket cannot monopolize
.agent-doc/controller.sock, and readiness checks release their socket before issuing follow-up RPCs. - Supervisor lifecycle reports now go through the project controller —
agent-doc startlazy-launches the project controller, records the starting actor generation and supervisor lease, and reports prompt-ready, busy dispatch, waiting-input, blocked, and closed transitions through controller IPC with stale session/pane/generation rejection. A newer register/heartbeat from the same supervisor lease can replace aClosedactor for the same pane, which lets a reopened Codex/OpenCode child in the same route-owned supervisor become authoritative immediately instead of replaying the closed session.session status/doctoralso refresh the controller lease heartbeat from a live supervisor only when the IPC state proves the same actor session, pane, and generation.session status <FILE>additionally prints direct live-pane evidence (alive-idle,alive-busy,closed-clean, orprojection-stale) from tmux current-command and recent output so projected controller state cannot hide a still-running pane; when direct evidence is idle but projections remain busy, status/clear reconcile the actor and controller lease back to ready. File-scoped restart refusesalive-busypanes. Every turn stage independently detects a proven-stale supervisor and writes the same idempotent, CRDT-checkpointed recycle request; the controller waits for a safe idle boundary before replacing the process, and no stale marker is inserted into the document. This integrity recovery applies even when proactive recycle polling is opted out. File-scoped clear is an explicit operator action: it does not refuse solely becausepane_current_commandisagent-doc, but it still refuses protected prompt input and explicit busy cues such as an active Codex turn, hook-review prompt, or help screen.session interrupt-clear <FILE>is the explicit discard path that interrupts the owning pane, waits for idle/closed evidence, then retries clear. Interrupt-clear timeouts include the final blocking state, evidence source, prompt-ready value, current command, and recent pane tail in both ops logs and user-facing errors. - Supervisor recycle gates are controller projections — route/direct/dispatch-only callers no longer poll recycle-in-flight marker files before injecting work. Recycle starts and settles are recorded as lazily-backed
SupervisorRecycleStarted/SupervisorRecycleSettledfacts in the project controller; prompt injection waits on the controller projection so a trigger cannot disappear during supervisorexecve. Self-driving loop yield forstale_binary_drainandstate_flush_drainuses the same projection, so preflight/session-check/queue continuation reportqueue_recycle_yield=truewhile the supervisor is recycling and then continue once the projection settles. - Installing the cdylib auto-broadcasts a reload to editor plugins (
#cdylib-reload-broadcast) —agent-doc lib-install(andmake install) writes a single global reload-broadcast file (agent-doc-reload-broadcast.json, a sibling of the installed cdylib) after the symlink swap and controller/supervisor auto-recycle. The JetBrains and VS Code plugins both watch that global file and, when it changes, force their existing native cdylib-reload path immediately instead of waiting for the next lazy mtime-checked FFI call — so a fresh build goes live in the editor without a manual plugin restart. The broadcast write is best-effort (a failure is logged, never swallowed, and never fails the install).agent-doc admin reload-libre-announces the broadcast for the currently-installed cdylib on demand (the API-driven "reload via install broadcast" counterpart toadmin recycle) and reports how many editor-connected project roots it could also signal directly. Transport-symmetric: JetBrains additionally force-reloads on areload_libsocket message; running supervisors/controllers still recycle onto the new binary at their idle boundary. agent-doc admin recycle <FILE>just works;--forceonly interrupts a busy pane (#recycle-no-boundaries) —admin recyclere-execs a live controller onto the fresh binary at the next idle boundary. When no live controller answers the single-project form and a session-document path was supplied (agent-doc admin recycle <FILE>), it no longer dead-ends with "nothing to recycle": it escalates automatically to a kill+cold-start throughsession restart-supervisor— no--forcerequired — which routes a live supervisor to a continue-restart and a dead one to a cold-start, so a single command covers every degraded state. That escalation carries the same self-ancestor guard asadmin kill-supervisor(it never tears down the caller's own ancestor supervisor).--forceis a real flag (no--separator needed) that composes with--all-projectsand the single-project form; it overrides the controller-side cycle-open / in-flight-dispatch deferral so the recycle takes effect at the next serve-loop tick even mid-turn, and in the escalation path it interrupts a busy live pane (the default escalation keeps the busy-pane guard). It still requires the controller to beStableso it never strands a half-promoted handoff. A bare project-root /--project-rootform with no live controller has no document to cold-start and still prints a one-step remedy.--jsonaddsforced(andescalated_cold_starton the single-project arm).- Route re-checks associated-pane evidence immediately before cold-start — stale registered-pane cleanup does not relax the ownership guard. If a legacy associated pane becomes provable only after the earlier recovery branches run, route still fails closed instead of treating auto-start as a safe tie-breaker.
- Passive sync now fails closed on legacy associated panes instead of reclaiming them implicitly — when
sync --no-autostartsees only session-log/process-tree/registry_rebindevidence for a pane, it blocks that file and requires an explicit claim/repair instead of silently re-registering the pane or cold-starting around ambiguous ownership. - Route readiness is binary-owned — prompt detection / trigger acceptance lives in
route.rs, must tolerate shell startup noise, and keys off the actual harness prompt shapes rather than generic shell>echoes; the skill should not try to infer pane readiness from echoed command text - Route progress logging is UTF-8 safe — live reroute diagnostics trim captured tmux lines on char boundaries, so Unicode prompt/status glyphs such as
…or·cannot panic the binary while route is waiting for readiness - Harness-specific arg aliases —
agent_argsis the generic override;claude_args,codex_args, andopencode_argsare harness-specific aliases used only by their matching backends; submodule-hosted Claude/Codex documents also auto-add the superproject working tree plus any external git metadata directories they need (.git/modules/...plus the superproject.git) so workspace-write sessions can patch parent-repo docs and still complete the normal git lifecycle - Streaming — recovery-only partial checkpoints followed by one final CRDT write (
agent-doc stream), with optional chain-of-thought routing - Task orchestration —
agent-doc orchestrate --mode sequential|parallel|daggives one surface for stepwise fresh-agent execution, worktree fan-out, and dependency-aware DAG scheduling; sequential injects each prompt intoexchange, buffers backend streaming outside the document, and publishes one complete response throughfinalize+session-check; parallel preserves the existing worktree backend, DAG mode honors dependencies in deterministic topological order, and--mode dag --from-queuepersists an auto-DAG schedule plus schedule-backed job packets for active queue batches - Auto-DAG queue scheduling — active
agent:queuebatches can be expanded intoagent-doc-auto-dag-schedule-v1nodes with dependency batches, node state, attempt counts, replay/repair commands, tsift graph/ownership gates, and ops-log guard decisions before child work launches;--resume-schedule <ID>resumes the durable schedule without relaunching complete or failed/gated nodes - tsift graph-backed planning — when a materialized
.tsift/graph.dbworks,planandorchestrateattachgraph-db evidencehandles plusconflict-matrixownership summaries to queueddo #idwork and pass bounded<tsift_graph_evidence>context to child/job prompts without writing that context into the session document; if tsift is stale, unavailable, times out, or violates the graph contract, agent-doc warns and continues without graph evidence/manual packets instead of failing the whole turn - Editor plugins — JetBrains and VS Code plugins for hotkey integration and IPC writes
- Watch daemon — auto-submit on file change with debounce and reactive mode for stream documents; watched markdown sessions also emit node-keyed
document_node_eventsbatches for AST insert/remove/replace/move/strike/unstrike changes - Linked resources —
linksfrontmatter field for local files and URLs; URL content fetched, converted HTML→markdown viahtmd, cached, and diffed on each preflight - Session logging — persistent logs at
.agent-doc/logs/<session-uuid>.logfor debugging session crashes and restarts - Preflight gate —
agent-doc preflightauto-recovers openresponse_captured/write_appliedcycles, treatsstaged snapshot already matches HEADas an already-committed no-op closeout instead ofcommit_failed, repairs stalepreflight_startedlocks when the recorded snapshot/file hashes still match exactly, otherwise still requires a real pending/capture replay before auto-closingpreflight_started, fails closed when an emptypreflight_startedcycle has unresolved prompt-bearing drift and no response capture to replay, fails closed on unrecoverablepreflight_starteddrift instead of snapshot-committing over newer live content, also fails closed on hidden uncommitted closeout drift (snapshot != HEAD/ visible bypassed### Re:with no recoverable cycle) before diffing, preserves ordinary post-exchange HTML comments as user scratch content, does not auto-compact exchanges during preflight, emitswarnings[]such asharness_mismatchwhen frontmatteragent:differs from the detected active harness andstale_installwhen installed/builtagent-docartifacts predate the latest source commit (#install-stale-guard, dogfood/dev only), and emitseffective_tier,required_tier,suggested_tier,model_switch(_tier),agent_model, plus boundedsession_accretionwarnings when exchange/log heuristics show churn-heavy growth - Bounded recent-context packs — when resumed prompt targets land in a warn/block accretion session,
run/stream/orchestratekeep the full document on disk but replace the full exchange tail in the agent prompt with a bounded pack containing prompt targets, session summary, backlog head, a lightweight live+archive response TOC, and the### Re:turns anchored to those prompt positions inexchange(the enclosing response for inline edits, or the immediately previous response for tail prompts), plus a reminder to ask for older turns or useagent-doc response-fetchwhen no clean anchor exists or more neighboring history is required - Accretion advisory —
session_accretionstill summarizes exchange growth, closeout churn, and restart-heavy reopen signals so prompts can choose bounded recent-context packs or suggest compaction/restart when useful. These signals remain advisory:agent-doc planmust not turn exchange-size accretion or repeated no-op closeout churn into acompacthandoff unless the prompt or document explicitly requests compaction. Claude skill auto-update uses restart by default;/compactreload is allowed only with explicitagent_doc_auto_compactfrontmatter or project.agent-doc/config.tomlopt-in. A Codex skill-version mismatch installs without a reload request, re-reads the installed skill completely, and continues the active turn in place (#codex-skill-reload-in-place). - Durable response capture — every final response is persisted to
.agent-doc/captures/<doc-hash>/<cycle-id>.jsonbefore write-back, so interrupted cycles can replay the exact response body instead of regenerating it; streaming paths also keep the latest partial output in<cycle-id>.partial.jsoncheckpoints without treating those incomplete checkpoints as replayable final captures; lifecycle timestamps such asreplayed_atandcommitted_atpreserve whether a response only patchbacked later during recovery - Backbone closeout facts — accepted cycle-state transitions append typed lazily state-backbone facts (
PreflightStarted,ResponseCaptured,WriteApplied,CommitObserved,CycleAbandoned) using stable event ids, so lifecycle re-entry can prove or replay transitions without relying solely on.agent-doc/state/cycles/<doc-hash>.json;session-checkand preflight now prefer the closeout projection for open/terminal phase authority, preflight fails closed when an open projection is hidden behind missing or mismatched-stale JSON recovery state, and the JSON remains a compatibility recovery projection for detailed guard/recovery payloads while the remaining readers migrate - Git-owned commit proof — real commits and already-current no-op closeouts append an exact
HEADSHACommitObservedfact into the closeout projection, superseding the cycle-state bridge's compatibility content-hash observation when git proof is available - Bidirectional transport proof — maintained editor plugins publish lazily transport receipt facts (
EditorPatchApplied/EditorPatchRejected) alongside binary write intent / expected response hash and visible-buffer hash facts; ACK-only plugins are incompatible and closeout reads the lazily projection instead of treating whole-buffer sidecars as snapshot authority - Template exchange guard — template writes fail closed when prompt/response content escapes either below
<!-- /agent:exchange -->or into the gap before later agent components such as backlog; explicit repair/compaction still normalize the safe escaped-conversation shapes, while comment-only notes without escaped conversation headings stay outside and ambiguous mixed structure is rejected - Boundary singleton guard — outside fenced examples, a session document may contain exactly one
agent:boundarymarker and it must occupy its own tail line; ordinary write/finalize paths reject inline or duplicate markers before mutation, while explicit legacy repair collapses them after preserving complete exchanges - IPC timeout ordering guard — timeout fallbacks and
repairnow normalize stale-boundary response placement so multi-paragraph prompt text stays before the assistant response and the boundary closes the completed turn; if that order cannot be proven, closeout fails closed instead of committing a split prompt - Backlog prompt cleanup — when a template/CRDT closeout answers prompt-target text typed directly inside
agent:backlog/ legacyagent:pending, the write path removes those resolved raw prompt lines after merging the exchange response while preserving ordinary backlog edits and pending state changes - Cross-document backlog capture — prompt presets or user instructions that name another backlog file must close through
--pending-add-to <target-file> "<item>", so the item is added to the named document instead of the current session. The write path fails closed when the target is missing or lacks anagent:backlog/agent:pendingcomponent. - Respect manual cleanup — if a user deletes that escaped conversation tail by hand in a template doc,
agent-doc repairnow discards the stale captured response and advances the snapshot to the repaired file instead of failing on a capture-baseline mismatch or reapplying the removed tail repaircloses git-backed recovery immediately — directagent-doc repair(legacy alias:recover) now runs the normal commit boundary after replaying or deduping a pending response in git, instead of leaving repaired assistant content uncommitted until a laterpreflight- Hard response commit boundary — every appended response should cross a commit boundary unless the operator explicitly wants it left open; the normal happy path is
agent-doc finalize <file>, while missed-patchback repair usesagent-doc write --commit <file> - Explicit no-followup closeout — pass
--no-followups(alias--no-pending-capture) on the firstfinalizeattempt when the response intentionally creates no actionable follow-up work. The runtime records that intent as transient pending-capture evidence for retry/pre-commit checks and removes it from the visible and committed document; agents do not need to search for or inject the internal guard marker. - Manual repo commit ordering keeps the session doc on the finalize path — when an
agent-docturn includes ordinary repocommit + push, manual git commits should stage only the intended non-session repo files, stop immediately on any stage failure, verify the staged diff still matches that intended path set, and commit only that validated set. The session document itself still closes throughagent-doc finalize <file>oragent-doc write --commit <file>, and the push happens after that closeout commit lands so the response commit is included - Harness-native entrypoints are binary-owned workflow starts —
/agent-doc <file>in Claude Code,agent-doc <file>in Codex/OpenCode/direct-exec, and equivalent harness-native entry forms must be treated as the start of the binary-managed response cycle, not as permission to patch the document manually and later say "not committed" - Session-document
write --commitis strict — whenwrite --commitis used to patch back a response into a real session document (agent_doc_session/ legacysession), it now requires git before mutation and only succeeds once the cycle reachescommitted; best-effort--commitremains only for non-session docs and--pending-onlymaintenance - Mode-aware bare/run entrypoint —
agent-doc <file>andagent-doc run <file>now share the same document-mode-aware path: template docs use template patchback, append docs use inline blocks, and missing format defaults to template - Direct run dispatch is bounded and foreground-safe — after
runopens its freshpreflight_startedcycle, the agent child has a bounded wait (AGENT_DOC_RUN_AGENT_TIMEOUT_SECS, default 1800s). Timeout or recursive Codex-in-owning-pane invocation records a recoverablepreflight_startedtimeout event with cycle/pane/actor diagnostics instead of leaving the CLI silent afterSubmitting to codex.... Whenrunis 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.logunless verbose input diagnostics are enabled, so progress output cannot paint over the foreground TUI after a restart - Owner-pane self-invocation preserves the unresolved prompt (
#codex-owned-pane-prompt-miss) — when a Codex-owned pane re-invokesagent-doc <file>for the document it already owns and an unresolved exchange prompt is still pending,runnow fails closed before pre-commit and before opening a cycle. The diagnostic names the unresolved prompt and the in-pane recovery path (answer it in this owner pane's turn, then persist withagent-doc finalize/write --commit) and tells the operator not to re-run the same direct command from the same pane. Because the early guard bails before pre-commit, the prompt stays uncommitted and executable instead of being baselined intoHEADby the older late recursive-deadlock guard (which still abandons the empty cycle for the no-prompt / queue-only case).session-checkis the backstop: an abandonedrecursive_direct_invocation_blockedcycle with an unresolved exchange prompt still remaining is reported as a missed-prompt recovery, not accepted as terminal closeout - Direct run never dispatches an already-committed repair diff — if pre-commit repair proves the only diff was an already-committed missed patchback and no new response body exists,
runrechecks the diff, stops before invoking the child agent, and points the operator toagent-doc write --commit <file> - Run closeout is durable before commit — once
runhas written the final response (and anyresumeupdate), it recordswrite_appliedbefore the post-write commit so interrupted runs can be finished deterministically bypreflight; git-backedrunnow shares the same strict post-write closeout helper asfinalize,write --commit,repair, and the Codex Stop-hook, so success also requires the snapshot/HEADproof plussession-check - Binary-owned finalize path —
agent-doc finalize <file>is the strict happy-path response command: it reuses the normal write pipeline but requires the document to live in git and fails unless the cycle reaches a terminal committed state - FlowCore closeout diagnostics — strict pre-write/pre-commit guard blocks, document-mutation patchback parse outcomes, repair recovery boundaries, committed-cycle late fallback rejection, and commit completion now emit typed
flow_eventrecords soagent-doc ops summarycan group closeout failures by stage instead of relying on ad hoc proof strings - Ops bug clusters —
agent-doc ops summaryranks closeout/captured-response drift, route/start replay gaps, Codex manifest warning storms, SQLite correlation counts, cross-harness markers, session-review guardrails, and working-tree drift with example lines plus file/session/cycle/thread correlation keys - Direct-exec post-write guard — the direct-exec Codex and OpenCode instruction path runs
agent-doc session-check <file>afterfinalizeor manualwrite --commit, and a nonzero check blocks success reporting until recovery finishes; it flags likely direct response patchbacks (### Re:/## Assistant) that bypassedagent-doc, names tracked side-effect files plus the exactagent-doc write --commit <FILE>repair path when the closeout is still only in the working tree, fails closed when committed-cycle exchange drift appends a prompt+response pair or other response content, fails closed when prompt-bearing user edits exist with no newer cycle start or when the live exchange tail is still prompt-only with no assistant response, and still self-heals already-committed historical response drift whenHEADproves the response is no longer out-of-band, including committed prompt+response pairs that precede newer local drift as long as that later drift did not add another assistant patchback - Optional closeout sidecars are advisory —
session-checkand related closeout helpers treat lateNotFoundreads for cycle-state, capture, startup-miss, ops-log, pre-response, and CRDT sidecars as absent state instead of surfacing a transientENOENTduring otherwise-valid closeout verification - Codex Stop-hook and repair replay guard —
agent-doc skill installfor Codex now also writes.codex/hooks.json, enablesfeatures.hooks = true, and sets[mcp_servers.agent-doc] default_tools_approval_mode = "approve", so agent-doc MCP calls do not repeatedly pause active Codex turns after local reinstall andUserPromptSubmittracks the active document even when the submitted prompt body includes injected AGENTS/instruction preambles ahead of the realagent-doc <FILE>line.Stopfirst tries to finish the response cycle deterministically fromlast_assistant_messageonly when that payload validates as a single assistant closeout; tracked state survives nested.agent-docroot / CWD drift and later-stop turn drift within the same Codex session, while transcript-shaped or full-document payloads are kept as diagnostics and blocked instead of being replayed. Guard comments such as<!-- no-pending-capture -->may wrap an otherwise valid patch response, and plain progress commentary before the first patch is stripped before replay. Direct template writes use the same guard when unmatched text surrounds an exchange patch, so progress prose is not appended intoagent:exchange. Iflast_assistant_messageis empty because Codex stopped after a tool-only/authentication step such as an MCP OAuth /authenticateflow, the hook still fails closed, saves a diagnostic record with the tracked prompt, and forces the turn back through the normalfinalize/session-checkrecovery boundary. The same replay-shape guard now fails closed insideagent-doc repair, writing blocked payload diagnostics under.agent-doc/repair-blocked/rather than appending a full exchange dump back intoagent:exchange. - Malformed patchback guard — template write paths reject responses that contain patch/replace markers but no closed patch blocks parsed, logging marker counts, patch counts, unmatched length, response hash, and source before failing. Socket IPC attempts also log payload shape and lazily visible-write receipt hashes/lengths so live corruption reports can identify whether the fault was malformed parsing, editor projection drift, or a stale fallback writer.
- Normal maintenance covers stale starting actors —
preflight,start, andsyncnow close stalestartingcontroller actors older than one hour unless a live supervisor PID still has a fresh heartbeat for that generation, then re-emitsession-actors.jsonfrom SQLite. A live but non-heartbeatingagent-doc startprocess does not keep a record instartingforever. The heavier orphan-file GC and old diagnostic pruning remain on the daily.agent-doc/gc.stampcadence. - MCP auth is a sub-step, not a closeout boundary — bundled harness instructions now state explicitly that browser/authenticate pauses inside an
agent-docturn do not satisfy the response boundary; after the auth step, the same turn must still close throughfinalize/write --commitplussession-check, or fail closed. - Explicit repair no longer false-passes blocked post-commit drift — when
agent-doc repair <file>finds no pending artifact butsession-checkwould still interrupt the document, the command now surfaces that interruption instead of printingNo pending response found. That keeps the committed-historical-patchback-plus-later-prompt shape fail-closed until a real new cycle starts. - Stale empty preflight cycles preserve unresolved prompts — if a prior pane died after
preflight_startedwith no response capture,repairabandons the stale empty cycle after the timeout instead of writing a placeholder response. The unresolved prompt stays in the document and the next preflight starts a fresh cycle for it; recent empty cycles still fail closed to protect live work. - Response persistence is the close-out boundary — the instruction surface now requires requested implementation / verification / build-install work to finish before
finalizeorwrite --commit; after that point onlysession-check, recovery, and final reporting remain - Imperative document edits execute work — bundled Claude/Codex/OpenCode instructions now explicitly treat document-local directives like
do #id,run tests,build + install,commit + push, and pending-item task text that starts with an imperative verb (for example[#id] Fix the cross-repo ...) as authorization to perform that repo work from the session document itself; the agent should execute the work or stop on a concrete blocker, not append false-progress status prose. The binary now rejects status-only/meta-onlyrun/finalizeresponses for those directive diffs unless they include concrete execution evidence or a blocker. - Harness-owned full-suite verification — agent harnesses must run the full project verification suite explicitly after code, test, build, or instruction-surface changes;
agent-docno longer installs a pre-commit hook that runs the whole suite implicitly - Tmux CI review for test turns — when an agent turn runs or changes tests, it should inspect the latest CI tmux leg with
gh run list --workflow CI --limit 1; failures after runner startup should be reproduced locally withmake tmux-ci, while queued/in-progress runs should be recorded without blocking the turn for CI completion. Empty-step/no-log jobs that GitHub never started, such as billing/spending-limit exhaustion, are external CI-start blockers to record alongside local verification evidence - Model-attributed response headers —
### Re:headings should carry the resolved model short name (gpt-5,opus-4-7), not the harness label (codex,claude). For Claude Code, theopusalias resolves to the current concrete Claude Code opus id before attribution. - Git integration — auto-commit each run; squash history with
agent-doc clean - Commit self-heal —
agent-doc commitcan absorb a narrowly-scoped missed agent patchback (status,### Re:response-block insertion, pending-ID superset) into the snapshot before staging, while still leaving plain user prompts uncommitted; when the snapshot lags behind an already-committed response inHEAD,commitnow repairs the snapshot up to that committedHEADstate before later local drift can no-op closeout, as long as the later drift did not add another assistant patchback, so stale snapshots cannot rewind the document; when the snapshot already matchesHEADbut the working tree has later local edits,commitnow classifies that as post-commit local drift and explains that those edits remain uncommitted instead of vaguely implying a missed patchback, and the follow-up case recordspost_commit_user_follow_upinstead of missed-response or out-of-band-write markers; aHEAD-current staged snapshot still closes the cycle as an explicit no-op instead of a falsecommit_failed - Extreme-drift guard stays conservative — if a tracked document's snapshot is badly stale,
commitwarns but does not re-sync the snapshot from the live file wholesale; bootstrap scaffold auto-resync is limited to files with noHEADentry yet so unanswered prompts cannot be swallowed into a commit - Clean post-commit cleanup — commit strips transient
(HEAD)markers from the staged snapshot so the committed blob stays clean, and post-commit cleanup now collapses snapshot/editor state back to the same clean boundary shape instead of leaving marker-only working-tree churn behind - Manual repair guidance is explicit across harnesses — bundled skill/runbook content now distinguishes missing-user-prompt insertion from missed-response repair for both Claude Code and Codex: once the prompt is already present, the default documented repair path is
agent-doc write --commit <file>, not direct file patching or a bare write-back that stops before commit - Generated harness instructions stay aligned — installed Claude/Codex/OpenCode hot-path instructions are rendered from one shared source surface and parity-tested so completion-boundary guidance cannot silently drift between
.claude/skills/agent-doc/SKILL.md,.codex/skills/agent-doc/SKILL.md, and.opencode/skills/agent-doc/SKILL.md; bundled runbooks and OKF concept files are installed beside those surfaces as dynamic context resources;audit-docsfails generated managed skill surfaces that no longer match the running binary and rejects retired generated rootAGENTS.md/.codex/AGENTS.mdsurfaces while preserving custom root instructions, audits the superproject install root by default from submodule checkouts, still honors explicit--root DIRfor submodule-local managed artifacts, and reports broad mtime freshness only as an advisory - Bulk resync — validates session state and fixes stale/orphaned panes in 2 subprocess calls instead of ~20-40;
--fix --session <name>relocates WrongSession panes via join-pane instead of killing them - Column memory —
.agent-doc/last_layout.jsonremembers column→agent-doc mapping; preserves 2-pane tmux layout when one editor column switches to a non-agent file - Stash + rescue — replaced panes are stashed (alive in background); stash rescue brings them back when the user switches to that document again
- Startup lock —
.agent-doc/starting/<hash>.lockwith 5s TTL prevents double-spawn when sync fires twice in quick succession - Component-aware baseline guard — detects stale baselines by comparing append-mode components only; user edits to replace-mode components (status, pending) don't trigger false positives
- Hook system — cross-session event coordination via
agent-doc hook fire/poll/listen/gc;post_write/post_commitevents now includecapture_idandresponse_sha256when a durable capture exists, the system integrates with Claude Code hooks viaPostToolUse, and Codex installs a repo-localUserPromptSubmit/Stopbridge through.codex/hooks.json - Slash command dispatch —
preflightextracts slash commands from user-added diff lines (parse_slash_commands); the SKILL executes them before responding; guards exclude code fences, blockquotes, and non-added lines. In routed editor sessions, a bare exchange slash-command line such as/clearis prompt-bearing even without a❯prefix and is queued for the idle supervisor instead of being answered as a normal agent-doc turn. - Dedupe stale patch cleanup — after removing duplicate blocks,
dedupealso deletes the stale.agent-doc/patches/<hash>.jsonto prevent the plugin's startup scan from re-applying removed content
License
Licensed under either of MIT or Apache-2.0 at your option.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file agent_doc-0.34.132-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: agent_doc-0.34.132-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 14.0 MB
- Tags: Python 3, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: maturin/1.12.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
56fc76c30d08854935fa7c121c504b48b10755c730738342e09e226d4669c297
|
|
| MD5 |
453d88b491cc4707e773483e8ac8197c
|
|
| BLAKE2b-256 |
20b21fb0dd4b272f159e405910e16bce8356edd56bb906aa928f836c33cf6d00
|