@scotthuang/agent-knock-knock 0.12.4 → 0.12.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,38 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.12.6 - 2026-08-12
4
+
5
+ ### Added
6
+
7
+ - Add manual-only terminal-scoped Codex approval for one exact visible prompt when a human-entered task has no AKK dispatch owner or usable foreground UUID, while requiring a fresh list token, status fingerprint, and explicit confirmation.
8
+
9
+ ### Fixed
10
+
11
+ - Let an advertised ordinary Codex task proceed once in a narrow pane when AKK has a complete but foreground-unbound rollout inventory, then bind only the rollout that uniquely accepts the exact request without an internal `/status` probe.
12
+ - Reconcile callbackless terminal completion locally, release the exact dispatch ledger, and restart pending candidate monitors after a crash without creating a Gateway outbox or replaying terminal input.
13
+
14
+ ### Changed
15
+
16
+ - Publish action contract 12 and Store writer protocol 5. Protocol 4 Stores upgrade through an atomic manifest-only writer fence.
17
+
18
+ ### Security
19
+
20
+ - Freeze released predecessor Turn history throughout deferred candidate binding, preserve separate same-UUID and different-UUID Session lineages, and keep zero, multiple, drifted, or uncertain request acceptance non-retryable.
21
+ - Revalidate manual approval and cancellation against the canonical terminal endpoint, process incarnation, dispatch snapshot, Session revision, and prompt immediately before terminal keys, while keeping auto-approval and provisional managed controls unavailable.
22
+ - Serialize deferred recovery as terminal-to-writer-to-state and treat Store or state-lock contention as monitor backoff rather than native-acceptance uncertainty.
23
+
24
+ ## 0.12.5 - 2026-08-12
25
+
26
+ ### Fixed
27
+
28
+ - Let an advertised terminal-scoped ordinary Codex first task proceed in a narrow pane without an internal `/status` probe when the existing status-card-only context has a verified zero rollout, then bind the new AKK Session to the exact rollout that accepts the request.
29
+ - Preserve strict UUID proof for explicit Session sends, responses, approvals, cancellations, lifecycle operations, and native inspection while keeping uncertain terminal input non-retryable.
30
+
31
+ ### Security
32
+
33
+ - Isolate deferred foreground sends in a zero-UUID provisional Session and require exact process, terminal, request-acceptance, ownership, and binding-generation evidence before promoting it to the native thread.
34
+ - Add Store protocol 4 writer fencing plus crash-safe deferred-transfer receipts and recovery across pre-input aborts, post-input uncertainty, same-thread handoff, acceptance backfill, and downgrade attempts without replaying terminal input.
35
+
3
36
  ## 0.12.4 - 2026-08-11
4
37
 
5
38
  ### Fixed
package/README.md CHANGED
@@ -83,9 +83,13 @@ terminal resource / process incarnation
83
83
  └─ Turn 3 (turn_id)
