@staix/agent-hub 0.21.0 → 0.23.0

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 (100) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/README.md +2 -2
  3. package/docs/agent-notes/adapters.md +2 -1
  4. package/docs/agent-notes/budget.md +1 -1
  5. package/docs/agent-notes/bus.md +5 -2
  6. package/docs/agent-notes/daemon.md +5 -4
  7. package/docs/agent-notes/local-worker.md +1 -1
  8. package/docs/agent-notes/models.md +2 -1
  9. package/docs/agent-notes/tasks.md +2 -1
  10. package/docs/agent-notes/tests.md +2 -2
  11. package/docs/dogfood.md +10 -2
  12. package/docs/operations.md +192 -6
  13. package/docs/profiles.md +29 -4
  14. package/docs/quickstart.md +9 -1
  15. package/docs/security.md +7 -1
  16. package/docs/smoke.md +6 -0
  17. package/docs/specs/2026-09-19-agent-hub-design.md +94 -1
  18. package/docs/verification/2026-10-30-0.22.0.md +49 -0
  19. package/docs/verification/2026-10-30-0.23.0.md +70 -0
  20. package/docs/verification/2026-10-30-445-capability-probes.md +172 -0
  21. package/docs/verification/2026-10-30-adapter-operational-settings.md +261 -0
  22. package/docs/verification/2026-10-30-bus-delivery-operational-settings.md +77 -0
  23. package/docs/verification/2026-10-30-jcode-ac4.md +24 -0
  24. package/docs/verification/2026-10-30-jcode-ac6.md +52 -0
  25. package/docs/verification/2026-10-30-model-operational-settings.md +211 -0
  26. package/docs/verification/2026-10-30-operational-settings-closure.md +1217 -0
  27. package/docs/verification/2026-10-30-recovery-wait-settings.md +141 -0
  28. package/docs/verification/2026-10-30-ui-console-operational-settings.md +1845 -0
  29. package/docs/verified.json +15 -15
  30. package/package.json +1 -1
  31. package/plugins/agent-hub/.claude-plugin/plugin.json +1 -1
  32. package/plugins/agent-hub/ROLE-NOTICE.md +1 -1
  33. package/plugins/agent-hub/server.js +559 -115
  34. package/src/adapters/acp.ts +48 -2
  35. package/src/adapters/claude-channel.ts +6 -4
  36. package/src/adapters/codex-appserver.ts +19 -0
  37. package/src/adapters/jcode.ts +1 -1
  38. package/src/adapters/local-worker.ts +3 -3
  39. package/src/adapters/native-capabilities.ts +50 -0
  40. package/src/adapters/registry-types.ts +3 -10
  41. package/src/cli/capabilities-output.ts +30 -0
  42. package/src/cli/console-state.ts +8 -5
  43. package/src/cli/console.ts +27 -4
  44. package/src/cli/help.ts +3 -1
  45. package/src/cli/identity.ts +4 -1
  46. package/src/cli/learn-output.ts +38 -0
  47. package/src/cli/main.ts +28 -2
  48. package/src/cli/recovery-waits.ts +26 -0
  49. package/src/cli/smoke-pty-bridge.ts +67 -18
  50. package/src/cli/smoke-pty.ts +10 -2
  51. package/src/cli/upgrade-runtime.ts +16 -14
  52. package/src/cli/upgrade.ts +2 -1
  53. package/src/hub/board.ts +8 -2
  54. package/src/hub/bus.ts +117 -17
  55. package/src/hub/capabilities.ts +215 -0
  56. package/src/hub/config-apply.ts +8 -4
  57. package/src/hub/config-trust.ts +1 -0
  58. package/src/hub/control-client.ts +41 -8
  59. package/src/hub/daemon.ts +436 -33
  60. package/src/hub/deferred-hub.ts +2 -2
  61. package/src/hub/delivery-hints.ts +2 -2
  62. package/src/hub/delivery-journal.ts +80 -61
  63. package/src/hub/envelope.ts +12 -2
  64. package/src/hub/events.ts +2 -0
  65. package/src/hub/hub-tools.ts +16 -1
  66. package/src/hub/inference.ts +10 -5
  67. package/src/hub/invocations.ts +316 -0
  68. package/src/hub/learning.ts +33 -1
  69. package/src/hub/operational-settings.ts +180 -1
  70. package/src/hub/peers.ts +3 -0
  71. package/src/hub/restart.ts +2 -2
  72. package/src/hub/room-invocations.ts +145 -0
  73. package/src/hub/settings.ts +22 -2
  74. package/src/hub/shipped-packs.ts +5 -2
  75. package/src/hub/shipped-roles.ts +13 -0
  76. package/src/hub/tasks.ts +92 -1
  77. package/src/memory/capture.ts +2 -2
  78. package/src/models/relay.ts +20 -9
  79. package/src/rooms/application.ts +67 -2
  80. package/src/rooms/boundary.ts +43 -11
  81. package/src/rooms/service.ts +40 -2
  82. package/templates/checks/analysis.mjs +59 -0
  83. package/templates/checks/fixtures/analysis-expected.json +1 -0
  84. package/templates/checks/fixtures/analysis-input.json +1 -0
  85. package/templates/checks/fixtures/analysis.mjs +7 -0
  86. package/templates/checks/fixtures/ops.json +4 -0
  87. package/templates/checks/fixtures/writing-rules.json +4 -0
  88. package/templates/checks/fixtures/writing.json +5 -0
  89. package/templates/checks/ops.mjs +40 -0
  90. package/templates/checks/writing.mjs +40 -0
  91. package/templates/packs/analysis.pack.json +14 -0
  92. package/templates/packs/ops.pack.json +14 -0
  93. package/templates/packs/writing-pack.pack.json +14 -0
  94. package/templates/roles/NOTICE.md +1 -1
  95. package/templates/roles/ops/meeting-actions-owner.md +26 -0
  96. package/templates/roles/ops/project-manager.md +26 -0
  97. package/templates/roles/writing/editor.md +26 -0
  98. package/templates/roles/writing/style-checker.md +26 -0
  99. package/templates/roles/writing/terminology-checker.md +26 -0
  100. package/templates/roles/writing/translator.md +26 -0
