@staix/agent-hub 0.23.0 → 0.23.1

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
@@ -4,6 +4,13 @@ Issue and pull request numbers in the entries for 0.7.7 and earlier refer to the
4
4
 
5
5
  ## Unreleased
6
6
 
7
+ ## 0.23.1
8
+
9
+ - Pin `@staix/agent-mem` 0.14.0 (was 0.13.0). The hub uses the library API and does not activate amem 0.14.0's opt-in v2 public prune view (`amem migrate --public-prune-view`), so hub recall, capture, briefs and existing homes are unchanged. 0.13.0 and earlier readers refuse an activated v2 home: before a person activates it, upgrade every hub sharing the memory home to 0.23.1 or later (which bundles amem 0.14.0) and every global `amem` CLI to 0.14.0.
10
+ - Claude Code 2.1.314 is a receipt-verified headless implementer version (#888, #996): the model-free permission-transport and host shell-wrapper producers pass on it with 2.1.310 as the control (`docs/verification/2026-10-31-claude-implementer-2.1.314.md`). 2.1.311-2.1.313 stay unverified.
11
+ - Codex 0.166.0 stays an unverified reviewer version (#888, #997): it passed the model-free isolation procedure (`docs/verification/2026-10-31-codex-0166-reviewer-isolation.md`), but its one authorized model review missed the required synthetic marker in the persisted verdict (`docs/verification/2026-10-31-codex-0166-reviewer-tool-call.md`), so the proposed verified bump was reverted. The compat receipt pointer names the 0.166.0 isolation receipt; verified stays 0.146.0, 0.163.0 and 0.164.0.
12
+ - Kimi Code 2.4.1 is a receipt-verified fresh reviewer version and Qwen Code 0.26.4 a receipt-verified ACP version (#888, #1002), both model-free (`docs/verification/2026-10-31-kimi-241-reviewer-compat.md`, `docs/verification/2026-10-31-qwen-0264-acp.md`). The Qwen dual-output TUI stays verified on 0.26.1 only; the separate 0.26.4 dual-output attempt did not qualify (`docs/verification/2026-10-31-qwen-0264-dual-output.md`).
13
+
7
14
  ## 0.23.0
8
15
 
9
16
  - Write and external invocations (#445 C3, task 180, #991): a shared `write` or `external` capability runs only for a caller's open non-PII task (`hub_invoke` `task`) and only after a person allows that one call; unattended hubs refuse before prompting, and `destructive` still never runs. The approval shows caller, target, capability, class, digest, task and the screened, sanitized arguments (200 characters per value, marked when cut); the previews stay on person permission surfaces and never reach audit, events or logs. Every admission gate is rechecked after the approval. The task history records an invocation's queued and terminal metadata without changing the task's state. Only a `read` may replay, at most once after a safe failure; an uncertain write or external outcome is held as `needs_review`, never retried. `hub_invoke` waits up to the approval window instead of the 30 s tool timeout, and a closed or cancelled call is withdrawn before it can be granted. Not live-verified (C4).
package/README.md CHANGED
@@ -5,7 +5,7 @@ Code, Codex, Kimi Code, Pi and a hub-owned local worker (plus Qwen Code, Jcode a
5
5
  Antigravity if you want them) share a message bus, a task board and a memory, each
6
6
  connected through its own native interface.
7
7
 
8
- Status: 0.23.0, control protocol 16. Bun + TypeScript, one loopback daemon per
8
+ Status: 0.23.1, control protocol 16. Bun + TypeScript, one loopback daemon per
9
9
  project. Site: [agent-hub.staix.net](https://agent-hub.staix.net).
10
10
 
11
11
  ## Quick start
@@ -94,7 +94,7 @@ uses the home must run a version that understands the new layout.
94
94
  [#258](https://github.com/STAIxBWLB/agent-hub/issues/258)).
95
95
 
96
96
  Live checks that still need a real account or a person are listed in the
97
- [release verification report](docs/verification/2026-10-30-0.23.0.md) and the
97
+ [release verification report](docs/verification/2026-10-31-0.23.1.md) and the
98
98
  [smoke checklist](docs/smoke.md).
99
99
 
100
100
  ## Documentation
package/docs/memory.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Hub memory integration
2
2
 
3
- Agent-hub consumes the exact-pinned first-party [`@staix/agent-mem`](https://github.com/STAIxBWLB/agent-mem) library (current pin `0.13.0`, initial pin `0.1.1`). The package owns portable storage, tiers, graph, goals, sync, import and raw commands. Agent-hub owns caller authority, current project privacy policy, task lifecycle integration and presentation. Claude-mem is an optional, explicit import source only; runtime recall and capture make no worker HTTP requests.
3
+ Agent-hub consumes the exact-pinned first-party [`@staix/agent-mem`](https://github.com/STAIxBWLB/agent-mem) library (current pin `0.14.0`, initial pin `0.1.1`). The package owns portable storage, tiers, graph, goals, sync, import and raw commands. Agent-hub owns caller authority, current project privacy policy, task lifecycle integration and presentation. Claude-mem is an optional, explicit import source only; runtime recall and capture make no worker HTTP requests.
4
4
 
5
5
  ## Portable core and data directory
6
6
 
@@ -1441,7 +1441,7 @@ ahub memory forget 1a2b3c4d # a person's; also promote, demote, sup
1441
1441
 
1442
1442
  `"memory": { "native": false }` in `.agenthub/config.json` turns it off for a project.
1443
1443
 
1444
- The exact-pinned `@staix/agent-mem` 0.13.0 resolves `AMEM_HOME`, then `$AGENTHUB_HOME/memory`, then `~/.agenthub/memory`. An absent `M/profile.json` selects shared v1; an explicit generation selects `M/generations/G` with the package's readonly legacy bridge. All daemon memory consumers and the hub memory/goal CLI use that selected profile. Invalid metadata or a missing selected generation makes native memory unavailable while the bus and board continue; there is no fallback to legacy writes. Inspect the daemon's memory binding/availability before interpreting missing memory as an empty store.
1444
+ The exact-pinned `@staix/agent-mem` 0.14.0 resolves `AMEM_HOME`, then `$AGENTHUB_HOME/memory`, then `~/.agenthub/memory`. An absent `M/profile.json` selects shared v1; an explicit generation selects `M/generations/G` with the package's readonly legacy bridge. All daemon memory consumers and the hub memory/goal CLI use that selected profile. Invalid metadata or a missing selected generation makes native memory unavailable while the bus and board continue; there is no fallback to legacy writes. Inspect the daemon's memory binding/availability before interpreting missing memory as an empty store.
1445
1445
 
1446
1446
  The daemon checks its selector at hub operation entry and before candidate/counter writes. It does not hot-switch handles or provide an atomic fence against selection changes during an in-flight core call. Quiesce consumers and close their handles before migration or selection changes; reopen through the supported session-preserving lifecycle afterward. Candidate/counter storage remains `M/candidates.db`, independent of `G`; since agent-mem 0.7.0 `amem review` also lists and accepts candidates on a selected generation. Every running hub using this home needs an authenticated receipt: a matching ready binding, or a generation-capable unbound receipt (`disabled` when native memory is off, `unavailable` when opening failed) proving it holds no memory handle. An unbound daemon and zero running hubs are quiesced for memory; a stale bound handle, unreadable registry or unknown runtime is not ready. Existing JSON memory/goal results remain unchanged; the additive binding receipt belongs to daemon status, profile-check and the decay object. This source integration does not authorize installing a new runtime, migrating real memory, restarting sessions or claiming real-machine sync/capture receipts. Migration/deactivation and their limits belong to [agent-mem](https://github.com/STAIxBWLB/agent-mem); see [the hub profile contract](memory.md#selected-memory-profile).
1447
1447
 
@@ -4100,7 +4100,7 @@ selected roster and existing capabilities; the TUI is always a person's start.
4100
4100
 
4101
4101
  ### Qwen's own TUI, driven through dual output (#286 Part 3)
4102
4102
 
4103
- `ahub qwen --mode tui` runs `qwen --input-file <in> --json-file <out> --mcp-config <hub server> --approval-mode default` in the terminal you ran it from. The daemon prepares the two files (mode 0600, under `<state dir>/qwen/qwen-dual/`) and returns the launch; the hub then appends one `submit` line per delivery and tails the event file from a saved offset. It needs a Qwen the dual-output compat entry verifies (`ahub agents` shows `qwen-dual`, verified 0.26.1 only; the headless `qwen` entry is separate and unchanged) and refuses another version before it creates a file. The TUI is explicit only: `ahub qwen` without `--mode` is still headless, Qwen is not a start-mode peer, and the hub never opens this terminal by itself. The TUI start is refused for an extra Qwen instance, off roster, outside a terminal, and while a headless Qwen runs (`ahub stop qwen` first); a headless start is refused while the TUI holds its terminal.
4103
+ `ahub qwen --mode tui` runs `qwen --input-file <in> --json-file <out> --mcp-config <hub server> --approval-mode default` in the terminal you ran it from. The daemon prepares the two files (mode 0600, under `<state dir>/qwen/qwen-dual/`) and returns the launch; the hub then appends one `submit` line per delivery and tails the event file from a saved offset. It needs a Qwen the dual-output compat entry verifies (`ahub agents` shows `qwen-dual`, verified 0.26.1 only; the headless `qwen` entry has its own ACP receipts) and refuses another version before it creates a file. The TUI is explicit only: `ahub qwen` without `--mode` is still headless, Qwen is not a start-mode peer, and the hub never opens this terminal by itself. The TUI start is refused for an extra Qwen instance, off roster, outside a terminal, and while a headless Qwen runs (`ahub stop qwen` first); a headless start is refused while the TUI holds its terminal.
4104
4104
 
4105
4105
  - What the hub does: a delivery becomes a `submit`; the last assistant message of the turn (an `assistant` event whose `stop_reason` is not `tool_use`, then `message_stop`) is shared as the answer; busy and idle follow the events. A `can_use_tool` request goes to the console approval path (`ahub permit`, the dashboard), and the hub's own tools are approved only by their exact `mcp__agent-hub__<tool>` name. If you answer a prompt in the Qwen terminal first, the hub's pending approval is withdrawn.
4106
4106
  - **Limit 1, a deny ends the turn without an answer.** Qwen emits nothing when the hub denies: it cancels the whole turn. The hub ends the turn itself, shares no answer, settles the delivery as `completed` (a deny is a known outcome, and a `needs_review` would hold every later message to Qwen until a person resolved it) and says so in a notice. A turn whose outcome is not known (Qwen exited, an Esc followed by a new prompt, an event file that became unreadable) is the one that settles `needs_review`. Qwen's own notice that a background shell finished (a `user` event that is wholly one or more `<task-notification>` envelopes) is not a new prompt: it ends no hub turn and leaves an idle peer idle (task 517).
@@ -4109,7 +4109,7 @@ selected roster and existing capabilities; the TUI is always a person's start.
4109
4109
  - If the hub cannot read the event file the peer is `detached`, shown as offline with a notice, never idle: Qwen itself keeps working, and the hub reattaches when the file is readable again.
4110
4110
  - Restart: if the hub restarts while your Qwen keeps running, it reads on from its saved offset (no event twice, no launch). If Qwen is gone, `ahub qwen --mode tui` starts `qwen -r <session id>` on the same two files; the earlier submits are not replayed and the recorded answers are not shared again. Recovery never restores this terminal as a headless worker, and `ahub stop qwen` refuses: end Qwen in its own terminal.
4111
4111
 
4112
- Receipt-verified native ACP identities are qwen-code 0.25.0 and 0.26.0 ([dated receipt](verification/2026-10-22-kimi-qwen-compat.md)) and 0.26.1 ([0.26.1 receipt](verification/2026-10-26-qwen-0261-acp.md)). A CLI version label alone
4112
+ Receipt-verified native ACP identities are qwen-code 0.25.0 and 0.26.0 ([dated receipt](verification/2026-10-22-kimi-qwen-compat.md)), 0.26.1 ([0.26.1 receipt](verification/2026-10-26-qwen-0261-acp.md)) and 0.26.4 ([0.26.4 ACP receipt](verification/2026-10-31-qwen-0264-acp.md)). The separate [0.26.4 dual-output attempt](verification/2026-10-31-qwen-0264-dual-output.md) did not establish its queued-turn criterion, so `qwen-dual` stays at 0.26.1. A CLI version label alone
4113
4113
  is insufficient: startup verifies its native identity/version and advertised mode
4114
4114
  ids before any prompt. The earlier local installation reported CLI 0.25.0 while
4115
4115
  its package/ACP source said 0.24.1; that was not a ready identity. The 0.26.0 receipt
@@ -4743,7 +4743,7 @@ Default-branch capture runs only at daemon startup when a Claude implementer is
4743
4743
 
4744
4744
  Project Git retains the core policy that clears credential.helper and core.askpass; an HTTPS push needing those helpers may fail, rather than importing credentials or relaxing that policy. Task branch/config proof reads are bounded synchronous reads (1.5 seconds per reader); slow or unknown evidence asks. The existing sandbox profile discovery is also synchronous; moving it to an asynchronous inventory proof with a shared deadline remains a follow-up. The nonce is visible in a permission response, so it proves a bounded grant rather than native-dispatch provenance.
4745
4745
 
4746
- The [native permission receipt](verification/2026-10-23-headless-claude-permissions.md) covers Claude Code 2.1.309, and the [2.1.310 receipt](verification/2026-10-26-claude-implementer-2.1.310.md) repeats it on 2.1.310 (with 2.1.309 as a control), each with a deterministic loopback fixture and no real account/model call. It is not sandbox proof or a runtime receipt gate. The real account/model/person interaction remains a separate live leg.
4746
+ The [native permission receipt](verification/2026-10-23-headless-claude-permissions.md) covers Claude Code 2.1.309, and the [2.1.310 receipt](verification/2026-10-26-claude-implementer-2.1.310.md) repeats it on 2.1.310 (with 2.1.309 as a control), and the [2.1.314 receipt](verification/2026-10-31-claude-implementer-2.1.314.md) repeats it and the host-wrapper procedure on 2.1.314 (with 2.1.310 as a control), each with a deterministic loopback fixture and no real account/model call. It is not sandbox proof or a runtime receipt gate. The real account/model/person interaction remains a separate live leg.
4747
4747
 
4748
4748
  A headless Claude reviewer is run by the hub instead (task 223): declare
4749
4749
  `"claude-review": { "kind": "claude", "roles": ["reviewer"], "start_mode": "headless" }`
@@ -4781,9 +4781,9 @@ A reviewer has a review scope (#852): `full` (reads the code, runs the affected
4781
4781
 
4782
4782
  Start them with `ahub claude --as claude-review`, `ahub codex --as codex-review` and `ahub kimi --as kimi-review`; stop with `ahub stop <id>`. For the Claude and Codex reviewers the command asks the running hub to start the reviewer and returns: nothing runs in that terminal, it takes no launch arguments, and `--print-command` or `--dry-run` prints a hub-start note instead of a launch (#720). Fresh Claude and Codex variants share the project checkout; the Kimi variant runs in a clean temporary working directory and reviews only the screened brief and host facts. All fresh variants refuse a custom worktree or permission mode. Codex and Kimi require `review_mode: "fresh"`; without it, an existing headless instance with the reviewer role keeps its native app-server/ACP behavior, worktree and permission options and does not join this pool. Claude retains its task 223 automatic headless-reviewer declaration. The agy reviewer slot remains automatically unavailable (`agy is an implementer peer (#485)`). A failed or unsupported fresh start never downgrades to a native continuing session. Ordinary implementer instances retain their own adapters. The default logical pool order is Claude, Codex, Kimi. Only configured kinds with at least one declared reviewer count as slots, including declared ones that are offline, paused, quota-limited or failing, so availability never renumbers them; configured kinds with no declaration are listed after the walk as `no declared reviewer`. `review.rerotate` defaults to false. Pool selection starts at PR number modulo the number of declared kind slots, or task id when there is no PR, then skips the implementer's family and unavailable candidates. Delta review prefers the preceding eligible independent family in a fresh child. A preceding same-family fallback does not outrank a newly available independent family. `ahub route explain` shows the same pure walk.
4783
4783
 
4784
- Codex requires a verified `codex-cli` (0.146.0, 0.163.0 or 0.164.0) or one the person trusts on this machine, and a passing bounded runtime receipt before its model child starts. 0.146.0 and 0.163.0 passed the [2026-10-22 model-free production admission](verification/2026-10-22-codex-reviewer-isolation.md) and 0.164.0 the [2026-10-24 one](verification/2026-10-24-codex-0164-reviewer-isolation.md). A refusal names the installed and verified versions. Either set `codex_bin` to a verified executable, or run `ahub agents trust codex-review <version>`: trust lifts only the version pin, and every proof below still runs before each child (#691). Each launch approves exactly `hub_review` and `hub_task_show` per tool (`approval_mode = "approve"`), never through a server-wide default: without it Codex 0.164.0 listed the tools but refused the call, so reviews ended with no verdict (#783). A model-free receipt proves the inventory, not that a verdict reaches the hub; a [model-backed 0.164.0 run](verification/2026-10-25-codex-0164-reviewer-tool-call.md) recorded one verdict through that path. The producer checks native binary/config stability, configured MCP inventory with only the two hub tools, effective Apps/plugins/hooks disablement, an explicit empty legacy `notify` command and a named filesystem profile. Apps needs separate feature readback because configured inventory omits runtime connectors. Web search is requested disabled; its effective turn mode is not read back and managed requirements can select Cached (see the verification ceiling). Each launch proves public-read, exact/glob/symlink private-denial, standard host credential denial and write-denial in temporary fixtures. Standard credential and configured tool-home/XDG subtrees are denied independently of project `local.deny`. Its sandboxed shell is filesystem read-only with private paths denied and network configured disabled; it is not Claude's Read/Grep/Glob-only tool whitelist. No credential home is copied.
4784
+ Codex requires a verified `codex-cli` (0.146.0, 0.163.0 or 0.164.0) or one the person trusts on this machine, and a passing bounded runtime receipt before its model child starts. 0.146.0 and 0.163.0 passed the [2026-10-22 model-free production admission](verification/2026-10-22-codex-reviewer-isolation.md) and 0.164.0 the [2026-10-24 one](verification/2026-10-24-codex-0164-reviewer-isolation.md); 0.166.0 passed the [2026-10-31 model-free procedure](verification/2026-10-31-codex-0166-reviewer-isolation.md), but its [one authorized model review](verification/2026-10-31-codex-0166-reviewer-tool-call.md) missed the required synthetic marker in the persisted verdict, so the version remains unverified and its proposed verified bump was reverted. A refusal names the installed and verified versions. Either set `codex_bin` to a verified executable, or run `ahub agents trust codex-review <version>`: trust lifts only the version pin, and every proof below still runs before each child (#691). Each launch approves exactly `hub_review` and `hub_task_show` per tool (`approval_mode = "approve"`), never through a server-wide default: without it Codex 0.164.0 listed the tools but refused the call, so reviews ended with no verdict (#783). A model-free receipt proves the inventory, not that a verdict reaches the hub; a [model-backed 0.164.0 run](verification/2026-10-25-codex-0164-reviewer-tool-call.md) recorded one verdict through that path. The producer checks native binary/config stability, configured MCP inventory with only the two hub tools, effective Apps/plugins/hooks disablement, an explicit empty legacy `notify` command and a named filesystem profile. Apps needs separate feature readback because configured inventory omits runtime connectors. Web search is requested disabled; its effective turn mode is not read back and managed requirements can select Cached (see the verification ceiling). Each launch proves public-read, exact/glob/symlink private-denial, standard host credential denial and write-denial in temporary fixtures. Standard credential and configured tool-home/XDG subtrees are denied independently of project `local.deny`. Its sandboxed shell is filesystem read-only with private paths denied and network configured disabled; it is not Claude's Read/Grep/Glob-only tool whitelist. No credential home is copied.
4785
4785
 
4786
- Kimi requires a compat-admitted Kimi Code on the hub's PATH (receipt-verified 2.2.0, 2.3.0, 2.3.1 and 2.3.2), signed in through its managed OAuth provider, and a passing runtime preparation before each child; an unverified/untrusted version or a failed preparation is unavailable with its reason. The [2.3.0](verification/2026-10-22-kimi-qwen-compat.md), [2.3.1](verification/2026-10-25-kimi-231-reviewer-compat.md) and [2.3.2](verification/2026-10-26-kimi-232-reviewer-compat.md) receipts are model-free and do not verify real login/provider readiness. Each review runs a new `kimi -p` child without Seatbelt, in a private `KIMI_CODE_HOME` with managed-provider-only config, a clean temporary working directory and an empty skills directory. Its agent may call only `hub_review` and `hub_task_show`, through a task-bound loopback MCP session that never carries the hub's control token, and has no native read, file or shell tool: it reviews the screened brief and host facts only. Its `credentials/`, `oauth/` and `device_id` link to the person's native Kimi files, so it shares the native login, refresh lock and the Kimi account's budget; no token is copied. A stop revokes its verdict authority first, then waits briefly while an OAuth refresh holds the lock; a forced stop mid-refresh may require a native re-login. The Kimi backend records no measured token counts here, so its usage stays unknown; the 2.3.0 receipt makes no usage claim. This is a native tool-authority boundary, not filesystem or network isolation.
4786
+ Kimi requires a compat-admitted Kimi Code on the hub's PATH (receipt-verified 2.2.0, 2.3.0, 2.3.1, 2.3.2 and 2.4.1), signed in through its managed OAuth provider, and a passing runtime preparation before each child; an unverified/untrusted version or a failed preparation is unavailable with its reason. The [2.3.0](verification/2026-10-22-kimi-qwen-compat.md), [2.3.1](verification/2026-10-25-kimi-231-reviewer-compat.md), [2.3.2](verification/2026-10-26-kimi-232-reviewer-compat.md) and [2.4.1](verification/2026-10-31-kimi-241-reviewer-compat.md) receipts are model-free and do not verify real login/provider readiness. Each review runs a new `kimi -p` child without Seatbelt, in a private `KIMI_CODE_HOME` with managed-provider-only config, a clean temporary working directory and an empty skills directory. Its agent may call only `hub_review` and `hub_task_show`, through a task-bound loopback MCP session that never carries the hub's control token, and has no native read, file or shell tool: it reviews the screened brief and host facts only. Its `credentials/`, `oauth/` and `device_id` link to the person's native Kimi files, so it shares the native login, refresh lock and the Kimi account's budget; no token is copied. A stop revokes its verdict authority first, then waits briefly while an OAuth refresh holds the lock; a forced stop mid-refresh may require a native re-login. The Kimi backend records no measured token counts here, so its usage stays unknown; the 2.3.0 receipt makes no usage claim. This is a native tool-authority boundary, not filesystem or network isolation.
4787
4787
 
4788
4788
  A dangling or unreadable standard/configured credential root makes the Codex reviewer unavailable with only its path class in the reason (for example `~/.docker` or `$DOCKER_CONFIG`, never an expanded path or contents); repair the root and start the reviewer again.
4789
4789
 
@@ -4881,7 +4881,7 @@ Native launcher connections retry transport timeouts/unclean closes with bounded
4881
4881
 
4882
4882
  ## amem runtime (agent-mem#13 P4)
4883
4883
 
4884
- The hub exact-pins @staix/agent-mem 0.13.0 for recall, curated evidence and local deterministic capture. No runtime call reaches a claude-mem worker; `memory.worker_url` is ignored. The person's `ahub memory import claude-mem` remains explicit and off by default. Existing profile, alias, PII and private-turn fences still apply. `ask --remember` and context checkpoints propose machine-local candidates, never automatic curated evidence. See [memory integration](memory.md#in-process-recall-and-capture-agent-mem13-p4) for changed behavior and bounded-view ceilings.
4884
+ The hub exact-pins @staix/agent-mem 0.14.0 for recall, curated evidence and local deterministic capture. No runtime call reaches a claude-mem worker; `memory.worker_url` is ignored. The person's `ahub memory import claude-mem` remains explicit and off by default. Existing profile, alias, PII and private-turn fences still apply. `ask --remember` and context checkpoints propose machine-local candidates, never automatic curated evidence. See [memory integration](memory.md#in-process-recall-and-capture-agent-mem13-p4) for changed behavior and bounded-view ceilings.
4885
4885
 
4886
4886
  ## Backlog issue identity and notes
4887
4887
 
@@ -17,7 +17,7 @@ ahub setup # installs the Claude Code channel plu
17
17
  Or use the matching GitHub release:
18
18
 
19
19
  ```bash
20
- bun add -g github:STAIxBWLB/agent-hub#v0.23.0
20
+ bun add -g github:STAIxBWLB/agent-hub#v0.23.1
21
21
  ahub setup
22
22
  ```
23
23
 
@@ -30,6 +30,10 @@ and upgrade or crash recovery, see the [operations guide](operations.md). To
30
30
  move running projects to a newer release later, run `ahub upgrade` in a
31
31
  terminal: it reviews the plan with you, applies it and follows it.
32
32
 
33
+ ## Upgrading to 0.23.1
34
+
35
+ The hub now exact-pins `@staix/agent-mem` 0.14.0, with no storage change for the hub. amem 0.14.0 adds an opt-in v2 public prune view (`amem migrate --public-prune-view`) that 0.13.0 and earlier readers refuse once it is activated: before a person activates it, upgrade every hub that shares the memory home to 0.23.1 or later (which bundles amem 0.14.0) and every global `amem` CLI to 0.14.0. Claude Code 2.1.314 joins the verified headless implementer versions (#996), Kimi Code 2.4.1 the fresh reviewer versions and Qwen Code 0.26.4 the ACP versions (#1002); the Qwen dual-output TUI stays on 0.26.1 and Codex 0.166.0 stays unverified (#997).
36
+
33
37
  ## Upgrading to 0.23.0
34
38
 
35
39
  Nothing changes until you set something. Thirteen more operational numbers became settings in `config.local.json`, each keeping its old value when unset: three `adapter_timing.*` (at the next Kimi, ACP or Jcode launch, #982), four `model_relay.*` and `inference.backoff_min` (at the next daemon restart, #984) and five `console.*` (at the next console launch, #987). Capability sharing is new and opt-in. `ahub capabilities` (person only) lists the skills an attached Kimi 2.3.2, Qwen 0.26.1 or Codex 0.166.0 offers; nothing is offered to other agents until you pin an entry's digest under `invocation.share` in `.agenthub/config.local.json` (#985). Agents then call a shared `read` capability with `hub_invoke`. A `write` or `external` one needs an open task of the caller and your allow-once approval on every call, and one with no class is never invoked (#986, #991; see [invoking a shared capability](operations.md#invoking-a-shared-capability-445-c2c3)). Across a room, only a read capability both persons pinned crosses (#992). `ahub init --profile writing-pack|analysis|ops` applies the new shipped domain packs (#993). The `@staix/agent-mem` pin stays 0.13.0. Upgrade running hubs with `ahub upgrade` (an older hub refuses `hub_invoke`) and restart Claude sessions so they load the 0.23.0 plugin.
@@ -132,7 +136,7 @@ The restarted Claude planner gets the release-train tools (`hub_release_new`, `h
132
136
 
133
137
  Jcode must be 0.98.0 or later, below 1.0.0; 0.94.0 is no longer accepted, so `ahub doctor` fails its Jcode row for an older install and the peer does not start (#529). Every owned jcode process runs with `JCODE_NO_TELEMETRY=1`.
134
138
 
135
- Since 0.12.37 the hub opens a split memory home through its shards (#534); the current exact `@staix/agent-mem` pin is 0.13.0. Before anyone runs `amem migrate --shards` on a memory home, every hub using that home must run 0.12.37 or later: an older hub does not see the split and keeps writing the old layout. `ahub memory profile-check` is split-aware and compares each hub with its own project's shard (#536). See [memory profiles and rollout](memory.md#selected-memory-profile).
139
+ Since 0.12.37 the hub opens a split memory home through its shards (#534); the current exact `@staix/agent-mem` pin is 0.14.0. Before anyone runs `amem migrate --shards` on a memory home, every hub using that home must run 0.12.37 or later: an older hub does not see the split and keeps writing the old layout. `ahub memory profile-check` is split-aware and compares each hub with its own project's shard (#536). See [memory profiles and rollout](memory.md#selected-memory-profile).
136
140
 
137
141
  From 0.12.30 or earlier, existing Jcode project MCP entries need one refresh before conductor or dashboard starts. Once per project, the person runs:
138
142
 
@@ -200,7 +204,7 @@ More: `ahub help`. How it is built and why: [`docs/specs/2026-09-19-agent-hub-de
200
204
 
201
205
  ## Shared memory
202
206
 
203
- The hub exact-pins the first-party `@staix/agent-mem` 0.13.0 core, including deterministic capture; no claude-mem worker is needed. Existing shared-v1 memory remains the default; upgrading does not migrate it. Managed agents use screened `hub_memory_search`, `hub_memory_show` and `hub_memory_graph` tools, or propose a correction with `hub_memory_correct`; only a person accepts candidates through the supported `amem review` path. Since agent-mem 0.7.0, `amem review` also accepts candidates on a selected generation.
207
+ The hub exact-pins the first-party `@staix/agent-mem` 0.14.0 core, including deterministic capture; no claude-mem worker is needed. Existing shared-v1 memory remains the default; upgrading does not migrate it. Managed agents use screened `hub_memory_search`, `hub_memory_show` and `hub_memory_graph` tools, or propose a correction with `hub_memory_correct`; only a person accepts candidates through the supported `amem review` path. Since agent-mem 0.7.0, `amem review` also accepts candidates on a selected generation.
204
208
 
205
209
  Before any real generation migration, upgrade every hub sharing that memory home to 0.12.30 or later and check its authenticated binding with `ahub memory profile-check` in each custom registry. Ready bindings prove compatibility, not an atomic live cutover: quiesce consumers and close their handles before migrating, then reopen through the supported session-preserving lifecycle. Invalid or changed profiles disable native memory without falling back to legacy writes; the bus and board continue. See [memory operations](operations.md#hub-memory) for the remaining rollout gates.
206
210
 
package/docs/security.md CHANGED
@@ -24,7 +24,7 @@ agent-hub connects agents that can each run commands. This page says what the hu
24
24
 
25
25
  ## Native memory authority and profile selection
26
26
 
27
- The portable core is the exact-pinned first-party `@staix/agent-mem` 0.13.0 package; it does not replace the hub's caller identity, PII policy or task-write authority. Deny, hardened git, real paths and process identity are single-sourced in its Node-safe platform entry. Current project privacy is applied by the hub before promotion and again before model-facing reads. Standalone person reads are unscreened, and the standalone `--policy-free` acknowledgement grants no hub or peer authority.
27
+ The portable core is the exact-pinned first-party `@staix/agent-mem` 0.14.0 package; it does not replace the hub's caller identity, PII policy or task-write authority. Deny, hardened git, real paths and process identity are single-sourced in its Node-safe platform entry. Current project privacy is applied by the hub before promotion and again before model-facing reads. Standalone person reads are unscreened, and the standalone `--policy-free` acknowledgement grants no hub or peer authority.
28
28
 
29
29
  `hub_memory_search`, `hub_memory_show` and `hub_memory_graph` take the project from the daemon, require `memory_read`, refuse private turns and validate UTF-8 input before logs or storage work. Complete records and graph metadata are screened before counts and truncation. Search is at most 20 lines/4 KiB (default 8); show accepts at most 8 ids and returns at most 8 KiB; graph is at most 120 nodes/240 edges/6 KiB (default 60 nodes), with no edge lacking an endpoint. Unknown, ambiguous and withheld ids share one neutral refusal. Arguments and results are excluded from hub-managed capture; this does not govern a vendor's independent transcript or memory hooks.
30
30
 
@@ -543,7 +543,7 @@ withholds the scoped mode on these writes so an older hook grants nothing too.
543
543
 
544
544
  Agent CLI versions (#691). One policy gates the Codex and Kimi fresh reviewers, the headless Claude implementer, Jcode, agy, Qwen (ACP and the dual-output TUI) and Pi (#843): a receipt-verified version passes, Jcode and agy also start an untested version inside their compatible line with a note, and any other version is refused unless the person trusts that exact version on this machine with `ahub agents trust <id> <version>`. The record is `agent-compat.json` in the hub home (`~/.agenthub`), written atomically with mode 600 and at most 64 entries; an unreadable, linked, oversized or invalid record trusts nothing. Agent shells and `--live-test` may read `ahub agents` but cannot trust or revoke. Trust lifts only the version pin: the fresh reviewers' runtime proofs still run before every child, and an untested version's native contract stays unverified.
545
545
 
546
- Qwen Code's optional production ACP peer requires the qwen-code native identity, a compat-admitted version (receipt-verified 0.25.0, 0.26.0 and 0.26.1)
546
+ Qwen Code's optional production ACP peer requires the qwen-code native identity, a compat-admitted version (receipt-verified 0.25.0, 0.26.0, 0.26.1 and 0.26.4)
547
547
  and advertised mode ids before setting a policy or starting work. Its own tools
548
548
  have no hub sandbox; auto-edit approves file edits, yolo every tool. Configured
549
549
  never-ask still requires the person's confirmation. qwen_cmd is machine-local and
@@ -675,7 +675,7 @@ A terminal Claude implementer or verifier instance (#525-5) owns write-class tas
675
675
 
676
676
  A planner-only instance (#525-6: `planner` without `implementer` or `verifier`) plans on the project checkout, so a declared `worktree` is refused. A Codex planner's `thread/start` and `thread/resume` are requested read-only, and a thread is adopted only when Codex's reply positively confirms a read-only sandbox; an unconfirmed or malformed reply refuses that RPC and closes the link before the hub adopts the thread or delivers work, and the current roles are rechecked before each injection. This is an initial ceiling, not confinement of the person's attached TUI, which can change its native sandbox later. A declared planner-only Claude channel instance gets no automatic grant from its facts hook for any tool but Read, LS, Glob and Grep, whatever the permission mode.
677
677
 
678
- The headless Claude implementer (#525-4) runs one owned `claude -p` child per turn in its declared worktree, with `--setting-sources ""`, `--strict-mcp-config`, native permission mode `default`, the hub's managed PreToolUse hook and `--permission-prompt-tool mcp__agent-hub__hub_permission_request`; never `--bare`, `acceptEdits`, `dontAsk` or `bypassPermissions`, and `never-ask` is refused. Each task keeps its own persisted session; unscoped chat reuses one only while exactly one task is in progress, and a `hub_inbox` read refuses a batch attributed to another task. The approval path fails closed: `hub_permission_request` is accepted only from the current child's launch and generation, goes to the console's existing approval queue and `approvals.timeout_s`, and offers allow-once and deny only, with no allow-always or session grant. A timeout, a prompt failure, a disconnect, a hub that is down or refusing, or a stale child binding answers deny; a failed hook decides nothing, so the call still waits for a person. The approval title is the tool name and a JSON rendering of the arguments passed through `sanitize()` and the public-text screen (any PII, secret or private-path match withholds the whole value as `[withheld]`, before any cut), never task text, cut at 600 characters with a `[cut, N chars]` marker; the original arguments stay with the child and are not logged. The MCP wire cannot tell a native permission dispatch from a call the model makes itself; a person allow still refers only to its original arguments. Automatic Bash authorization uses the separate single-use host wrapper contract below, never a caller-supplied tool id as native provenance. A stop holds an uncertain delivery until the owned process group is confirmed gone. The [native permission receipt](verification/2026-10-23-headless-claude-permissions.md) is model-free on Claude Code 2.1.309, [repeated on 2.1.310](verification/2026-10-26-claude-implementer-2.1.310.md); it is not sandbox proof, and a real account, model and person interaction remains a live leg.
678
+ The headless Claude implementer (#525-4) runs one owned `claude -p` child per turn in its declared worktree, with `--setting-sources ""`, `--strict-mcp-config`, native permission mode `default`, the hub's managed PreToolUse hook and `--permission-prompt-tool mcp__agent-hub__hub_permission_request`; never `--bare`, `acceptEdits`, `dontAsk` or `bypassPermissions`, and `never-ask` is refused. Each task keeps its own persisted session; unscoped chat reuses one only while exactly one task is in progress, and a `hub_inbox` read refuses a batch attributed to another task. The approval path fails closed: `hub_permission_request` is accepted only from the current child's launch and generation, goes to the console's existing approval queue and `approvals.timeout_s`, and offers allow-once and deny only, with no allow-always or session grant. A timeout, a prompt failure, a disconnect, a hub that is down or refusing, or a stale child binding answers deny; a failed hook decides nothing, so the call still waits for a person. The approval title is the tool name and a JSON rendering of the arguments passed through `sanitize()` and the public-text screen (any PII, secret or private-path match withholds the whole value as `[withheld]`, before any cut), never task text, cut at 600 characters with a `[cut, N chars]` marker; the original arguments stay with the child and are not logged. The MCP wire cannot tell a native permission dispatch from a call the model makes itself; a person allow still refers only to its original arguments. Automatic Bash authorization uses the separate single-use host wrapper contract below, never a caller-supplied tool id as native provenance. A stop holds an uncertain delivery until the owned process group is confirmed gone. The [native permission receipt](verification/2026-10-23-headless-claude-permissions.md) is model-free on Claude Code 2.1.309, [repeated on 2.1.310](verification/2026-10-26-claude-implementer-2.1.310.md) and [on 2.1.314](verification/2026-10-31-claude-implementer-2.1.314.md); it is not sandbox proof, and a real account, model and person interaction remains a live leg.
679
679
 
680
680
  The #845 host shell wrapper is the only automatic Bash path for a headless implementer. In `ask-when-needed`, a complete public input must pass the existing #816 read-only proof or the closed task-command proof, with an active owned task and registered worktree. Enabled action-policy classes still ask, and `ask`, PII handling and the `never-ask` refusal are unchanged. The native request and authenticated host response both name wrapper protocol 1, so an older plugin cannot drop the rewrite and execute an original command automatically.
681
681
 
@@ -685,7 +685,7 @@ Task branch authority uses recorded `refs.branch`, otherwise a host-observed non
685
685
 
686
686
  The fresh Codex reviewer (#519) needs `review_mode: "fresh"` and a compat-admitted Codex (receipt-verified 0.146.0, 0.163.0 and 0.164.0; `ahub agents` shows the current policy); an unverified/untrusted version is unavailable. Before each review it requires a model-free isolation receipt: binary and config unchanged, only the two hub tools in the configured MCP inventory (each approved by its own name, never by a server-wide default, #783), plugins, hooks and Apps disabled (Apps by a separate feature readback), and a named filesystem profile whose fixtures prove public reads, private-path denial (exact, glob and symlink), standard host credential denial and write denial. Credential and tool-home roots are denied even with an empty `local.deny`; that list does not cover every personal file. A dangling or unreadable credential root refuses the reviewer, and the reason names only its path class (`~/.docker`, `$DOCKER_CONFIG`), never the path or its contents. A failed per-review start names one class from a closed list (`version`, `binary`, `mcp_inventory`, `plugins_hooks_apps`, `sandbox_proof`, `credential_root`, `timeout`, `unknown`) with a fixed sentence in the unavailable reason, `hub.log` and the `reviewer` line of `ahub status`; it never carries a path, native CLI text or a token (#722). Its shell is sandboxed read-only, not Claude's Read/Grep/Glob whitelist. Network and web search are configured disabled but not observed: managed requirements can still select cached web search, and no run has shown the review selecting the profile through `default_permissions`. A failed receipt or start never falls back to a continuing native session, and a child that ends without a saved verdict is never approval. The agy reviewer slot is an unavailable placeholder and never runs; it binds nothing, so agy's own `hub_task_show` reads are not fenced as a review (#792).
687
687
 
688
- The fresh Kimi reviewer (#533) needs `review_mode: "fresh"` and a compat-admitted Kimi Code (receipt-verified 2.2.0, 2.3.0, 2.3.1 and 2.3.2; `ahub agents` shows the current policy) with its native OAuth login; an unverified/untrusted version, or a failed preparation, is unavailable. The [2.3.0](verification/2026-10-22-kimi-qwen-compat.md) and [2.3.1](verification/2026-10-25-kimi-231-reviewer-compat.md) receipts are model-free and do not prove real login or a model review. It is a native tool-authority boundary, not a sandbox: no Seatbelt wraps it, and same-user native code is not isolated from the filesystem or network. Each review starts a new child in a private `KIMI_CODE_HOME` with managed-provider-only config, a clean temporary working directory and an empty skills directory. Its agent may use only `hub_review` and `hub_task_show`, served by a loopback MCP session bound to the task, head and review revision that never carries the hub's control token; it has no native read, file or shell tool and sees only the screened review brief and host facts. Its `credentials/` and `oauth/` directories and `device_id` link to the person's native ones, so refresh keeps Kimi's own lock and atomic rename; no token is copied and `KIMI_DISABLE_OAUTH_LOCK` is never set. A stop revokes its verdict authority before termination; killing it mid-refresh may require a native re-login. Private tasks are never given to it, and a child that ends without a saved verdict is never approval.
688
+ The fresh Kimi reviewer (#533) needs `review_mode: "fresh"` and a compat-admitted Kimi Code (receipt-verified 2.2.0, 2.3.0, 2.3.1, 2.3.2 and 2.4.1; `ahub agents` shows the current policy) with its native OAuth login; an unverified/untrusted version, or a failed preparation, is unavailable. The [2.3.0](verification/2026-10-22-kimi-qwen-compat.md) and [2.3.1](verification/2026-10-25-kimi-231-reviewer-compat.md) receipts are model-free and do not prove real login or a model review. It is a native tool-authority boundary, not a sandbox: no Seatbelt wraps it, and same-user native code is not isolated from the filesystem or network. Each review starts a new child in a private `KIMI_CODE_HOME` with managed-provider-only config, a clean temporary working directory and an empty skills directory. Its agent may use only `hub_review` and `hub_task_show`, served by a loopback MCP session bound to the task, head and review revision that never carries the hub's control token; it has no native read, file or shell tool and sees only the screened review brief and host facts. Its `credentials/` and `oauth/` directories and `device_id` link to the person's native ones, so refresh keeps Kimi's own lock and atomic rename; no token is copied and `KIMI_DISABLE_OAUTH_LOCK` is never set. A stop revokes its verdict authority before termination; killing it mid-refresh may require a native re-login. Private tasks are never given to it, and a child that ends without a saved verdict is never approval.
689
689
 
690
690
  The review brief (#520) withholds private changes whole (both sides of a move) and counts them; a rule file that fails the private-data screen is named, not shown. Attributes and rules are read at the merge base, so a change cannot loosen its own review. Optional changed symbols (#684) come from ripwire 0.6.7 on the daemon's host PATH, run as an owned process on a disposable snapshot of the task's commit; each path, name and kind passes the hub's public metadata screen before the brief, the console's task detail or the dashboard shows it, a private task stores and shows none, and a failed or missing read is `unknown`, never a gate. Spec acceptance, plan review, plan conformance, premature-review, cost, test-integrity (#481 S4), issue and PR identity linking (#694) and dogfood scorecard (#687) reads fetch GitHub metadata only (edit times, check states, thread authorship and resolution, changed file names, open PR heads, workflow run conclusions), never issue bodies, comments or patches. Issue identity linking at propose and accept (#723) parses the task's title and refs locally, reads nothing from GitHub and skips PII tasks. The CI workflow keeps `contents: read` and `actions: read`.
691
691
 
@@ -0,0 +1,74 @@
1
+ # 0.23.1 release verification
2
+
3
+ This record covers release preparation and source review. It claims no installation, no running-hub upgrade to 0.23.1 and no live TUI launch.
4
+
5
+ ## Candidate
6
+
7
+ Version 0.23.1, prepared from main 95032a74 (2 commits since v0.23.0, 0 of them `feat`; bump rule: patch); main de0c4386 (#997, `test`) was merged into the release branch afterwards, and #1002 (`test`) reached main while the release PR #1003 was open; this second release PR covers it, so the release covers 4 commits, still patch. The release commits carry the version, the CHANGELOG section, the bundle and the documentation stamps.
8
+
9
+ ## Reviews
10
+
11
+ Pull requests named by the commits since v0.23.0: #998, #996 (release-prepare); #997 (merged into the release branch from main); #1002 (on main before the #1003 merge commit).
12
+
13
+ All four merged with exact-head CI green and no unresolved review thread. The claude[bot] review on each is the "extra usage unavailable" notice, not a review.
14
+
15
+ - #996 (task 577): codex approved 6ba5f1ef in `hub.db`, the merged head; the codex connector reported no findings at that head.
16
+ - #998 has no hub task: the person asked for the pin bump directly in a Claude session. It was reviewed by OCR delegation (Kimi Code, read-only, 12/12 files) at each head: a P2 at 1e1c475 and a P3 at ed19b82, both historical notes the pin rewrite had changed, were fixed; be43b4a, the merged head, had no introduced finding. The one pre-existing P3 it found is #1001.
17
+ - #997 (tasks 576 and 579): claude approved task 576 at 894a590f and task 579 at b33ce9a5, the merged head; task 579 carries the follow-up for the codex connector's finding at 894a590f (the incomplete model receipt, so 0.166.0 stays unverified).
18
+ - #1002 (task 578): claude approved 7c167db9, the merged head, after its rebase on de0c4386.
19
+
20
+ Release merges: #1003 merged release/0.23.1 at 00576eef with a merge commit, cdf35135 (default subject); `release-tag.ts` then refused because #1002's source commits were newer than the stamps. This second release PR records #1002 and restamps.
21
+
22
+ ## Native acceptance receipts
23
+
24
+ Receipts added under `docs/verification/` since v0.23.0: `docs/verification/2026-10-31-codex-0166-reviewer-isolation.md`, `docs/verification/2026-10-31-codex-0166-reviewer-tool-call.md`, `docs/verification/2026-10-31-kimi-241-reviewer-compat.md`, `docs/verification/2026-10-31-qwen-0264-acp.md`, `docs/verification/2026-10-31-qwen-0264-dual-output.md`.
25
+
26
+ The release-prepare run printed none; the Codex receipts arrived with #997 and the Kimi and Qwen receipts with #1002 afterwards, and the list above is the same `git diff --diff-filter=A v0.23.0..HEAD -- docs/verification` query on the release branch. That query also drops `docs/verification/2026-10-31-claude-implementer-2.1.314.md` (#996), because its name ends in a version like a release report (`-X.Y.Z.md`); it is a model-free receipt this release rests on.
27
+
28
+ This list is read from the repository, never written by hand. Native acceptance and the person's release consent are separate records: consent is `ahub sdlc authorize-release 0.23.1`, person only, and is not recorded in this file. The tag run refuses without it.
29
+
30
+ ## Document review
31
+
32
+ `node scripts/check-docs.mjs --require-fresh` reported 6 stale documents, each stamped at ce8da3ec with #996 (a6497d49) and, except adapters.md and security.md, #998 (95032a74) as source commits. Each was read against those two commits and restamped at 57fe2130:
33
+
34
+ - README.md: the Status line (release-prepare) and the report link now name 0.23.1.
35
+ - docs/quickstart.md: the install pin is v0.23.1 and an "Upgrading to 0.23.1" note names the amem 0.14.0 pin, the activation order and Claude Code 2.1.314. The current-pin lines were already updated by #998; the historical 0.21.0 note keeps 0.13.0.
36
+ - docs/security.md: the headless implementer receipt sentence now links the 2.1.314 receipt (#996 updated only operations.md). The #525-5 terminal-instance sentence names a different receipt and is unchanged.
37
+ - docs/operations.md: no statement changed; #996 and #998 had updated the receipt and pin lines.
38
+ - docs/agent-notes/adapters.md and tests.md: no statement changed; the compat rule (add a version only with a receipt) and the fixture rules hold for #996.
39
+ - The CHANGELOG gained the missing #996 entry.
40
+
41
+ After #997 was merged in, the same six documents were stale again with #997 (894a590f, f7f1d546, b33ce9a5) as source commits, and were read against them:
42
+
43
+ - docs/operations.md: #997 already records the 0.166.0 receipts and why the version stays unverified.
44
+ - docs/security.md: the fresh Codex reviewer sentence lists 0.146.0, 0.163.0 and 0.164.0 as verified, still true.
45
+ - docs/quickstart.md: the 0.23.1 note now separates the hub version (0.23.1, bundling amem 0.14.0) from the amem CLI version (0.14.0), an OCR P2 on the release PR; the 0.12-era reviewer note keeps its historical versions.
46
+ - README.md, docs/agent-notes/adapters.md and tests.md: no statement changed; adapters.md's rule (add a version only with a receipt) holds for the reverted bump.
47
+ - The CHANGELOG gained the #997 entry, and the pin entry got the same hub/CLI wording fix.
48
+
49
+ At the #1003 merge commit cdf35135 the same six documents were stale again with #1002 (85d265b2) as the source commit, and were read against it:
50
+
51
+ - docs/security.md: the Qwen ACP peer sentence now lists 0.26.4 and the fresh Kimi reviewer sentence 2.4.1 as receipt-verified. The dual-output owner sentence (measured on 0.26.1) is about `qwen-dual`, still 0.26.1 only.
52
+ - docs/quickstart.md: the 0.23.1 note names Kimi 2.4.1, Qwen 0.26.4, the unchanged dual-output TUI and Codex 0.166.0.
53
+ - docs/operations.md: #1002 already lists the new receipts and the dual-output attempt.
54
+ - docs/agent-notes/adapters.md: its `qwen-dual` lines (verified 0.26.1, the event-file offset measured on 0.26.1) are unchanged by #1002.
55
+ - README.md and docs/agent-notes/tests.md: no statement changed.
56
+ - The CHANGELOG gained the #1002 entry.
57
+
58
+ ## Checks
59
+
60
+ On dgx02 at ec50a6f9 (the second release PR, after #997 and #1002) with its own frozen install (`@staix/agent-mem` 0.14.0):
61
+ - `node scripts/check-docs.mjs --require-fresh` printed `docs: OK (0 stale documents)`.
62
+ - `bun x tsc --noEmit` was clean.
63
+ - `bun scripts/build.mjs --check` exited 0.
64
+ - `node scripts/check-package.mjs` printed `package: OK (680 files, @staix/agent-hub@0.23.1)`.
65
+
66
+ The release PR's exact-head CI is the full gate on both OSes.
67
+
68
+ ## Known gaps, not blocking
69
+
70
+ - No live receipt in this release. The 2.1.314 receipt is model-free; a real account, model and person interaction remains a separate leg.
71
+ - Nothing here activates the amem 0.14.0 v2 public prune view; a home with it active is refused by 0.13.0 readers, including installed hubs older than this release.
72
+ - The running hub on this machine has not been upgraded to 0.23.1.
73
+ - A local full `scripts/check.sh` on dgx02 for #998 was stopped by the hang watchdog (#115/#121); the full suite evidence is the PR and release PR CI on both OSes.
74
+ - Release preparation, the bundle and the checks ran on dgx02 (the Mac runs no heavy work until further notice); dgx02's checkout has no tags, so v0.23.0 was recreated there at 24d685b9 for `release-prepare` only.
@@ -0,0 +1,67 @@
1
+ # Claude Code 2.1.314 headless implementer receipt
2
+
3
+ Date: 2026-10-31. Scope: #888 (claude-implementer row). This repeats both model-free procedures that `COMPAT["claude-implementer"]` rests on, on the installed Claude Code 2.1.314 with 2.1.310 run through the same producers as a control: the permission transport of the [2.1.310 receipt](2026-10-26-claude-implementer-2.1.310.md) (including the production-name Bash variants of the [2026-10-28 triage](2026-10-28-claude-implementer-permission-triage.md)) and the host shell wrapper of the [wrapper receipt](2026-10-26-headless-claude-shell-context.md). Source head: `24d685b9` (0.23.0). Platform: macOS arm64, host Bun 1.4.3.
4
+
5
+ Result: every case passed on both binaries. `2.1.314` is added to `COMPAT["claude-implementer"].verified`. 2.1.311 and 2.1.312 are not verified by this receipt.
6
+
7
+ | Native version | Binary SHA-256 |
8
+ | --- | --- |
9
+ | Claude Code 2.1.310 (control) | `ffb64331bc0ee1b69efb7c2c428bd3ab516bc31b75bf60886b356c97c1c25ffd` |
10
+ | Claude Code 2.1.314 | `21d6e7b9a6f07b4cfcb7df13760b3b72aa25e084e13a5354413382987ba832ed` |
11
+
12
+ The 2.1.310 hash matches both earlier receipts, so the control is the binary they certified.
13
+
14
+ ## Upstream changes since 2.1.310
15
+
16
+ Read from the upstream [CHANGELOG](https://github.com/anthropics/claude-code/blob/main/CHANGELOG.md) for 2.1.311, 2.1.312 and 2.1.314 (no 2.1.313 entry). Items that touch permissions, MCP, hooks, settings sources or the Bash tool:
17
+
18
+ - **2.1.314, `--setting-sources` excluded file still supplied some settings** (auto mode rules, saved permission consents): fixed. The hub launches with `--setting-sources ''`, so this tightens the isolation the hub already assumes; it loosens nothing.
19
+ - **2.1.314, hooks matching Bash now run on shell commands started by the Monitor tool**, able to block or ask but not approve or rewrite. The 2.1.310 receipt already records that Monitor reaches the host prompt tool as `tool_name: "Monitor"`; this changes hook coverage, not the prompt-tool path. A Monitor command is still never rewritten by the host wrapper, which binds Bash only (ceiling unchanged).
20
+ - **2.1.314, `permissions.blockWritesOutsideWorkingDirectories`**: a new opt-in setting the hub does not set.
21
+ - **2.1.314, stream-json acknowledgement of prompts containing `<bash-stdout>`-style tags**: host output framing; the producers parse structured `tool_use_result` frames, not prompt text.
22
+ - **2.1.312, prompt and agent hooks capped at 24 concurrent per session**: the hub runs no prompt or agent hooks in the implementer child.
23
+ - **2.1.311, Bash tool description no longer claims the working directory always persists**: a description change. The wrapper's persistent-cwd control below still observes persistence on 2.1.314.
24
+ - **2.1.311, subagents can use MCP tools from servers that connect late**, and interrupt no longer waits on an unanswered MCP resource read: neither changes the prompt-tool request or reply shape, and the MCP error, disconnect and pending legs are unchanged in outcome.
25
+
26
+ Nothing in these entries changes `--permission-prompts host`, `--permission-prompt-tool`, `--strict-mcp-config` or the `updatedInput` reply contract. This reading is of the changelog text, not the binary's source, which is not public.
27
+
28
+ ## Runs
29
+
30
+ Each producer ran both binaries sequentially with an isolated HOME and `CLAUDE_CONFIG_DIR`, a fixture MCP server, a deterministic loopback provider and the literal API key `synthetic-probe-not-a-credential`. No account, provider request or model inference was involved. Every native child's process group was confirmed empty afterwards and every binary hash was unchanged.
31
+
32
+ ```sh
33
+ python3 docs/verification/claude-permission-transport-native.py OUT/write --claude 2.1.310 --claude 2.1.314
34
+ python3 docs/verification/claude-permission-transport-native.py OUT/bash --tool Bash --server-name agent-hub --permission-tool hub_permission_request --require-tool-use-id --claude ... --claude ...
35
+ python3 docs/verification/claude-permission-transport-native.py OUT/rewrite --tool Bash --rewrite-bash --server-name agent-hub --permission-tool hub_permission_request --require-tool-use-id --claude ... --claude ...
36
+ python3 docs/verification/claude-shell-wrapper-native.py OUT/wrapper --bun ABSOLUTE_BUN --claude ... --claude ...
37
+ ```
38
+
39
+ (binary arguments are the absolute installed paths; `--bun` must be an absolute path, a bare `bun` fails the host fixture with `FileNotFoundError`).
40
+
41
+ | Producer | Cases per binary | 2.1.310 | 2.1.314 |
42
+ | --- | --- | --- | --- |
43
+ | Write transport (allow, deny, missing tool, hook deny/allow, MCP error, disconnect, pending, deadline) | 9 | 9 pass | 9 pass |
44
+ | Bash transport, production server and tool names, `tool_use_id` required | 9 | 9 pass | 9 pass |
45
+ | Bash `updatedInput` command replacement (allow, deny) | 2 | 2 pass | 2 pass |
46
+ | Host shell wrapper (persistent-cwd control, fixed-wrapper rewrite with replay refusal) | 2 | 2 pass | 2 pass |
47
+
48
+ Per-case shapes on 2.1.314 match the control: allow/deny 2 requests and 1 permission call; missing tool 1 request, 0 calls, native exit 1; pending stopped externally at the 25-second deadline; wrapper control 3 requests and 2 permission calls, wrapper rewrite 4 requests and 3 permission calls with the effect counter at exactly 1 after replay.
49
+
50
+ The only producer change is the version allow-list in `claude-shell-wrapper-native.py`, which now admits `2.1.314` beside `2.1.309` and `2.1.310`.
51
+
52
+ | Artifact | SHA-256 |
53
+ | --- | --- |
54
+ | Permission producer | `8f8885f7153b3a236f3b3f8ce49a344b908f2af3b3aba8b064762d82d1ecf12a` |
55
+ | Wrapper producer (this change) | `6834da808c8cd6615a841234ef2e1dfff152cfd2e637908c4542d0bdacdfb053` |
56
+ | Wrapper host fixture | `616e6711e392f0eee7e3fa1c7bdc47a537dfa86bcc8ffb30e549ca94e5a71cef` |
57
+ | Fixed CLI wrapper | `8ff56514a6e3f25bce0784775d396df199b58b1b93f55ad0e8747bbc729d2fd8` |
58
+ | Write receipt JSON | `efea5aa3ec86a6673c5ecfbff051f05591603b8a54b8f78a7e4c672c9e3dc332` |
59
+ | Bash receipt JSON | `9184559d28482dca4a53267cb4b43af7c189fc9105f50708df34b40c23caa3b2` |
60
+ | Rewrite receipt JSON | `c3839e5a3bd612552f6155c960b3bd4cc64df3d937c8fda896f730b6a09f893f` |
61
+ | Wrapper receipt JSON | `6ef5a42e971af4a5c8b6db17449782d38dc0c0b94bf9a93276a9a7caf4324c8b` |
62
+
63
+ The receipt JSON files stay in the local diagnostic directory; they carry local paths and are not committed.
64
+
65
+ ## Evidence boundaries
66
+
67
+ Unchanged from the earlier receipts: no real provider authentication, model tool selection, person approval interaction, task-session resume or production-daemon task binding is proved, and this is not a runtime receipt gate. Native version admission and binary fencing remain required. The Monitor tool is still an unrewritten prompt-tool path. Exact-head package gate and CI are recorded on the PR.
@@ -0,0 +1,52 @@
1
+ # Codex 0.166.0 fresh-reviewer isolation receipt
2
+
3
+ Date: 2026-10-31. Platform: macOS arm64, Bun 1.4.2. Scope: issue #888, task 576. This repeats the [0.164.0 model-free production preparation](2026-10-24-codex-0164-reviewer-isolation.md), retaining the 0.146.0 control and the earlier evidence boundaries. Source base: `a6497d495759e8a1176eb95dc19e31eaff5dbb70` (0.23.0). No `codex exec`, model request, login, credential copy or live reviewer run was performed. The returned launch was inspected, never started. The person's real HOME and `~/.codex` were never supplied to a Codex process.
4
+
5
+ Result: all four model-free legs returned the expected outcome. The subsequent [one-run model-backed receipt](2026-10-31-codex-0166-reviewer-tool-call.md) persisted an approved native verdict but failed its required synthetic-marker readback. The proposed 0.166.0 verified bump was therefore reverted. Both 0.165.0 and 0.166.0 remain unverified; this positive model-free inventory alone does not qualify a version.
6
+
7
+ ## Source identity and re-read regions
8
+
9
+ `git ls-remote https://github.com/openai/codex.git 'refs/tags/rust-v0.166.0' 'refs/tags/rust-v0.166.0^{}'` returned annotated tag object `593389380740f7b4762771573c447ccfdc59742f` and peeled commit `6ff1e1ca3b30fc8b914720681fcf5fe62e95f856`. The same readback retained the earlier 0.164.0 tag object `fe3b29455488c2e189e43ad5526a107900c5e1b7` and peeled commit `6aaac694803004a63c6f393d153c96d22521a6b9`, matching its receipt.
10
+
11
+ Each of the seven files below was fetched successfully at the 0.166.0 peeled commit in the remote source-analysis workspace. The implementation regions were read, including moved anchors, rather than inferring behavior from matching names or old line numbers.
12
+
13
+ - [Exec switches, lines 40-50](https://github.com/openai/codex/blob/6ff1e1ca3b30fc8b914720681fcf5fe62e95f856/codex-rs/exec/src/cli.rs#L40): ephemeral sessions, ignoring the user config file and ignoring user/project execpolicy rules remain independent global exec switches. Auth still uses CODEX_HOME; ignoring user config does not remove every configuration layer.
14
+ - [Apps projection, lines 279-285](https://github.com/openai/codex/blob/6ff1e1ca3b30fc8b914720681fcf5fe62e95f856/codex-rs/core/src/mcp.rs#L279) and [registration, lines 464-485](https://github.com/openai/codex/blob/6ff1e1ca3b30fc8b914720681fcf5fe62e95f856/codex-rs/core/src/mcp.rs#L464): disabling MCP servers clears the Apps gate; implicit Apps registration still requires Apps enabled and a session without isolated-session metadata, and is removed otherwise. Configured MCP inventory alone cannot prove this runtime server absent, so effective feature readback remains required.
15
+ - [Plugin manager, lines 831-834](https://github.com/openai/codex/blob/6ff1e1ca3b30fc8b914720681fcf5fe62e95f856/codex-rs/core-plugins/src/manager.rs#L831): disabling plugins returns the default empty load result before plugin discovery.
16
+ - [MCP schema, lines 243-245](https://github.com/openai/codex/blob/6ff1e1ca3b30fc8b914720681fcf5fe62e95f856/codex-rs/config/src/mcp_types.rs#L243) and [291-297](https://github.com/openai/codex/blob/6ff1e1ca3b30fc8b914720681fcf5fe62e95f856/codex-rs/config/src/mcp_types.rs#L291): a disabled server is not initialized; enabled tools restrict exposure, and disabled tools filter that result afterwards.
17
+ - [Session hook configuration, lines 5735-5743](https://github.com/openai/codex/blob/6ff1e1ca3b30fc8b914720681fcf5fe62e95f856/codex-rs/core/src/session/mod.rs#L5735) and [registry, lines 179-197](https://github.com/openai/codex/blob/6ff1e1ca3b30fc8b914720681fcf5fe62e95f856/codex-rs/hooks/src/registry.rs#L179): legacy notify arguments are copied independently of the hooks feature. A non-empty legacy command becomes an after-agent hook independently of the engine feature flag. The [session-static comment, lines 2389-2392](https://github.com/openai/codex/blob/6ff1e1ca3b30fc8b914720681fcf5fe62e95f856/codex-rs/core/src/session/mod.rs#L2389) remains. The host therefore still pins `notify=[]` for metadata proofs and the returned exec argv; no model-driven notify execution is claimed.
18
+ - [Seatbelt glob compiler, lines 624-705](https://github.com/openai/codex/blob/6ff1e1ca3b30fc8b914720681fcf5fe62e95f856/codex-rs/sandboxing/src/seatbelt.rs#L624): unreadable globs produce anchored read/write denies, canonicalized static-prefix variants and directory-unlink denies for ancestors. The root-recursive literal-basename form still protects descendants without needing ancestor guards.
19
+
20
+ ## Native production preparation
21
+
22
+ A throwaway producer outside the source checkout invoked the actual `codexReviewerBackend.prepare`. A frozen install in this worktree supplied the exact `@staix/agent-mem@0.13.0`; the producer checked that local package version before importing the backend. Each leg used fresh project, HOME, CODEX_HOME and TMPDIR directories under its own temporary root. A child received only PATH, LANG, HOME, CODEX_HOME, TMPDIR and a fixture-root marker. Before importing the production backend, it rejected extra environment variables, a mismatched `os.homedir()`, or any home/project/temp directory outside that root. No real configuration or credentials were copied. The MCP transport was inert `/usr/bin/false`, without a control token, and private paths were `**/*.env`, `.private`, `nested/secret` and `~/private-proof`.
23
+
24
+ The command was the explicitly selected installed npm `codex.js` launcher, resolved by production to its native arm64 binary. The control used the retained Homebrew npm launcher. Both native binaries remained outside the project and the producer checked the returned receipt, stable `current()` binding and empty notify override. Production `prepare` ran its own metadata and native sandbox canaries. Temporary homes and canaries were removed after each leg; the returned exec launch was never executed.
25
+
26
+ | Leg | Outcome | Elapsed |
27
+ | --- | --- | --- |
28
+ | Before compat edit, 0.166.0, empty homes | Refused only at version admission, `causeClass: version`; previous verified set 0.146.0, 0.163.0, 0.164.0 | 122.32 ms |
29
+ | After exact 0.166.0 addition, empty homes | All production preparation legs pass | 344.82 ms |
30
+ | After addition, synthetic ambient config | All production preparation legs pass | 352.80 ms |
31
+ | Retained 0.146.0 control, empty homes | All production preparation legs pass | 477.53 ms |
32
+
33
+ The ambient file enabled Apps, plugins and hooks, supplied a legacy notify command and declared one stdio and one HTTP MCP server. Metadata preparation disabled the ambient servers, retained only the hub server with exactly `hub_review` and `hub_task_show`, and proved effective Apps/plugins/hooks disablement. Per-tool approval remains configured only for those two hub tools; actual MCP tool execution is outside this receipt.
34
+
35
+ | Version | Native binary SHA-256 | Production binary identity |
36
+ | --- | --- | --- |
37
+ | 0.166.0 | `39acf979729dd290f9a24ee38b2914e036c91b65952872e28ae2a6b88a7db7c1` | `sha256:77c2eae1013cec5acaa8a2d980bb760a7ca7657ebb9cb3033550cad787ab2fdd` |
38
+ | 0.146.0 | `ae1d3ffe6d48aec6a4dc3f50e7eb8e0d11962485a6a9406c5a7012139383da02` | `sha256:4a6398187165c5bd75ad92c9a6fba6df6d401a59b62f7e1ecf9218a8196852a6` |
39
+
40
+ The production identity hashes the native file digest again, so it differs from the direct binary digest. The 0.146.0 production identity matches the earlier receipts.
41
+
42
+ All successful launches returned `backend: codex`, `readOnly: true`, `strictMcp: true`, `ephemeral: true`, `current(): true` and `notify=[]`. Their evidence lists were identical: `model-free-mcp-inventory-disabled-ambient`, `hub-tools-exact-allowlist`, `plugins-and-hooks-disabled`, `legacy-notify-disabled`, `apps-disabled-effective-feature-readback`, `web-search-disabled`, `project-untrusted`, `native-public-read-private-deny-write-deny`, `native-glob-and-symlink-private-deny`, `portable-core-name-and-state-deny`, `standard-host-credential-roots-denied`, `binary-config-stable`, `binary-hash-once-metadata-fence`, `session-ephemeral`.
43
+
44
+ Native canaries passed for a public read, denied exact private read, denied nested private glob and symlink alias, denied portable-core `.env` and `.agenthub/state`, denied synthetic gh/kube/docker credential roots and credential alias, and denied creation of a new file with the file remaining absent. Production's metadata commands retain their existing 2-second command and 12-second overall limits and owned-group cleanup; none failed.
45
+
46
+ ## Compatibility and evidence boundaries
47
+
48
+ The verified reviewer versions remain 0.146.0, 0.163.0 and 0.164.0 after the incomplete model-backed receipt. The existing 0.165.0 unverified/trust fixtures stay unverified. The exact-version test now refuses 0.166.0 as well as 0.166.1, 0.167.0, a prerelease and a prefixed string. Capability pins for the attached Codex adapter are a separate contract and unchanged. No isolation implementation, sandbox ceiling or trust bypass changes.
49
+
50
+ The network setting is configured disabled without a separate network probe. Web search is requested disabled without model-turn readback. No run proves exec selecting the named default profile, model tool selection, real account authentication or verdict delivery. The [0.164.0 model-backed tool-call receipt](2026-10-25-codex-0164-reviewer-tool-call.md) is evidence for that version only. A separately authorized [0.166.0 model review](2026-10-31-codex-0166-reviewer-tool-call.md) did reach persisted native verdict delivery, but its required synthetic marker was missing, so the full receipt remains failed. No model retry was made. No native Linux result is claimed. Same-user mutation after the final metadata check is outside atomic snapshot guarantees, and the bounded credential-root list is not a classifier for every private host file.
51
+
52
+ Source claims apply to this peeled 0.166.0 commit only. Each upgrade repeats the procedure; the throwaway producer is not a new supported command. Raw local probe records carry temporary paths and stay outside git. The pinned-Bun bundle rebuild, changed-source gate and exact-head hosted CI are separate evidence recorded on the PR.
@@ -0,0 +1,49 @@
1
+ # Codex 0.166.0 reviewer tool-call receipt, failed marker check
2
+
3
+ Result: the single authorized native review persisted one approved verdict through production stdio MCP and `Tasks`, but the required private synthetic marker was absent. The full receipt failed and 0.166.0 was removed from the proposed verified set. No model retry was made. Date: 2026-10-31, macOS arm64, Bun 1.4.2. Scope: issue #888, task 579, PR #997 connector P1. The positive [model-free receipt](2026-10-31-codex-0166-reviewer-isolation.md) remains available and does not independently qualify the version.
4
+
5
+ ## One production review
6
+
7
+ This repeated the [0.164.0 fixture](2026-10-25-codex-0164-reviewer-tool-call.md) using the actual `startDaemon`, `ReviewerPrintPeer`, `codexReviewerBackend`, stdio plugin and `Tasks`. A temporary builder proposed and accepted one synthetic arithmetic task. Its temporary console assigned `codex-review`; builder completion triggered the real native reviewer. The harness never invoked `hub_review` itself or substituted a tool result.
8
+
9
+ Read-only SQLite inspection found state `approved`, reviewer `codex-review` and exactly one persisted reviewer verdict. The stored task refs and running-child binding matched the synthetic fixture head. Two successful `hub_review` observations were retained at the production trace observer; host and native observations may duplicate one invocation, so they are not claimed as two distinct calls. No `hub_task_show` observation was retained.
10
+
11
+ The private-marker check returned false. The marker was placed in task detail, while the accepted plan contained no marker. Current `Tasks.reviewRequest` omits task detail when a rendered plan is present. This is a fixture-visibility concern, but the retained metadata does not establish whether model omission or host screening caused the missing marker. Raw prompts and model prose were not preserved. The next attempt's fixture correction is to place the marker in the done summary or accepted plan, where the reviewer is actually shown it, and assert model-free that the rendered review request contains it before consuming a new model-run authorization. This is a fixture correction, not an established 0.166.0 defect. Successful native verdict persistence does not waive this task's explicit marker requirement.
12
+
13
+ | Evidence | Observed |
14
+ | --- | --- |
15
+ | Tested source head | `894a590fd0c1312adb165ace5b49f0d542185b41` |
16
+ | Native version / production binary identity | 0.166.0 / `sha256:77c2eae1013cec5acaa8a2d980bb760a7ca7657ebb9cb3033550cad787ab2fdd` |
17
+ | Backend source SHA-256 | `8e6ce4e64c6787a81e48a97172d25bbf1876ae5bc24a54934e7a107075a72214` |
18
+ | Stdio plugin SHA-256 | `2cc09f4fd8916861586fe2d962e6520437b555bc4590df319fde0b614a43a879` |
19
+ | Startup profile SHA-256 | `cf0eded7535d42f115de1675929c889fc9ccae3aebb451f2a922e02dea4ce3da` |
20
+ | Actual review profile SHA-256 | `dcadeea11ba12471f6a2f7cfd30a86c362758d846d50e2ccaf7347a17c9ca148` |
21
+ | Fixture task / reviewer | 1 / `codex-review` |
22
+ | Fixture head | `9ef3805146367c58d391afb25816056107433e9d` |
23
+ | Persisted state / verdict count | `approved` / 1 |
24
+ | Stored refs and running review head matched | true |
25
+ | Required marker matched | **false** |
26
+ | Marker SHA-256 | `a62118802585320868c5432c031e3c40c841a8a7e92674e700eefaaf476abea6` |
27
+ | History SHA-256 | `aac0fab5efe89e27cfe14fb186e04df0d24c011d80f9156ca0a9b9083645e069` |
28
+ | Review attempts / delivery states / final peer state | 1 / accepted, completed / idle |
29
+ | Fixture start / verdict readback, UTC | 03:54:18.164 / 03:54:36.045 |
30
+
31
+ ## Isolation, authorization and cleanup
32
+
33
+ The controller acquired the local repository lock before creating fresh HOME/CODEX_HOME and one auth.json symlink to the configured account. No personal configuration or credential value was copied or read by the harness. 17 bounded private roots covered the original account and the original HOME's credential locations, in addition to production's private state and native canaries. No production task, daemon, PR assignment or personal machine trust was changed by the fixture.
34
+
35
+ The actual review receipt retained `readOnly: true`, `strictMcp: true`, `ephemeral: true` and all 14 model-free evidence markers. Effective Apps/plugins/hooks and legacy notify remained disabled; only the two hub review tools were configured, with per-tool approval overrides. The existing public-read, private/glob/symlink, portable-core, credential-root and write-denial native canaries passed. No separate effective network-isolation or web-search model-turn readback is claimed.
36
+
37
+ A persistent exclusive authorization file and a wrapper around the original production review entry prohibited a second review attempt. The trace observer delegated to the original method and recorded only tool names, refusal booleans and the immutable running head. It did not grant tool or verdict authority. The immutable backend object and production source were not changed. The fixture deadline remained 110 seconds and controller deadline 120 seconds.
38
+
39
+ Before the actual run, a setup-only attempt failed while installing an observer on the immutable backend, before daemon startup, an auth link or any model review. The corrected setup-only attempt passed with zero native preparations and zero model requests, without an auth symlink. This did not consume the actual model authorization.
40
+
41
+ After the one actual attempt, production daemon/process-group teardown was awaited, the driver group was absent and an additional fixture-root argv scan found zero matching processes. The controller released only its own inode/owner-bound lock. The auth symlink, fresh homes, project, task state and temporary directory were removed. This is bounded cleanup evidence, not universal orphan detection. The fail path did not separately read back the synthetic source file before removing it, so no measured unchanged-source claim is made for this attempt.
42
+
43
+ The source-account auth metadata was unchanged before/after: both hashes were `09a890fea6df1c2c40e746b479336e26d74482127916449126e37930bba9b62f`, without reading credential contents. Private proof metadata was mode 0600, 3477 bytes, SHA-256 `680ed4ee54b7c7825a6472e14c66e74295b7aa84c689f67421c5e01c9676a252`; the harness output log was empty. Account paths, token values, marker value and model prose are omitted here.
44
+
45
+ ## Decision and limits
46
+
47
+ The connector finding is addressed by removing automatic version admission. Verified versions remain 0.146.0, 0.163.0 and 0.164.0; the ordinary person-owned exact-version trust path and all runtime proofs remain unchanged. This failed receipt is preserved alongside the positive model-free inventory. Any later model attempt needs a new authorization; none is implied by this record.
48
+
49
+ This establishes that a native 0.166.0 verdict reached the temporary production host boundary. It does not establish the complete required marker-bearing receipt, production deployment, Linux behavior or every reviewer workflow. The changed-source gate and hosted CI at the subsequent documentation/rollback head are separate evidence on the PR.
@@ -0,0 +1,63 @@
1
+ # Kimi 2.4.1 fresh-reviewer compatibility receipt
2
+
3
+ Date: 2026-10-31. Scope: issue #888, task 578. This repeats the [2.3.2 model-free procedure](2026-10-26-kimi-232-reviewer-compat.md), with the actual production preparation and native tool-call loop driven by fixed loopback responses. The broker callback is synthetic: no real account, inference or persisted `Tasks` verdict was run. No real Kimi home, global prefix, personal trust or hub instance was changed.
4
+
5
+ ## Artifact and installation
6
+
7
+ | Artifact | Binding |
8
+ | --- | --- |
9
+ | Upstream annotated tag | `@moonshot-ai/kimi-code@2.4.1`, tag object `1fc1d165c83b175873a46897e1e9db73dc70c984` |
10
+ | Peeled source commit | `2c73f3f50af4fa7f2540ca0d2e33b07a1408e3a7` |
11
+ | Official macOS arm64 archive | `kimi-code-darwin-arm64.tar.gz`, 62,671,109 bytes |
12
+ | Archive SHA-256 | `17f848e7b9b159aed9b2ad0df917c4be3c484393d924a6540171ede7b87cc66d` |
13
+ | Standalone executable SHA-256 | `1a8539eae87ffbd9bf480b8a47beafc9668f66b048b96cfa631310dc12dab3a7` |
14
+ | Host / hub core | macOS arm64, Bun 1.4.2, own frozen `@staix/agent-mem@0.14.0` |
15
+
16
+ The archive was obtained from the official release at that tag and checked against both its GitHub asset digest and sibling checksum file before bounded extraction into a new scratch prefix. No global installer ran. An earlier privately installed npm 2.4.1 distribution also passed the same two probe modes at the 0.13.0 hub-core checkpoint; its Node entry hash is `fd15d5c9b48892bb4f1d5fe82df9f790c8c19a44ca9a81054cc592b6fb9e2c90`. The primary receipt below is for the standalone executable, matching the previous artifact form. After rebasing onto main with the 0.14.0 core pin, both standalone modes were repeated successfully against that exact frozen dependency; prior 0.13.0 records remain separate. The npm postinstall was reviewed and invoked only in non-global mode, where it returns before global shim migration.
17
+
18
+ ## Isolated production and native controls
19
+
20
+ The existing producer was adapted to require the private executable path and current source checkout, assert its own exact dependency version, and use the ordinary macOS temporary root. It created fresh HOME, native KIMI_CODE_HOME, cwd, skills and temporary directories with only synthetic managed-provider config, an invented access-only OAuth record and device identity. The production backend made its own private config/agent/MCP files and linked only these fixture credential directories. No personal credential or config was copied.
21
+
22
+ The original managed-provider endpoint was used for production config validation. A separate owned native fixture copied the generated config and redirected only its provider/OAuth endpoint and scoped synthetic credential slot to a fixed loopback server. The prepared original stayed unchanged, preserving its `current()` check. The synthetic provider emitted tool-use frames and fixed final text; it performed no inference. Application-level network preloads and a separate positive control blocked non-loopback attempts; this is not kernel network isolation.
23
+
24
+ Two complete standalone runs passed:
25
+
26
+ | Leg | Fixture-trust run before Kimi bump | Verified run without trust |
27
+ | --- | --- | --- |
28
+ | `kimiReviewerBackend.prepare`, version/current/private config/replace env | pass | pass, `fixtureTrustOnly: false` |
29
+ | Exact two MCP tools and `subagents: []`, config mode 0600, empty skills | pass | pass |
30
+ | Task-bound MCP wrong task, third tool, missing auth and revocation refusals | pass | pass |
31
+ | Actual native two-tool loop, four fixed-response requests | pass | pass |
32
+ | Injected Write absent from inventory, native tool-not-found result, marker unchanged | pass | pass |
33
+ | Explicit Write positive control, two requests, marker written | pass | pass |
34
+ | Trust-workspace environment decoy removed from launch env | pass | pass |
35
+ | Owned groups, original synthetic config/credential bytes and temporary-tree cleanup | pass | pass |
36
+
37
+ Every native two-tool request advertised exactly `mcp__agent-hub__hub_review` and `mcp__agent-hub__hub_task_show`. Both calls reached the production task-bound broker and its synthetic callback. Wrong task id, a third tool and missing authorization were refused; revocation refused reads. The callback never invoked a real task board or persisted a reviewer verdict. The positive control explicitly added Write to the agent, proving the absent Write effect in the restricted run came from the native tool allowlist.
38
+
39
+ The first run used only an invented trust record in its temporary hub home while 2.4.1 was absent from the source verified set. The second used the proposed exact verified entry and asserted the `verified` assessment without a trust record. No real machine trust was written.
40
+
41
+ ## Source review
42
+
43
+ The old 2.3.2 source readback still resolves to `b8dd3a134060c6e80ba4a1659335cd63b68483f2`. The 2.4.1 tag above was independently read back. This was a scoped contract review at both commits, not a review of all changed UI assets or commits.
44
+
45
+ - `workspaceTrust/trustEnv.ts`, agent-file parsing, builtin tool assembly, native managed Kimi OAuth binding and `packages/oauth/src/oauth-manager.ts` were byte-identical in the inspected regions/files.
46
+ - [Workspace MCP config service](https://github.com/MoonshotAI/kimi-code/blob/2c73f3f50af4fa7f2540ca0d2e33b07a1408e3a7/packages/agent-core-v2/src/workspace/workspaceMcpConfig/workspaceMcpConfigService.ts) adds reconnect-delay tunable change notifications and retains the deferred/startup/tool timeout fields. The native explicit two-tool inventory and actual broker calls above exercise the relevant result rather than inferring it from defaults.
47
+ - The 2.3.3, 2.4.0 and 2.4.1 changelog entries were read for plan-mode, MCP loading, trust, tool and subagent changes. Plan-mode entry is now user-controlled; print mode skips the default plan mode. Dynamic MCP loading fixes do not bypass the observed exact agent allowlist. The 2.4.1 read-tool output ceiling is outside an agent that has no native Read tool.
48
+
49
+ ## Decision and limits
50
+
51
+ All required Kimi model-free legs passed, so exactly 2.4.1 may join `COMPAT["kimi-review"].verified`; 2.4.0 and other nearby versions remain unverified. This follows the existing 2.3.1/2.3.2 model-free Kimi procedure. The receipt records synthetic broker execution, not a real-account or persisted-Tasks verdict. No reviewer is enabled or launched on the actual hub by this change.
52
+
53
+ Real account/login/provider readiness, OAuth refresh under a real token, attached-TUI coexistence, model behavior/quality, token usage/quota and other platforms remain unverified. Kimi's native tool-authority boundary is not a kernel filesystem sandbox. Frozen-install, pinned-Bun bundle freshness, host changed gate and exact-head CI are separate PR evidence.
54
+
55
+ ## Evidence fingerprints
56
+
57
+ Producers and result JSONs stay outside git under `scratchpad/temp/agent-hub-578`.
58
+
59
+ | File | SHA-256 |
60
+ | --- | --- |
61
+ | `kimi-probe.ts` | `5985aef11fb111f3f04640323130dfae98fd8f6934d4be4433307b89abdee8a5` |
62
+ | `kimi-native-result.json` | `0c4838f66835220103b525f05354fbe8729c1de236ec674c1eeeb9e2d05d0951` |
63
+ | `kimi-verified-result.json` | `e69bfd33569139e05788e8c29a3a45aeb92526eb7c3cba11b402b615cfb6583c` |