84
84
  ```
85
85
 
86
- Once an AKK session exists, an ordinary `send(session_id, request)` is **session-scoped**: it creates a new `turn_id` in that exact native coding-agent context and never silently follows a different thread now visible in the pane. A listed terminal may instead advertise a **terminal-scoped follow-current** send with its exact full `selector` and a fresh `expected_terminal_token`. Using that prefilled action says “continue in whatever verified context the human selected in this pane”; when the old Session is quiescent and the handoff is exact, AKK atomically detaches the old binding, restores or creates the Session for the live native thread, and only then creates the Turn. The token fences the terminal snapshot so a later pane, process, workspace, or native-thread change cannot be adopted by accident. Legacy selector-based first attach remains supported. Never infer a selector or token, copy one from another row, reuse one after another terminal action, or pass a selector as `session_id`. The `turn_id` is not a destination for later ordinary sends; it is the exact identity used for status, approval, cancellation, renewal, callback retry, close, and callback correlation. If a Turn is `waiting_for_openclaw`, `respond(turn_id, answer)` supplies the answer inside that same Turn instead of creating another one.
86
+ Once an AKK session exists, an ordinary `send(session_id, request)` is **session-scoped**: it creates a new `turn_id` in that exact native coding-agent context and never silently follows a different thread now visible in the pane. A listed terminal may instead advertise a **terminal-scoped follow-current** send with its exact full `selector` and a fresh `expected_terminal_token`. Using that prefilled action says “send this ordinary task to the current verified pane, even when AKK cannot yet name its foreground native thread.” The token fences the terminal, process, workspace, composer, dispatch owner, and—when present—the complete set of exact Codex rollout candidates. AKK sends the task once, then binds only the single rollout that durably accepts that exact request. Legacy selector-based first attach remains supported. Never infer a selector or token, copy one from another row, reuse one after another terminal action, or pass a selector as `session_id`. The `turn_id` is not a destination for later ordinary sends; it is the exact identity used for status, approval, cancellation, renewal, callback retry, close, and callback correlation. If a Turn is `waiting_for_openclaw`, `respond(turn_id, answer)` supplies the answer inside that same Turn instead of creating another one.
87
87
 
88
- Human-friendly selectors such as `only`, `codex`, `claude`, a terminal ID, or `@short-ref` remain a discovery layer. A natural-language tool call may preserve one only when the user explicitly named it; otherwise use the exact selector returned by `AKK list`, or omit it and require a unique eligible pane. Normally a managed row pre-fills its authoritative `session_id` for strict continuation. After a human changes the native thread outside AKK, an adoptable row instead pre-fills the exact terminal selector and `expected_terminal_token` for follow-current continuation. Merely observing that mismatch never mutates the Store. AKK advertises the fenced send only when it can prove a single source claim, exact live identity, idle empty composer, and no unresolved Turn, transition, dispatch, or approval. Active, ambiguous, stale, or unverifiable cases remain blocked and require the user to resolve or select the context explicitly. The same raw terminal row may advertise status, approval, cancellation, or orphan-close with its own prefilled `conversation_id` compatibility selector. Never infer, guess, or reuse compatibility selectors or tokens.
88
+ v12 generalizes the human-priority Codex path. It covers both a status-card-only Session with no rollout and a quiescent managed pane whose exact open-rollout inventory is complete but cannot identify the foreground candidate. Under the terminal lock, AKK isolates the old Session, creates a separate zero-UUID provisional Session and Turn, sends only the real task, and promotes that target only after the post-submit monitor finds a unique exact request acceptance in the pinned rollout domain. The resulting native UUID may match or differ from the old Session; it is never silently merged back into the predecessor. A narrow pane does not force `/status` for this ordinary terminal-scoped send. Until promotion commits, strict `session_id` send, `respond`, managed `approve`, `cancel`, native lifecycle, callback delivery, and `native_inspect` remain unavailable. If terminal delivery or native acceptance is uncertain, AKK does not retry the input.
89
+
90
+ v12 also separates human-confirmed Codex approval from managed attribution. When `list` can prove one exact visible Codex approval prompt, it may advertise a terminal-scoped `approve` even when the foreground rollout UUID is temporarily unavailable. The authority may be either one exact current AKK dispatch owner or one exact bound managed Session whose dispatch owner is already released; the latter covers a task that the human entered directly in the pane. After the user reviews the current `status` fingerprint and explicitly confirms, AKK revalidates the Store/terminal/process snapshot, token, and approval fingerprint immediately before sending the exact key once. This action does not attribute the approval to a Turn, mutate Session identity, or create a durable approval receipt, so an uncertain transport result must not be retried blindly. It is never available to auto-approve. Known native-thread changes, unresolved dispatches, transitions, stale tokens, or changed prompts remain blocked.
91
+
92
+ Human-friendly selectors such as `only`, `codex`, `claude`, a terminal ID, or `@short-ref` remain a discovery layer. A natural-language tool call may preserve one only when the user explicitly named it; otherwise use the exact selector returned by `AKK list`, or omit it and require a unique eligible pane. Normally a managed row pre-fills its authoritative `session_id` for strict continuation. A human-priority row instead pre-fills the exact terminal selector and `expected_terminal_token` for follow-current continuation. Merely observing a mismatch or an unbound rollout inventory never mutates the Store. AKK advertises the fenced send only when it can prove a single source claim, an exact live terminal/process incarnation, an idle empty composer, a stable complete rollout inventory, and no unresolved Turn, transition, dispatch, or approval. A foreground ambiguity inside that complete inventory may be resolved after the real request is accepted; incomplete, stale, or unverifiable evidence remains blocked. The same terminal row may advertise status, manual approval, cancellation, or orphan-close with its own prefilled `conversation_id` compatibility selector and, where required, a fresh token. Never infer, guess, or reuse compatibility selectors or tokens.
89
93
 
90
94
  An exact human switch while the old Session still has one active Turn is a decision point, not an automatic redirect. In that case the terminal row may expose `handoff_decision` instead of a follow-current send. Its nested `choices.take_over_current.action` is the only authoritative supersede action: after explicit user confirmation, invoke its complete `agent_knock_knock_close` arguments unchanged (`turn_id`, `reason="superseded_by_human_context_switch"`, and `expected_handoff_token`). The snapshot-bound close records the old Turn's disposition and sends no terminal input. Then list again and use only the newly advertised follow-current send; never chain the old token into a send. Choosing `keep_source` changes no AKK state: restore the old native thread in the Codex or Claude TUI, then refresh the list. A completed/changed Turn or another human thread switch makes the decision token stale and requires a fresh decision.
91
95
 
@@ -232,19 +236,19 @@ The core command surface is intentionally small:
232
236
 
233
237
  `/akk list` performs a controlled reconciliation across managed turns, and `/akk status` limits reconciliation to the selected turn. This can close records whose idle retention has elapsed and restore eligible missing monitors, but it does not send terminal input or retry callback delivery. Independently, the running OpenClaw plugin supervises eligible `waiting_for_agent` monitors every five seconds; this liveness pass only restores missing monitors and likewise never retries callback transport. Standalone shell queries are read-only unless `--reconcile` is explicitly passed, and resolving a selector never changes turn state.
234
238
 
235
- Selectors fail closed: `only` works only with one actionable target, `latest` requires a unique newest target, and `codex` or `claude` must identify exactly one eligible pane. These names and `@short-ref` are human-facing resolution inputs; a natural-language tool call may preserve one explicitly named by the user, but must not infer one. Managed JSON actions normally contain the authoritative full `session_id` or `turn_id`. For first attach, an unmanaged raw-terminal row's send action may instead contain its own prefilled `selector`. For a safe human handoff, a terminal row may prefill its exact full `selector` together with `expected_terminal_token`; preserve both exactly to follow the pane's current context. Its advertised raw controls may contain that row's prefilled `conversation_id`. No compatibility selector or token may be guessed, copied from another row, or passed in an authoritative ID field. Before every terminal operation, AKK revalidates the expected agent PID and provider-owned terminal identity, then confirms that the process and pane working directories still match; every send also revalidates the idle prompt immediately before typing.
239
+ Selectors fail closed: `only` works only with one actionable target, `latest` requires a unique newest target, and `codex` or `claude` must identify exactly one eligible pane. These names and `@short-ref` are human-facing resolution inputs; a natural-language tool call may preserve one explicitly named by the user, but must not infer one. Managed JSON actions normally contain the authoritative full `session_id` or `turn_id`. For first attach, an unmanaged raw-terminal row's send action may instead contain its own prefilled `selector`. For a human-priority current-pane send, a terminal row may prefill its exact full `selector` together with `expected_terminal_token`; preserve both exactly. A terminal-scoped manual Codex approval may likewise prefill its `conversation_id` and `expected_terminal_token`; preserve both and additionally use only the current status fingerprint after explicit user confirmation. No compatibility selector or token may be guessed, copied from another row, or passed in an authoritative ID field. Before every terminal operation, AKK revalidates the expected agent PID and provider-owned terminal identity, then confirms that the process and pane working directories still match; every send also revalidates the idle prompt immediately before typing.
236
240
 
237
241
  To ask AKK itself to change native context, first copy the full `terminal_id` from `/akk list`; lifecycle commands do not accept an ordinary-send `@short-ref` or loose agent selector. `/akk threads <exact-terminal-id>` lists exact, same-workspace candidates with a deterministic number, a collision-safe display-only `@short-id`, an opaque snapshot handle, and the complete UUID. `/akk resume-thread <exact-terminal-id>` without a selection shows that list. A complete UUID remains compatible. A number or short ID resolves only against the latest list displayed in the same OpenClaw session, while an opaque handle names its exact snapshot; all expire after five minutes and fail after terminal, process, workspace, binding, candidate-set, or relevant action changes. None is ever passed to Codex or Claude Code as native identity: AKK resolves the saved tuple back to its full UUID and fresh evidence tokens first. `previous` (or `刚才那个`) is advertised only when the current Session's latest committed lifecycle transition identifies exactly one currently verified resumable source; it never guesses from title, recency, or static lineage. `/akk new-thread` and its human alias `/akk clear-thread` start a clean context. AKK does not poll bindings or adopt observed switches in the background: a human-driven switch is adopted only as part of an explicit, fresh terminal-scoped send. If a recorded owner process exits, the next lifecycle listing can classify that sole historical binding as resumable, and the resume mutation compare-and-swap detaches it before touching the terminal. Stale, expired, unsupported, busy, ambiguous, active-elsewhere, or unverifiable transitions fail closed. Do not ask AKK to send `/clear`, `/new`, `/resume`, `/status`, Codex `/fork`, `/side`, or `/btw`, Claude `/branch`, or any other first-line native slash command as an ordinary task or answer; use an advertised AKK action, express the request in natural language, or enter an unsupported native command manually in the terminal UI.
238
242
 
239
- To request a native Codex status card or Claude Status panel, first run `agent_knock_knock_list` and use only that terminal row's advertised `native_inspect` action. The structured tool schema is closed to `inspection="status"`; callers cannot provide `/status` or another slash command as text. AKK serializes the inspection with terminal mutations, revalidates the fresh token and exact terminal identity, and returns only after it proves one fresh bounded status result and an idle postcondition. Codex status probes additionally require an exact viewport large enough to preserve the full Session UUID, cross the versioned paste-settle boundary, and dispatch Enter exactly once. An initially narrow or unknown viewport fails before text input with a widen/zoom diagnostic; post-injection viewport or composer drift fails closed before Enter and leaves the draft for manual inspection. For Claude, the inspection safely dismisses the exact modal once. It never turns ordinary `send` or `respond` into a slash-command escape hatch.
243
+ To request a native Codex status card or Claude Status panel, first run `agent_knock_knock_list` and use only that terminal row's advertised `native_inspect` action. The structured tool schema is closed to `inspection="status"`; callers cannot provide `/status` or another slash command as text. AKK serializes the inspection with terminal mutations, revalidates the fresh token and exact terminal identity, and returns only after it proves one fresh bounded status result and an idle postcondition. Codex status probes additionally require an exact viewport of at least 80 columns to preserve the full Session UUID, cross the versioned paste-settle boundary, and dispatch Enter exactly once. An initially narrow or unknown viewport fails before text input with a widen/zoom diagnostic; post-injection viewport or composer drift fails closed before Enter and leaves the draft for manual inspection. Codex `/status` and that viewport requirement apply only to operations that must prove the UUID before terminal input. An otherwise eligible terminal-scoped ordinary task can send once and bind from exact native acceptance afterward, so it does not run `/status` or fail merely because the pane is narrow. For Claude, the inspection safely dismisses the exact modal once. It never turns ordinary `send` or `respond` into a slash-command escape hatch.
240
244
 
241
- The top-level v10 `action_contracts` documents this closed inspection alongside the existing lifecycle and Turn actions. `available_actions` remains the authority for ordinary current actions. Two deliberate nested exceptions require explicit user confirmation: an active human-handoff conflict may expose the snapshot-bound `handoff_decision.choices.take_over_current.action`, while a collateral terminal-wide unresolved Turn may appear in `blocking_turns[]` with its exact Store-only `recovery_action`. An active handoff source Turn is never generically closable through `blocking_turns`; it remains governed only by the snapshot-bound handoff decision. Copy only the complete listed action, then refresh the list before doing anything else.
245
+ The top-level v12 `action_contracts` documents this closed inspection alongside human-priority current-pane send/approval, lifecycle, and Turn actions. `available_actions` remains the authority for ordinary current actions. Two deliberate nested exceptions require explicit user confirmation: an active human-handoff conflict may expose the snapshot-bound `handoff_decision.choices.take_over_current.action`, while a collateral terminal-wide unresolved Turn may appear in `blocking_turns[]` with its exact Store-only `recovery_action`. An active handoff source Turn is never generically closable through `blocking_turns`; it remains governed only by the snapshot-bound handoff decision. Copy only the complete listed action, then refresh the list before doing anything else.
242
246
 
243
247
  For natural-language tool use, `agent_knock_knock_list` is terminal-first. Each live pane appears exactly once in `terminals[]`; `process_state` reports whether its coding-agent process is alive and `activity_state` reports the parsed screen state. `managed.session_id` identifies the continuing AKK session, `managed.current_turn` is its optional active Turn, and `managed.recent_turn` is retained history; retained Turns do not occupy the terminal. A human-driven native-thread mismatch remains honestly classified as `management_state="conflict"`; its `handoff_state` is `external_handoff_adoptable` only when the row advertises the fenced follow-current `send`, otherwise it is `external_handoff_blocked`. Listing never performs the adoption. Pass `all=true` to include older entries in `managed.history`. By default, `unavailable_managed_turns[]` contains attention-needed records whose pane cannot be presented as a live terminal; `all=true` also includes retained unavailable history.
244
248
 
245
- Use only an `available_actions` entry returned in that snapshot, begin with its prefilled authoritative arguments, and supply every `missing_required` field. The only additional action sources are a terminal row's nested `handoff_decision.choices.take_over_current.action` and an exact `blocking_turns[].recovery_action`; both require explicit user confirmation and must be copied whole. A managed Session's strict `send` uses its prefilled `session_id` and creates a new Turn only in that Session's native context. A terminal-scoped follow-current `send` instead carries the selected row's exact full `selector` and `expected_terminal_token`; preserve both and add only `request`. This is the safe path for continuing after a human changed threads directly in the pane. Legacy first attach may still use a discovery selector explicitly named by the user or the unmanaged raw-terminal row's prefilled `selector`; do not infer or reuse one. `respond` is available only while a Turn is `waiting_for_openclaw`; it uses `turn_id` and keeps the answer inside that Turn. Managed status, approval, cancellation, renewal, callback retry, and close also use the exact `turn_id`. Native inspection instead uses the exact terminal row's `terminal_id`, closed `inspection`, and snapshot-bound `expected_binding_token`; do not substitute AKK status or ordinary send. A raw terminal may be controlled only through the exact status, approval, cancellation, or orphan-close action that its own row advertises with a prefilled `conversation_id`; never construct or guess one. `timeoutSeconds` is unsupported, and monitoring limits should be omitted unless the user explicitly asks to change them. AKK revalidates availability before every side effect.
249
+ Use only an `available_actions` entry returned in that snapshot, begin with its prefilled authoritative arguments, and supply every `missing_required` field. The only additional action sources are a terminal row's nested `handoff_decision.choices.take_over_current.action` and an exact `blocking_turns[].recovery_action`; both require explicit user confirmation and must be copied whole. A managed Session's strict `send` uses its prefilled `session_id` and creates a new Turn only in that Session's native context. A terminal-scoped follow-current `send` instead carries the selected row's exact full `selector` and `expected_terminal_token`; preserve both and add only `request`. This is the human-priority path when the pane is exact but its foreground Codex UUID is not yet attributable. Legacy first attach may still use a discovery selector explicitly named by the user or the unmanaged raw-terminal row's prefilled `selector`; do not infer or reuse one. `respond` is available only while a Turn is `waiting_for_openclaw`; it uses `turn_id` and keeps the answer inside that Turn. Managed status, approval, cancellation, renewal, callback retry, and close also use the exact `turn_id`. Native inspection instead uses the exact terminal row's `terminal_id`, closed `inspection`, and snapshot-bound `expected_binding_token`; do not substitute AKK status or ordinary send. A terminal-scoped manual Codex approval may use the exact listed `conversation_id` plus `expected_terminal_token` and the latest status fingerprint; it never authorizes auto-approve or changes managed identity. Other raw controls may be used only through the exact action their row advertises. `timeoutSeconds` is unsupported, and monitoring limits should be omitted unless the user explicitly asks to change them. AKK revalidates availability before every side effect.
246
250
 
247
- The top-level v10 action contracts include `send`, `native_inspect`, `list_resumable_threads`, `new_thread`, `resume_thread`, and the conflict-only `reconcile_binding` recovery action. `send` has two deliberately different managed scopes: `session_id` is strict context, while the exact terminal `selector` plus `expected_terminal_token` is follow-current context. A supported idle Codex or Claude Code terminal may advertise `native_inspect` with its exact terminal ID, the closed `status` inspection kind, and a fresh binding token. The terminal row also advertises `list_resumable_threads` and, when currently safe, `new_thread`. Thread listing is read-only with respect to Session/Turn state, takes only the full `terminal_id`, and returns a fresh `expected_binding_token` plus candidate rows; each `resumable=true` row retains its complete UUID and exact prefilled `resume_thread` action. If `previous` is present, use only its exact prefilled action for a natural-language “刚才那个” request. Numbers, short IDs, and handles are human display/navigation aids, never tool arguments or authoritative native identity. The `new_thread` and `resume_thread` mutations require the fresh token, and resume additionally requires the candidate's complete `native_thread_id` and opaque `candidate_token`. `reconcile_binding` remains a low-level compatibility/recovery action for a safely detachable conflict when no ordinary follow-current send is appropriate; it never adopts the replacement thread, sends terminal input, or creates a Turn. Never construct, guess, truncate, combine across snapshots, or reuse those values after another terminal action. Native inspection and lifecycle results contain no `turn_id` because no work was sent.
251
+ The top-level v12 action contracts include `send`, manual `approve`, `native_inspect`, `list_resumable_threads`, `new_thread`, `resume_thread`, and the conflict-only `reconcile_binding` recovery action. `send` has two deliberately different managed scopes: `session_id` is strict context, while the exact terminal `selector` plus `expected_terminal_token` is follow-current current-pane context. Manual Codex approval likewise has a strict managed-Turn form and a separately advertised terminal-scoped form; only the latter carries the terminal token, and neither permits the model to enable automatic approval. A supported idle Codex or Claude Code terminal may advertise `native_inspect` with its exact terminal ID, the closed `status` inspection kind, and a fresh binding token. The terminal row also advertises `list_resumable_threads` and, when currently safe, `new_thread`. Thread listing is read-only with respect to Session/Turn state, takes only the full `terminal_id`, and returns a fresh `expected_binding_token` plus candidate rows; each `resumable=true` row retains its complete UUID and exact prefilled `resume_thread` action. If `previous` is present, use only its exact prefilled action for a natural-language “刚才那个” request. Numbers, short IDs, and handles are human display/navigation aids, never tool arguments or authoritative native identity. The `new_thread` and `resume_thread` mutations require the fresh token, and resume additionally requires the candidate's complete `native_thread_id` and opaque `candidate_token`. `reconcile_binding` remains a low-level compatibility/recovery action for a safely detachable conflict when no ordinary follow-current send is appropriate; it never adopts the replacement thread, sends terminal input, or creates a Turn. Never construct, guess, truncate, combine across snapshots, or reuse those values after another terminal action. Native inspection and lifecycle results contain no `turn_id` because no work was sent.
248
252
 
249
253
  Workspace is not a routing boundary. AKK can list, inspect, and control verified panes across projects; when more than one target matches, use a selector to choose one explicitly.
250
254
 
@@ -278,7 +282,9 @@ For Claude Code, manual approval is deliberately narrow:
278
282
  - When no trusted rule matches, the callback takes the manual path. The user must personally inspect the named terminal pane, explicitly confirm the exact request, and then run `/akk approve @a1b2c3d4 --expected-approval-fingerprint <fresh-fingerprint>` using the fingerprint from that current notification; the hash-only callback is not sufficient for review.
279
283
  - AKK re-evaluates the evidence and revalidates the process and pane immediately before sending one Enter.
280
284
 
281
- Unknown, stale, changed, ambiguous, or unmanaged dialogs fail closed and must be resolved in the terminal.
285
+ For Codex, a currently visible one-time approval may also be handled through the terminal row's list-prefilled manual action when managed foreground UUID attribution is unavailable. The user must first inspect the current AKK status, explicitly confirm that exact prompt, and preserve the listed terminal token plus fresh approval fingerprint. The action is current-pane-only, sends the detected key once, leaves Session/Turn identity unchanged, and is never an auto-approval fallback.
286
+
287
+ Unknown, stale, changed, process-drifted, ownership-conflicted, or unmanaged dialogs without an advertised action fail closed and must be resolved in the terminal.
282
288
 
283
289
  Trusted Codex and hookless Claude terminal commands can optionally be auto-approved with a deterministic policy:
284
290
 
@@ -380,7 +386,7 @@ than a publishing prerequisite.
380
386
 
381
387
  Managed state now lives in the stable `~/.agent-knock-knock/store` root. Its manifest prevents an incompatible AKK writer from changing authoritative Session or Turn state. Directories use mode `0700`; state and log files use `0600`.
382
388
 
383
- The manifest checks storage format and writer behavior separately. An unknown `format_version` is not read. The current writer protocol is 3, and writer protocols 1 and 2 are its supported predecessors: inspection reports either as `upgradeable`. Before the first mutation publishes a protocol-3 manifest, AKK validates the predecessor Turn records, deterministically derives and durably materializes authoritative Session records, and quarantines ambiguous Session bindings instead of routing through them. Existing Turn state and event logs remain unchanged, and the manifest's `created_at` is preserved. Any other writer-protocol mismatch remains readable for normal queries, while explicit reconciliation reports `skipped` and every mutation fails closed before terminal or Gateway side effects.
389
+ The manifest checks storage format and writer behavior separately. An unknown `format_version` is not read. The current writer protocol is 5, and writer protocols 1, 2, 3, and 4 are its supported predecessors: inspection reports them as `upgradeable`. Upgrading protocol 1 or 2 validates predecessor Turn records, deterministically derives and durably materializes authoritative Session records, and quarantines ambiguous Session bindings before atomically publishing protocol 5. Protocols 3 and 4 already have Session authority, so their upgrade is an atomic manifest-only writer fence with no data migration. Existing Turn state and event logs remain unchanged, and the manifest's `created_at` is preserved. Any other writer-protocol mismatch remains readable for normal queries, while explicit reconciliation reports `skipped` and every mutation fails closed before terminal or Gateway side effects.
384
390
 
385
391
  The former `~/.agent-knock-knock/conversations` directory is left untouched; AKK does not read or migrate it. Existing Codex and Claude Code tmux panes remain available through live discovery, while their old managed-turn IDs, callback associations, and legacy conversation aliases are not carried into the new Store. Compatible future upgrades continue using the stable Store rather than creating a directory per package version.
386
392
 
@@ -26,12 +26,46 @@ export interface ActiveAgentSessionIdentity {
26
26
  };
27
27
  evidence: string;
28
28
  }
29
+ export interface CodexOpenRootRolloutIdentity extends ActiveAgentSessionIdentity {
30
+ processUuid: string;
31
+ processBirth: string;
32
+ rollout: {
33
+ fd: string;
34
+ device: string;
35
+ inode: string;
36
+ path: string;
37
+ };
38
+ evidence: "codex_open_root_rollout";
39
+ }
40
+ interface CodexOpenRootRolloutInventoryBase {
41
+ schema: "agent-knock-knock/codex-open-root-rollout-inventory";
42
+ version: 1;
43
+ pid: number;
44
+ processUuid: string;
45
+ processBirth: string;
46
+ cwd?: string;
47
+ roots: CodexOpenRootRolloutIdentity[];
48
+ inventoryFingerprint: string;
49
+ }
50
+ export type CodexOpenRootRolloutInventory = (CodexOpenRootRolloutInventoryBase & {
51
+ status: "verified_absent";
52
+ roots: [];
53
+ }) | (CodexOpenRootRolloutInventoryBase & {
54
+ status: "resolved";
55
+ roots: [CodexOpenRootRolloutIdentity];
56
+ }) | (CodexOpenRootRolloutInventoryBase & {
57
+ status: "unbound";
58
+ reason: "multiple_open_root_rollouts";
59
+ roots: CodexOpenRootRolloutIdentity[];
60
+ });
29
61
  export interface CodingAgentSessionProvider {
30
62
  agent: CodingAgentSessionProviderAgent;
31
63
  getCapabilities(): Promise<AgentSessionCapabilities>;
32
64
  listHistoricalSessions(): Promise<CodexSessionSummary[]>;
33
65
  listActiveSessions(): Promise<ActiveCodexProcess[]>;
34
66
  resolveActiveSessionIdentityForPid(pid: number, cwd?: string, preferredSessionId?: string, allowedCompanionIdentity?: ActiveAgentSessionIdentity, allowedAdditionalIdentities?: readonly ActiveAgentSessionIdentity[]): Promise<ActiveAgentSessionIdentity | undefined>;
67
+ inspectOpenRootRolloutInventoryForPid?(pid: number, cwd?: string): Promise<CodexOpenRootRolloutInventory>;
35
68
  getSession(sessionId: string): Promise<CodexSessionSummary | undefined>;
36
69
  getForkContext(options: ForkContextOptions): Promise<ForkContextPackage | undefined>;
37
70
  }
71
+ export {};