@@ -0,0 +1,49 @@
1
+ # 0.22.0 release verification
2
+
3
+ This record covers release preparation and source review. It claims no installation, no running-hub upgrade to 0.22.0 and no live TUI launch.
4
+
5
+ ## Candidate
6
+
7
+ Version 0.22.0, prepared from main 28acd10e (9 commits since v0.21.0, 3 of them `feat`; bump rule: minor). The release commits carry the version, the CHANGELOG section, the bundle and the documentation stamps.
8
+
9
+ ## Reviews
10
+
11
+ Pull requests named by the commits since v0.21.0: #981, #976, #980, #979, #978, #977, #975, #972, #973.
12
+
13
+ Each of these merged with `gh pr merge --squash --match-head-commit <head>` after its review, with exact-head CI green and no unresolved review thread at that head:
14
+ - #981 (jcode, docs only): the two nits from the #979 review (task 445). The conductor read the diff and merged on green CI; it has no hub task of its own.
15
+ - #980 (task 428): approved at 0045cdc5 after one change request that removed real config-file hashes from the AC6 receipt.
16
+ - #979 (task 445, #489 H4): approved at b06839f7 with two doc nits, fixed by #981.
17
+ - #978 (task 177, #445 C0): approved by the person at 4713fdb8, which includes owner decision O6.
18
+ - #976 (task 560): approved at ab8af600 after one change request (the caller captured before `Bun.spawn`, PTY tests within 20 s). Its first fix at 3d22f048 failed the ubuntu leg on a macOS-only assertion, which was then limited to darwin.
19
+ - #977 (task 564), #975 (task 444, #489 H3), #973 (task 563) and #972 (task 323) were approved at their merged heads.
20
+ No merge was bound to an approval at an earlier head.
21
+
22
+ ## Native acceptance receipts
23
+
24
+ Receipts added under `docs/verification/` since v0.21.0: `docs/verification/2026-10-30-445-capability-probes.md`, `docs/verification/2026-10-30-bus-delivery-operational-settings.md`, `docs/verification/2026-10-30-jcode-ac4.md`, `docs/verification/2026-10-30-jcode-ac6.md`, `docs/verification/2026-10-30-recovery-wait-settings.md`.
25
+
26
+ This list is read from the repository, never written by hand. Native acceptance and the person's release consent are separate records: consent is `ahub sdlc authorize-release 0.22.0`, person only, and is not recorded in this file. The tag run refuses without it.
27
+
28
+ ## Document review
29
+
30
+ `node scripts/check-docs.mjs --require-fresh` reported 12 stale documents. Each was checked against its source commits since its stamp (#972 `ahub learn`, #975 `bus.*`, #979 `recovery.*`, #976 the PTY bridge; #977 and #973 for tests.md) for statements those commits made untrue, then restamped at cb942e06:
31
+ - src/cli/help.ts (1): the `ahub learn` line matches the usage string in `src/cli/main.ts`.
32
+ - README.md (5) and docs/quickstart.md (5): the status line, the report link, the install pin and a new "Upgrading to 0.22.0" note.
33
+ - docs/operations.md (5): the `bus.*` and `recovery.*` rows and sections; the H3 ledger paragraph placement was fixed by #981. `ahub learn` is documented in docs/profiles.md and the help, not here.
34
+ - docs/agent-notes/bus.md and daemon.md: three statements named constants that are now settings (`PULL_BUDGET_BYTES` and `DIGEST_MAX`, `RECONNECT_WAIT_MS`, the 30 s recovery control cap). They now name the settings, in 0737fa19.
35
+ - docs/agent-notes/tasks.md and tests.md: already updated by #972 and #976 (the `runStarted` line). adapters.md, budget.md and docs/security.md: no statement changed by these commits. docs/agent-notes/README.md: stale only through daemon.md.
36
+ The CHANGELOG gained the missing #975 entry.
37
+
38
+ ## Checks
39
+
40
+ In the release worktree with its own frozen install (`@staix/agent-mem` 0.13.0): `node scripts/check-docs.mjs --require-fresh` printed `docs: OK (0 stale documents)`, `bun x tsc --noEmit` was clean, `bun scripts/build.mjs --check` exited 0 and `node scripts/check-package.mjs` printed `package: OK (645 files, @staix/agent-hub@0.22.0)`. The release PR's exact-head CI runs the full gate on both OSes.
41
+
42
+ ## Known gaps, not blocking
43
+
44
+ - The release adds no new live receipt. Still open: #912 AC1, #793 AC6 (task 468: the hub must be restarted with the remote runner), #418 AC8, and #332 AC6 (Jcode 0.99.1 still does not echo the loaded session id; the jcode-ac6 receipt).
45
+ - The ten new settings were exercised through fixtures and a real daemon in tests, never edited live against a running hub. No real `ahub upgrade` ran with a configured `recovery.*` value.
46
+ - The PTY start gate is a workaround for Bun bug #45300 (fixed in 1.4.4). The pin stays 1.4.2: 1.4.4 is under two weeks old until 2026-11-05 (task 565).
47
+ - #445 capability skill execution (Kimi, Qwen, Codex) is unverified; it needs accounts, in phase C4.
48
+ - The full `scripts/check.sh` was not run locally; the release PR's CI runs it on both OSes.
49
+ - Not in this release: #982 (task 446, #489 H5), approved and merging after the tag.
@@ -0,0 +1,70 @@
1
+ # 0.23.0 release verification
2
+
3
+ This record covers release preparation and source review. It claims no installation, no running-hub upgrade to 0.23.0 and no live TUI launch.
4
+
5
+ ## Candidate
6
+
7
+ Version 0.23.0, prepared from main 2dbd4853 (11 commits since v0.22.0, 8 of them `feat`; bump rule: minor). The release commits carry the version, the CHANGELOG section, the bundle and the documentation stamps.
8
+
9
+ ## Reviews
10
+
11
+ Pull requests named by the commits since v0.22.0: #993, #992, #991, #990, #989, #986, #987, #567, #988, #985, #984, #982.
12
+
13
+ Every one merged with exact-head CI green and no unresolved review thread. The conductor (claude) read each hub approval in `hub.db` and compared its head with the merged head:
14
+
15
+ - Merged at the approved head: #993 (task 322, ae6900e6), #990 (task 572, 58ba2e2b), #988 (task 567, 104d5eb5).
16
+ - Merged after the conductor re-reviewed a follow-up diff on top of the approved head, because the hub refuses a second approval of an approved task:
17
+ - #992 (task 187): approved d1bcf22c, merged e492e359. The follow-up sorts the remote argument keys, a connector P2.
18
+ - #991 (task 180): approved 4b54d96f, merged 17c3df2a. The follow-up gives `hub_invoke` an approval-sized control timeout with cancellation, a connector P2.
19
+ - Merged after a rebase whose `git range-diff` against the approved head shows no code change:
20
+ - #987 (task 448): approved 6bae3153, merged 8452d254; every commit is identical.
21
+ - #986 (task 179): approved 08096575, merged 5920c228; one commit message differs.
22
+ - #984 (task 447): approved eaeeb7b2, merged 1f8e3d7a. The H5 commits dropped out after #982 merged, and the H6 commit is identical.
23
+ - #982 (task 446): approved 473d0d63, merged 90643007; one `docs/operations.md` conflict hunk was resolved in the release rebase.
24
+ - #985 (task 178): approved 5e2fccba, merged f21fe4fb. The rebase added one docs-only commit (the `acpManifest` comment and the parser location in the spec) and rebuilt the bundle.
25
+ - #989 is docs only (the #489 disposition, Fixes #489), with no hub task; claude reviewed it on the PR before the merge.
26
+
27
+ Release merge: #994 merged release/0.23.0 at 18947c14 with a merge commit, c3e322f4, so the stamp commit ce8da3ec is an ancestor of main. It was given a custom subject (`Merge release 0.23.0 (#994)`). `scripts/release-tag.ts` accepts only the default `Merge pull request #N from <owner>/release/0.23.0` subject, so it refused that commit. This note is carried by a second release PR merged with the default subject, and the tag goes on that merge commit; no history was rewritten and no guard was changed. The connector's P1 on #994 (stamps not in the ancestry) did not apply: it reviewed a squashed view (3c7b0aa) that is not in the branch history.
28
+
29
+ ## Native acceptance receipts
30
+
31
+ Receipts added under `docs/verification/` since v0.22.0: `docs/verification/2026-10-30-adapter-operational-settings.md`, `docs/verification/2026-10-30-model-operational-settings.md`, `docs/verification/2026-10-30-operational-settings-closure.md`, `docs/verification/2026-10-30-ui-console-operational-settings.md`.
32
+
33
+ This list is read from the repository, never written by hand. Native acceptance and the person's release consent are separate records: consent is `ahub sdlc authorize-release 0.23.0`, person only, and is not recorded in this file. The tag run refuses without it.
34
+
35
+ ## Document review
36
+
37
+ `node scripts/check-docs.mjs --require-fresh` reported 15 stale documents. Each was checked against its source commits since its stamp (cb942e06, or aeeaeb04 and 43867c65 for local-worker.md, models.md and benchmarks.md). The check looked for statements those commits made untrue and for rules an agent editing that area now needs. Every proposed fix was confirmed against the code before it was applied in ce8da3ec, and all 15 were then restamped at ce8da3ec.
38
+ - README.md (9): the report link now names this report. docs/quickstart.md (9): the install pin and a new "Upgrading to 0.23.0" note.
39
+ - docs/operations.md (10): the capabilities listing no longer says invoking is a later slice. The #489 line records the #989 closure. The relay cooldown names the `model_relay.*` settings (the streak resets after twice the cap, `src/models/relay.ts:251`). The `role list` groups and the `init --profile` text name the shipped packs.
40
+ - docs/security.md (9): `invocation` joins the machine-local field list, and the X4 boundary section states what X6 lets cross.
41
+ - src/cli/help.ts (1): the `ahub init` line names the shipped packs. Its watched paths do not include `src/hub/shipped-packs.ts`, so freshness alone would not have caught this.
42
+ - Agent notes:
43
+ - bus.md: invocation kinds go alone and are never condensed or steered into; the `onAnswer` capture order; no ordinary replay; add a kind only to `KINDS`; `remoteEnvelope` for provenance.
44
+ - daemon.md: the `invocation` recovery feature floor, next-use and restart settings captured once by their consumer, and the `hub_invoke` socket/`rid` abort binding.
45
+ - adapters.md: `adapter_timing.*` passed at construction, and native capability listings.
46
+ - budget.md: the invocation exception to the quota-pause retry rule.
47
+ - local-worker.md: remote turns are `remoteEnvelope`.
48
+ - models.md: `model_relay.*` and `inference.backoff_min` are restart-bound.
49
+ - tasks.md: the `Tasks.recordInvocation` audit rule.
50
+ - tests.md, benchmarks.md and agent-notes/README.md: no statement changed (#990 had already updated the CI shard lines).
51
+ - The CHANGELOG gained the missing #982, #984, #987, #988, #991, #992 and #993 entries, and the C1 and C2 entries no longer say invocation is a later slice.
52
+
53
+ ## Checks
54
+
55
+ In the release worktree with its own frozen install (`@staix/agent-mem` 0.13.0):
56
+ - `node scripts/check-docs.mjs --require-fresh` printed `docs: OK (0 stale documents)`.
57
+ - `bun x tsc --noEmit` was clean.
58
+ - `bun scripts/build.mjs --check` exited 0.
59
+ - `node scripts/check-package.mjs` printed `package: OK (673 files, @staix/agent-hub@0.23.0)`.
60
+
61
+ The release PR's exact-head CI is the full gate on both OSes.
62
+
63
+ ## Known gaps, not blocking
64
+
65
+ - No new live receipt in this release. #445 C4 (Claude invoking a Kimi command and a Codex skill on a real task, with a person approving) needs this release installed and is task 181. #446 X7 (a live room run on two Macs) is task 188. Still open: #912 AC1, #793 AC6 (task 468: the hub must be restarted with the remote runner), #418 AC8 and #332 AC6.
66
+ - Capability invocation (C1-C3, X6) is proved with fixture peers and two in-process daemons with the real broker and crypto; no native account executed a shared skill.
67
+ - The thirteen new settings were exercised through fixtures and real daemons in tests, never edited live against a running hub.
68
+ - The running hub on this machine is 0.20.0; no `ahub upgrade` to 0.23.0 has run.
69
+ - The Bun pin stays 1.4.2: 1.4.4 is under two weeks old until 2026-11-05 (task 565).
70
+ - The full `scripts/check.sh` was not run locally; the release PR's CI runs it on both OSes.
@@ -0,0 +1,172 @@
1
+ # #445 C0 capability-source probes (Kimi, Qwen, Codex)
2
+
3
+ Date: 2026-10-30. Refs #445 (C0 row of the binding design, D1 "Sources, one per adapter"). Model-free probes of the native capability listings each adapter would read, run against the CLIs installed on the probe host, not the versions the card names (Kimi 2.1.x, Qwen 0.25.0, Codex pinned 0.154.0).
4
+
5
+ ## Versions probed
6
+
7
+ | CLI | Version | Artifact SHA-256 |
8
+ | --- | --- | --- |
9
+ | Kimi Code (`kimi`, native macOS arm64) | 2.3.2 (served `agentInfo` `Kimi Code CLI` 2.3.2) | `d84a94c7d73405283a279348d2de78abbf31d2b1f7c92a8d739eeb40cf2a2f9f` |
10
+ | Qwen Code (`@qwen-code/qwen-code`) | 0.26.1 (served `agentInfo` `qwen-code` 0.26.1) | `cli-entry.js` `113efe4104a9fc66f507d34bfd6abbd896ceb77de47f4b468a0825a327fdc6a5` (same as the 0.26.1 ACP receipt) |
11
+ | Codex (`codex-cli`, native darwin-arm64) | 0.166.0 (initialize `userAgent` `.../0.166.0`); source tag `rust-v0.166.0` = `593389380740f7b4762771573c447ccfdc59742f` | `39acf979729dd290f9a24ee38b2914e036c91b65952872e28ae2a6b88a7db7c1` |
12
+
13
+ ## Isolation
14
+
15
+ - Every probe ran through one wrapper: `env -i` with `PATH`, `HOME`, `KIMI_CODE_HOME`, `KIMI_HOME`, `QWEN_HOME`, `QWEN_RUNTIME_DIR`, `CODEX_HOME`, `XDG_CONFIG_HOME`, `XDG_DATA_HOME`, `TMPDIR`, `LANG`, `TERM` only, all homes pointing into a fresh scratch tree, cwd a scratch directory (never the repo), under `sandbox-exec` with a profile that denies all outbound IP (`(deny network-outbound (remote ip))`, checked first: a plain HTTPS fetch failed to connect).
16
+ - No auth file was copied. Where a leg needed a configured model to open a session, it used a fixture model on an unreachable loopback base with a literal non-key string (`fixture-not-a-key`), the same method as the earlier Qwen receipts. No session/prompt that starts a model turn was sent. Only builtin slash commands that the CLIs answer locally were prompted.
17
+ - Each probe was one short run (8-9 s for ACP, 3 s for Codex). The probe started the CLI in its own process group, sent SIGTERM to the group at the end, and confirmed with `pgrep -g` that the group was gone (all 7 runs: `group_gone` true). The kimi/qwen/codex process list before and after is identical, and no process referencing the scratch tree remains.
18
+ - The running agent-hub daemon and `.agenthub` state were not touched; the repo test suite was not run.
19
+ - Deviation: `kimi --version`, `qwen --version` and `codex --version` were run once on the real home before the baseline hashes were taken (version print only). Every later run used the isolated wrapper.
20
+
21
+ ## Real config check (before = after)
22
+
23
+ Each file's SHA-256 was taken before the first isolated probe and after the last one; every pair matched (`diff` empty). The hashes themselves are not published, because they would fingerprint the probe host's credential and identity files.
24
+
25
+ | File | Before = after |
26
+ | --- | --- |
27
+ | `~/.kimi-code/config.toml` | unchanged |
28
+ | `~/.kimi-code/mcp.json` | unchanged |
29
+ | `~/.kimi-code/tui.toml` | unchanged |
30
+ | `~/.kimi-code/device_id` | unchanged |
31
+ | `~/.kimi-code/credentials/kimi-code-env-<id>.json` | unchanged |
32
+ | `~/.kimi-code/oauth/kimi-code-env-<id>` | unchanged |
33
+ | `~/.kimi-cu/identity.json` | unchanged |
34
+ | `~/.kimi-webbridge/identity.json` | unchanged |
35
+ | `~/.qwen/settings.json` | unchanged |
36
+ | `~/.qwen/.env` (symlink target) | unchanged |
37
+ | `~/.qwen/installation_id` | unchanged |
38
+ | `~/.qwen/oauth_creds.json` | absent |
39
+ | `~/.codex/config.toml` | unchanged |
40
+ | `~/.codex/auth.json` | unchanged |
41
+ | `~/.codex/hooks.json` | unchanged |
42
+ | `~/.codex/installation_id` | unchanged |
43
+
44
+ `~/.kimi-work` holds only a `bin/` directory (no config or auth files).
45
+
46
+
47
+ ## Leg 1a: Kimi 2.3.2 ACP `available_commands_update`
48
+
49
+ Command: `kimi acp` (the hub's default `kimi_cmd`), under the isolated wrapper. Client sent the same `initialize` params as `acp.ts` (`protocolVersion` 1, `fs` read/write false, `terminal` false), then `session/new { cwd, mcpServers: [] }`.
50
+
51
+ Run A, no model configured:
52
+
53
+ - `initialize` -> `agentInfo { name: "Kimi Code CLI", version: "2.3.2" }`, `authMethods` one terminal method `login` (args `--login`), `agentCapabilities.loadSession` true, `sessionCapabilities` list/resume/close/delete/fork/additionalDirectories.
54
+ - `session/new` -> error `-32000` `"Authentication required"`. No `session/update` of any kind arrived in the 6 s that followed: without a session there is no `available_commands_update`.
55
+ - Source (installed binary, `ensureAuthed`): the gate passes when `auth.ensureReady()` resolves a configured model, or any OAuth provider reports logged in. `kimi acp` has no flag that disables it.
56
+
57
+ Run B, fixture model through Kimi's documented env model (`KIMI_MODEL_NAME`, `KIMI_MODEL_API_KEY`, `KIMI_MODEL_PROVIDER_TYPE=openai`, `KIMI_MODEL_BASE_URL` = unreachable loopback):
58
+
59
+ - `session/new` succeeded (`sessionId` `session_<uuid>`, `configOptions` model/thinking/mode, `modes` default/plan/auto/yolo).
60
+ - Right after the response, one `session/update` with `update.sessionUpdate: "available_commands_update"`.
61
+ - Update fields: `sessionUpdate`, `availableCommands`.
62
+ - Per command: `name`, `description`, optional `input: { hint }` (only `compact` has one). No schema, no side-effect class, no source field.
63
+ - 14 entries in a clean home: 6 ACP builtins (`compact`, `status`, `usage`, `mcp`, `tasks`, `help`), then bundled skills (for example `check-kimi-code-docs`, `sub-skill.review`, `write-goal`). Names can contain `.`; descriptions run up to 320 chars here.
64
+ - Run C, same plus a fixture user skill at `$KIMI_CODE_HOME/skills/probe-fixture/SKILL.md`: the list gained `skill:probe-fixture`. User skills carry the `skill:` prefix; builtin-source skills and sub-skills use the bare name (matches source `buildAcpSkillSlashCommands`).
65
+ - Source: the list is re-pushed on the session's `skills.changed` event, and after `session/load`, `fork` and `resume`.
66
+
67
+ `/name` execution:
68
+
69
+ - Run B also sent `session/prompt` with text `/help`. Kimi answered locally: one `agent_message_chunk` listing the same commands, then the result `stopReason: "end_turn"`. No model turn ran (builtin path; the fixture endpoint is unreachable anyway).
70
+ - Source: a leading `/name` is routed builtin -> local text; skill name -> `agent.activateSkill({ name, args })`, a normal model turn; unknown -> a local `agent_message_chunk` "Unknown ACP command: /x" with `end_turn`, not a JSON-RPC error.
71
+
72
+ Verdict: `available_commands_update` SUPPORTED (live, fixture-configured session; refused with `-32000 Authentication required` without one). Builtin `/name` execution SUPPORTED (live). Skill `/name input` execution UNVERIFIED: it starts a model turn, which needs an authenticated account; not run.
73
+
74
+ ## Leg 1b: Qwen Code 0.26.1 ACP `available_commands_update`
75
+
76
+ Command: `qwen --acp` (the hub's default `qwen_cmd`); Run B added `--auth-type openai --model fixture-model --openai-base-url <unreachable loopback> --telemetry=false` and env `OPENAI_API_KEY=fixture-not-a-key`.
77
+
78
+ Run A, no auth:
79
+
80
+ - `initialize` -> `agentInfo { name: "qwen-code", title: "Qwen Code", version: "0.26.1" }`, `authMethods` `openai` only.
81
+ - `session/new` -> error `-32000` `"Authentication required: Use Qwen Code CLI to authenticate first."` with `data.authMethods`. No `session/update` arrived in the following 6 s.
82
+
83
+ Run B, fixture auth, with a fixture user skill `probe-fixture` in the isolated home:
84
+
85
+ - `session/new` succeeded (`models`, `modes`, `_meta.generatedUi`). Then one `session/update` with `sessionUpdate: "available_commands_update"`.
86
+ - Update fields: `sessionUpdate`, `availableCommands`, `_meta` (`availableSkills`: names; `availableSkillDetails`: name and description per skill).
87
+ - Per command: `name`, `description`, `input` (`{ hint }`, sometimes empty, absent on some builtins), `_meta { source, sourceLabel, supportedModes, subcommands, modelInvocable, argumentHint?, altNames? }`.
88
+ - 53 entries: 35 `source: "builtin-command"` (for example `status`, `config`, `export`), 17 `bundled-skill` (for example `review`, `simplify`, `batch`), 1 `skill-dir-command` (`probe-fixture`). `supportedModes` includes `acp` on all 53. No input schema and no side-effect class.
89
+ - Gotcha: `modelInvocable` is not a side-effect hint. It is false for every builtin and for a few skills.
90
+
91
+ `/name` execution:
92
+
93
+ - Run B sent `/help`: JSON-RPC error `-32603` "Internal error", `data.details` "Slash command not supported in ACP integration: The command \"/help\" is not supported in this mode." (`help` is not in the advertised list.)
94
+ - Run D (same fixture, fresh process) sent `/status` (advertised, `supportedModes` includes `acp`): one `agent_message_chunk` (`_meta.source: "slash_command"`) with version/model/auth/session text, then `stopReason: "end_turn"`. No model turn.
95
+
96
+ Verdict: `available_commands_update` SUPPORTED (live, fixture auth; refused with `-32000` without it). Builtin `/name` execution SUPPORTED (live). A command outside the ACP set fails natively with `-32603` (live). Skill `/name input` execution UNVERIFIED: it is a model turn and needs an account.
97
+
98
+ ## Leg 2: Codex 0.166.0 app-server
99
+
100
+ Schema: `codex app-server generate-json-schema --out <dir>` (and `--experimental`), under the isolated wrapper. The stable bundle lists 106 client request methods, the experimental one 179.
101
+
102
+ `skills/list`:
103
+
104
+ - Present in the stable schema. Params `{ cwds?: string[], forceReload?: boolean }`. Response `{ data: [{ cwd, errors[], skills[] }] }`. Each skill (`SkillMetadata`) has `name`, `description`, `path`, `scope` (`user|repo|system|admin`), `enabled`, optional `pluginId`, `interface`, `shortDescription`, `dependencies`. No input schema, no side-effect class.
105
+ - Live: `codex app-server` over stdio (the hub runs it with `--listen ws://127.0.0.1:<port>`; same protocol). Sent `initialize { clientInfo }`, then the `initialized` notification, then `skills/list { cwds: [scratch cwd], forceReload: true }`. No thread was started and no auth was needed.
106
+ - Result: 1 entry, `errors` empty, 6 skills: the fixture `probe-fixture` (`scope: user`, path under the isolated `CODEX_HOME/skills`) and 5 `system` skills the CLI unpacks into the isolated home (for example `imagegen`, `skill-creator`, `review-agent`).
107
+ - One unsolicited notification arrived: `remoteControl/status/changed` (`status: disabled`).
108
+ - Verdict: SUPPORTED (live).
109
+
110
+ `turn/start` input item `{ type: "skill", name, path }`:
111
+
112
+ - `TurnStartParams.input` is `UserInput[]`. `UserInput` is a `oneOf` with `text`, `image`, `localImage`, `audio`, `localAudio`, `skill` and `mention`. `skill` has properties `type`, `name`, `path`, all three required, and is in the stable schema. (`mention` has the same shape.)
113
+ - Verdict: SUPPORTED by the 0.166.0 schema. Whether a turn started with that item actually loads the skill is UNVERIFIED: it is a model turn and needs an account.
114
+
115
+ `mcpServer/tool/call`:
116
+
117
+ - Present in the stable schema. Params `{ threadId, server, tool, arguments?, _meta? }` (`threadId`, `server`, `tool` required). Response `{ content[], isError?, structuredContent?, _meta? }`. The schema says nothing about approvals.
118
+ - Source at `rust-v0.166.0` (`app-server/src/request_processors/mcp_processor.rs` `call_mcp_server_tool`, `core/src/codex_thread.rs` `call_mcp_tool`):
119
+ - The handler loads the thread and checks only `ensure_direct_input_allowed` (refuses direct input to a multi-agent v2 subagent thread).
120
+ - It then calls the MCP runtime's `latest_call_tool` directly. No tool-call approval request (`item/*/requestApproval`) is on that path, so the thread's approval policy does not gate the call.
121
+ - The thread's approval policy does shape elicitations that the MCP server itself raises during the call (`tests/suite/v2/mcp_tool.rs`: `mcpServer/elicitation/request` round-trips under `unlessTrusted`; full-access threads decline form elicitation without the client capability).
122
+ - Not called live: it needs a thread and a configured MCP server.
123
+ - Verdict: the method EXISTS. "Subject to thread approvals": NO, by a source reading at the tag, not run live (UNVERIFIED live). The design excludes it either way. `command/exec` ("Execute a standalone command (argv vector) under the server's sandbox") also remains in the stable schema.
124
+
125
+ ## Summary
126
+
127
+ | Source (D1) | Verdict | Basis |
128
+ | --- | --- | --- |
129
+ | Kimi 2.3.2 `available_commands_update` | SUPPORTED | live, fixture-configured session |
130
+ | Kimi builtin `/name` | SUPPORTED | live (`/help`) |
131
+ | Kimi skill `/name input` | UNVERIFIED | model turn needs an account |
132
+ | Qwen 0.26.1 `available_commands_update` | SUPPORTED | live, fixture auth |
133
+ | Qwen builtin `/name` | SUPPORTED | live (`/status`); `/help` refused `-32603` |
134
+ | Qwen skill `/name input` | UNVERIFIED | model turn needs an account |
135
+ | Codex 0.166.0 `skills/list` | SUPPORTED | live, no thread, no auth |
136
+ | Codex `turn/start` `{type:"skill",name,path}` | SUPPORTED (schema) | generated schema; live turn UNVERIFIED |
137
+ | Codex `mcpServer/tool/call` | exists; no approval gate (source) | schema + tag source; not live |
138
+
139
+ Findings that touch the frozen design:
140
+
141
+ - Neither native listing carries an input schema or a side-effect class. Kimi gives `input.hint` on one builtin, Qwen gives `input.hint` plus `_meta`. This supports O1: the class comes from the person.
142
+ - Native names include `:` (Kimi `skill:x`) and `.` (Kimi `sub-skill.review`). Both fit the D1 name regex `/^[A-Za-z0-9_.:-]{1,64}$/`. The capability id `command:skill:x` is then valid but double-prefixed.
143
+ - Builtins are mixed into the same lists as skills: Kimi `compact`; Qwen `clear`, `config`, `export`, `update`, `remember`, `forget`, `auth`. Some of these change session or host state. Kimi marks no source on its entries; Qwen has `_meta.source`. A C1 parser has to choose which entries to list.
144
+ - Kimi answers an unknown `/x` with a normal `end_turn` and an "Unknown ACP command" chunk (source), not a JSON-RPC error. Qwen answers a command outside its ACP set with `-32603`. So D3's "native rejection -> failed" holds for Qwen but needs text matching for Kimi.
145
+ - Both ACP agents refuse `session/new` without auth (`-32000`), so the listing exists only for an authenticated peer. Neither emits `available_commands_update` before a session exists.
146
+
147
+ ## Not verified
148
+
149
+ - Executing a skill through `/name input` on Kimi or Qwen, and a Codex `turn/start` with a `skill` item: each starts a model turn and needs an authenticated account. Not run without one.
150
+ - Kimi and Qwen listings under a real login (a logged-in home may add user, project or plugin skills and MCP-derived commands). Only clean isolated homes plus one fixture skill were seen.
151
+ - `mcpServer/tool/call` live behavior: approval-free is a reading of the tag source, not a run.
152
+ - Kimi's unknown-command handling (source only; no unknown command was sent).
153
+ - The card's versions (Kimi 2.1.x, Qwen 0.25.0, Codex 0.154.0 pin). Only the installed versions above were probed.
154
+ - Outbound connection attempts were blocked by the sandbox profile, but not counted (the earlier Qwen receipts counted them with a Node preload guard).
155
+ - Linux and Intel macOS builds.
156
+
157
+ ## Evidence fingerprints (scratch, not committed)
158
+
159
+ | Item | SHA-256 |
160
+ | --- | --- |
161
+ | `scripts/acp_probe.py` | `879ee4da9e42043ff5aa633b05aa5aef4115c2cf3c6f42dd645833d7bba196fc` |
162
+ | `scripts/codex_probe.py` | `021a8196c7d3a879a49d6703d1f369c1376b8f56150d2c6acec0043825888926` |
163
+ | `scripts/iso.sh` | `4b1bb766bcbe64d492e0d6f3f9bbf70fc2197f29cd1fc7680f240515b4ec148c` |
164
+ | `scripts/nonet.sb` | `ad9d4fdb76db3a41beb3fd5ad6557ef57e1b051663850048e51357ed46812edf` |
165
+ | `scripts/hashes.sh` | `3e100d6906a75ea23fe43e8f49bc0af1bef5ded87ec82d84231a3d419080aa37` |
166
+ | `out/kimi-plain.json` | `3a4c73d303f1ec190f6190482da50971be3652c6d8b71e765edc0b59ecd6a871` |
167
+ | `out/kimi-fixture.json` | `c29d4173c4cc53bb49ff2d50f6a584b217c828560569e2fa0d4dd5b9d588a548` |
168
+ | `out/kimi-fixture-skill.json` | `d18962889da6888eebf2c22af8e360d2b797e6be84c58fb8d2b451aa47d12140` |
169
+ | `out/qwen-plain.json` | `1c343778484440fec310ea15b197f06da7fd96308837e256eb8b2f77bb811ea9` |
170
+ | `out/qwen-fixture.json` | `3ebb27fede3f98930164a9b20d65267aa752ed4038ac77ff55e38b4ac52924a3` |
171
+ | `out/qwen-fixture-status.json` | `743e272ddbfe9002fc3c7e627d9a5e6eda31a0f2829c00ce5c9df9621af23943` |
172
+ | `out/codex-skills.json` | `70e2d6e4e4c59ff257720aa1c0f5a3e18fc4a7a761652513fa4c17d622034079` |