@staix/agent-hub 0.12.36 → 0.12.38

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.
Files changed (85) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/README.md +18 -11
  3. package/docs/agent-notes/adapters.md +19 -6
  4. package/docs/agent-notes/budget.md +2 -1
  5. package/docs/agent-notes/bus.md +3 -2
  6. package/docs/agent-notes/daemon.md +9 -3
  7. package/docs/agent-notes/tasks.md +8 -4
  8. package/docs/agent-notes/tests.md +2 -2
  9. package/docs/memory.md +3 -1
  10. package/docs/operations.md +57 -10
  11. package/docs/quickstart.md +15 -7
  12. package/docs/sdlc.md +29 -3
  13. package/docs/security.md +10 -2
  14. package/docs/smoke.md +38 -2
  15. package/docs/specs/2026-09-19-agent-hub-design.md +58 -4
  16. package/docs/verification/2026-10-19-0.12.37.md +60 -0
  17. package/docs/verification/2026-10-19-agy-p1-t0.md +55 -0
  18. package/docs/verification/2026-10-19-bus-defer-reset.md +9 -0
  19. package/docs/verification/2026-10-19-jcode-0.98.1.md +30 -0
  20. package/docs/verification/2026-10-19-kimi-agy-reviewer-isolation.md +220 -0
  21. package/docs/verification/2026-10-19-reviewer-isolation.md +119 -0
  22. package/docs/verification/2026-10-20-0.12.38.md +56 -0
  23. package/docs/verified.json +27 -15
  24. package/package.json +2 -2
  25. package/plugins/agent-hub/.claude-plugin/plugin.json +1 -1
  26. package/plugins/agent-hub/server.js +5627 -3670
  27. package/src/adapters/acp.ts +3 -2
  28. package/src/adapters/agy/definition.ts +61 -0
  29. package/src/adapters/agy/entry.ts +76 -0
  30. package/src/adapters/agy/hooks.ts +81 -0
  31. package/src/adapters/claude-channel.ts +1 -0
  32. package/src/adapters/claude-print.ts +18 -156
  33. package/src/adapters/codex-review-isolation.ts +290 -0
  34. package/src/adapters/definitions/builtin-metadata.ts +9 -6
  35. package/src/adapters/definitions/native-cli-entry-claude.ts +3 -0
  36. package/src/adapters/definitions/native-cli-entry-codex.ts +5 -1
  37. package/src/adapters/definitions/native-cli-entry-jcode.ts +2 -0
  38. package/src/adapters/definitions/native-cli-entry-kimi.ts +12 -4
  39. package/src/adapters/definitions/native-cli-entry-local.ts +3 -0
  40. package/src/adapters/definitions/native-cli-entry-pi.ts +7 -1
  41. package/src/adapters/definitions/native-cli-entry-qwen.ts +3 -0
  42. package/src/adapters/definitions/native-cli-entry.ts +2 -0
  43. package/src/adapters/definitions/native-cli-retained.ts +15 -0
  44. package/src/adapters/definitions/native-factories.ts +17 -0
  45. package/src/adapters/definitions/native-policy-aux.ts +1 -1
  46. package/src/adapters/definitions/qwen.ts +1 -1
  47. package/src/adapters/definitions/reviewer-variants.ts +33 -0
  48. package/src/adapters/jcode.ts +20 -5
  49. package/src/adapters/kimi-review.ts +161 -0
  50. package/src/adapters/registry-types.ts +36 -4
  51. package/src/adapters/registry.ts +28 -7
  52. package/src/adapters/reviewer-mcp.ts +85 -0
  53. package/src/adapters/reviewer-print.ts +382 -0
  54. package/src/cli/agy-mcp.ts +370 -0
  55. package/src/cli/console-state.ts +6 -0
  56. package/src/cli/console.ts +2 -0
  57. package/src/cli/facts-hook.ts +15 -2
  58. package/src/cli/help.ts +2 -0
  59. package/src/cli/identity.ts +1 -1
  60. package/src/cli/init.ts +7 -0
  61. package/src/cli/launch.ts +3 -1
  62. package/src/cli/main.ts +20 -0
  63. package/src/cli/memory.ts +13 -12
  64. package/src/cli/output.ts +5 -0
  65. package/src/hub/board.ts +34 -6
  66. package/src/hub/bus.ts +17 -6
  67. package/src/hub/config-apply.ts +3 -2
  68. package/src/hub/control-client.ts +7 -1
  69. package/src/hub/daemon.ts +266 -46
  70. package/src/hub/envelope.ts +1 -1
  71. package/src/hub/host-executable.ts +1 -1
  72. package/src/hub/hub-tools.ts +5 -0
  73. package/src/hub/instances.ts +13 -3
  74. package/src/hub/memory-profile.ts +67 -11
  75. package/src/hub/native-hook-launch.ts +37 -0
  76. package/src/hub/peer-catalog.ts +2 -3
  77. package/src/hub/planning.ts +2 -0
  78. package/src/hub/release-admission.ts +64 -0
  79. package/src/hub/reviewer-pool-config.ts +11 -0
  80. package/src/hub/reviewer-pool.ts +76 -0
  81. package/src/hub/routing.ts +45 -3
  82. package/src/hub/sdlc-release.ts +113 -0
  83. package/src/hub/tasks.ts +261 -36
  84. package/src/ui/index.html +6 -1
  85. package/templates/AGENTS.block.md +1 -1
@@ -0,0 +1,60 @@
1
+ # 0.12.37 release verification
2
+
3
+ This record covers release preparation and source review. It does not claim publication, installation, a running-hub restart or native/live acceptance.
4
+
5
+ ## Candidate
6
+
7
+ Version 0.12.37, control protocol 16 (unchanged; the daemon now advertises the `release_trains` and `reviewer_pool` features), from merged main `86693a2a`. The person directed the release on 2026-10-19.
8
+
9
+ - #529 (PR #530): the Jcode adapter accepts any plain jcode release in `[0.98.0, 1.0.0)` instead of exactly 0.94.0; the owned daemon's private socket is named `j.sock` so jcode's derived debug socket no longer collides; every owned jcode process runs with `JCODE_NO_TELEMETRY=1`.
10
+ - #481 S11 (PR #527): release trains through the board's release assignments, missed-work moves with a reason, admitted cuts through host resource admission and fresh peer quota checks.
11
+ - agent-mem#15 T2 host prerequisite (PR #534, hub task #237): the hub opens a split agent-mem home through `openShardStore` at the canonical memory directory; an inactive split refuses with the resume remedy; the exact `@staix/agent-mem` pin rises to 0.4.0.
12
+ - #519 (PR #535, hub task #229): reviews rotate across fresh Claude and Codex reviewer sessions; `review_mode: "fresh"` opt-in; Codex isolation (plugins, hooks, Apps and web search disabled, native read-only sandbox, credential-root denies); optional-pool exhaustion keeps the planner fallback, a required pool blocks for the person.
13
+ - #237 review fixes (PR #537): the daemon and `ahub memory`/`ahub goal` bind the alias-resolved project key the `amem` CLI uses, a later alias latches a bound hub unavailable, and a dangling or unreadable `shards.json` counts as a split marker.
14
+ - CI (PR #538): the macOS check gate gets a 960 s hang bound inside a 20-minute job ceiling (the test step ran 650-808 s).
15
+ - First-party dependency: `@staix/agent-mem` 0.4.0 (agent-mem PRs #24, #25, #26), published by its tag workflow and read back from the registry (`latest` 0.4.0, integrity `sha512-JJCOm8Pq...`, matching `bun.lock`).
16
+ - Still open (unchanged): live native clients, installed managed-Pi #418 AC8 (#142), #438 AC7, the native console settings leg (#439 AC5), real upgrades with reattach (#463) and with a managed terminal and cancelled rows (#478), the live advise cycle of #481 AC9, the installed #493 D3 leg, the live two-instance run (#450 I4, #138), a live headless Claude review (#223) and a live long session over 32 MiB (#517).
17
+ - New open legs:
18
+ - A live fresh Codex review with a real account: `default_permissions` selecting the `ahub-review` profile is configured, not observed (docs/verification/2026-10-19-reviewer-isolation.md).
19
+ - A live split of a real memory home with `amem migrate --shards` after every sharing hub runs 0.12.37; `ahub memory profile-check` is not split-aware yet (#536).
20
+ - Not in this release: the Kimi fresh reviewer (#533, task #234, in progress) and the agy implementer peer (#485, task #241).
21
+
22
+ ## Reviews
23
+
24
+ | PR | Final head | Review | CI |
25
+ | --- | --- | --- | --- |
26
+ | #530 (#529) | 4921ebe4 | planner via OCR delegation (read-only Claude subagent), approved | exact head, success |
27
+ | #527 (#481 S11) | 18b96955 | planner: round 1 findings (quota for unread peers, receipt invalidation, cost-report paging, upgrade-gate scope ruled by the person), round 2 approved | exact head, success |
28
+ | #534 (#237) | ba8e0755 | OCR delegation (read-only Claude subagent): I1 (symlinked home) fixed; the README warning updated after a bot P2, and the README and CHANGELOG older-hub wording corrected after the reviewer showed agent-mem 0.3.1 does not detect a split; approved. codex post-merge review: two findings, fixed in #537 | exact head, success |
29
+ | #535 (#519) | ccb62a48 | planner with two read-only reviewers: round 1 two Important (planner fallback, ChatGPT Apps MCP), round 2 one Important (canonical credential roots on a symlinked TMPDIR), round 3 approved; 387/0 affected tests on macOS with the default TMPDIR | exact head, success |
30
+ | #537 (#237 review) | 6b87d144 | OCR delegation (read-only Claude subagent) approved at a339848d after two bot P1s (daemon-start fallback, late-alias latch); only main merges followed. codex approved the merged commit 86693a2a | exact head, success (macOS after #538) |
31
+ | #538 (CI) | 23f6fc2b | OCR delegation (read-only Claude subagent), approved | exact head, success |
32
+
33
+ ## Document review
34
+
35
+ Eleven documents were stale against the 0.12.36 stamps. Two fresh-context reviewers read them against the six PRs above: one took the person-facing documents, the other the agent notes and `AGENTS.md`. The planner checked their edits and fixed `docs/sdlc.md`'s S11 status line.
36
+
37
+ | Document | Result | Checked claims and correction |
38
+ | --- | --- | --- |
39
+ | `README.md` | corrected | Status 0.12.37 (protocol 16 unchanged); the jcode range 0.98.0 up to 1.0.0 (#529); the verification link; open legs add a live fresh Codex review (#519) and a live split of a real memory home (#536); shard rollout now says every sharing hub must run 0.12.37 or later. |
40
+ | `docs/quickstart.md` | corrected | Install pin `v0.12.37`; "Upgrading to 0.12.37" covers restarting Claude sessions for the release-train tools (#481 S11), the reviewer pool and `review_mode: "fresh"` (Kimi not offered, agy planned as an implementer under #485), the upgrade refusal for targets without `release_trains` or `reviewer_pool`, the jcode range and telemetry opt-out, and agent-mem 0.4.0 with the split rollout rule (#536). |
41
+ | `docs/operations.md` | corrected | Version and upgrade commands 0.12.37; the agent-mem pin was still 0.3.0 (already stale) and is now 0.4.0; a shard paragraph in Hub memory (#534, #537); S11 marked shipped; Jcode telemetry opt-out; the reviewer pool section dated to 0.12.37 with the agy decision and the native-acceptance caveat kept. |
42
+ | `docs/security.md` | corrected | Shard binding (project shard plus user overlay, entry recheck, late-alias latch, inactive split never read as empty); the jcode version fence and telemetry opt-out; the fresh Codex reviewer's pinned policy, receipt, read-only shell and its configured-not-observed limits. |
43
+ | `docs/sdlc.md` | corrected | S11 release-train governance ships in 0.12.37. |
44
+ | `docs/agent-notes/adapters.md` | corrected | Registry `isSupportedPeer` answers from `ADAPTERS`; `reviewer` is a restricted builtin field; reviewer-variant selection needs headless, roles exactly `["reviewer"]`, and an automatic declaration or `review_mode: "fresh"`; `ReviewerPrintPeer` replaces `ClaudePrintPeer`; new rules for the jcode range, owned env and `.sock` name (#530), reviewer backends (receipt and `current()` before every spawn, bus admission after `start()`, failure reports after group exit, output caps), Codex isolation, and never passing the control token to a reviewer child. |
45
+ | `docs/agent-notes/tasks.md` | corrected | Scope adds `reviewer-pool.ts`, `reviewer-pool-config.ts`, `release-admission.ts`; rules for pool selection inside `assign()`, required versus optional pool, `retryReviewer` fences, and S11 release trains. |
46
+ | `docs/agent-notes/daemon.md` | corrected | Scope adds `memory-profile.ts` and `usage.ts`; rules for `memoryProjectFor` and the `projectKey` latch (#537), `lstat` marker detection and `openShardStore` (#534), recovery target-feature floors, and `review_mode`/`review.pool` validation. |
47
+ | `docs/agent-notes/budget.md` | corrected | Reviewer variants keep their base kind's account; the release-cut quota rule. |
48
+ | `docs/agent-notes/tests.md` | corrected | Raise the macOS job ceiling together with `AHUB_CHECK_HANG_S` (#538); the Codex reviewer fake never stands in for native isolation. |
49
+ | `docs/agent-notes/bus.md` | no change | Only `envelope.ts` gained an optional `refs.reviewRevision`, whose rule lives in `tasks.md`. |
50
+ | `docs/agent-notes/benchmarks.md` | no change | The `acp.ts` change (a version predicate) is Jcode-only. |
51
+ | `docs/agent-notes/README.md` | no change | Stale only because `daemon.md`, a tracked path, changed; its index still matches the notes. |
52
+
53
+ `AGENTS.md` lists `reviewer-pool.ts`, `reviewer-pool-config.ts` and `release-admission.ts` under tasks and `memory-profile.ts` under daemon.
54
+
55
+ Found during the review, not changed here: `src/hub/peer-catalog.ts` and the daemon's local `isSupportedPeer` (`daemon.ts:645`) still answer from `definitionOf`, so the declaration-only `agy` passes the person-only `ahub permission` peer check (`daemon.ts:4887`). agy cannot start in this release, so the effect is a stored, unused mode; it is handed to the agy implementer task (#485, hub task #241).
56
+
57
+ ## Checks
58
+
59
+ - Each merged PR's exact-head CI passed (table above). The release branch is main `86693a2a` plus the version, release notes and document corrections; the bundle is rebuilt with the pinned Bun 1.4.2 and is fresh; `tsc` is clean.
60
+ - The twelve stale stamps are restamped to the reviewed commit `9a4869c5`; `node scripts/check-docs.mjs` reports 0 stale documents. `--require-fresh` runs again on the merged main before the tag.
@@ -0,0 +1,55 @@
1
+ # Antigravity P1 T0 receipt
2
+
3
+ Status: pinned native plugin/hook and actual scratch-hub transport receipt collected on 2026-10-19. Permission prompt mappings and interactive TUI/IDE behavior remain separate gates.
4
+
5
+ ## Environment and isolation
6
+
7
+ - Observed CLI version: `agy 1.4.2`.
8
+ - Executable SHA-256: `74935642426b5bb1fcf07a5555f847c478f4517dd002c72b9c98159cb773b932`.
9
+ - Each invocation uses a new temporary HOME, isolated `.gemini`, workspace and temporary directory. The native binary runs with an explicit environment and a Seatbelt profile denying the person's home except the executable. This is probe isolation, not a sandbox claim for the proposed agy peer.
10
+ - Generation is supplied by a loopback Gemini protocol fixture. No real account or cloud model call is part of this receipt.
11
+ - Before/after hashes of the person's Gemini CLI settings, config, MCP config, import manifest and legacy settings are equal for completed probes. Owned process groups are stopped and temporary roots removed.
12
+ - Raw bounded receipts and scripts remain in the local scratch workspace; they are not public artifacts.
13
+
14
+ ## Observed native behavior
15
+
16
+ - `--version` returns `1.4.2`.
17
+ - `--help` advertises `--conversation`, `--continue`, `--dangerously-skip-permissions`, `--mode`, `--new-project` and stream JSON print input/output. It does not advertise `--new`.
18
+ - `--acp` exits 2 with an unknown-flag error. No ACP command appears in the advertised subcommands. This establishes the tested flag's refusal; it does not prove the absence of every undocumented transport.
19
+ - A workspace `.agents/plugins/agent-hub/plugin.json` and adjacent `mcp_config.json` are discovered without a plugin install or global settings write. The native model's MCP inventory names that server `agent-hub_agent-hub` (plugin name plus configured server name).
20
+ - Calling the unprefixed server name fails before execution. Using the observed prefixed name reaches the fixture MCP's `tools/call`; the fixture calls are not an actual hub-tool receipt.
21
+ - Workspace `.agents/hooks.json` is loaded. `SessionStart`, `PreInvocation`, `PostInvocation`, `Stop`, `PreToolUse` and `PostToolUse` run. Tool hooks require an entry with `matcher: ".*"` and a nested `hooks` array in the tested configuration.
22
+ - Shared hook stdin fields include `conversationId`, `workspacePaths`, `transcriptPath`, `artifactDirectoryPath`, and `modelName`. The observed transcript is named `transcript_full.jsonl`.
23
+ - Tool hooks include `toolCall: { name, args }` and `stepIdx`; the tested native read is `view_file` with `AbsolutePath`, `StartLine` and `EndLine`. Post-tool input includes an empty `error` on success.
24
+ - `SessionStart` and `PreInvocation` accept `injectSteps` containing an `ephemeralMessage`. Pre-tool `{ "decision": "allow" }` allows the tested calls under the native rules. This does not demonstrate that `allow` overrides a native approval prompt.
25
+ - `Stop` reports `executionNum`, `terminationReason`, `error` and `fullyIdle`. The observed normal termination reason is `NO_TOOL_CALL`. Stop continuation and post-invocation termination overrides remain unverified.
26
+
27
+ ## Actual hub transport and ownership amendment
28
+
29
+ - The corrected native run exited 0 with no stderr. It invoked actual `hub_inbox` once through the shipped hub MCP bundle and the workspace plugin. A random nonce, held only in the scratch bus preface, appeared in the following fixture-provider request. The temporary hub had memory, inference, snapshots and auto-start disabled and explicit agy roster admission. Native output SHA-256: `51dc9c1ba7cde9524b15a6bb07207b5cbfec8e8983475d49e48319a84bb58a3f`.
30
+ - Interactive TUI/IDE attach and permission prompt behavior are separate from print-mode plugin discovery.
31
+ - Keep the peer unmanaged until each permission mapping is independently observed. In particular, do not equate native `allow` with `auto_approve`.
32
+ - Planner ruling on 2026-10-19 amends ownership to three files: `plugin.json`, `mcp_config.json` and `hooks.json` inside `.agents/plugins/agent-hub/`, with the same person-only launcher, link/foreign-entry refusal and cleanup rules. It never writes project-level `.agents/hooks.json` or global settings. The successful actual-hub run loaded all six hooks from that plugin-local file with no global hook setting. No manual-setup fallback is needed or authorized.
33
+
34
+ Official documentation was refreshed on 2026-10-19: [hooks](https://antigravity.google/docs/hooks/) and [plugins](https://antigravity.google/docs/plugins/). Documentation alone is not native proof.
35
+
36
+ ## Probe failures retained separately
37
+
38
+ - Admission deferrals (exit 75) launched no native process and are not execution evidence.
39
+ - The initial actual-hub source import failed on an absent worktree-local dependency; a frozen Bun 1.4.2 install supplied the exact agent-mem 0.4.0 pin.
40
+ - A first sandbox profile was refused before any model request. The corrected profile uses the supported localhost port filter and passes an inert sandbox validation before native execution.
41
+ - The first admitted native tool call reached the scratch hub but the provider fixture then emitted an OpenAI `[DONE]` marker in a Gemini SSE stream. That run exited 3; its successful readback does not make the run pass. Removing the invalid fixture marker produced the passing run above.
42
+
43
+ ## Implementation and live boundary
44
+
45
+ - Test-only commit `1db64b15` fails both new peer/admission regressions against its source tree (0 pass, 2 fail); the implementation passes the same checks. A temporary detached verification worktree was removed after the red run.
46
+ - Native permission prompts, unattended and resume mappings remain unsupported. P1 observes native hooks and injects verified advisory facts while preserving unmanaged native permission policy. The definition enforces an implementer/verifier role ceiling, including explicit plan/review nominations.
47
+ - Audited source CLI preview against the current project succeeded without writes. The actual person-authorized launch attempt refused before plugin writes because the running daemon lacks `native_hook_launch`. No active peer was restarted or upgraded. The actual project TUI/account participation leg remains pending a compatible runtime rollout.
48
+
49
+ ## Early review regressions
50
+
51
+ - The foreground spawn-options regression fails with the previous `detached: true` behavior restored, and passes without detachment or process-group tracking. This is a fixture assertion, not an interactive controlling-terminal receipt.
52
+ - A real fixture daemon refuses every later launch after its original console socket closes on the pre-fix source. Socket-owned authority now releases on close, while closing an old owner cannot revoke a replacement launch.
53
+ - A real conductor tool request now receives the person-only policy refusal and never calls the fixture terminal provider. Before the fix the definition allowed conductor starts; an unrelated missing preview blocked the tested request later.
54
+ - A config assigning agy reviewer, planner and conductor alongside Claude conductor fails before startup on the pre-fix source. Filtering agy's out-of-ceiling roles before conductor validation preserves its implementer/verifier roles, logs the refusal, and lets console and ordinary-peer hellos succeed.
55
+ - A valid native hook envelope over one MiB is refused before connecting to a hub or forwarding its unused fields. The regression fails on the unbounded hook path.
@@ -0,0 +1,9 @@
1
+ # Recovery deferral reset
2
+
3
+ - Scope: hub task #192, follow-up to #479.
4
+ - Regression: a deferring recovery hold is released, then a bare `fenceRecovery` is taken. A subsequent hub notice must enter the recipient queue rather than `deferredHub`.
5
+ - Test-only commit `872df66f`: the new regression failed because the later notice stayed deferred.
6
+ - Fix commit `2d24a919`: clear `deferHub` after `flushDeferredHub()` succeeds and before releasing `recoveryHeld`. A failed flush retains both the hold and deferral mode.
7
+ - Focused checks: the new regression passed (1 test); the existing `fenceRecovery` cases passed (3 tests); `git diff --check` passed.
8
+ - Bundle: rebuilt using Bun 1.4.2 with worktree-local frozen dependencies; the generated artifacts are unchanged.
9
+ - Initial remote `scripts/check.sh` attempt stopped at `docs: ERROR HEAD does not resolve`: the remote mirror excludes git metadata. This is setup failure, not a full-gate pass. Exact-head CI and a git-backed remote gate remain separate evidence.
@@ -0,0 +1,30 @@
1
+ # Jcode 0.98.1 and the version range (#529)
2
+
3
+ Installed release builds, read through `--quiet version --json`: 0.94.0 (b6c63ff04, the pinned contract in 2026-10-11-jcode-peer-contract.md), 0.95.0 (6487bbd7e) and 0.98.1 (1c7426eb1, installed by jcode's own updater on 2026-10-17), all kept side by side by jcode's updater. All three are [1jehuang/jcode](https://github.com/1jehuang/jcode). The full probe ran on 0.94.0 and 0.98.1; 0.95.0 ran only the old-socket `serve` check below.
4
+
5
+ ## Live probe
6
+
7
+ A probe spawned the owned daemon and the ACP client with the adapter's own argv (`jcodeCommand`), under an isolated `HOME` and `JCODE_HOME` (an empty `mcp.json`, no credentials), `JCODE_SOCKET` and `JCODE_READY_FD` set as the adapter sets them. A before/after hash of the person's real Jcode config files showed no change.
8
+
9
+ - With the adapter's socket name `s`, `serve` exits 1 with `Address already in use (os error 48)` on 0.94.0, 0.95.0 and 0.98.1 alike. Source: `debug_socket_path()` (`crates/jcode-app-core/src/server/socket.rs`, unchanged between the tags) names the debug socket `file_name.replace(".sock", "-debug.sock")`, so a name without `.sock` binds the main path twice. The owned peer could never start natively before this fix; the fake did not bind a debug socket, so tests passed.
10
+ - With `j.sock` (the fix), on both 0.94.0 and 0.98.1:
11
+ - `serve` signals readiness on the private socket within about 100 ms and leaves `j-debug.sock`, `j.sock.hash` and `j.sock.server.json` beside it (0.98.1 adds `j.sock.daemon.lock`). The process group is gone after SIGTERM.
12
+ - `initialize`: `protocolVersion` 1, `agentInfo` `{ name: "jcode", title: "Jcode", version: <semver> }`, `loadSession: true`, `authMethods: []`.
13
+ - `session/new` returns `sessionId` with `configOptions` and `models`.
14
+ - `session/load` returns `configOptions` and `models` only, with no `sessionId`. The restored identity stays unproven, so `requireLoadSessionEcho` and the withheld automatic recovery are unchanged.
15
+
16
+ Telemetry: without an opt-out, the first 0.98.1 `serve` wrote `telemetry_id` and milestone files into `JCODE_HOME` and tried to send an event (`telemetry payload send failed` in its log, the probe host being offline for that endpoint). With the adapter's `JCODE_NO_TELEMETRY=1` (and none in the caller's environment), the patched `JcodePeer` start and stop on 0.98.1 left no telemetry file and logged no send. Source: `is_truthy("JCODE_NO_TELEMETRY") || is_truthy("DO_NOT_TRACK")` in `crates/jcode-telemetry-core/src/lib.rs`.
17
+
18
+ No prompt was sent: provider/model serving, a real hub-tool call through the project MCP entry, native tool policy and child teardown under load stay unverified, as in the 0.94.0 record.
19
+
20
+ ## Source comparison v0.94.0..v0.98.1
21
+
22
+ 234 commits, read only (nothing built from the clone).
23
+
24
+ - ACP (`src/cli/acp.rs`): protocol pinned to 1, the same methods, still no `session/set_mode` or `request_permission`, session `mcpServers` still ignored. Additions: `Subscribe` sends `supports_user_response: false`, and a corrected trailing text piece arrives as an extra `agent_message_chunk`.
25
+ - CLI and socket: every flag the adapter passes is still defined; `JCODE_SOCKET` wins, `JCODE_READY_FD` gets one byte; the update check is still skipped for `serve` and `acp`. The daemon lock now follows a custom socket (`<socket>.daemon.lock`) instead of one runtime-wide lock, so an owned `serve` no longer collides with the person's own jcode daemon.
26
+ - MCP: project file order, the `mcpServers` alias, `shared: false`, the first-use Codex import and `JCODE_DISABLE_CLAUDE_MCP` are unchanged. New: http, streamable-http and sse entries in project MCP files are now connected instead of skipped (OAuth only through `jcode mcp login`).
27
+
28
+ ## Decision
29
+
30
+ The adapter accepts a plain release from 0.98.0 (the minimum, set by the owner; 0.98.1 is the release verified live) up to, not including, 1.0.0 (the assumed breaking version); the minor is not pinned. Releases before 0.98.0 are refused, 0.94.0 included, although the probe above also passed on it. A release shown to break the contract lowers `JCODE_BREAKING_VERSION` (`src/adapters/jcode.ts`).
@@ -0,0 +1,220 @@
1
+ # Kimi and agy reviewer isolation (#533)
2
+
3
+ ## Status
4
+
5
+ Task #234 implements the Kimi reviewer and task-bound in-process MCP. The person moved agy to implementer work under #485; its retained reviewer slot is unavailable as `agy is an implementer peer (#485)`. Kimi is available only on receipt-covered 2.2.0 when runtime preparation passes, otherwise unavailable with a reason. Authenticated fresh verdicts and the complete-collector measurements below are recorded separately from the original aggregate collector failure and its account-free GET reproduction. The reviewer accepted that error as a collector fault, not reviewer-isolation failure; the exact old request method was not retained. Verdict prose was scrubbed, so finding quality is not claimed. Actual interactive-TUI coexistence and print token-usage measurement remain separate ceilings. Earlier holds and kernel probes are historical, not active requirements or relabelled passes. The review-fix revision and its pending final gate are recorded at the end.
6
+
7
+ ## Earlier hold ruling (2026-10-19, superseded)
8
+
9
+ Continue R0 OAuth-isolation research only. No static-API-key provider mode, launch code or production changes are authorized. Both variants remain unavailable with their existing route-explanation reasons. Earlier dummy-key/local-provider receipts below are account-free historical isolation controls, not an approved production auth path.
10
+
11
+ The remaining Kimi question is a review-length OAuth credential path without a refresh-token copy or broader home/Keychain access, while the person's TUI stays attached on the same account. The remaining agy questions are a narrow 1.4.2 OAuth credential/egress contract and authorization of its local listeners. Do not refresh, copy or widen a real credential to investigate them. Report a proved narrow path, or the bounded evidence that prevents proving one, for the next ruling. The host-owned two-tool broker remains a direction to investigate; it must not receive the full hub control token.
12
+
13
+ ## Superseding implementation rulings (2026-10-19)
14
+
15
+ The person replaced the kernel-sandbox requirement with native execution-time policy. Kimi uses `kimi -p`/stream-json, private HOME/tool config/clean cwd/empty skills, and an exact two-hub-tool agent. Its private tool home symlinks the native `credentials/` and `oauth/` directories, plus `device_id`; it never copies a credential file or disables native OAuth locking. Shared refresh uses Kimi's own locking, re-read and atomic rename. Stop/timeout must allow SIGTERM grace while the shared OAuth lock is present. Interruption during refresh can still require re-login; that residual is accepted.
16
+
17
+ Agy retains the person's real HOME and native Keychain/OAuth handling, with a fresh temporary workspace, `excludeDefaultComponents` agent, disabled slash commands, and no built-in read/write/shell tools. Exactly one marked hub-owned project entry at `~/.gemini/config/projects/agent-hub-fresh-review.json` is authorized, selected by `--project`. It grants the two hub MCP operations and denies write/command/URL operations. Exclusive creation and refusal of unmarked or aliased state protect other projects/settings. User hooks and plugin MCP may still load; hooks may observe the prompt. The native loopback listeners and native per-review conversation history are accepted residuals. Never resume history; delete only the owned workspace. No speculative history cleanup or other personal `.gemini` edits are authorized. Agy receipts therefore report `strictMcp:false`, `ephemeral:false`, fresh invocation and native-policy enforcement honestly.
18
+
19
+ The current Claude transport was found to use the stdio plugin bundle, whose ControlClient reads the full control token; it is not a reusable task-scoped in-process MCP server. New variants therefore receive a dedicated in-process two-tool MCP session, bound to one task and the running child generation. It does not read a full control token or accept caller-selected peers/roles. Existing Claude/Codex transports are unchanged.
20
+
21
+ ## Shared-directory native OAuth race receipt
22
+
23
+ At 08:38 UTC on 2026-10-19, `test/fakes/kimi-oauth-race.ts` ran installed Kimi 2.2.0 against a fake OAuth host and fake Anthropic model. Two concurrent print processes represented reviewer and TUI, with separate private homes and directory symlinks to shared synthetic credentials/locks/device identity. The native flow, not a hub refresh implementation, performed rotation.
24
+
25
+ | Phase | Cumulative refresh requests | Cumulative successful model requests |
26
+ | --- | --- | --- |
27
+ | Expired generation 0 | 1 | 2 |
28
+ | Host atomic-expired generation 1 | 2 | 4 |
29
+ | Already-fresh reuse | 2 | 6 |
30
+
31
+ Both owned invocations were active during each refresh. No stale-token/401 or unexpected request occurred; credential targets remained regular files, shared directory symlinks retained their targets, locks were released and owned groups/temp trees were removed. This proves the concurrent native fixture, not an attached interactive TUI or a live account. Command: pinned Bun runs `test/fakes/kimi-oauth-race.ts --binary <installed-kimi> --receipt <new-output.json>` under serialized native admission.
32
+
33
+ ## Agy dedicated-project native control
34
+
35
+ Installed agy 1.4.2 was tested under synthetic HOME with the marked project JSON and `--project`: only `hub_task_show` and `hub_review` reached the fixture MCP; a third MCP operation was auto-denied. Baseline and grant-removed controls made zero calls. The custom agent exposed no built-in read/write/shell schemas. Unrelated synthetic project bytes stayed unchanged and owned temporary trees/groups were cleaned. A subsequent broad-global control admitted all four operations, including an ambient server and a third hub operation: project grants are additive over global grants. A structural, read-only check of the person's global grant sources returned only the class `global MCP grant too broad`. No global settings were modified and no agy live-account call followed.
36
+
37
+ The first portable agy unit run exposed Bun's cached `os.homedir()` behavior: despite synthetic `HOME`, the backend selected the actual home and used the authorized dedicated marked project path. No other personal settings or credentials were touched. The backend now selects `process.env.HOME` explicitly; the fake CLI refuses an unexpected HOME before project writes. No actual native project file was removed by guess. The corrected portable agy tests passed 11/0 before the final scope change. The unshipped backend and fixtures were then removed from this PR; their scratch copies are historical evidence only.
38
+
39
+ ## Implementation check state
40
+
41
+ The focused Kimi backend/daemon, task-MCP and lifecycle suites passed 24/0 (166 assertions across five files), including four red-first regressions for pre-spawn privacy drift, cleanup before confirmed teardown, managed-model protocol fields and native auth-link retargeting. The expanded focused run passed 59/0 (388 assertions across eleven files), including binding, locked-stop and policy-watch regressions, and typecheck passed. The later expanded run passed 62/0 (407 assertions), including malformed-config/resource-method cases, with typecheck clean. Three mutation seeds passed normal code and detected the specified assertion after introducing a write tool or removing the MCP tool/task fence. Pinned Bun 1.4.2 rebuilt the bundle. The updated registry contract separately passed 9/0, and the fake daemon shared-account pause/resume case passed. Full exact-head CI and a successful live-account review remain unmet. A later check was deferred by host admission (exit 75); deferral is not a passing test.
42
+
43
+ ## Agy native exclusion follow-up, retained for #485
44
+
45
+ A synthetic-HOME native 1.4.2 run used tight global and selected-project grants, the custom `excludeDefaultComponents:true` agent, and no built-in tools. The positive `hub_task_show` control passed. Explicit `write_to_file` and `run_command` attempts returned unknown-tool results and created no markers; a host control had confirmed the owned cwd was writable.
46
+
47
+ However, the native schemas still included `list_resources`, `read_resource` and `manage_task` beside `call_mcp_tool`. Valid list/read-resource calls reached an ambient-decoy MCP server, and its synthetic nonce appeared in the next model request despite the tight MCP-call grants. This is a demonstrated resource path, not a conclusion from a schema name or an invalid tool argument. The first harness run had an invalid positive control and is not evidence; the corrected v2 receipt is the recorded result. The run removed its owned groups and temporary files. No real account or personal resource content was used.
48
+
49
+ Scratch receipts: `r0-agy-project-grants-ambient.json` and `r0-agy-exclusion-attempts-v2.json` under the external `scratchpad/temp/agent-hub-533` evidence directory. The earlier probe observed two native loopback listeners; it did not establish their authentication. The latest person decision moves agy to #485, so no agy reviewer backend, global-admission code, launcher, live-account run or speculative personal-state cleanup ships here. Real-HOME native Keychain handling was the approved direction; no authenticated agy success is claimed by these account-free receipts.
50
+
51
+ ## Initial native metadata receipt
52
+
53
+ On 2026-10-19 both installed arm64 binaries ran `--version` and `--help` under `/usr/bin/sandbox-exec`, using a new HOME, tool home, cwd and TMPDIR. The profile was built from `src/local/sandbox.ts` in read-only-data mode, with real-home read/write denied, exact native executable reads allowed and writes restricted to owned temporary paths. Network was denied. Children used independent tracked process groups, a 5-second deadline and a 64 KiB combined output cap; cleanup was confirmed.
54
+
55
+ | Tool | Reported version | Installed binary SHA-256 |
56
+ | --- | --- | --- |
57
+ | kimi | 2.2.0 | `dab42ead275f8a49e9ce30a6263f614fce5926455bed103d0d16940655619bf5` |
58
+ | agy | 1.4.2 | `74935642426b5bb1fcf07a5555f847c478f4517dd002c72b9c98159cb773b932` |
59
+
60
+ Before CLI execution, a fixed shell read a synthetic project canary successfully, then attempted a new project file, an existing-file overwrite and a hardlink into the writable temporary directory. All three mutations were denied, the new file stayed absent and the canary stayed unchanged. This preliminary check does not replace a final production-profile probe or cover arbitrary preexisting aliases.
61
+
62
+ Real Kimi config/MCP/plugin registry, the real project's Kimi MCP file and documented agy/Gemini config locations were hashed by the host before/after the probe. Configuration contents were never printed or staged. The canonical aggregate digest of logical IDs, presence and SHA-256 values was `1bf6927f9f77ea0f82556314e1d44156074771b88e0dd2ae596fd3999cbc645c` both times. Temporary roots were removed; no child remained.
63
+
64
+ ## Account-free native MCP receipt
65
+
66
+ At 07:24-07:26 UTC on 2026-10-19, each installed binary completed a fresh session against a host-owned loopback fake model and a fixture stdio MCP server. The server returned synthetic data and never connected to the live hub. All credentials were fixed fixture strings. Each tool used its own new HOME, tool home, cwd and TMPDIR; the real home remained kernel-denied. Only the fake model port was allowed outbound. Real configuration hashes remained unchanged, and each temporary home/session tree and owned process group was removed after exit.
67
+
68
+ Kimi used `KIMI_CODE_HOME`, the `KIMI_MODEL_*` static OpenAI-provider overrides, an explicit agent Markdown file and an empty `--skills-dir`. Its agent tools list contained exactly `mcp__agent-hub__hub_review` and `mcp__agent-hub__hub_task_show`. The native model request exposed exactly those two function schemas on all three requests. Two synthetic model tool calls reached the fixture MCP server, in order: `hub_task_show`, then `hub_review`; both results returned to the next model request. The final native output was `R0_OK`, followed by a session resume hint. The hint demonstrates persistence inside the temporary home; it does not authorize a resume. Kimi's watcher startup needed an additional `mach-lookup` grant for `com.apple.FSEvents`; without it startup failed before any model request.
69
+
70
+ Agy used private `~/.gemini/antigravity-cli/settings.json` with `modelProvider: gemini`, a dummy `GEMINI_API_KEY` and a loopback `GOOGLE_GEMINI_BASE_URL`. Its sole MCP entry was in private `~/.gemini/config/mcp_config.json`. Without explicit MCP permissions, the native child discovered the fixture server but auto-denied the first MCP call, despite exiting with code zero. With exactly `mcp(agent-hub/hub_review)` and `mcp(agent-hub/hub_task_show)` in `permissions.allow`, both calls reached the fixture server and completed. No dangerous permission-skipping flag was used. Agy sends MCP arguments as JSON strings; a production boundary must normalize bounded JSON and still validate arguments. Its model schemas include native write/command tools, so the kernel profile remains the write boundary. Agy needs both loopback bind and inbound permission for its internal ephemeral listener; outbound permission alone fails at startup. This startup requirement does not prove the listener's production security or authorize general loopback access.
71
+
72
+ A separate account-free native-tool probe deliberately exposed the write tool: Kimi `Write` and agy `write_to_file` each attempted a fresh project file and an existing-file overwrite. Valid native calls reached the filesystem and returned permission-denied errors; neither file mutation occurred. An earlier Kimi attempt used the wrong `file_path` field and was rejected by schema validation; that attempt is not counted as a kernel refusal. The corrected probe used `path`. Agy had an explicit synthetic-project `write_file` allow rule, so its permission prompt was not the boundary. Both children exited zero after the fake model acknowledged the refusals, which also shows why exit zero alone cannot establish task success.
73
+
74
+ Agy listener ownership was observed while the fake model response was held: the native agy process owned two `127.0.0.1` TCP listening sockets and no separate process in its owned group. No authentication conclusion is drawn from this observation.
75
+
76
+ These receipts establish private-home startup, successful MCP round trips and preliminary native-tool mutation refusal. The following positive controls establish the tested ambient-source exclusions. Authenticated account compatibility and the final broker/profile remain unproved.
77
+
78
+ ## Kimi ambient-source positive control
79
+
80
+ A synthetic ambient HOME/tool home and synthetic trusted project were populated with user, root-project, cwd-project and installed-plugin MCP decoys. The plugin had a skill description nonce and a `UserPromptSubmit` hook writing an owned marker. In the ambient native positive control, all four decoy servers received `initialize` and `tools/list`, the model request contained the plugin skill description, and the hook marker appeared. This establishes that the fixtures were active rather than malformed or hidden only by a tool whitelist.
81
+
82
+ The isolated native leg switched both HOME and KIMI_CODE_HOME, used a clean cwd, explicit empty skills directory and explicit agent file, and denied reads of the synthetic project's two MCP config files. The same configured ambient sources remained present. No decoy connection, skill description or hook marker appeared. Both legs returned through the local fake model, preserved real configuration hashes, and removed their temporary home/session tree after verified group teardown. This proves these source exclusions for the preliminary R0 profile; final production broker/profile receipts remain required.
83
+
84
+ ## Agy ambient-source positive control
85
+
86
+ A synthetic ambient HOME and project held distinct user/project MCP entries, hooks and skills. A local synthetic plugin contained its own MCP entry, hook and skill and was installed with native `agy plugin install` inside the same synthetic HOME and sandbox. The install completed with one MCP server, one hook and one skill processed. The ambient native run initialized and listed tools from all three MCP sources, and all three hook markers appeared. The isolated native leg switched to a fresh HOME and clean cwd, did not reuse imported plugin/config/cache state, disabled slash commands, and denied reads of the synthetic project's `.agents` tree. No decoy connection or hook marker appeared. A follow-up captured `systemInstruction`: the ambient model requests contained all three skill-description nonces, while the isolated leg contained none. Installation output alone was not counted as proof of model disclosure.
87
+
88
+ ## Auth and listener evidence boundary
89
+
90
+ Host inspection of only the configured Kimi OAuth slot confirmed file storage and the expected token field names. No token value was printed, staged or supplied to a native child. The snapshot was not valid beyond a ten-minute review deadline. It was not refreshed or copied. Pinned source supports a non-refresh static access-token provider, but managed protocol/header compatibility and real service acceptance remain unverified. Missing/expired snapshots must be unavailable, rather than triggering login or independently refreshing a copy while the person's TUI may refresh the same account.
91
+
92
+ Agy's private-home Gemini API-key mode is proven only with a fixture key/local provider. The person's existing settings use the native account mode. Historical Keychain service reports for 1.0.0 and desktop language-server CSRF flags do not prove 1.4.2 CLI auth or listener protection. No Keychain access was granted or attempted. Neither broad `*.googleapis.com` egress nor a copied native OAuth token is justified by the receipts.
93
+
94
+ ## Native OAuth follow-up under the hold ruling
95
+
96
+ At 08:19 UTC on 2026-10-19, installed Kimi 2.2.0 ran four bounded native OAuth cases under the same private-HOME/Seatbelt restrictions. This probe did not set any static API-key provider or `KIMI_MODEL_*` override. A private provider of type `kimi` used its native file-backed OAuth reference and an Anthropic-protocol local model endpoint. Its synthetic credential record contained an invented access token, positive expiry and token metadata, with `refresh_token` omitted. No actual credential was read, refreshed or copied for this probe. The only network destination was the host-owned fake endpoint; launching `/usr/bin/open` was denied.
97
+
98
+ | Synthetic native OAuth case | Native result | Model requests | OAuth refresh requests | Synthetic token unchanged |
99
+ | --- | --- | --- | --- | --- |
100
+ | Fresh (7,200 seconds remaining; `expires_in: 7200`) | Exit 0, `R0_OAUTH_OK` | 1 | 0 | Yes |
101
+ | Inside refresh threshold (60 seconds remaining) | Exit 1, missing refresh token | 0 | 0 | Yes |
102
+ | Expired | Exit 1, missing refresh token | 0 | 0 | Yes |
103
+ | Fresh token, model returns 401 | Exit 1, missing refresh token | 1 | 0 | Yes |
104
+
105
+ The successful native request used `x-api-key` to carry the synthetic OAuth access token, as selected by the native Anthropic requester. That header does not turn this fixture into a static provider: credentials were resolved through the native OAuth reference, and the forced-401 case entered OAuth recovery. In the threshold, expired and forced-401 cases the OAuth lock-target sentinel file appeared only under the private tool home; the transient lock directory is its `.lock` sibling. No refresh request followed. Real configuration hashes remained unchanged in all cases, owned groups were reaped, and the complete temporary home/session tree was deleted. The cases were short probes, not a ten-minute authenticated review or TUI coexistence test.
106
+
107
+ Pinned Kimi source explains the result: omitted refresh fields become empty; fresh credentials return before lock/refresh; the refresh threshold is `max(300, expires_in / 2)` seconds; forced refresh and missing refresh credentials fail before the refresh network operation. A review-length admission would therefore need `expires_at - now` greater than the entire review deadline plus that threshold and clock margin. Checking only that expiry exceeds the deadline is insufficient. Zero/unknown expiry cannot be used to claim freshness. [Token decoding](https://github.com/MoonshotAI/kimi-code/blob/472192c34c1efad89a369870eff0da0b708ce9bb/packages/oauth/src/types.ts#L84), [threshold and refresh ordering](https://github.com/MoonshotAI/kimi-code/blob/472192c34c1efad89a369870eff0da0b708ce9bb/packages/oauth/src/oauth-manager.ts#L303), [401 recovery](https://github.com/MoonshotAI/kimi-code/blob/472192c34c1efad89a369870eff0da0b708ce9bb/packages/agent-core-v2/src/human/credentials/credentials.ts#L21).
108
+
109
+ This establishes a version-specific synthetic access-only OAuth candidate, not a documented dedicated access-only mode or a real-account path. Sharing the real JSON read-only would expose its refresh token too, so it is not an acceptable substitute. No CLI credential IPC or guarantee that a TUI refresh preserves the snapshot's validity has been established. A host-only projection of access fields into a private OAuth record could be assessed in a later ruling; no such real projection is authorized or performed here.
110
+
111
+ ## Bounded agy OAuth and listener investigation
112
+
113
+ The official 1.4.2 tag resolves to `86a5bdda81a063d707ac4ab87fb72f7dfe30ab67`. Its complete, untruncated public tree contains documentation, issue templates and examples, not the native OAuth/listener implementation. The current authentication documentation describes OS-keyring silent sign-in, browser/SSH OAuth and enterprise ADC, without a version-applicable access-only credential/profile interface. [Tagged tree](https://github.com/google-antigravity/antigravity-cli/tree/86a5bdda81a063d707ac4ab87fb72f7dfe30ab67), [official authentication contract](https://antigravity.google/docs/install).
114
+
115
+ As checked on 2026-10-19, upstream auth-profile request [#381](https://github.com/google-antigravity/antigravity-cli/issues/381), subscription-headless request [#1194](https://github.com/google-antigravity/antigravity-cli/issues/1194), and local-service-authentication request [#965](https://github.com/google-antigravity/antigravity-cli/issues/965) remain open. They are requests from users, not maintainer confirmation that every narrow path is impossible. A maintainer describes the shared token source used during refresh in 1.2.9 in [#1091](https://github.com/google-antigravity/antigravity-cli/issues/1091); this does not establish an isolated, no-refresh contract for 1.4.2. Enterprise network allowlists similarly do not prove a minimal consumer-subscription endpoint set.
116
+
117
+ No supported narrow 1.4.2 OAuth path or authenticated local-listener contract was established within this public-source and credential-free probe boundary. In particular, exact-port discovery cannot prove the client authenticates the service, that another local client is rejected, or that reconnect/rebind/IPv6 changes fail closed. These are unresolved requirements, not a finding that agy is vulnerable. No real-account native run, Keychain lookup, login, credential export, broad egress or listener privilege expansion was attempted under the hold ruling.
118
+
119
+ The next decision needs either a version-applicable supported contract covering those boundaries or separately authorized, bounded evidence gathering that does not refresh, copy or widen real credentials. Neither production availability nor impossibility is claimed.
120
+
121
+ ## Primary-source constraints
122
+
123
+ Kimi print mode forwards `--agent-file` and explicit `--skills-dir`; ACP bootstrap does not forward those options. MCP startup merges config sources, and even untrusted-project diagnostics can try to read project MCP files. An isolated clean native cwd and kernel denial of ambient files must therefore be proved. OAuth refresh storage/locking must preserve the person's TUI; copying a refresh token into a separate home is not accepted as coexistence evidence. [Pinned Kimi source](https://github.com/MoonshotAI/kimi-code/tree/472192c34c1efad89a369870eff0da0b708ce9bb).
124
+
125
+ Agy's headless workspace writes are automatically allowed and its plan mode is a prompt prefix. Its own sandbox is not the reviewer read-only guarantee. Account-free inventory can use the documented Gemini provider setting, dummy key and local base URL, but installed-version behavior must be observed. [Headless](https://antigravity.google/docs/cli/headless), [authentication/provider configuration](https://antigravity.google/docs/install), [GitHub's pinned private-home harness](https://github.com/github/gh-aw/blob/8c885156117f098a280fb75c0f47f750a566ff3e/actions/setup/js/agy_harness.cjs).
126
+
127
+ A whole-process sandbox cannot give an ordinary MCP child access to the full hub `control-token`: token holders can select other control roles. A fixed, revocable, task-bound two-tool broker outside the sandbox is the agreed direction. The broker itself receives only the two host-bound operations and never the full control token; no broker implementation is included in R0.
128
+
129
+ ## Historical strict-isolation requirements, superseded by the native-policy ruling
130
+
131
+ - Final broker inventory/self-check, including refused unknown MCP tools and malformed arguments.
132
+ - Final-profile ambient-source exclusion and immutable host-owned broker/config files (R0 ambient-source controls passed for both installed tools).
133
+ - Final production-profile target read and mutation refusals, preexisting alias checks, private/credential denial and model-only network.
134
+ - Exact auth source and safe refresh behavior, without whole-home access.
135
+ - Session/home cleanup after success, failure and timeout; real config hashes unchanged.
136
+ - Kimi TUI identity/project MCP byte parity and shared-account quota fanout.
137
+
138
+ No runtime availability claim is made until these receipts pass.
139
+
140
+ ## Earlier R0 gate state (historical)
141
+
142
+ This is an R0 evidence report, not a feature-completion or availability receipt. No launcher, registry, daemon, spec contract or default pool was changed. Full tests, typecheck, mutation seeds and exact-head CI have not run for an implementation. One agy skill-disclosure probe was refused before execution by resource admission (exit 75, another heavyweight process). After a fresh process read confirmed that process had exited, one admitted follow-up completed and established the three skill-description positive/negative controls. The deferral itself is not counted as a test result. Auth-scope and native-listener questions were sent to the planner before production work.
143
+
144
+
145
+ ## Kimi quota observation ceiling
146
+
147
+ Kimi 2.2.0 print stream-json forwards no token-count or terminal usage event. The native internal status event is not forwarded by the print writer. The backend therefore reports no invented usage. Existing account-level quota/manual pauses still bind all declared Kimi account members; the optional token soft limit can only reflect actual measurements available from other supported sources. [Print event dispatch](https://github.com/MoonshotAI/kimi-code/blob/472192c34c1efad89a369870eff0da0b708ce9bb/apps/kimi-code/src/cli/v2/run-v2-print.ts#L681), [JSON writer](https://github.com/MoonshotAI/kimi-code/blob/472192c34c1efad89a369870eff0da0b708ce9bb/apps/kimi-code/src/cli/prompt-render.ts#L149).
148
+
149
+
150
+ ## Single live Kimi attempt, incomplete
151
+
152
+ At 09:27 UTC on 2026-10-19, one authorized native-account invocation ran against an independent disposable git fixture and scratch hub, not the person's project board. The public fixture deliberately returned subtraction from an addition function. The host managed-config projection and native Kimi 2.2.0 version probe passed, and one fresh running-child authority was observed. The version probe does not exercise native agent parsing, session creation or OAuth readiness. The child ended after approximately 1.9 seconds without a verdict; the scratch task remained `in_review`. This is not a successful authenticated review or a defect-finding pass. Native stderr/prose was intentionally not retained by that harness, so an auth, quota, CLI or model failure cannot be distinguished from this receipt. No retry, re-login, manual refresh or credential repair was attempted.
153
+
154
+ The native config, user MCP and canonical project MCP SHA-256 values were identical before/after. Both owned reviewer preparation roots, the scratch daemon and fixture root were removed after teardown. No actual attached Kimi TUI was running; the concurrent fake-OAuth native TUI stand-in remains the only coexistence race evidence. Receipt: external `scratchpad/temp/agent-hub-533/live-kimi-review-20261019.json`, producer source `9f548261333b8d820fd8ff7604083160e526dcd9`. A later source-only registry/test change does not supply the missing live verdict. A bounded diagnostic follow-up or a confirmed account window was requested from the planner; live acceptance remains open.
155
+
156
+ The pinned registry expectations changed intentionally with the #533 amendment: Kimi now resolves its native-policy/task-MCP factory and joins the default pool; agy alone retains unavailable metadata with its #485 reason. The legacy non-fresh Kimi transport, ordinary implementer selection and agy ownership refusals remain tested. These are changed contract assertions, not a relaxed guard.
157
+
158
+
159
+ ## Authorized diagnostic follow-up, weekly quota refusal
160
+
161
+ The planner authorized one bounded diagnostic invocation after the incomplete live attempt. It repeated the disposable scratch setup with at most 64 KiB of combined stdout/stderr captured privately, plus the native exit status. Native Kimi exited 1. The classified cause is quota/rate limit, supported by the minimal redacted line: `error: failed to run prompt: provider.auth_error: 403 You've reached your weekly (7-day) usage limit. Your quota will reset when the current 7-day window ends.` The response supplied no exact reset timestamp. No auth-expiry or argument failure is inferred.
162
+
163
+ Only 586 diagnostic bytes were captured; authentication fields, bearer/cookie/device identifiers and opaque values were scrubbed before reporting. Raw diagnostic state was removed with the owned root after classification. Configuration/MCP hashes remained identical, both reviewer roots were removed and daemon teardown completed. There was no re-login, manual refresh, credential repair or additional invocation in the same quota window. The first failed-run receipt is retained as historical evidence, not rewritten as a pass. A single live-verdict rerun waits for a confirmed new quota window. External receipt: `diagnostic-live-kimi-review-20261019.json`.
164
+
165
+ The first exact-head CI stopped at a new test's optional `variant.budget` access. That test now uses the optional type correctly; typecheck and the two affected registry/daemon files passed 10/0 afterward. Full CI must run again on the corrected head; the earlier passing focused count is not a full-gate receipt.
166
+
167
+
168
+ ## Post-topup live verdict and receipt coverage
169
+
170
+ After the person enabled additional Kimi usage, exactly one authorized account invocation ran on PR #539 head `b957a28375ae995abf0b0a106564ed65c7fa8d96`. Native Kimi exited 0 after 39.4 seconds. One running-child authority and one actual `changes_requested` verdict were recorded with `reviewContext: fresh`, `reviewerFamily: kimi` and `reviewerReason: rotation`, against the unchanged fixture head `ed5ed6bc9db3b054f8b1faefe790c8d2df73adee`. The task returned to `in_progress` through the normal reopen after changes requested. No quota refusal occurred.
171
+
172
+ The verdict text was scrubbed, so this proves transport and a fresh verdict, not the quality of the finding. The extra lexical predicate was false and is now recorded as `advisory: false (note scrubbed, not attributable)`; it is excluded from execution pass/fail and was not changed to true. The original failed harness receipt remains byte-for-byte preserved. The lineage-bound advisory receipt separates the accepted transport result from incomplete observational coverage. No additional account invocation was made.
173
+
174
+ | Live-receipt item | Evidence and limit |
175
+ | --- | --- |
176
+ | No canary write; project tree byte-identical and no canary file | Not collected before teardown. The fixture commit stayed unchanged, but there was no working-tree byte snapshot or explicit canary-absence check. The deleted fixture cannot now establish this. No kernel sandbox is claimed. |
177
+ | Only hub MCP server and its two tools | The current backend produces only the task-bound hub server and exact-two-tool agent; the receipt records its policy metadata. Earlier native R0 model disclosure showed exactly two tools. The account-run runtime inventory was not retained, so producer metadata is not presented as that observation. |
178
+ | Decoys absent | Earlier R0 native positive/negative controls are retained above with their original isolation-profile limit. This account invocation did not collect live decoy connection counters, so the earlier control is not relabelled as the final no-Seatbelt account run. |
179
+ | No session files retained | Observed: both owned reviewer preparation roots, scratch daemon and fixture root were removed after teardown; the reviewer was offline. |
180
+ | Real configuration hashes unchanged | Observed: native config, user MCP and canonical project MCP before/after SHA-256 values were identical; the worktree MCP file stayed absent. |
181
+
182
+ The accepted fresh-verdict result therefore does not fill the listed collection gaps. They were reported to the reviewer before marking ready, as requested; no second call is authorized to fill them. The producer files and raw native output were already removed. External receipts are `live-kimi-post-topup-20261019.json` (original) and `live-kimi-post-topup-20261019-advisory.json` (original SHA-256 lineage, advisory false and explicit coverage matrix). The harness source now treats model wording as advisory without a new account run.
183
+
184
+ Exact-head CI `39230896104` at the tested source head was green: Ubuntu `4262 pass`, macOS `4316 pass`, both `0 fail` and `check: OK`, plus all 424 mutation guards across four shards. These gate results do not substitute for uncollected native observations.
185
+
186
+
187
+ ## Complete-collector live run, 2026-10-19
188
+
189
+ The person authorized exactly one further live invocation after the collectors were proved account-free. The normal fake Kimi CLI passed every required observation with `advisory: false`. Each of the three decoy detectors first saw one direct local positive-control request and was reset. A negative fake then deliberately contacted the user decoy: it recorded one request and failed the final decoy fence despite a valid fresh verdict and all other checks passing. These are account-free controls, not relabelled R0 native observations.
190
+
191
+ The subsequent single live invocation used PR source head `50c2f9358ddbe7a27a2bfb33198329c896e24a59` and installed Kimi 2.2.0. It exited 0 after 35.754 seconds and recorded one fresh `changes_requested` verdict for fixture head `6a3dbdcb59681e14fbfb79e1ab39011d6a1b4984`, with family `kimi` and rotation reason. Verdict prose was scrubbed; its quality is not proved and the false lexical advisory is not a gate. No further live invocation followed.
192
+
193
+ | Required live item | New observation before teardown |
194
+ | --- | --- |
195
+ | Project tree byte parity and no canary | Before/after tree hash was `eaa1f231c7ec278b121eb25720cf77a8b4017343dc5fb90e4610b081e3e85326`. The bounded lstat snapshot included every file's bytes/hash, directory modes and symlink targets outside `.git`. Both status replies were `?? .kimi-code/mcp.json`, the intentionally planted decoy. HEAD matched the fixture head and explicit `AHUB_REVIEW_CANARY` absence checks were true before/after. This is end-state parity, not proof against write-then-restore or `.git` metadata writes. |
196
+ | Hub runtime inventory and calls | The host-side server fetch observer recorded one authenticated, matching-id `tools/list` response containing exactly `hub_review` and `hub_task_show`, then successful matching-id, same-task calls to `hub_task_show` and `hub_review`. It checked JSON-RPC errors and `result.isError`, not just HTTP 200. It retained no headers, arguments or result prose. This is hub-side inventory, not a capture of every native model schema. |
197
+ | User/project/plugin decoys absent | The synthetic ambient HOME/tool home, project `.kimi-code/mcp.json`, and enabled local-path plugin manifest/registry each referenced an independent owned decoy server. Their detector positive controls were each 1 before reset; all three request counters stayed 0 through confirmed daemon teardown. Counters observe HTTP/MCP requests, not raw TCP SYNs. Real user/plugin/project config was not edited. Managed-only config was projected by the production backend; the synthetic ambient tool home linked the same real credential/lock directories and device identity without token reads or copies. |
198
+ | No session files retained | Both private reviewer roots and the complete owned scratch tree were removed after daemon/child teardown; the reviewer was offline. |
199
+ | Unchanged real config hashes | Captured real paths were fixed before switching to synthetic ambient source paths. Native config, user MCP and canonical project MCP hashes were identical before/after. The source-worktree MCP file stayed absent. |
200
+
201
+ The original aggregate harness result is still **failed**: it also recorded one generic `bounded hub MCP observation failed` entry and therefore failed its completeness assertion, despite all required observations above being present. Its error entry did not retain method/status metadata, so the actual extra request cannot be attributed. It is not reported as a production failure or silently changed to pass.
202
+
203
+ An account-free fake CLI adding a normal `GET /mcp` reproduced that exact extra error: the observer tried to parse the empty GET body as JSON after the fixed server refused it. A corrected observer records non-POST 405 transport refusals separately; the same fake GET control then passed with the required observations intact. This establishes a collector false-positive path, not retrospective proof of which request caused the live entry. No new live call was made after that fix. The original receipt and producer source hashes remain preserved for review.
204
+
205
+ External receipts under `scratchpad/temp/agent-hub-533`: `complete-kimi-fake-positive.json`, `complete-kimi-fake-negative.json`, `complete-kimi-live-20261019.json`, `complete-kimi-fake-get-repro.json`, and `complete-kimi-fake-get-fixed.json`. `complete-kimi-harness-source.json` pins the four original producer files. The earlier incomplete and advisory receipts remain historical; this new table supplies their previously missing measurements without rewriting them. The last production-source change remains the code tested by exact-head CI `39230896104`; later commits change only this verification report, and their final-head gate is tracked separately.
206
+
207
+
208
+ ## Review follow-up at source 70fe6825
209
+
210
+ Independent review requested the following host-only fixes; no additional Kimi account invocation was made.
211
+
212
+ - P1: each running print child now keeps its immutable envelope head/review revision. Both task-MCP current checks and the daemon's captured verdict-authority closure recheck `Tasks.reviewBindingCurrent`. Legacy print `hub_task_show` is fenced before and after its host await as well. Real daemon/Tasks tests reproduced stale head and same-reviewer revision access before the fix; they now refuse reads and approvals over both transports with unchanged history. A lifecycle-head replacement is also covered.
213
+ - A successful host-committed verdict ends its own in-review binding. Its existing acknowledgement may return, while subsequent calls and read results after lost authority remain refused; a red-first acknowledgement regression and a read-result control cover this distinction.
214
+ - M1: close spies cover normal exit, admission revocation during preparation and native-policy abort. The abort case initially observed zero closes at settlement; explicit idempotent revocation now closes before abort/stop settlement. A dropped-close mutation is detected.
215
+ - M2/M3: credential and OAuth fixture files survive cleanup. Parsed YAML tools must equal exactly the two hub names and subagents must be empty. The mutation adds native Kimi `Write`, not an invented identifier.
216
+ - M4: stop fixtures record actual SIGTERM, verify elapsed locked grace, prove incomplete stops preserve the child, and cover lock removal during grace and no-lock group teardown.
217
+ - M5/M6: rotation takes the modulo over kinds with declared candidates, retaining blocked declared kinds and appending undeclared trace slots afterward. Seeds 0 through 5 split two declared kinds 3/3. Three pinned old-contract expectations changed with the planner's spec amendment. Smoke, area notes and the spec consistently describe receipt-covered Kimi availability and the remaining native ceilings.
218
+ - M7: preparation refuses lexical or physical private-cwd ancestors containing `.git`, `.kimi-code` or `AGENTS.md`, including gitfiles and dangling markers. The current fence repeats the check if a marker appears after preparation. Four initial ancestor regressions and the late-marker regression failed before their fixes.
219
+
220
+ Validation: pinned Bun 1.4.2 focused tests passed `87 pass`, `0 fail`, 624 assertions across 11 files, and TypeScript was clean. Six selected mutation guards passed unmodified code and failed their named assertion after changing the write allowlist, MCP close, captured daemon binding, initial/current ancestor guards or declared-kind denominator. All 429 manifest anchors are unique. The 0.12.37 plugin bundle was regenerated. The new exact-head CI remains the completion gate; the earlier source-head CI and native receipts are preserved as historical evidence, not claimed for a changed tree. The connector thread will be answered with the pushed fix and final gate result.
@@ -0,0 +1,119 @@
1
+ # Reviewer isolation evidence (#519)
2
+
3
+ Status: source integration and model-free production-backend admission are verified. Exact-head CI is a separate required PR gate. This report separates offline native evidence, fake-CLI regressions and unverified account/model behavior. No live review prompt, account login or credential copy was performed for this investigation.
4
+
5
+ ## Admission ruling
6
+
7
+ - Planner ruling, 2026-10-19: #229 ships #519 R3-R6 for Claude and Codex only; ship only reviewer profiles with demonstrated isolation. Kimi and agy remain unavailable and outside the default pool until they have a passing isolation receipt. #229 adds unavailable-reason metadata for them and no launch code. All of their launch/isolation/receipt work belongs to [#533](https://github.com/STAIxBWLB/agent-hub/issues/533), hub task #234; the future agy launcher belongs in `src/adapters/agy/`. Failure, missing evidence and quota exhaustion never count as a verdict.
8
+ - The default logical kind order is Claude, Codex, fixed before modulo; undeclared or unavailable slots are skipped without renumbering. An explicit pool may name the registered unavailable Kimi/agy placeholders; local/Pi are refused. An explicit pool with no declarations blocks, while an omitted pool without declarations preserves legacy routing. An unavailable result must be skipped, never treated as approval. With no explicit required pool, exhausted fresh candidates retain #223 R5 eligible-planner fallback; without one the person reviews. The exhausted walk remains in trace/history. Required explicit-pool exhaustion remains blocked for the person.
9
+ - Existing #223 Claude behavior is retained. This work adds no new live Claude acceptance proof.
10
+ - Codex/Kimi fresh reviewer declarations require `review_mode: "fresh"`. Existing headless instances with roles `["reviewer"]` but no opt-in retain native transport/worktree/permission behavior and stay outside the fresh pool. Claude keeps #223 automatic selection; agy remains metadata-only unavailable. A failed fresh start never downgrades to a continuing native session.
11
+
12
+ ## Codex native evidence
13
+
14
+ - Exact executable used for offline probes: `/opt/homebrew/bin/codex`, reporting `codex-cli 0.146.0`. Its npm package resolves to a native binary. A separate fnm executable on PATH reports 0.163.0; that version has no receipt in this slice and must be unavailable.
15
+ - Primary source pin: `openai/codex`, tag `rust-v0.146.0`, commit `e363b08c9175ac1cbe5893615dd2cb9ddf95043b`.
16
+ - `exec --ephemeral --ignore-user-config --ignore-rules` is accepted by the installed help. These switches respectively remove session persistence, the user config layer and user/project execpolicy rules. They do not remove every config layer. [Pinned exec implementation](https://github.com/openai/codex/blob/e363b08c9175ac1cbe5893615dd2cb9ddf95043b/codex-rs/exec/src/lib.rs)
17
+ - Native `mcp list --json` in temporary homes showed that a CLI `mcp_servers={agent-hub={...}}` table merges with user/project servers. Self-contained disabled stdio/HTTP stubs retained valid configuration both with and without the original user layer. Only the fixed hub remained enabled among configured servers. This inventory does not enumerate runtime ChatGPT Apps contributions and cannot alone prove strict MCP isolation. Native `mcp get agent-hub --json` exposes the exact `enabled_tools` allowlist. The schema specifies that disabled servers are not initialized and only listed enabled tools are registered. [Pinned MCP schema](https://github.com/openai/codex/blob/e363b08c9175ac1cbe5893615dd2cb9ddf95043b/codex-rs/config/src/mcp_types.rs)
18
+ - The original inventory probes included `--disable plugins --disable hooks` and a CLI override marking the physical project root untrusted. The review correction adds `--disable apps` and `web_search="disabled"`, with separate effective-feature proof (see below). Plugin loading has an explicit disabled return path; `--ignore-user-config` alone is insufficient. [Pinned plugin manager](https://github.com/openai/codex/blob/e363b08c9175ac1cbe5893615dd2cb9ddf95043b/codex-rs/core-plugins/src/manager.rs), [config loader](https://github.com/openai/codex/blob/e363b08c9175ac1cbe5893615dd2cb9ddf95043b/codex-rs/config/src/loader/mod.rs)
19
+
20
+ The named profile used filesystem `/ = read`, private entries `= deny` and `network.enabled = false`. Native `sandbox -P <profile>` fixtures produced:
21
+
22
+ ```text
23
+ nested/secret.env READ_DENIED
24
+ alias.env READ_DENIED
25
+ nested/SECRET.ENV READ_DENIED
26
+ public.txt READ_ALLOWED
27
+ WRITE_DENIED
28
+ ```
29
+
30
+ Both exact and glob deny entries passed; the symlink and case alias existed. No write file appeared. A plain read-only profile without a deny entry could read the private fixture. `debug models --bundled` accepted the CLI profile configuration offline. [Pinned permission schema](https://github.com/openai/codex/blob/e363b08c9175ac1cbe5893615dd2cb9ddf95043b/codex-rs/config/src/permissions_toml.rs)
31
+
32
+ The source receipt producer repeats bounded model-free inventory and sandbox checks before a review, including nested glob and symlink private-read denial. It hashes the native executable/prefix once per preparation and binds the profile and config metadata, then checks dev/ino/size/mtime/ctime through `current()` immediately before model spawn. Repeated current checks do not synchronously reread the native binary. A bare deny name is compiled at the project root and at nested segment depth; `~/` is resolved against the home directory. Raw MCP output, transport environments and config contents are not receipt evidence. Unsupported version, changed/unknown inventory, own-server collision, failed sandbox proof, abort or changed metadata makes the backend unavailable.
33
+
34
+ Codex "read-only tools" means sandboxed shell with filesystem read-only/private-deny policy and network disabled. It does not mean Claude's Read/Grep/Glob tool whitelist. No native LLM review, network-denial probe, post-start glob mutation or concurrent filesystem/config swap was tested. No recorded run shows exec selecting `ahub-review` through `default_permissions`; argv pinning and `sandbox -P ahub-review` test different paths. The profile declares the network boundary; it is not a measured network result. Same-user concurrent changes after the final check remain a ceiling, not a claimed atomic filesystem snapshot.
35
+
36
+ ## Kimi evidence and gap
37
+
38
+ - Installed version: 2.2.0. Primary source pin: `MoonshotAI/kimi-code`, tag `@moonshot-ai/kimi-code@2.2.0`, commit `472192c34c1efad89a369870eff0da0b708ce9bb`.
39
+ - An explicit `--agent-file` profile can allow only Read/Grep/Glob and the two hub MCP tools, with `subagents: []`. The runtime executor registers a tool-policy guard; the allowlist is more than prompt text. [Pinned policy guard](https://github.com/MoonshotAI/kimi-code/blob/472192c34c1efad89a369870eff0da0b708ce9bb/packages/agent-core-v2/src/agent/toolPolicy/toolPolicyService.ts)
40
+ - `KIMI_CODE_HOME` separates config, sessions and credentials. ACP session MCP servers are additive: trusted project/user/plugin servers can still load. No strict-MCP or no-persistence CLI profile was demonstrated. Reusing ordinary authentication through an isolated home was not tested or authorized by this investigation. Kimi remains unavailable. [Pinned MCP loader](https://github.com/MoonshotAI/kimi-code/blob/472192c34c1efad89a369870eff0da0b708ce9bb/packages/agent-core-v2/src/workspace/workspaceMcpConfig/workspaceMcpConfigService.ts), [bootstrap paths](https://github.com/MoonshotAI/kimi-code/blob/472192c34c1efad89a369870eff0da0b708ce9bb/packages/agent-core-v2/src/app/bootstrap/bootstrapService.ts)
41
+
42
+ ## agy evidence and gap
43
+
44
+ - Installed version: 1.4.2. Help exposes `-p`, `--output-format stream-json`, `--mode plan`, `--sandbox` and `--agent`; no isolation receipt was produced.
45
+ - Official documentation describes plan mode as a `/plan` prompt prefix. Headless mode auto-allows workspace reads and writes; the terminal sandbox mounts project folders read-write. These are insufficient for a read-only reviewer. [Execution modes](https://www.agy.dev/docs/cli/modes/), [headless permissions](https://www.agy.dev/docs/cli/headless/), [terminal sandbox](https://www.agy.dev/docs/sandbox/)
46
+ - Custom-agent documentation lists tool limits and MCP settings, but this investigation did not establish a CLI-only, host-owned profile path with strict config/MCP isolation. agy remains unavailable. No profile, account or model execution was attempted. [Custom agents](https://www.agy.dev/docs/subagents?tab=cli)
47
+
48
+ ## Remaining verification
49
+
50
+ - Final integration tests and exact-head CI must validate pure rotation, delta continuity, start-failure/no-verdict walking, blocked exhaustion, fresh child authority and additive family/reason metadata. Any child ending without a saved verdict retries the remaining eligible walk; no quota classification is inferred from vendor text.
51
+ - Native account/model smoke remains manual, as listed in [smoke.md](../smoke.md#reviewer-pool-native-legs-519-2026-10-19). Fake CLI tests prove the host contract and refusal paths, not vendor model behavior.
52
+
53
+ ## Production admission readback
54
+
55
+ On 2026-10-19 the actual `codexReviewerBackend.prepare` ran against `/opt/homebrew/bin/codex` 0.146.0 in a new temporary repository directory, with empty temporary HOME and CODEX_HOME and a fixed inert hub transport. It returned `readOnly: true`, `strictMcp: true`, `ephemeral: true` and `current: true` after the native MCP, exact/glob/symlink denial, public read and write-denial probes. The temporary home and fixtures were removed. This did not execute `codex exec`, initialize an account, copy credentials or issue a model request. Network blocking remains a configured restriction, not a separately observed network probe.
56
+
57
+ The first correctly initialized native run exposed an admission bug: the pinned bundled model catalog exceeds the 128 KiB inventory-output cap. Configuration validation now drains that one command without retaining its output, with a separate 4 MiB ceiling; MCP/version/sandbox metadata retain the 128 KiB ceiling. A red-first regression covers a larger valid catalog and refuses a catalog above the ceiling. The production-backend admission then passed.
58
+
59
+ The shared review child also bounds a stream frame to 256 KiB and total stdout to 4 MiB. Overflow revokes verdict authority before process-group teardown and only then reports head/revision-bound `no_verdict` failures for the current and unprocessed requests. A person's stop suppresses automatic fallback. Fake-CLI regressions cover both limits, batch failure, watchdog cleanup and stop-generation revocation.
60
+
61
+ Agy declaration metadata is separate from the native runtime catalog. Existing supported/optional peer projections, exact legacy catalog tests, registry-guard expectations and the empty baseline are unchanged. An unavailable-only declaration set cannot fall through to automatic approval; an omitted pool may select an eligible planner under #223 R5; its static #533 reason remains in routing explanations, including explicit nominations.
62
+
63
+ ## Core deny policy
64
+
65
+ Codex imports the exact-pinned portable core's `DENY_NAMES` and `DENY_SEGMENTS` and translates the supported literal-prefix/suffix regex forms into conservative native deny globs. Unknown syntax refuses admission. The profile includes each subtree explicitly, and the daemon also supplies its concrete state directory. Runtime fixtures now require both `.env` and `.agenthub/state/private.txt` to be unreadable. The production backend passed again with these global core rules on 2026-10-19, with `portable-core-name-and-state-deny` in its evidence. Explicit private paths protect lexical and existing real paths and include descendants; plain relative substring entries are conservatively broadened.
66
+
67
+ This global policy does not enumerate the filesystem on the verified macOS path: the pinned native implementation translates unreadable globs into anchored Seatbelt regular expressions, including `**/`, at read time. A glob containing `**` does not automatically protect descendants, which is why the explicit `/**` rules are required. [Pinned Seatbelt compiler](https://github.com/openai/codex/blob/e363b08c9175ac1cbe5893615dd2cb9ddf95043b/codex-rs/sandboxing/src/seatbelt.rs#L441-L581), [policy-level glob semantics](https://github.com/openai/codex/blob/e363b08c9175ac1cbe5893615dd2cb9ddf95043b/codex-rs/protocol/src/permissions.rs#L306). Other native platforms must pass their runtime proof; no native Linux account/model success is claimed.
68
+
69
+ ## Focused verification
70
+
71
+ Pinned Bun 1.4.2 on the remote Linux runner passed TypeScript, plugin-bundle freshness and 365 tests in 20 affected files (2,883 assertions). The actual macOS Codex 0.146.0 preparation passed again with core deny, explicit paths and nested substring rules. All 421 existing seed anchors remain unique; this static check is not a seeded-runtime result. These focused results predate the compatibility repair and do not establish a successful final-head full gate. Existing catalog/guard tests, the registry baseline and seed manifest are byte-unchanged.
72
+
73
+
74
+ ## Compatibility repair checkpoint
75
+
76
+ The full CI run at historical head `4aa64c12` exposed nine failures in unchanged I2 compatibility tests: the original headless Codex/Kimi reviewer-role declaration had been reinterpreted as a fresh variant. That head's 421 seeded guards passed; seed success did not waive the compatibility failures. The repair adds explicit `review_mode: "fresh"` opt-in for Codex/Kimi, preserves existing Claude selection and keeps legacy native reviewer-role instances outside the fresh pool. The native production privacy-profile proof is unchanged by this declaration repair. The repaired head's final full CI gate is pending.
77
+
78
+ After the explicit-fresh declaration correction, pinned Bun 1.4.2 passed TypeScript, bundle freshness and 381 tests in 24 affected files (3,052 assertions), including every previously failing I2/reload/worktree/revert test. The isolation producer and common child lifecycle are byte-identical to the native-probed implementation. All 421 existing source anchors remain unique. Final full CI for the corrected head remains a separate PR gate.
79
+
80
+
81
+ ## Review correction: runtime Apps contribution
82
+
83
+ Independent review found that the original `strictMcp` claim exceeded its evidence. In the pinned source, Apps is stable and enabled by default; the runtime MCP projection adds the ChatGPT Apps compatibility server independently of plugin loading. `mcp list` calls `configured_servers`, which intentionally omits those runtime contributions. The earlier empty-home admission did not exercise ChatGPT-authenticated connectors and is not proof that they were excluded. [Feature defaults](https://github.com/openai/codex/blob/e363b08c9175ac1cbe5893615dd2cb9ddf95043b/codex-rs/features/src/lib.rs), [runtime/configured MCP projections](https://github.com/openai/codex/blob/e363b08c9175ac1cbe5893615dd2cb9ddf95043b/codex-rs/core/src/mcp.rs), [CLI inventory](https://github.com/openai/codex/blob/e363b08c9175ac1cbe5893615dd2cb9ddf95043b/codex-rs/cli/src/mcp_cmd.rs).
84
+
85
+ The corrected policy explicitly disables Apps and requires a bounded, unique effective-feature readback of `apps` as false, as well as plugins/hooks false, before granting a receipt. The fixed exec argv carries the same switches and disables web search, whose cached mode is served remotely. Missing, duplicate, malformed or enabled Apps readbacks refuse admission even if configured MCP inventory looks strict. Fake producer regressions and daemon argv assertions cover this distinction. On 2026-10-19 the corrected production backend passed again with empty temporary HOME and CODEX_HOME, using Codex 0.146.0 and an inert `/usr/bin/false` hub transport. It returned `apps-disabled-effective-feature-readback`, `web-search-disabled`, the existing filesystem/MCP evidence and `current: true`; no exec/model/account call ran. This verifies the effective Apps feature gate in addition to configured-server inventory, with the pinned source proving that the disabled gate removes the runtime compatibility server. The daemon argv regression pins Apps/plugins/hooks disable switches, project trust, named default permissions and disabled web search. Final-head CI remains a separate gate; account/model execution remains unverified.
86
+
87
+
88
+ ## Review correction: standard host credentials
89
+
90
+ The PR bot identified a second privacy gap: portable core filename/state rules do not cover ordinary files such as `.config/gh/hosts.yml`, `.kube/config` and `.docker/config.json` under the host home. With `/ = read`, configured project-private patterns alone are insufficient. The correction adds fixed standard host credential directory/file denies, configured XDG/tool-home roots, existing real-path aliases and descendants. Credential protection does not depend on a person configuring `local.deny`.
91
+
92
+ Regressions use a synthetic HOME and configured roots, never real credential contents. The native admission fixture also requires synthetic gh/kube/docker credential reads to fail. This is a bounded standard credential list, not a claim to discover or classify every personal/private file on the host; projects must continue to declare additional private paths. On 2026-10-19 the actual corrected production backend passed with Codex 0.146.0 in empty temporary HOME/CODEX_HOME. Its native sandbox denied synthetic gh/kube/docker credential files and a symlink alias, returning `standard-host-credential-roots-denied` alongside Apps-effective-state and existing filesystem evidence, with `current: true`. These fixtures contained only canary text; no account/model/exec call or credential copy was involved. Final-head CI remains the PR gate.
93
+
94
+
95
+ ## Review-fix focused gate
96
+
97
+ After both Important fixes, the related nits and the host-credential correction, pinned Bun 1.4.2 on the remote Linux runner passed 445 tests in 29 affected files (3,164 assertions), TypeScript and generated-bundle freshness. The final native model-free preparation also passed on macOS as described above. All 421 existing seed anchors are unique; runtime seed success is a separate exact-head CI gate. Legacy/frozen tests, the registry baseline and seed manifest remain unchanged. These results do not supply independent approval or native account/model acceptance.
98
+
99
+
100
+ ## Review correction: canonical credential ancestors
101
+
102
+ The prior Linux and CI evidence did not expose the developer Mac's default `/var` to `/private/var` TMPDIR alias. Local pinned Bun 1.4.2 reproduced both the existing synthetic-HOME failure and an explicit symlinked-HOME/missing-descendant regression before the fix. Standard names are now joined under both lexical HOME and its canonical deepest existing ancestor; every credential root also resolves its deepest existing ancestor before appending absent components. Both spellings and existing final symlink targets remain denied. Dangling links and unreadable ancestors refuse admission. The adapter keeps this short strict ancestor walk local because importing `path-policy` would introduce a registry cycle.
103
+
104
+ Privacy ceilings remain explicit: credential roots are derived from the child environment's HOME and configured overrides. If HOME is overridden, the separate account home returned by `os.userInfo().homedir` is not automatically included. The bounded list also does not include shell history/rc files (`.zsh_history`, `.bash_history`, `.zshrc`), `Library/Application Support`, `.pgpass`, `.m2/settings.xml`, `.gradle/gradle.properties` or `.oci`; additional private paths must be declared. This is not a universal private-home sandbox.
105
+
106
+ `web_search="disabled"` is a requested config value, without effective-turn readback. At the pinned source, managed requirements that prohibit Disabled can make `resolve_web_search_mode_for_turn` select Cached instead. The receipt evidence label `web-search-disabled` records only that configured value. Therefore the flag is not proof that remote cached search is unavailable; the effective Apps feature proof and native filesystem denial evidence do not establish that separate boundary. [Pinned web-search resolution](https://github.com/openai/codex/blob/e363b08c9175ac1cbe5893615dd2cb9ddf95043b/codex-rs/core/src/config/mod.rs#L2979-L3005).
107
+
108
+
109
+ Local verification after this correction used pinned Bun 1.4.2 and the unmodified default macOS TMPDIR: 40 tests across `codex-review-isolation` and `reviewer-pool-tasks` passed (166 assertions). A model-free native Codex 0.146.0 preparation also passed under a synthetic symlinked HOME; after the returned profile was built, a new synthetic `.kube/config` was created under the physical HOME and a direct native sandbox cat of that canonical path was denied. The fixture was removed. No account, credential copy, model request or `codex exec` was involved. The named exec-profile-selection and effective web-search ceilings remain unverified as described above.
110
+
111
+
112
+ The corrected source then passed the remote Linux focused gate: 447 tests in 29 files (3,176 assertions), TypeScript and pinned Bun 1.4.2 bundle freshness. All 421 existing seed anchors remain unique. Final-head CI is required separately; the local default-TMPDIR result is the developer-Mac regression evidence, not inferred from CI.
113
+
114
+
115
+ ## Main rebase after shard-store merge
116
+
117
+ The reviewer-pool branch was rebased onto main `29719a78` after #534 merged, retaining the memory-open changes and exact agent-mem 0.4.0 pin. The only rebase conflict was the generated plugin bundle; it was regenerated with pinned Bun 1.4.2 and the installed 0.4.0 dependency. Reviewer source/tests, including the canonical credential fix and same-family reason, are byte-identical to the locally verified pre-rebase versions. The imported platform helper file is also byte-identical between published 0.3.1 source and installed 0.4.0 (SHA-256 `2ab3908eb317833e000616760ad04c1dffe7befadea542535d8d9dba330411eb`).
118
+
119
+ I separately ran the exact merged main's memory tests: 220 pass, 1 environment skip, 0 fail in 25 files (1,584 assertions), plus TypeScript. Further local integration/native reruns after rebase were deferred by host resource admission; no bypass was used. The new final-head CI must establish the combined tree's full gate. No new native-account/model result is claimed.