@staix/agent-hub 0.34.1 → 0.35.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 (159) hide show
  1. package/CHANGELOG.md +47 -0
  2. package/README.md +35 -6
  3. package/docs/adding-an-ai-tool.md +2 -2
  4. package/docs/addons/claude-mem.md +4 -4
  5. package/docs/addons/open-code-review.md +1 -1
  6. package/docs/agent-notes/README.md +6 -0
  7. package/docs/agent-notes/adapters.md +9 -5
  8. package/docs/agent-notes/budget.md +1 -1
  9. package/docs/agent-notes/bus.md +1 -1
  10. package/docs/agent-notes/daemon.md +4 -3
  11. package/docs/agent-notes/local-worker.md +1 -1
  12. package/docs/agent-notes/models.md +2 -0
  13. package/docs/agent-notes/tasks.md +1 -1
  14. package/docs/agent-notes/tests.md +5 -0
  15. package/docs/design/adapters.md +110 -2
  16. package/docs/design/agent-hub-architecture.md +63 -1
  17. package/docs/design/agent-hub.md +6 -0
  18. package/docs/design/bus.md +18 -0
  19. package/docs/design/execution-reference.md +146 -0
  20. package/docs/design/task-board.md +10 -0
  21. package/docs/dogfood.md +33 -12
  22. package/docs/events.md +38 -20
  23. package/docs/memory.md +21 -7
  24. package/docs/operations.md +539 -24
  25. package/docs/quickstart.md +12 -4
  26. package/docs/research.md +71 -13
  27. package/docs/roles.md +1 -1
  28. package/docs/sdlc.md +9 -7
  29. package/docs/security.md +87 -11
  30. package/docs/smoke.md +14 -0
  31. package/docs/specs/2026-09-19-agent-hub-design.md +8 -3
  32. package/docs/verification/2026-11-07-compat-python-startup-1248.md +51 -0
  33. package/docs/verification/2026-11-07-compat-receipt-harness-1248.md +105 -0
  34. package/docs/verification/2026-11-07-compat-receipt-producers-1248.md +96 -0
  35. package/docs/verification/2026-11-07-compat-workflow-1248.md +94 -0
  36. package/docs/verification/2026-11-07-daemon-startup-1232.md +169 -0
  37. package/docs/verification/2026-11-07-jcode-receipt-reconstruction-1248.md +118 -0
  38. package/docs/verification/2026-11-07-kimi-delayed-usage.md +34 -0
  39. package/docs/verification/2026-11-07-kimi-review-watch-1284.md +115 -0
  40. package/docs/verification/2026-11-08-agy-1.5.3.md +96 -0
  41. package/docs/verification/2026-11-08-agy-acp-t0.md +56 -0
  42. package/docs/verification/2026-11-08-hub-visual-1058.md +161 -0
  43. package/docs/verification/2026-11-08-jcode-0991-model-setter-1317.md +143 -0
  44. package/docs/verification/2026-11-08-kimi-252-model-setter-1317.md +137 -0
  45. package/docs/verification/2026-11-08-kimi-tui-completion-1282.md +45 -0
  46. package/docs/verification/2026-11-08-kimi-wire-yield-1283.md +31 -0
  47. package/docs/verification/2026-11-08-live-model-override-1317.md +250 -0
  48. package/docs/verification/2026-11-08-qwen-0269-acp.md +138 -0
  49. package/docs/verification/2026-11-08-qwen-0269-model-setter-1317.md +91 -0
  50. package/docs/verification/2026-11-09-0.35.0.md +129 -0
  51. package/docs/verification/2026-11-09-headless-records-1320.md +157 -0
  52. package/docs/verification/claude-permission-transport-native.py +10 -3
  53. package/docs/verification/claude-shell-wrapper-native.py +8 -8
  54. package/docs/verified.json +245 -15
  55. package/package.json +3 -3
  56. package/plugins/agent-hub/.claude-plugin/plugin.json +1 -1
  57. package/plugins/agent-hub/kimi-hook.js +20397 -0
  58. package/plugins/agent-hub/kimi-review-policy-worker.js +217 -0
  59. package/plugins/agent-hub/server.js +2701 -664
  60. package/scripts/check-docs.mjs +12 -1
  61. package/src/adapters/acp-model-policy.ts +56 -0
  62. package/src/adapters/acp.ts +175 -5
  63. package/src/adapters/agy/entry.ts +8 -5
  64. package/src/adapters/agy/hooks.ts +65 -15
  65. package/src/adapters/channel-peer.ts +33 -1
  66. package/src/adapters/claude-implementer.ts +16 -3
  67. package/src/adapters/codex-appserver.ts +118 -8
  68. package/src/adapters/codex-review-isolation.ts +3 -1
  69. package/src/adapters/compat.ts +11 -6
  70. package/src/adapters/definitions/builtin-metadata.ts +8 -1
  71. package/src/adapters/definitions/native-cli-entry-kimi.ts +76 -7
  72. package/src/adapters/definitions/native-cli-preview-common.ts +2 -2
  73. package/src/adapters/definitions/native-cli-preview-kimi.ts +9 -2
  74. package/src/adapters/definitions/reviewer-variants.ts +3 -1
  75. package/src/adapters/kimi-review-policy-worker.js +2 -0
  76. package/src/adapters/kimi-review-policy-worker.ts +85 -0
  77. package/src/adapters/kimi-review-policy.ts +68 -0
  78. package/src/adapters/kimi-review.ts +41 -41
  79. package/src/adapters/kimi-tui-facts.ts +153 -0
  80. package/src/adapters/kimi-wire-usage.ts +33 -8
  81. package/src/adapters/local-worker.ts +59 -20
  82. package/src/adapters/model-token.ts +3 -0
  83. package/src/adapters/pi.ts +27 -5
  84. package/src/adapters/registry-types.ts +34 -3
  85. package/src/adapters/registry.ts +1 -0
  86. package/src/adapters/reviewer-policy-watch.ts +86 -0
  87. package/src/adapters/reviewer-print.ts +80 -18
  88. package/src/cli/agents.ts +1 -1
  89. package/src/cli/facts-hook.ts +4 -2
  90. package/src/cli/help.ts +3 -2
  91. package/src/cli/identity.ts +3 -0
  92. package/src/cli/kimi-facts-hook.ts +11 -0
  93. package/src/cli/kimi-plugin.ts +157 -0
  94. package/src/cli/main.ts +48 -9
  95. package/src/cli/model.ts +52 -0
  96. package/src/cli/output.ts +23 -1
  97. package/src/cli/reset.ts +1 -1
  98. package/src/cli/status-lines.ts +8 -4
  99. package/src/hub/budget.ts +1 -1
  100. package/src/hub/bus.ts +40 -2
  101. package/src/hub/code-facts.ts +10 -3
  102. package/src/hub/completions.ts +3 -1
  103. package/src/hub/config-apply.ts +2 -1
  104. package/src/hub/control-client.ts +1 -1
  105. package/src/hub/daemon.ts +1050 -106
  106. package/src/hub/deliverable-files.ts +38 -5
  107. package/src/hub/dogfood-profile.ts +1 -1
  108. package/src/hub/envelope.ts +1 -1
  109. package/src/hub/events.ts +28 -18
  110. package/src/hub/execution-lineage.ts +120 -0
  111. package/src/hub/execution-reference.ts +36 -0
  112. package/src/hub/hub-tools.ts +21 -2
  113. package/src/hub/instances.ts +4 -3
  114. package/src/hub/kimi-events.ts +46 -0
  115. package/src/hub/kimi-usage.ts +132 -29
  116. package/src/hub/lifecycle.ts +31 -15
  117. package/src/hub/limits.ts +13 -4
  118. package/src/hub/manager.ts +15 -2
  119. package/src/hub/memory-policy.ts +2 -1
  120. package/src/hub/memory-sync-attestation.ts +54 -0
  121. package/src/hub/memory-sync-state.ts +20 -5
  122. package/src/hub/model-overrides.ts +115 -0
  123. package/src/hub/native-hook-launch.ts +12 -3
  124. package/src/hub/operational-view.ts +2 -2
  125. package/src/hub/peers.ts +27 -0
  126. package/src/hub/permission-mode.ts +1 -1
  127. package/src/hub/person-figures.ts +88 -0
  128. package/src/hub/report.ts +38 -4
  129. package/src/hub/research-dataset.ts +158 -0
  130. package/src/hub/research-memory.ts +68 -0
  131. package/src/hub/research-quality.ts +118 -0
  132. package/src/hub/research-record.ts +279 -0
  133. package/src/hub/research.ts +126 -27
  134. package/src/hub/restart.ts +14 -0
  135. package/src/hub/settings.ts +3 -0
  136. package/src/hub/startup-event-seeds.ts +51 -0
  137. package/src/hub/startup-readiness.ts +65 -0
  138. package/src/hub/startup-timing.ts +38 -0
  139. package/src/hub/tasks.ts +29 -9
  140. package/src/hub/ui.ts +9 -5
  141. package/src/hub/visual-assets.ts +50 -0
  142. package/src/hub/visual.ts +257 -0
  143. package/src/memory/brief.ts +169 -14
  144. package/src/memory/capture.ts +2 -1
  145. package/src/memory/recall.ts +46 -5
  146. package/src/memory/record-provenance.ts +82 -0
  147. package/src/memory/records.ts +116 -0
  148. package/src/models/route/adec.ts +190 -0
  149. package/src/models/route/config.ts +37 -3
  150. package/src/models/route/decision-evidence.ts +83 -0
  151. package/src/models/route/decision.ts +143 -0
  152. package/src/models/route/runtime.ts +13 -6
  153. package/src/ui/index.html +134 -6
  154. package/src/ui/plugin.ts +65 -4
  155. package/templates/AGENTS.block.md +1 -1
  156. package/templates/config.json +1 -1
  157. package/templates/profiles/general.json +1 -1
  158. package/templates/profiles/research.json +1 -1
  159. package/templates/profiles/writing.json +1 -1
package/docs/dogfood.md CHANGED
@@ -14,11 +14,13 @@ agent-hub is developed with agent-hub. This page lists every feature, whether it
14
14
  | Claude channel attach evidence (#1171) | source and fixture coverage after merge and plugin/daemon upgrade; native Claude push proof remains unverified until a live `ahub claude` session | `ahub status` shows `channel` or `tools-only` with its evidence label; a marker-inheriting non-channel parent remains pull-only and its delivery is read by `hub_inbox` (`test/claude-channel-evidence.test.ts`, `test/daemon.test.ts`); inspect native TUI attaches separately, since fixtures use a synthetic parent row |
15
15
  | Accepted channel delivery settlement (#1172) | source and fixture coverage after merge and plugin/daemon upgrade; native channel handling and long-running-session behavior remain unverified | `bus.accepted_settle_ms` defaults to 10 minutes; explicit channel `hub_inbox` metadata shows accepted/held ids and revisions even when a pull is blocked; a timeout becomes `needs_review` without replay; an important/task/review timeout yields one ids-only status notice when the configured conductor feed is on, with `feed: off` remaining an opt-out; daemon and MCP fixtures cover timeout and opt-out; live accepted-to-completed/timeout behavior remains unverified |
16
16
  | Cross-project task handoff with state follow-back (#604, `task_handoff`) | on after release and upgrade: `ahub task handoff` and `hub_task_handoff` register work for another registered project that runs agent-hub on this machine as an ownerless proposal on its board; the requesting peer is told each state change as a `kind: task` message. Nothing is queued, and the origin has no authority there | `ahub board --handoffs` lists what this project handed over with the last state each target reported; `ahub board` and `ahub task show` in the target name the origin project and peer; a handoff for a spec issue that already has an open task there is refused with the task ids unless `duplicate_ok` gives a reason, and the receiving conductor can cancel an unaccepted handoff (#1175; the share of refused handoffs and the cancels the person no longer has to run show whether duplicates still reach the board); a handoff the target did not confirm (a timeout, #1203 T1) is reported as `outcome_unknown` with a key and a retry with `--key` files it once, and a follow-back names the target's task (`refs.handoff`) so a local task of the same number cannot drop it (count `outcome_unknown` refusals, and any target task filed twice for one origin: there should be none; from T2 (#733) the origin also asks every 5 minutes and when a target restarts, so a missed notify arrives within a period: compare how long a handoff row stays behind its target (its `updated` against the target's state), and count `changes requested` and `reopened` messages, which used to be silent; from T3 (#734) `ahub task handoff --list` shows each handoff's age and whether its target is reachable, unreachable (with the cause) or moved, `--sync` asks the targets now, a wire-version refusal is `older_target` and an instance mismatch is `mismatch` instead of "not running", and a failed notify or catch-up logs one line per target and cause per 15 minutes: count the `handoff catch-up of ... failed` and `... skipped` lines in `hub.log` by cause, how often `--list` shows a target unreachable or moved for more than a day, and whether `--sync` is ever needed after a restart (it should not be: the catch-up reads the state within a period); T1 and T2 and T3 of #1203 are now all built; test/handoff-daemon.test.ts runs two real daemons (AC1 to AC5, #1175, the recovery label and #1203 T1 AC1 and AC4, T2 AC2, AC3 and AC5, T3 AC6 and AC7), test/handoff-core.test.ts and test/handoff-board.test.ts hold the pure core and the tables |
17
- | Staged project upgrades (#1039) | off: available for the person to upgrade projects independently; this development hub is not upgraded by a fixture | test/published-protocol-compat.test.ts uses both the published 0.25.0 protocol-floor and 0.29.0 release N-1 clients/plugins and reverse daemons; test/staged-upgrade.test.ts checks independent holds and scoped effects; test/staged-runtime-daemon.test.ts checks a real release-root daemon after mutable install removal; test/board-schema-guard.test.ts checks named pre-effect refusal and WAL metadata; `test/project-runtime.test.ts` and `test/project-runtime-lifecycle.test.ts` cover updated resolver retention/refusal and real lifecycle/dashboard routing with synthetic captured daemons; `test/runtime-capture-prune.test.ts` covers references, bounded retention and publication races; `test/upgrade-stopped-project.test.ts` verifies no preservation for stopped projects. These fixtures do not prove published pre-0.26 CLI behavior |
17
+ | Staged project upgrades (#1039) | off: available for the person to upgrade projects independently; this development hub is not upgraded by a fixture | test/published-protocol-compat.test.ts uses both the published 0.25.0 protocol-floor and release N-1 (pinned in `PUBLISHED_FIXTURES`) clients/plugins and reverse daemons; test/staged-upgrade.test.ts checks independent holds and scoped effects; test/staged-runtime-daemon.test.ts checks a real release-root daemon after mutable install removal; test/board-schema-guard.test.ts checks named pre-effect refusal and WAL metadata; `test/project-runtime.test.ts` and `test/project-runtime-lifecycle.test.ts` cover updated resolver retention/refusal and real lifecycle/dashboard routing with synthetic captured daemons; `test/runtime-capture-prune.test.ts` covers references, bounded retention and publication races; `test/upgrade-stopped-project.test.ts` verifies no preservation for stopped projects. These fixtures do not prove published pre-0.26 CLI behavior |
18
18
  | Approval head binding and re-review (#1047, #1121) | source/fixture coverage; the #1121 stale-head protections and actionable refusals await release and upgrade; live re-file verification not run | `test/review-head-binding.test.ts` covers both-head refusals, moved-PR commitless re-files and omitted-head stale approvals; `test/task-review-refile.test.ts` covers owner re-submit, reviewer withdrawal, legacy verdict heads, merged/cancelled refusals and held-screen races; `test/sdlc-queue.test.ts` and `test/sdlc-merge.test.ts` reject stale approval at queue and dispatch. `ahub task show <id> --json` exposes `approval.head`, `latestHead`, `mismatch` and `current`; verdict history retains `reviewedHead` |
19
19
  | Default agent set started by `ahub up` (#608, `start.agents`) | off here: this repository's agents are started by their own terminals; it is a machine-local setting and a committed config cannot turn it on. On for a person who runs `ahub setup` and `ahub up` on a project that lists agents. | each `ahub up` prints one line per agent (started, already attached, or the refusal with the manual command); the `peer_start` replies in `hub.log` and the terminal provider's recorded starts show whether a listed agent attached, and `ahub status` shows its state after |
20
20
  | `ahub down` (counterpart of `ahub up`) | on: an alias of `ahub kill` for stopping this project's hub | the person stops the hub with `ahub down` and `ahub status` then reports it stopped; test/identity.test.ts keeps it person-only (`console`) and labelled `down`, and test/help.test.ts holds its help entry |
21
+ | Daemon startup timing and pending readiness (#1232) | isolated source/fixture coverage; the running development hub is unchanged until release and restart | one `startup timings ms:` line per completed startup; representative synthetic benchmark under 5 s with one streaming seed pass, no full-file event read and no abandoned snapshot body read; private copied-state observations and separate bounded rollup I/O are in the startup receipt; fake-clock and real owned-child tests cover the 12 s notice, late confirmation, cancellation and 120 s outer bound |
21
22
  | Person takeover of a channel peer (#1174) | source and isolated fake-session coverage; active after release and plugin upgrade; no live handover receipt yet | one explicit takeover request, old next-tool person-detachment cause, standby attachment identity, no process stop or automatic delivery replay; fake CLI/console authority and stale-generation regressions |
23
+ | Owner attachment in detailed status (#1310) | on here, display only: `ahub status` and `ahub status --json` name the current owner of an attached channel peer (pid, attach time, native session or `unverified`), withheld from `status.json` and every non-console reader. Coverage is fixture-only so far: a fake hello pid, and the native session through agy `native_facts` fixtures. No live Kimi or Claude plugin attach has been observed | the share of pull-only queue incidents (a queued peer that does not answer) diagnosed from the owner line without inferring the owner from process start times, counted by hand from the incident notes until a record carries it; `test/owner-attachment.test.ts` for the lifecycle (attach, takeover, detach, roster removal, stop) |
22
24
  | Encrypted rooms (#446 X1) | off; source-only crypto/wire, with no broker, room link, invitation CLI or delivery enabled | real WebCrypto vectors and negative wire fixtures; atomic memory fake ports establish ordering only; durable X3 state and the X7 two-machine person receipt remain unverified |
23
25
  | Blind room broker (#446 X2) | off; standalone source/fixture work, no public TLS service or hub room link configured here | fake-client auth/fan-out/revocation/restart, ciphertext-only child-process canary, owner admission/offline room reset, queue caps/TTL/FIFO/migration, safe directory modes, and person-only CLI tests; live proxy/account/X7 receipts remain unverified |
24
26
  | Room membership and presence (#446 X3) | off; no person room enrollment or exposure configured here | isolated fake-hub/broker tests for OOB enrollment, MITM refusal, durable sequence/replay/grace, explicit fingerprint confirmation/abort, refused-frame retirement, exposure revocation and ids-only presence; room list/status for ids and link state; #1204 T1 fixtures cover unchanged-presence dedupe, 1,000 flips with an offline member, latest-only ephemeral broker retention, old-broker wire fallback and same-frame queue_full backoff; CI task 742 adds counter-bounded deferred-presence reuse, concurrent chat ciphertext/Store FIFO and post-close publication regressions (test/rooms-presence-coalescing-742.test.ts, test/bus-closed-publication-742.test.ts); Linux diagnostic counts and targeted hosted macOS acceptance (unchanged AC1 787.72 ms; controlled idle-entry 783.51 ms) are in docs/verification/2026-11-06-rooms-presence-cost.md; no live rooms receipt; X4 chat and X7 two-machine live receipt remain separate and unverified |
@@ -36,6 +38,9 @@ agent-hub is developed with agent-hub. This page lists every feature, whether it
36
38
  | Headless Claude host shell grants (#845) | source/fixture work; active only after release and hub/plugin upgrade with `ask-when-needed` on the declared implementer | automatic wrapper grants versus person requests; native poisoned-environment and replay receipt; unknown/expired/reused/stale task, branch, root or child tickets execute zero commands |
37
39
  | Headless Claude failure stages (task 551, #845) | source and fake-native fixtures; installed/native/account proof unverified until release and restart | fixed stage and host metadata in failed outcomes/logs; private stub, raw-canary absence, stale/foreign launch and bounded-probe cases in `test/claude-failure-stage-daemon.test.ts` |
38
40
  | Optional model for a headless Claude implementer (#844) | on after the release and once the person sets `model` on `instances.claude-impl` in `config.local.json` (a hub daemon restart applies it); unset it changes nothing | `ahub status` shows `model source` on the instance row; the native argv carries `--model <value>` on every turn and none when unset (test/claude-implementer.test.ts, test/claude-implementer-daemon.test.ts); a tracked-file or non-implementer declaration is refused or ignored with a reason (test/instances.test.ts, test/jcode-instances.test.ts) |
41
+ | adec decision routes (#554 consumer) | not enabled on this repository; offline fake-service proof only, no native decider or gain claim | shadow chosen alias/effort versus actual tier, margin and latency joined to route outcomes; zero off-campus sensitive/observer requests and no raw evidence in events |
42
+ | Person-only live peer model override (#1317 T1) | source and model-free fake checks passed at the [recorded heads](verification/2026-11-08-live-model-override-1317.md); installed-hub rollout and native model changes unverified | next-turn argv/transport model, unchanged active turns and steering, last desired value, clear/persistence/reset, source and pending status, person-only refusals, unsupported no-write/no-restart, and model_change boundary audit |
43
+ | Receipt-gated ACP model selection (#1317 T2) | exact headless Kimi 2.5.2 native loopback A/B/clear/A setter passed; installed-hub rollout unrun; Jcode shared-TUI safety unqualified and Qwen clear failed, so both remain unsupported | current owned identity/version and advertisement, held-turn selection, next-turn setter and admission acknowledgement, baseline clear in fixtures, revoked admission and timeout refusal, reviewer isolation unchanged; native receipts separate account/model use |
39
44
  | Remote isolated check transport (#793) | off here; fake checks, a bounded local Docker transport receipt and a local run of the lockfile-keyed dependency volume; person opt-in, SSH and the live receipt follow separately | remote tests capability unavailable on failed SSH/Docker/image/transfer probe; one networked install per new lockfile key, none on later runs, the check mounting the volume read-only with no network; exact Git receipt, non-root hardened argv, zero Mac dependency copies and confirmed Docker cleanup before lease release; Darwin tar ignores PATH shims, probe warnings do not pollute JSON, bounded probes do not become unknown task-run orphans |
40
45
  | Task board, routing, roles | on (claude planner, reviewer and implementer; codex, jcode, agy implementers) | board history: lead time from propose to approve, review rounds, escalations; owner new-head re-files and stale-verdict refusals (#1000 fixtures; active after upgrade) |
41
46
  | Readable `sdlc` output by default (#814 T1, #899) | on after the release: `ahub sdlc status\|explain\|queue\|release\|metrics\|costs\|authorize-release\|merge` print tables and labelled fields here; since #899 `ahub sdlc merge` (guarded merge, dry-run included) prints its report for a person by default and the JSON document only with `--json`, and `ahub doctor --orphans --kill` likewise prints the stopped pids by default and the hub's reply only with `--json`; scripts pass `--json` | the person reading `ahub sdlc status`, `sdlc metrics` and a `sdlc merge --dry-run` report without `--json`; `test/sdlc-output.test.ts` holds every `sdlc merge` outcome's readable default with `--json` byte for byte the pre-#899 output and the exit code unchanged; `test/conductor-cli.test.ts` holds the same for `doctor --orphans --kill`; `test/cli-json-guard.test.ts` lists the CLI paths that still print JSON by default (since #899 only the named data formats: its not-yet-converted list is empty) |
@@ -56,6 +61,8 @@ agent-hub is developed with agent-hub. This page lists every feature, whether it
56
61
  | Confirmation-point inventory (#999 T0) | source and test coverage; `ahub autonomy status` reads the inventory after this feature is released, with no default prompt change from the data alone | `test/confirmation-matrix.test.ts`: every adapter-catalog kind has a tool-approval and a classed-action row per environment, kinds facts equal the definitions, cited source lines exist; the `unknown` rows are the list T4's live receipt must close |
57
62
  | Project autonomy preset (#999 T1) | off on this repository until released and explicitly enabled by the person; project scope only | focused person-only, retained-consent, metadata-independent off and authenticated/fallback preset undo tests; the preset writes `action_policy.floor` (#999 T3) and off removes it; status leads with a peer table separating current modes from desired defaults, groups identical floor verdicts and unknowns once with peer lists (#1137), and reads each floor class from the host verdict (`floorEnforcement`), naming the unverified guard where the hub does not see the call first; the Orca zero-prompt native task remains T4 |
58
63
  | Machine autonomy and used Claude homes (#999 T2) | off until released and explicitly opted in by the person; no real home is changed by fixture tests | trusted-default/unsafe-default startup consent, all-project preview/apply, init inheritance with unchanged absent-file ask defaults, and isolated per-home plugin/hook setup/status tests; #1069 covers preserving project/local plugin rows while configuring only user scope, plus recording `start.agents` after a failed home step; metric: applied/refused registered targets and missing/unknown discovered-home states; #1245 fixtures cover a verified current alias surviving A-to-B upgrades without marketplace removal, exactly one managed hook, actionable non-user-row refusals, stale-hook doctor warnings in an unselected default home, and PATH-selected global CLI update advice with a pure handoff doctor pointer; real-home setup remains unverified for that change; native Orca receipt remains T4 |
64
+ | Model-free compat receipt harness (#1248 T1) | disposable-runner command after merge; local personal Mac refused, automation off pending T2, native candidate qualification unverified | fake-only pass/fail/model-not-run and leg/total deadlines, SRI-before-effects and archive refusal tests; JSON/Markdown artifacts, scoped owned stop and lifetime cleanup reported unproven; detached-helper and output-parent-swap regressions; promoted Kimi/Qwen native producers have fake protocol coverage; reconstructed Jcode has an actual 0.99.1 Linux control with four native legs passing and telemetry/context binding failing, without a qualification or trust change |
65
+ | Automated compatibility receipts (#1248 T2) | after merge: daily watch and hosted isolated harness; manual dry mode is the default; no personal Mac candidate install or model/account leg | structured candidate/verified IDs, per-leg artifacts, validated read-only bundle preparation, zero-write dry plans, exact-row bot PRs and explicit check dispatch; failed/not-run rows stay visible and stale verified rows clear; no auto-merge |
59
66
  | Read-time memory code neighbours (#684 phase 4) | off until released; dashboard toggle is opt-in | derived call edges with current SHA; attached fail/decision brief coverage; explicit unknown/truncated results; unchanged authoritative memory log bytes |
60
67
  | Canonical memory symbol anchors (#684 phase 3) | off until released; optional `doctor --stale-anchors` report only | actual-symbol completion anchors versus plan guesses; symbol-related earlier notes at memory hop two; stale/unknown/truncated report counts; zero note mutations during inspection |
61
68
  | Symbol preparation and historical recall (#684 phase 3 follow-ups) | off until release | exists calls per no-reviewer completion; raw-signature fail recall; indexed-definition/unknown labels; unchanged note/candidate bytes and neutral cleanup failures |
@@ -67,7 +74,7 @@ agent-hub is developed with agent-hub. This page lists every feature, whether it
67
74
  | Planned backlog starts (#1076) | source/fixture coverage; active after release and hub upgrade | future planned cards appear as `scheduled` in planner grooming; no auto-pull, `backlog_ready` notice or ready-queue owner offer before `plannedStart`; exact-boundary and after-date eligibility; queue-pressure origins remain retryable until due |
68
75
  | Task sweep (stalls, idle owners) | on | stall and sweep events per week |
69
76
  | Turn-free coordination | off: experimental; needs a separate measured trial | coordination events, conflict notices |
70
- | Pull-only peers (agy) | on; `hub_inbox` drains to 64 KiB (#713) | unread offers, empty-inbox polling (#681); queued count and oldest queued age per pull-only peer in `ahub status`; reads that said `N more waiting` |
77
+ | Pull-only peers (agy) | on; `hub_inbox` drains to 64 KiB (#713); native hook Write/Edit/partial-Read normalization, `SYSTEM_MESSAGE` fact readback, `GEMINI.md` instruction protection, and `agy_transcript` token telemetry (#1280 P1), and a count-only inbox hint at `SessionStart`/`PreInvocation` when mail waits (#1280 P2) active after release and upgrade | unread offers, empty-inbox polling (#681); queued count and oldest queued age per pull-only peer in `ahub status`; reads that said `N more waiting`; `fact_ack` events on 1.4.x (`EPHEMERAL_MESSAGE`) and 1.5.x (`SYSTEM_MESSAGE`), `by agy` attribution on `write_file`/`edit_file` facts, and `ahub usage` / `events.jsonl` rows with `source: "agy_transcript"`; for the hint, the `[agent-hub: N message(s) waiting` line in an agy invocation followed by an inbox read that drains the same queue (`test/agy-peer.test.ts`) (`test/agy-hooks.test.ts`, `test/agy-peer.test.ts`, `test/permission-modes.test.ts`) |
71
78
  | Bulk clear of failed queue rows and the settled-row filter (#1096, `queue_discard_states`) | on after release and upgrade: `ahub queue discard --peer <id>` also takes the peer's unsettled failed rows and `ahub queue list` hides settled rows (`--all` shows them); fixture coverage only (`test/queue-discard.test.ts`: real daemon and CLI, a fake old hub for the capability refusal). A person using it on a real backlog is not yet recorded | `ahub queue discard --peer` runs that name a failed count, `queue list` stderr lines `N settled deliveries hidden`, and the failed-row count per peer in `ahub status` falling after a discard; a refusal that names `queue_discard_states` means an older hub is still running |
72
79
  | Failed-delivery cause and status signal (#1178) | source and isolated fixture coverage after validation; active after release and hub upgrade; real-backlog use is not yet recorded here | `ahub queue show` and `queue list --json` expose the fixed public-safe cause (legacy absence stays unknown); `ahub status` names each nonzero unresolved failed count and the peer-specific discard step; resolution removes the count, including retry parents; new journal, bus, output and daemon regressions cover cause privacy and metadata-only counts |
73
80
  | Completed-change notices, grouped and superseding (#713) | on after release; accepted tasks only | queued `is done and touches` notices per peer (one per done, not per task and per repeat); `superseded completed-change notice` discards; `ahub queue discard` uses |
@@ -76,6 +83,7 @@ agent-hub is developed with agent-hub. This page lists every feature, whether it
76
83
 
77
84
  | Feature | State here | Measured by |
78
85
  | --- | --- | --- |
86
+ | Execution references and bounded lineage (#1220 T1) | source-only pure contract and fixtures; no running hub surface or native lineage receipt; Tasks admission and CLI/MCP are T2, console and performance are T3 | neutral address vectors, explicit and missing-edge fixtures, separate states/evidence, unavailable equivalence, page/byte caps and source-bound continuation invalidation in `test/execution-reference.test.ts` and `test/execution-lineage.test.ts` |
79
87
  | Optional changed-symbol advice (#682, #684 phase 1a) | on after release when ripwire 0.6.7 is installed; change kinds unknown | review brief symbol observations/unknowns; deleted definitions not covered, no gate |
80
88
  | Head-bound task symbol observations (#684 phase 2a) | on after release with optional code facts; observed names only | task/UI receipts and completed-change labels; unknown/filtered evidence keeps ordinary overlap, deleted definitions not covered |
81
89
  | Console changed-symbols block (#684 phase 2b) | on with 2a data; matching, unplanned and untouched against the plan; overlap lines follow in #379; related-note count remains phase 4 | task detail shows the block or `unknown (no code facts)`; no block for a private task |
@@ -84,13 +92,13 @@ agent-hub is developed with agent-hub. This page lists every feature, whether it
84
92
  | Dashboard task sheet Code group (#684 phase 2c) | on after release; read-only, observed names only, none for a private task | task sheet Code group shows the changed symbols or `unknown (no code facts)`; symbol clicks that reach a non-empty graph once phase 3 lands |
85
93
  | Review brief, review findings, Important gate (#481 S3) | advise | Important findings per PR, rounds to approval |
86
94
  | Anchored review comments and findings (#1056) | source and synthetic-fixture coverage; active after release and hub upgrade; the owner's live document package-format confirmation remains open | draft/edit peer turns (target 0); one envelope and one history count per explicit Send; anchored/moved/outdated/unavailable counts; console-only refusals and quote/body canaries in logs, capture and public views; immutable shared acon fixtures; explicit refresh, task-bound memory versus current-turn capture scope, pruned reviewer requests, refused terminal resend, anchored-batch sibling remember/propose refusals, invocation answers after mid-turn inbox pulls, actionable provenance refusals, anchored-submission final-answer/history canaries, same-session restart retention, real sessionless WsPeer handoff and ordinary-input release, unidentified earlier-SID holds and reconnect status, safe first-SID confirmation, legacy coverage completion and NULL-receipt pruning, corrupt-provenance status, clean new-session admission, evidence-backed sticky restored pull-only holds, saved-package recovery and final-only resolution regression fixtures |
87
- | Memory sync health and write policy (#1173, #743) | source adoption of exact-pinned agent-mem 0.21.0 and isolated fixtures; not deployed here; AC4 bounded diagnostics available, AC5 successful-result count projection only; default-host v3 sync lacks fresh-attestation integration; legacy activation blocked on agent-mem#281; #1173 stays open; activation, live rollout and successful person-home sync unverified | automatic sync outcome/cause/count; SDK successful-placement result projection with withheld/exported counts (fixture seam; active-v3 sync unverified); legacy declined-sync refusal names inactive placement and the missing core activation command; bounded SDK inspection of physical declined IDs and safe rule categories, with explicit incomplete results; one failure log per unchanged known signature; existing declined long-write and kept-short promotion fences |
95
+ | Memory sync health and write policy (#1173, #743) | source adoption of exact-pinned agent-mem 0.23.0 and isolated fixtures; not deployed here; AC4 bounded diagnostics available, AC5 result counts and host attestation; the daemon passes agent-mem's createPlacementAttestation on every sync pass and a refusal is the closed cause `writer` (fixture-tested; an activated store is not exercised here); legacy activation remains person-only; #1173 stays open; activation, live rollout and successful person-home sync unverified | automatic sync outcome/cause/count; SDK successful-placement result projection with withheld/exported counts (fixture seam; active-v3 sync unverified); legacy declined-sync refusal names inactive placement and the person-only activation preview; refused writer attestation names its category, cause class and next step; bounded SDK inspection of physical declined IDs and safe rule categories, with explicit incomplete results; one failure log per unchanged known signature; existing declined long-write and kept-short promotion fences |
88
96
  | Spec acceptance (#481 S1) | advise | build entries without acceptance |
89
97
  | Lifecycle identity linked by the hub (#694, #723) | on in advise; links at propose and accept from the title and `refs.repo`, with a groom backfill as the safety net | open tasks still showing `issue identity missing` right after propose (should be only titles that name no issue or a qualified title without `refs.repo`) |
90
98
  | Planner plan review (#481 S9) | advise | plans reviewed before build |
91
- | Planner board-changed notice (#758) | on here, with the lifecycle in `advise`: `claude` is the planner, so a card another peer proposes or re-plans reaches it once at task weight, and its own writes, state moves, reviews and assignments cost it no turn | per planner and week: `task`-kind hub envelopes whose body starts `The board changed` (target: one per planning change, none after the planner's own write), the same envelopes at `fyi` priority (recorded, no turn: at most one per 10 minutes), and the count still queued at once (target: at most one). Read from `ahub log` and the event log; the 12 copies in 44 minutes seen on 2026-10-24 are the baseline |
99
+ | Planner board-changed notice (#758) | on here, with the lifecycle in `advise`: `claude` is the planner, so a card another peer proposes or re-plans reaches it once at task weight, and its own writes, state moves, reviews and assignments cost it no turn | per planner and week: `task`-kind hub envelopes whose body starts `The board changed` (target: one per planning change, none after the planner's own write), the same envelopes at `fyi` priority (recorded, no turn: at most one per 10 minutes), and the count still queued at once (target: at most one). Read from `ahub logs` and the event log; the 12 copies in 44 minutes seen on 2026-10-24 are the baseline |
92
100
  | Planner capacity and dependency notices (#785 P1a) | source/fixture coverage; active after release and hub upgrade | write-triggered `capacity_released` and `backlog_ready` lines in `Planner work ready:` task envelopes; at most one queued envelope per effective planner, peer/WIP/card ids only; no automatic pull |
93
- | Release preparation and guarded tag (#787 P3b) | scratch-repo fixtures with a local bare remote; the real history was dry-run in a disposable clone; first real use is the next release | `scripts/release-prepare.ts` run on a `release/<version>` branch and a release PR that carries the version, CHANGELOG, report and stamps; `scripts/release-tag.ts` refusing without the person's consent and pushing one tag after it; native version-named receipts retained while dated release reports are excluded (#1004 fixture) |
101
+ | Release preparation and guarded tag (#787 P3b) | scratch-repo fixtures with a local bare remote; the real history was dry-run in a disposable clone; release branches are prepared with it, and since #1273 it also renders the generated README facts blocks | `scripts/release-prepare.ts` run on a `release/<version>` branch and a release PR that carries the version, CHANGELOG, report and stamps; `scripts/release-tag.ts` refusing without the person's consent and pushing one tag after it; native version-named receipts retained while dated release reports are excluded (#1004 fixture) |
94
102
  | Opt-in auto pull (#785 P1c) | source/fixture coverage and a real daemon test; off by default, active only where a person sets `tasks.auto_pull` in `config.local.json` | `backlog pulled` history entries with `by: hub` and an `auto_pull:` note; at most one per capacity release; no pull with the setting off, for unreserved, PII, pinned, frozen or dependency-blocked cards |
95
103
  | Opt-in assignment queue backpressure (#800) | off by default; this change enables no live repository policy | `ahub route explain` and status queue-count/age/unknown reasons beside WIP; bounded summary reads, held-offer release, post-await offline/not-attached origin retention with plan-policy handoff, and role-scoped override regressions; no delivery disposition or routing-template change |
96
104
  | Per-head CI watcher and `ci_completed` (#785 P1b) | source/fixture coverage with a fake gh; active after release and hub upgrade | one `ci_completed:` task notice per head to owner and reviewer, a premature review re-offered once green; watchers started per `hub_task_done` head and gone at the result, deadline, newer head, verdict or shutdown; no gh read outside a watcher |
@@ -99,10 +107,17 @@ agent-hub is developed with agent-hub. This page lists every feature, whether it
99
107
  | Eval gate for agent configuration (#481 S5) | advise; mechanism only, `eval_check` is not set here until the person chooses a suite (#251, #266), so configuration PRs show `eval check not configured` as a note | configuration PRs with a missing, failing or unreported eval check; recorded pass rate and suite on the approval note |
100
108
  | Merge-time PR readback, release metrics and security-scan baseline (#481 S7, AC12) | source and fixture coverage with a fake gh and real train transitions; the readback is on wherever auto merge is `on`, release metrics need shipped trains with recorded history, and the security scan and its bands stay off here until `[security_scan]` and `[bands.security_open_alerts]` are set | `cost` on merge records, `ahub sdlc metrics` review/CI-at-merge rows, the releases row of `ahub sdlc release`, `security_scans` rows and `security_open_alerts` cards |
101
109
  | Required checks | advise (`check (ubuntu-latest)`, `check (macos-latest)`, `seeded guards`) | first-pass CI rate, same-head reruns (`hub_sdlc_costs`) |
110
+ | Bounded visual attachments (#1058) | source/focused guards and isolated acon 0.1.7 rendering passed at the [recorded heads](verification/2026-11-08-hub-visual-1058.md); installed-hub rollout remains unverified; final canonical gate pending | all four payload kinds round-trip, private/over-bound inputs write nothing, peers receive only ids/stubs, changed assets refuse, and stream/task cards use acon's kit or readable standalone fallback; native/render evidence is recorded separately |
111
+ | macOS shards deferred on stacked PRs (#1307) | on in CI for every PR after merge | macOS job-minutes per day and the longest macOS queue wait (57 runs, about 2,250 job-minutes and waits over an hour on 2026-11-07, before); `check (macos-latest)` deferral failures that were followed by a full macOS run on the same PR after it targeted `main` |
102
112
  | Seed anchor diagnostics (#684) | on in the seeded checker; exact-match failure remains mandatory | missing anchors report the base commit, enclosing symbol and current file/line or explicit unknown; `test/seeded-check.test.ts` |
103
113
  | Release authorization (#481 S6, #1063, #1120) | fixture coverage; delegated live consent awaits release and project upgrade | `test/sdlc-release-authorization.test.ts` and flow fixtures retain exact candidate/docs/origin/restart bindings and record the actual user/conductor actor; agent-read and floor fixtures refuse other peers, private turns and live-test; `test/runtime-capture-checker.test.ts` proves a real capture carries the documentation checker and that a missing or failing one is refused as its own cause, not as stale documentation; no fixture authorizes a live release |
104
114
  | SDLC metrics and control bands (#481 S7) | `ahub sdlc metrics` on; bands off until `[bands]` is set in `.agenthub/sdlc.toml`, and they write cards only in advise or enforce (in off the report still shows tiers). Completion checks are off here, so `first_pass_check` and the PR-based figures read unknown | its own report; breach episodes per week by tier, and band cards the planner accepted rather than dropped |
105
115
  | Fresh headless reviewers (#223, #519) | configured here (`codex-review`); per-tool approval correction and no-verdict diagnostics/re-offer (#783) take effect after release and upgrade | reviews by fresh sessions, findings they add; a per-review start failure names a closed cause class (#722): `ahub status` reviewer line and hub.log `[cause: ...]`, with the share of failures that are `unknown`; stale admission skips and current-policy `no_verdict` reroutes leave the reviewer available (#781); a real `hub_review` verdict per verified backend/version, beyond inventory-only proof; bounded refusal diagnostics, confirmed re-offers without queue holds, and uncertain fallback holds |
116
+ | Optional Orca companion (#1198 O0) | off; contract and fake-host/CLI fixtures only, no installed companion or runtime change | versioned capability matrix and three manual baseline procedures; observed UI action counts unknown; O1/O2 must prove actual open, selection, disable and standalone behavior, with remote/Windows/mobile separate; plugin terminal-id to CLI-handle mapping remains unproven |
117
+ | Kimi periodic review isolation (#1284) | source and isolated fixture coverage; running-hub/native-account behavior is unchanged until release and restart | max-input benchmark records historical inline blocking and worker control-response ordering separately from synchronous authority cost; fake-clock absolute cadence/no-overlap, complete filesystem tamper checks, source and plugin-only workers, and native/worker cleanup retry tests; no new native compatibility or model-quality claim |
118
+ | Optional Orca companion chooser and entry points (#1198 O1) | off; the companion exists under `integrations/orca/` but is not installed here, enabled by nothing and not in the package; fake-host and fake-CLI checks pass, **the native open and disable receipt is a person-run leg not yet run** | `integrations/orca/native-receipt.md` filled in by a person in an isolated Orca profile: actions counted after selection for the dashboard, console and family console, the refusal on a changed workspace, and agents, worktrees and terminals unchanged after `orca plugin disable`; until then the action counts are procedure counts and the native result is unknown |
119
+ | Optional Orca companion read-only status (#1198 O2) | off; fixture checks only, not installed here; the status view, its distinct states and the stale-binding refusals are tested against fakes and real scripts, **native testing that it reaches the same project is a person-run leg not yet run**; terminal focus is not built (O0: unproven mapping) | `integrations/orca/native-receipt.md` steps 8a to 8c filled in by a person in an isolated Orca profile: the status shown is for the selected project, offline reads as offline and starts nothing, and an old reading is labelled stale without being re-read |
120
+ | Optional Orca companion platform support (#1198 O3) | off; no combination is supported: macOS local is fixture-only and remote, Windows, browser or mobile and Linux are unsupported, each with a **person-run** receipt (`integrations/orca/receipts/`) that has not been run; remote and Windows are refused before anything runs | `integrations/orca/support-matrix.json` verdicts; a combination turns `supported` only after a person fills in its receipt (action count, observed result, standalone and disable checks as separate claims) and a reviewed commit changes the matrix, which a test enforces |
106
121
  | Completion checks per class | off: the implementer already runs `scripts/check.sh`; a hub-run copy would double the heavy-slot use | time to verdict when on |
107
122
 
108
123
  ## Memory and knowledge
@@ -128,7 +143,7 @@ agent-hub is developed with agent-hub. This page lists every feature, whether it
128
143
 
129
144
  | Feature | State here | Measured by |
130
145
  | --- | --- | --- |
131
- | Quota budgets and pauses | on | pauses, resets, time paused (#683) |
146
+ | Quota budgets and pauses | on; this repository's hubs run the 0.99 gate from the machine-local `budget.gate` since 2026-11-07 (#1292), and projects created before #1292 still pin 0.9 in their tracked config until the key is removed | pauses, resets, time paused (#683); for #1292, the count of soft `budget_pause` rows per week before and after the change, and the window share each pause's `reason` names (`5h window at 99%`; a hard refusal names the provider instead). The ledger row has no numeric `used` field, so the share is read from that reason text |
132
147
  | Token usage per peer and task | `ahub report` and, from the roll-up in `hub.db`, `ahub usage [--by peer\|task\|issue\|pr\|release\|day\|model]`, `usage limits` and `usage total` (#683 U2); console tab `7` (U3) and dashboard Usage view (U4) shipped | tokens per merged PR |
133
148
  | Operational settings mechanism (#489 H1) | available after release; this PR does not change this hub's running configuration; planner FYI interval defaults to the existing 10 minutes | shared descriptor/schema/UI/apply parity, independent legacy-default pins, real planner-notice boundary and settings inherit/undo/reload fixtures; native console/dashboard editing remains unverified |
134
149
  | Recovery and upgrade wait settings (#489 H4, task 445) | available after release; this PR does not change this hub's running configuration: the five `recovery.*` settings default to the waits they replace (managed attach 600 s, unmanaged reconnect 90 s, control request 30 s, shutdown 30 s, terminal idle 120 s) and nothing is set in this repository's config | every default equals its old constant (pinned with independent literals), every person-visible wait refuses a value below what shipped, a bad or unreadable file is the default and never an error inside a recovery, the coordinator reads both layers and the file at each wait, and inherit and undo go through the local file; the waits' use inside the real recovery driver (a configured value changing an actual attachment, shutdown or control wait) is covered only as far as the tests in this PR reach, and no real upgrade was run with a configured value |
@@ -149,7 +164,7 @@ agent-hub is developed with agent-hub. This page lists every feature, whether it
149
164
  | External module-kind instances (#754) | off here: no person-pinned module with an explicit headless-instance opt-in is configured | fake mixed builtin/module starts, current-owner and MCP refusal counters, retained stopped bindings and no-import source/target fences (`test/external-instance-*.test.ts`); native/account receipts remain unmeasured |
150
165
  | Multiple Jcode instances (#685) | pending | turns per instance |
151
166
  | Jcode TUI refusal causes and the recovery hint (#1085) | on for the base jcode wherever `roster.jcode` is on; fixture coverage only (fake jcode server drives each cause class, a resumed session and the status hint). A live recovery of a real jcode under a person's home is unverified and is not run here | hub.log lines `native_tui_launch jcode refused: <code>` per class (a class that dominates names the real failure), and `ahub status` showing the `jcode is running headless after recovery` line only until a ready TUI launch is served |
152
- | Peer terminals open in the target project's Orca worktree (#1089) | on wherever a TUI start opens a terminal through Orca; fixture coverage only (a fake `orca` CLI answers `worktree list` and records every call: a start from another project's terminal, refusals for no match, a parent or child root, an archived entry, two matches, a cut-off list and an Orca failure). Run against a real second project in Orca is unverified and not run here (no live panes) | hub.log lines `the hub opened no watch pane (Orca has no worktree whose root is this project's root ...)` and `ahub start` refusals that name the same cause, and no `ahub <peer>` failing its project-root readback after a hub-made start |
167
+ | Peer terminals open in the target project's Orca worktree (#1089) | on wherever a TUI start opens a terminal through Orca; fixture coverage only (a fake `orca` CLI answers `worktree list` and records every call: a start from another project's terminal, refusals for no match, a parent or child root, an archived entry, two matches, a cut-off list and an Orca failure). Run against a real second project in Orca is unverified and not run here (no live panes) | hub.log lines `the hub opened no watch pane (Orca has no worktree whose root is this project's root ...)` and `ahub up` or `hub_peer_start` refusals that name the same cause, and no `ahub <peer>` failing its project-root readback after a hub-made start |
153
168
  | Crash-recovery notices that clear (#1082) | on after release and upgrade, for the first crash a hub recovers from after that; fixture coverage only (`test/crash-notices.test.ts`: a real daemon over a planted crashed run, peers attached through the bus, rows resolved through the control path). A real `kill -9` recovery on a project with live peers is not recorded here | the `crash` lines of `ahub status --json` after every peer is attached and the held rows are resolved (expected: the headline only); the headline count against `ahub queue list` for the crash's own rows; any `run ahub ... again` line still showing next to an attached peer |
154
169
  | Urgent accept takes back unaccepted offers; WIP refusal splits accepted from offered (#1080) | on after release and upgrade; fixture coverage only (`test/urgent-wip.test.ts`: a real `Tasks` over a real board, an owner at its limit with one accepted task and offers). A live urgent task for a busy owner is not recorded here | task history: `unassigned` by `hub` with a `displaced by urgent task` note; the planner notice `was taken back from`; any `planner WIP capacity` refusal that still reads as one undivided list of open tasks |
155
170
  | Declared needs keep work from a peer that cannot do it (#1081: `needs_network`, `needs_worktree`) | on after release and upgrade, for tasks proposed with `needs_network` or `needs_worktree` (or `--needs-network`, `--needs-worktree`); fixture coverage only (`test/routing-network-needs.test.ts` and `test/routing-worktree-needs.test.ts`: routing, `route explain`, explicit assignment, a reservation, accept with a rostered fake Pi and Codex, and a real git repo showing a refused accept creates no branch ref; `test/capabilities-network-worktree.test.ts`: a real daemon's per-peer capabilities). A real Pi or local worker offered flagged work is not recorded here. A hub-made worktree for a sandboxed peer (#1115) is covered by fixtures only (`test/task-worktree.test.ts`: real git, a bare origin, the hub's commit and push, a moved branch or HEAD refused, the path policy, decline and cancel cleanup; `test/task-worktree-sandbox.test.ts`: the real `sandbox-exec` profile, unchanged, with the peer editing and the hub's commit after (the peer's own commit failing is asserted in `test/sandbox-git-refs.test.ts`, #1123); `test/task-worktree-tasks.test.ts`: accept, refusal, decline, cancel and the done hand-off through `Tasks`), so it is on after release and upgrade, for flagged work offered to Pi or local in a git repository with a GitHub origin, and its metric is a Pi or local task whose branch was committed and pushed by the hub and reviewed, with no `.git` write attempt from the sandbox (expected: none) and no empty `task/*` refs left by a declined or cancelled one | `ahub route explain` lines `skipped, no network` and `skipped, no worktree` for Pi or local; Pi or local declines of work that needed the network or a worktree (expected: none once the task is flagged); empty branch refs left by a declined Pi or local task (expected: none for flagged tasks); unflagged tasks that were declined for a missing worktree or registry, which show the planner is not flagging them |
@@ -164,15 +179,17 @@ agent-hub is developed with agent-hub. This page lists every feature, whether it
164
179
 
165
180
  | Feature | State here | Measured by |
166
181
  | --- | --- | --- |
167
- | `ahub init --specs/--no-specs/--spec-review` and person-only `ahub specs stamp` (#1064 T3) | on after release: a new or existing project gets the specs block by default; no repository design specs or stamps are recorded with it here yet; fixture coverage only (real CLI against scratch repositories: `test/init-specs.test.ts`, `test/specs-stamp.test.ts`, `test/check-docs-parity.test.ts`). A person stamping a real spec in a terminal is unverified and not run here (no live terminal session) | `ahub init --dry-run --json` `settings` rows for `specs.enabled` and `specs.review`; the specs block present in `AGENTS.md` of projects where `specs.enabled` is true and absent where it is false; `specs stamp` runs that end with `stamped N documents` against refusals for uncommitted covered paths; no `verified-against` change authored by an agent (`git log -p` on spec files) |
182
+ | `ahub init --specs/--no-specs/--spec-review` and person-only `ahub specs stamp` (#1064 T3) | on after release: a new or existing project gets the specs block by default; this repository enrolled five draft design specs under `docs/design/` and the specs block (#1117, #1119, 2026-11-02), none stamped yet; fixture coverage only (real CLI against scratch repositories: `test/init-specs.test.ts`, `test/specs-stamp.test.ts`, `test/check-docs-parity.test.ts`). A person stamping a real spec in a terminal is unverified and not run here (no live terminal session) | `ahub init --dry-run --json` `settings` rows for `specs.enabled` and `specs.review`; the specs block present in `AGENTS.md` of projects where `specs.enabled` is true and absent where it is false; `specs stamp` runs that end with `stamped N documents` against refusals for uncommitted covered paths; no `verified-against` change authored by an agent (`git log -p` on spec files) |
168
183
  | Per-call write outcomes (#1078) | source/fixture coverage; installed-hub activation and the reported live 35-45 s stall remain unverified | `test/tool-request.test.ts`, `test/control-client.test.ts` and real daemon/channel fixtures count one effect per request ID, preserve pending joins and reject changed scope/payload; the 600-task synthetic p95 receipt is `docs/verification/2026-11-02-control-write-outcomes.md` |
169
184
  | Control-write timing and event-loop delay (#1126) | source and isolated fixture coverage; live activation and cause of the reported stall remain unverified | `test/control-write-trace.test.ts` pins metadata/privacy/caps, lazy screens, five-minute diagnostic expiry and completed-span correlation; `test/control-write-telemetry.test.ts` checks admission before scanning, forces a blocked real daemon write and checks phase logs/status counters; historical UTC windows are in `docs/verification/2026-11-03-control-write-stall-windows.md` |
170
185
  | Recipient settlement and inbox reads behind held rows (#1079) | source/fixture coverage; installed-hub activation and a live busy-peer settlement remain unverified | `test/recipient-settlement.test.ts` checks busy own-row completed/discard with reason and revision, foreign-row refusal and queued reads behind an unchanged held row; pause/recovery/lifecycle fences remain covered |
171
- | Design spec inspection and task notices (#1064 T1/T2) | source/fixture coverage only; no repository design specs configured yet; dogfood drafts follow in later phases | `test/specs.test.ts` checks graph/freshness and empty-project silence; `test/specs-tasks.test.ts` checks report/require, head-bound acknowledgements and privacy; committed-head inspection fixtures exclude dirty/main-checkout bypasses; adoption metrics are the counts of `spec not updated` reports, acknowledged reasons and unchanged-spec refusals |
186
+ | Design spec inspection and task notices (#1064 T1/T2) | on in this repository since 2026-11-02: five draft specs (goal, architecture, bus, task-board, adapters) under `docs/design/`, `ahub specs check` 0 errors; the four-week AC11 report runs `bun scripts/spec-dogfood-report.ts` (#1064 T6), baseline `--since 2026-10-05T19:41:16Z --until 2026-11-02T19:41:16Z --baseline` (the four weeks before #1119 merged; 39 release merges excluded): 408 of 577 PRs touched dogfood paths and 219 (54%) changed the design monolith alongside; first dogfood days `--since 2026-11-02T19:41:17Z --until 2026-11-07T09:00:00Z` (10 release merges excluded): 21 of 51 (41%) changed the covering spec, below the 70% target | `test/specs.test.ts` checks graph/freshness and empty-project silence; `test/specs-tasks.test.ts` checks report/require, head-bound acknowledgements and privacy; committed-head inspection fixtures exclude dirty/main-checkout bypasses; adoption metrics are the counts of `spec not updated` reports, acknowledged reasons and unchanged-spec refusals |
172
187
  | Screened room chat and person inbox (#446 X4/X5/X5b) | default off here; requires person enrollment/exposure; console panel 8 and dashboard Agents remain metadata-only; person CLI alone can show one inbox body; real two-machine/account leg remains unverified | signed completed (admitted) versus immutable completed (inbox); once-only inbound count, body-free metadata/list JSON, framed/control-stripped person show, done/discard/expiry purge and fixed stored-byte cap/age refusals, post-ack retries; 1,100-row complete-list ceiling; no broadcast/roles/board/body telemetry, key/storage creation from status or mixed-version success claim; existing restart/binding/disposition regressions |
173
188
  | Capability discovery (#445 C1) | off here until a person shares an entry: nothing is listed without `invocation.share` in `.agenthub/config.local.json`; Kimi 2.3.2, Qwen 0.26.1 and Codex 0.166.0 list, every other version lists nothing; the live listing under a real login and a Codex 0.166.0 install remain unverified (the C0 probes used fixture homes); invoking is C2 | `ahub capabilities --json` per-peer entry counts and share states; `hub_capabilities` calls (the `capabilities_list` and tool lines in the hub log) against the count of shared entries; a peer on an unprobed version showing zero entries is the pin working, not a fault |
174
189
  | Capability invocations (#445 C2/C3) | off here until a person shares a capability; read needs no approval, write/external require task scope and allow-once approval for each call; unattended refuses effects. Stand-in round trips and approval/audit/hold tests are the verification target; live Kimi/Qwen/Codex receipts remain C4 | `invocation` events and rows by outcome (completed, refused, failed, expired, timeout, needs_review), approval ids and task audit entries, result bytes, time from queue to settle; a read that times out against a live peer is the signal to look at that peer, not at the hub |
175
190
  | Cross-hub read invocations (#446 X6) | off until both persons expose peers and independently pin the exact capability/digest/read class; discovery is manual; two-daemon broker/crypto fixtures are the verification target, live X7 receipts remain unverified | source/target invocation ids, request admission versus capability result and result transport outcomes; needs_review counts and no duplicate native dispatch |
191
+ | Headless amem Records (#1320) | source and disposable fixtures only; off in the running hub until release/upgrade and coordinated shared-home upgrades; production source uses the exact 0.23.1 policy API; no native/provider-backed receipt | Record capture accepted/dropped counts, forwarded answer/digest bytes, injected brief/recall bytes; proven saved-ID/anchor overlap compaction, unchanged unrelated notes, privacy/owner/steering fences and restart fallback in `test/headless-record*.test.ts` |
192
+ | Research record v2 and dataset export (#1277; person, memory and budget hand-off blocks #1278, #1279, task 802) | off here: `research.enabled` is not set in this repository's config; source and fixture coverage after merge (`test/research-record-v2.test.ts`, `test/research-quality.test.ts`, `test/research-dataset*.test.ts`: a real `hub.db` with hand-computed blocks, the privacy canary and the CLI over two registered projects); no live research pilot has run | `ahub research export --dataset <dir>` then `quality.json`: per-field `unknown` share (a share near 1 for a block means its source is not reaching the record), token attribution share, quota gaps |
176
193
  | Dogfood scorecard (#687) | on after release; read-only weekly receipt | `ahub report --dogfood --since 7d --json`; bounded evidence and explicit unknowns |
177
194
  | Claim verdicts and fact_check provenance (#901) | source/fixture coverage; the live research pilot (a person entering verdicts with `ahub task claim`) remains unverified | `ahub report --dogfood` research rows: `claims.reachedPersonVerdict`, per-slot `personVerdict`/`modelLabel`/`agreement`, `factCheck.selection`/`passed`/`failed`/`missingKeysPerRun`; null until a verdict or a keyed check is recorded |
178
195
  | Claim evidence links (#931 T1) | source/isolated fixtures after merge; this dev-profile repository publishes no evidence writer and has no live research evidence pilot | binding from `hub_task_show` / `ahub task show --json` records support/counterevidence and refuses after a claim edit; PII/Dev views expose no bindings; unknown/stale/private/foreign writes leave no revision, duplicate replay adds none, changed links retain prior revisions; ids-only receipts and capture canaries; projection/Unicode resolution, private-upgrade readback and synthesis readiness remain T2/T3, not verified by T1 |
@@ -197,11 +214,11 @@ agent-hub is developed with agent-hub. This page lists every feature, whether it
197
214
  | Pi/local session titles (#1055) | available after release for hub-owned Pi/local sessions; native Pi setter/readback is probed, installed use and the live restart receipt remain unverified (#1143) | first `hub_set_title` succeeds once, later agent writes return `already_named`, and person rename replaces it; live status shows the title or a screened unnamed label while `status.json` omits both |
198
215
  | Floating pet retirement (#1012) | pointer available after release; acon Mini use on this repository remains unverified | `ahub pet --window` and `--window --close` print the `acon ui` Mini pointer with exit 0 for person/agent/live-test; no window host starts; retired `--palette` prints the same pointer without writing config, legacy `pet.window` is ignored once, terminal pet frames remain covered by their unchanged tests |
199
216
  | Console and dashboard | on; #719 pending-history reads and bounded native launch retries take effect after release | control-request latency, connection timeouts and launch retry notices; daemon CPU/RSS samples, measured separately from lifetime CPU |
200
- | Completions: a run a person started settles into a result record (#1054 T2/T3, `completions`) | source and fake-adapter coverage only until released: a completion exists only for an adapter with a code-verified settle signal (Claude, Codex, Pi, local, Kimi/Jcode headless, Qwen); Kimi in its own TUI, agy and person-typed Codex turns create none, so this repository's TUI-driven agents (Claude, Kimi) will show few until a signal lands. The person reads them with `ahub results` (unread marked, `--read`, `--read-all`, `--unread-last`), as a `watch` need in `ahub status` and `ahub console` (and, from #1054 T6, in the Results section of the Agents view and in the acon inbox: see the next row) | `completion` events count `done`, `failed`, `limit` and `interrupted` with `ms`, and `completion_seen` events count how many results a person actually read and on which surface (the share of unread results older than a day shows whether results are noticed at all); the share of `interrupted` over all shows how often a restart cuts a run, and a run that never settles shows as an open row in `hub.db` `completion_runs`; `test/completions.test.ts`, `test/completions-daemon.test.ts` and `test/completions-receipts.test.ts` pin the rule, AC1 to AC7 and the privacy sinks; no prompt or reply text is ever stored |
217
+ | Completions: a run a person started settles into a result record (#1054 T2/T3, `completions`) | source and fake-adapter coverage until released: a completion exists only for an adapter with a code-verified settle signal (Claude, Codex, Pi, local, Kimi/Jcode headless, Qwen); agy and person-typed Codex turns create none. Kimi 2.5.2's own TUI also earns them only through the `ahub kimi` launcher's ephemeral `native_hook_launch` and exact-version native-turn/background readback (#1282); other TUI versions keep the old no-completion behavior. The person reads them with `ahub results` (unread marked, `--read`, `--read-all`, `--unread-last`), as a `watch` need in `ahub status` and `ahub console` (and, from #1054 T6, in the Results section of the Agents view and in the acon inbox: see the next row) | `completion` events count `done`, `failed`, `limit` and `interrupted` with `ms`, and `completion_seen` events count how many results a person actually read and on which surface (the share of unread results older than a day shows whether results are noticed at all); the share of `interrupted` over all shows how often a restart cuts a run, and a run that never settles shows as an open row in `hub.db` `completion_runs`; `test/completions.test.ts`, `test/completions-daemon.test.ts`, `test/completions-receipts.test.ts`, `test/kimi-tui-facts.test.ts` and `test/kimi-tui-completion-1282.test.ts` pin the rule, AC1 to AC7, final-turn correlation, background quiescence and privacy sinks. The exact-version live receipt is `docs/verification/2026-11-08-kimi-tui-completion-1282.md`: ordinary `done`, background completion delayed to quiescence, and one `done` after a real `hub_inbox` pull; no prompt, answer, error or task command is stored |
201
218
  | Results in the dashboard and the acon inbox (#1054 T6, T7) | on after release; with a console that advertises `inbox.result` and `action.meta` (acon 0.1.3 does) the person sees unread results as `result` items in the acon inbox, and in any case in the Results section of the Agents view with Mark read, Mark all read and Mark last unread again; the one-line detail is the head of the request, read from the bus at display and never stored. This repository's TUI-driven agents (Claude, Kimi) create few completions until a settle signal lands, so the first live receipt is a headless run or a Codex or Pi session started from the console | the share of results marked read from `acon` versus `dashboard` versus `terminal` (`completion_seen` `surface`), how many unread results are older than a day, and whether any `result` item reached an acon console without the features (it must not: the plugin publishes only with both); `test/results-plugin-1054.test.ts`, `test/results-dashboard-1054.test.ts`, `test/results-panel-1054.test.ts` and `test/completion-detail-1054.test.ts` pin the item, the receipt authority, the page and the privacy canaries (AC6 plugin part, AC8). The item is checked against acon's own published `inboxItemProblems` and `stableAtProblems` (`@staix/agent-console/conformance`, 0.1.3), but it is not yet seen in a running acon console: that is the one open live receipt, and it needs acon with `inbox.result` and a person |
202
219
  | Questions for the person: `hub_ask` (#1053 T2 to T6, `questions`) | available after release; source and fake-adapter coverage only: no live receipt per client yet (T1 measures the MCP tool-call timeouts and confirms the 45 s and 300 s wait windows). A person answers in `ahub console` (`A`), with `ahub answer`, or in the acon inbox form where the console advertises `inbox.form` and `action.meta` (the form rendering is agent-console#27; before it ships the item is a plain decision with an `open` verb) | `question` events count `asked`, `answered`, `pending`, `superseded`, `cancelled`, `expired` and `unavailable` with `latencyMs` and `surface` (`terminal`, `console` and `acon` show which surface people use); the share of `pending` over `asked` shows whether the wait window is long enough, `expired` shows questions nobody saw, the `question` need in `ahub status` shows how long a question waits, and `test/questions.test.ts`, `test/questions-daemon.test.ts`, `test/questions-console.test.ts`, `test/questions-console-daemon.test.ts`, `test/questions-plugin.test.ts` and the Pi bridge test pin the paths; no question or answer text is ever in the events, the log or memory |
203
220
  | Usage view (#683) | CLI (`ahub usage`, U2), console Usage tab `7` (U3) and dashboard Usage view (U4) shipped | its own panels |
204
- | Kimi usage from its wire log (#285 phase 2) | on after the release when `budget.kimi_tokens_5h` is set; this repository sets it | `tokens` and `usage` (`kimi_wire`) events per Kimi turn, the `tokens` window in `ahub budget`, and the count of `kimi usage unknown` notices; the live check against Kimi's `/usage` (AC11) stays opens |
221
+ | Kimi usage from its wire log (#285 phase 2, delayed drain #1281, sliced drain #1283) | on after the release when `budget.kimi_tokens_5h` is set; this repository sets it | `tokens` and `usage` (`kimi_wire`) events per Kimi turn, delayed rows collected without another turn, the `tokens` window in `ahub budget`, correct task attribution without a later turn's `turn_end` changing, and the count of `kimi usage unknown` notices; the sliced-drain benchmark records before/after longest synchronous slice, discovery and bytes, with a real status request admitted between slices; [AC11](verification/2026-10-25-kimi-usage-ac11.md), the [current native receipt](verification/2026-11-07-kimi-delayed-usage.md) and the [sliced-drain receipt](verification/2026-11-08-kimi-wire-yield-1283.md) |
205
222
  | Doctor memory-capture rows from agent-mem setup state (#1008) | on after release; `ahub doctor` runs here and reads `amem setup <tool> --json` (a preview that writes nothing) for `codex` and `kimi`; no dotfiles text and no `dot ai memory status` call | `memory capture: codex` and `memory capture: kimi` rows read ok (set up), warn with `amem setup <tool> --apply` (pending), warn with `client missing` (the native CLI is not installed) or unknown (no `amem`, a refusal or unparseable output); the Codex row notes the native `/hooks` review; a fixture run proves `dot` is never called |
206
223
  | Budget window kinds and notes (#285 phase 4) | on after the release; `ahub budget`, the console peer detail, the dashboard Usage budgets row and `ahub doctor` (`kimi usage source`) run here | each window shows its kind and source, a peer without a number says why (Pi, local and Kimi included); a manual `ahub budget set` value outranks the Kimi count at the gate; the doctor row reads ok while the wire log counts |
207
224
  | Settings reload | on | reloads applied, pending restarts |
@@ -209,7 +226,7 @@ agent-hub is developed with agent-hub. This page lists every feature, whether it
209
226
  | Upgrade and recovery | on, per release | upgrade receipts in `docs/verification/` |
210
227
  | Office planning view (#264 phase 5) | source/fixture implementation; available after release when the person selects Flat or Isometric (Off by default); the live two-agent, both-theme AC9 browser look remains unverified | `test/office-model.test.ts` pins Backlog count/order/cap, reserved/pin/waits and release/planner metadata; `test/office-view.test.ts` pins dock and overflow navigation, keyboard access, stable wall-to-To do card nodes, geometry, reduced motion and light/dark token contrast; served-page raw/gzip deltas are measured against the PR merge base |
211
228
  | acon console plugin (#935) | off here until a person runs `ahub setup` after the release and `acon ui` on this machine; the plugin registers per agenthub home, not per repository | `acon plugins` shows `ahub verified`; the console's agent-hub panel shows this repository's live board, and an approval answered from the console inbox appears in hub.log as `answered option allow_once by dashboard`. Space (#1012): adopted with the plugin, no separate switch; acon's Space view (Flat, Room, 3D) shows this repository's peers as actors (state and marks matching the dashboard's office), the board columns as queue/work/review/done zones with the same counts, and overlap links plus message arcs (broadcasts to every other desk) as links; clicking an actor or card opens this project's agents or board panel |
212
- | Agent CLI version policy and trust (#691) | on after the release: Codex 0.163.0 verified by the [2026-10-22 receipt](verification/2026-10-22-codex-reviewer-isolation.md) and 0.164.0 by the [2026-10-24 receipt](verification/2026-10-24-codex-0164-reviewer-isolation.md); Kimi 2.3.0 and Qwen 0.26.0 verified by the [model-free receipt](verification/2026-10-22-kimi-qwen-compat.md), Kimi 2.3.1 by the [2026-10-25 model-free receipt](verification/2026-10-25-kimi-231-reviewer-compat.md) and 2.3.2 by the [2026-10-26 one](verification/2026-10-26-kimi-232-reviewer-compat.md), with account/provider live legs unverified; agy 1.4.4 in-line | model-free isolation receipts, `ahub agents` verdicts, versions trusted per machine, lead time from an `agent-compat` issue to a receipt |
229
+ | Agent CLI version policy and trust (#691) | on after the release: Codex 0.163.0 verified by the [2026-10-22 receipt](verification/2026-10-22-codex-reviewer-isolation.md) and 0.164.0 by the [2026-10-24 receipt](verification/2026-10-24-codex-0164-reviewer-isolation.md); Kimi 2.3.0 and Qwen 0.26.0 verified by the [model-free receipt](verification/2026-10-22-kimi-qwen-compat.md), Kimi 2.3.1 by the [2026-10-25 model-free receipt](verification/2026-10-25-kimi-231-reviewer-compat.md) and 2.3.2 by the [2026-10-26 one](verification/2026-10-26-kimi-232-reviewer-compat.md), with account/provider live legs unverified; agy exact 1.5.3 has an [account-free receipt](verification/2026-11-08-agy-1.5.3.md); effective after release and upgrade, with the 1.4.x line unchanged | model-free isolation receipts, `ahub agents` verdicts, versions trusted per machine, lead time from an `agent-compat` issue to a receipt |
213
230
  | Peer child environment isolation (#1077) | source and fixture coverage; no native account or Orca session used | daemon peer children, version probes and process-table helpers contain no `ORCA_*`; person-owned native launches keep their fixture pane's `ORCA_*` context while replacing agent identity; explicit Claude/Codex selectors pass through where the adapter inherits them; preload clears ambient selectors without changing fixture home bytes |
214
231
  | Qwen's own TUI over dual output (#286 Part 3) | off here: this repository's hub runs no Qwen peer (roster.qwen is off), and the limits (a hub deny ends the turn without an answer; a stalled turn is stopped only with Esc in the Qwen terminal) are for the person at that terminal to accept. Verified on Qwen 0.26.1 under an isolated HOME by the [2026-10-25 receipt](verification/2026-10-25-qwen-dual-output-t0.md); the live account leg is the person's | `test/qwen-dual.test.ts` against a fake dual-output Qwen; in real use `ahub status` stalled/detached notices per peer and the `needs_review` count of Qwen deliveries (an Esc or an exited terminal ends a turn that way; a deny completes) |
215
232
  | Benchmarks (#251, #637) | off: `bench.enabled = false`. The task-routing gate (#637 part 1) is on in CI for every PR: `routing-receipt` fails a change to `templates/routing.toml` without a matching receipt; the model-routing gate (#637 part 2) is the second step of the same workflow: `scripts/check-model-routing-receipt.ts` fails a change to the model-routing keys without a matching `-modelrouting-` receipt, and wants a by-hand `--live` half when an alias or judge moves | bench receipts; `docs/verification/*-routing-*.md` and `*-modelrouting-*.md` receipts; a `routing-eval` check run on every PR with `eval_pass_rate=` and `eval_suite=` in its title (name it as `eval_check` to make it the eval gate); `bun scripts/benchmarks/routing-gate.ts` and `model-routing-gate.ts` print the default's numbers (100% on both splits); the live half (served model ids) has not been run against a gateway yet |
@@ -219,6 +236,10 @@ agent-hub is developed with agent-hub. This page lists every feature, whether it
219
236
  | Global CLI and plugin step after `ahub upgrade` (#718, #1179) | on after release: a completed or scheduled upgrade ends with `bun add -g @staix/agent-hub@<version>` and `ahub setup` when the global CLI or the shared Claude plugin is older than the daemon it installed (a handed-over upgrade speaks for the older CLI that started it), and says nothing when both are current or the plugin cannot be read; `release-prepare` writes the same step into every new `Upgrading to <v>` note and `release-tag` refuses a release without it. Unverified: a live handed-over upgrade on the owner's Mac, where the old CLI starts the new coordinator through `bun x` | the upgrade's own output on the owner's Mac after the next release, whether `ahub doctor` still warns afterwards (it should not once the person followed the step), `test/runtime-version-warning.test.ts`, `test/upgrade-interactive.test.ts`, `test/upgrade-cli.test.ts` (a real hub with a fake `claude` and `npm`), `test/release-prepare.test.ts` and `test/release-tag.test.ts` |
220
237
  | Confirmed reattach of orphaned-but-connected Orca terminals in `ahub upgrade` (#1246) | on after release: the interactive plan screen offers `[t]` when the plan verified a pane as orphaned and connected, switches exactly those handles with `orca terminal switch`, polls each for at most 5 s and plans again; the blocker names the peer, project, handle and `[r] refresh`. Unverified: a live Orca restart on the owner's Mac (fixtures use a fake Orca) | count `[t]` uses against hand-typed `orca terminal switch` calls after an Orca restart (the latter should reach zero), and how often a pane is still orphaned at the 5 s bound (raise the bound if it is common); `test/terminal-recovery.test.ts`, `test/upgrade-interactive.test.ts` |
221
238
  | Hard-coded values inventory ratchet (#719, #1180) | on now: `scripts/check.sh` runs `bun scripts/inventory-hardcoded-values.ts --check`, so a new constant must be classified in `scripts/inventory-hardcoded-values.classifications.json` before it merges, and the 1222 keys still unclassified sit in `scripts/inventory-hardcoded-values.baseline.json`, which only shrinks. This does not close #1180: those 1222 are classified later in reviewed batches (`docs/verification/2026-11-05-hardcoded-values-ratchet.md`) | the unknown-key count (the baseline's length) falling to 0 over the follow-up batches and `check: OK` staying green with no key added to the baseline, `test/inventory-hardcoded-values.test.ts` |
239
+ | Optional Herdr companion host contract (#1199 H0) | off; contract and fixtures only: no mod is installed or loaded, nothing was written to a Herdr profile, and the three baseline journeys are **person-run** procedure counts that have not been run | `integrations/herdr/host-contract-v1.md` and `test/herdr-companion-contract.test.ts` pin the API surface, root resolution and fixture strictness; a native receipt in H1 to H3 (action count, observed UI, standalone and disable as separate claims) is what turns a journey from `not run` into a measurement |
240
+ | Optional Herdr project and machine entry (#1199 H1) | off; a three-file mod folder the person copies in and can delete, `place: none`, opened on purpose; the fake-host tests and `herdr-app check` in a scratch home pass, but the native open and disable receipt (`integrations/herdr/native-receipt.md`) is a **person-run** leg that has **not been run**, and the action counts are procedure counts | native receipt with the action count after selection (target at most 2), the observed result, and standalone and disable recorded as separate claims; remote needs a configured machine (H3) |
241
+ | Optional Herdr status card and existing-console focus (#1199 H2) | off; adds Status, Focus console and Peek console to the optional entry mod; fixture tests pass and `herdr-app check` accepts the files in a scratch home, but native focus is a **person-run** leg (`integrations/herdr/native-receipt.md`, Claim 1b) that has **not been run**; recognition rests on one observed foreground shape and a wrapper-started console is not recognized | native receipt: card legibility, whether Focus really moves to the console's pane, the action count, and that a missing console starts nothing; the share of consoles recognized is unknown until it is run |
242
+ | Optional Herdr platform support and baseline comparison (#1199 H3) | off; no combination is supported: macOS local is fixture-only and remote, Windows, Linux and browser or mobile are unsupported, each with a **person-run** receipt (`integrations/herdr/receipts/`) that has not been run; no remote machine is configured on the build machine, so the remote workflow was never run | `integrations/herdr/support-matrix.json` verdicts; a combination turns `supported` only after a person fills in its receipt (action count, observed result, standalone and disable as separate claims) and a reviewed commit changes the matrix, which a test enforces; `baseline-comparison.md` stays procedure counts until then |
222
243
 
223
244
  ## Decisions
224
245
 
package/docs/events.md CHANGED
@@ -12,42 +12,44 @@ marked `private: true`, and PII tasks `pii: true`.
12
12
 
13
13
  | type | fields |
14
14
  |---|---|
15
+ | `model_change` | `peer`, `previousModel` and `model` (previous/new desired override ids, null for inherited selection), `by: person`, `source` (`cli` or `dashboard`), `appliesFrom: next_turn`, optional `afterTurn` (an already existing hub turn id). The event records a person's desired-state change, not native model acceptance or provider availability; no future turn id, prompt or credentials. |
15
16
  | `envelope` | `id`, `from`, `to` (absent for broadcast), `priority`, `hop`, `kind`, `task` (task id from refs), `bytes` (UTF-8 size of the body; absent on a private envelope, whose size would say something about the PII text), `private`, `dropped` (`hop` or `fyi` when not delivered) |
16
17
  | `overflow`, `undeliverable` | `id`, `from`, `peer` |
17
18
  | `stale` | `id`, `from`, `peer`, `task`: a notice about the recipient's open task, dropped unsent because, right before it would have been handed over, that task was closed, had another owner or was gone (issue #106) |
18
19
  | `quiet` | `id`, `from`, `peers`: an agent message held back from these members of a silent turn-free cohort; its other recipients got it (issue #107) |
19
20
  | `fact` | `peer`, `id` (the offer), `files` (files whose diff it carried), `plans`, `unknown` (files whose change it showed with attribution unknown), `named` (files under a named directory it named without a diff, those counted as "N more" or held back by the PII filter included), `bytes` (the injected text), `via` (`hook` for Claude, `steer` for Codex, `done` with an integration request), `ms` (the hub's time to build it), `hookMs` (the hook process's own start-up and connect time), `accepted` (whether app-server took the steer), `unanswered` (app-server did not answer it within 10 s: it may have gone in), `rttMs` (an accepted steer: from sending it to app-server's answer), `probe` (a context check), `coverage` (it named files earlier changes are not covered for): one fact offer (issue #108) |
20
21
  | `fact_ack` | `peer`, `id`, `via` (`hook` and `steer`: a readback found the offer in the native session; `done`: the next `hub_task_done`), `ms` (from the offer): an acknowledged offer, the only thing that moves a peer's view |
21
- | `route` | `peer`, `route`, `tier`, `source` (`override`, `dimensions`, `hold`, `classifier`, `default`; for `hub/auto` also `load`: a busy MLX slot moved it to `dgx/fast` (opt-in, `[pi] efficient_wait_ms`), `cooldown`: a cooling MLX went to its fallback first, and `pin`: an enforced tool loop went to the backend it is pinned to, issue #199), `score`, `ms`. Local decisions also carry `decision`, `turn`, optional numeric `task`, `pii`, and decision-time `severity`, `spinning`, `exploring`, `production`. A `hub/auto` decision for a request without a session key carries `stateless: true` (`ahub report` then counts its sessions as unknown). `hub/auto` and hub stage decisions carry `turnType` (`tool_result`, `user`, `compaction`: what the call answers) and `prefillTokens` (estimated input a backend would prefill; absent on a PII route), and, unless `stay_switch` is `off`, `staySwitch` (`shadow`, `enforce`), `plan` (`stay`, `switch`) and `reason` (`new_pin`, `compaction`, `context_fit`, `same_tier`, `override`, `tool_loop`, `prefill_bound`, `user_turn`): the planner's verdict next to the tier taken (issue #197). No prompt text |
22
+ | `route` | `peer`, `route`, `tier`, `source` (`override`, `dimensions`, `hold`, `classifier`, `default`; for `hub/auto` also `load`: a busy MLX slot moved it to `dgx/fast` (opt-in, `[pi] efficient_wait_ms`), `cooldown`: a cooling MLX went to its fallback first, and `pin`: an enforced tool loop went to the backend it is pinned to, issue #199), `score`, `ms`. Local decisions also carry `decision`, `turn`, optional numeric `task`, `pii`, and decision-time `severity`, `spinning`, `exploring`, `production`. A `hub/auto` decision for a request without a session key carries `stateless: true` (`ahub report` then counts its sessions as unknown). `hub/auto` and hub stage decisions carry `turnType` (`tool_result`, `user`, `compaction`: what the call answers) and `prefillTokens` (estimated input a backend would prefill; absent on a PII route), and, unless `stay_switch` is `off`, `staySwitch` (`shadow`, `enforce`), `plan` (`stay`, `switch`) and `reason` (`new_pin`, `compaction`, `context_fit`, `same_tier`, `override`, `tool_loop`, `prefill_bound`, `user_turn`): the planner's verdict next to the tier taken (issue #197). Decision routes additionally use source `decision`, `decisionMode`, `chosenAlias`/`chosenEffort` (null when the hub has no validated pick), `margin`, `decisionLatencyMs`, closed `decisionReason`, `fallbackApplied` and the decider provider/model/latency metadata (null when no decider was asked). In shadow, `tier` is still the actual heuristic choice; the proposed pair never replaces it. The decider metadata additionally carries optional `version` when the provider reports a pinned version; absent remains unknown, never inferred from the model id. No prompt/evidence text, tool arguments, credentials or service error prose |
22
23
  | `cooldown` | `peer`, `alias`, `event` (`start`, `end`), `failures` (consecutive transport or startup failures), `ms` (on `start`, how long the alias cools down): a relay backend alias after repeated failures (issue #199). An `end` is recorded at an HTTP answer (any status) or when the hub next checks the alias after it expired |
23
24
  | `route_outcome` | `peer`, `decision`, `turnId`, `turn` (`completed` or `failed`), optional `task`, `pii`, `latched`, optional `next` (`severity`, `tests`: `pass`/`fail`/`none`, `repeat`) and `advisor` (`approve`/`redo`/`failed`). Exactly once per local decision at turn settlement, including failure/cancellation |
24
25
  | `advisor` | `peer`, `route`, `trigger`, `verdict` (`approve`, `redo`, `failed`), `discardedChars`: an advisor check result; no transcript or feedback text |
25
26
  | `progress` | `peer`, `task` (task id), `severity`, `spinning`, `exploring`, `production`: normalized tool activity dimensions for an open task; coverage differs by peer and no commands or task text are recorded |
26
27
  | `stuck` | `peer`, `task` (task id), `category` (`repetition`, `false_progress`, `drift`, `desperation`, `capability_gap`), `streak`, `latched`: an escalation verdict; it recommends considering reassignment and never reassigns automatically |
27
28
  | `capability` | `peer`, `state` (`verified` or `lost`), `via`: a peer's context path for facts |
28
- | `memory_brief` | `peer`, `task`, `native`, `fails`, `claudeMem`: what a task brief carried, as counts (#258, docs/memory.md) |
29
- | `hub_start` | `instance`: a hub run began, written once it holds its control port and before any peer can attach (a daemon that cannot bind writes none); every peer counts as detached until its next `state` event |
29
+ | `memory_brief` | `peer`, `task`, `native`, `fails`, `claudeMem`: what a task brief carried, as counts (#258, docs/memory.md); the research record's `memory` block reads agent-mem's counters for the task, not new events (#1279, docs/research.md) |
30
+ | `hub_start` | `instance`, `personAttribution: true` (this run writes `task` and `attribution` on `permission`, `question`, `completion` and `agent_cli`, #1278; a log with no such start says nothing about which task a person interaction belonged to): a hub run began, written once it holds its control port and before any peer can attach (a daemon that cannot bind writes none); every peer counts as detached until its next `state` event |
30
31
  | `tooling` | `peer`, `addons` (`{ name, version }` from a closed list, version null when unknown): the add-ons a peer works with, at each attach (#248, docs/research.md) |
31
- | `native_turn_end` | `peer`, `id` (an opaque hash that names the completed turn): the end of a Claude turn, recorded once the hub finds the turn its Stop hook reported completed in the native transcript (Codex's is its `turn_end`); quiescence evidence for an integration |
32
+ | `native_turn_end` | `peer`, `id` (an opaque hash that names the completed turn): the end of a Claude turn, recorded once the hub finds the turn its Stop hook reported completed in the native transcript (Codex's is its `turn_end`), or the correlated final `turn.ended` of a Kimi TUI turn (#1282), or an agy terminal `Stop` of an active, fully idle turn, which carries no `id` and a closed `reason` (`user_canceled`, `error`, `max_invocations`, `max_forced_invocations`, `max_token_budget_exceeded`, `terminal_step_type`, `terminal_custom_hook`; #1280); quiescence evidence for an integration, never a hook payload, prompt or error |
32
33
  | `supervision_turn` | `peer`, `turn` (the hub turn a supervision notice was delivered into, or `supervision-<uuid>` when none was open), `tokens` (when the adapter reported any for it), `ms` (from that turn's start, or from the delivery when none was open, to its native end): a completed native turn that received supervision, which `ahub report` counts; a failed delivery or turn, a peer that went offline or a changed native session records none |
33
34
  | `conduct` | `peer` (the conductor, or `user` when the console releases a conductor hold), `action`, `task` (when the action names or creates one), `target` (the peer an assignment, start, hold or release names): one action of the conductor that ran, the structured twin of the console's `conductor` notice. `action` is a tool name without its `hub_` prefix: a conductor tool (`status`, `task_show`, `task_assign`, `task_escalate`, `peer_start`, `peer_hold`, `peer_release`), or one of the conductor peer's own task tools, which are not conductor tools (`task_propose`, `task_accept`, `task_decline`, `task_done`, `review`, `checkpoint`, `remember`). The role-free reads and redirects (a task's owner or reviewer with `hub_task_show`, its proposer with `hub_task_assign`) record none, and neither does `hub_task_list` |
34
- | `agent_cli` | `peer` (`unknown` when the agent markers were invalid), `command` (the command and, where it has one, its subcommand, from a closed list; `unknown` otherwise; never an argument), `refused` (the CLI refused it before connecting: a human-only command, or an invalid identity; a later refusal by the hub is not recorded here): an `ahub` command run from an agent session. The hub reads these from the `cli-audit/` outbox, so `at` is when it read the record |
35
+ | `agent_cli` | `peer` (`unknown` when the agent markers were invalid), `command` (the command and, where it has one, its subcommand, from a closed list; `unknown` otherwise; never an argument), `refused` (the CLI refused it before connecting: a human-only command, or an invalid identity; a later refusal by the hub is not recorded here): an `ahub` command run from an agent session. The hub reads these from the `cli-audit/` outbox, so `at` is when it read the record. From #1278 it also carries `task` and `attribution` (the `turn_end` rule) when the record is drained within 15 s of the command; an older record is `unattributed`, never matched to the task open at drain time |
35
36
  | `hook_stats` | `peer`, `n` (facts hook calls in the turn, its Stop included), `startupMs` and `maxStartupMs` (the hook processes' start-up and connect time, summed and the largest), `hubMs` (the hub's own time for them): at Claude's Stop (issue #108) |
36
37
  | `cohort` | `id`, `event` (`formed`, `joined`, `lifted`), `silent`, `tasks`, `owners`: owners of overlapping tasks formed a cohort, it changed membership, or it stopped being silent (issue #107). Recorded in every regime; only a turn-free project's cohorts can be silent |
37
38
  | `split` | `task`, `where` (`routing`: routing chose the first owner of a task overlapping another owner's task not started yet, not an escalation, relay or reassignment, the record calibration reads; `cohort`: an overlap formed or changed a cohort), `verdict` (`split`, `single`, `unknown`), `single` (the peer that would finish both units alone soonest), `splitS`, `singleS`, `reason` (for `unknown`), `trace` (the inputs and steps: peer names, their profiles of versions and coordination, and numbers only): a shadow split prediction; it never changes the assignment (issue #109) |
38
39
  | `state` | `peer`, `state` |
40
+ | `visual` | `id`, `kind` (`mermaid`, `comparison`, `table`, `beforeAfter`), payload UTF-8 `bytes`, image `files` count, optional numeric `task`: a bounded public visual was stored (#1058). Never the title, source, comparison/table text, path or image bytes. Ordinary delivery records carry only the visual stub and id. |
39
41
  | `native_thread` | `peer` (`codex`), `thread` (its native thread id), `fresh` (`true` when the TUI started the thread, `false` when it resumed one): each thread the Codex adapter adopts, before any turn on it. The upgrade planner reads it: a thread with no rollout that the hub saw start, with no `turn_start` since, is planned as a fresh start (issue #215) |
40
42
  | `turn_start` | `peer`, `turn` (`<peer>#<hub run>.<n>`, unique across restarts). A turn follows the adapter: pausing a busy peer does not end it |
41
43
  | `turn_end` | `peer`, `turn`, `ms`, `tokens` (when the adapter reported any during the turn), `files` and `snapshotMs` (when snapshots are on: how many files the turn changed, and the time both snapshots took); optional numeric `task`, `attribution` (`delivery`, `single_open`, `unattributed`) frozen at turn start, `pii: true` for an attributed PII task |
42
- | `tokens` | `peer`, `n` (tokens added since the previous report), optional numeric `task`, `attribution` (`delivery`, `single_open`, `unattributed`), `pii: true` for an attributed PII task |
43
- | `usage` | `peer`, `source` (`omniroute`, `claude_transcript`, `codex_appserver`, `kimi_wire`, `jcode_acp`), opaque `id`, optional `measuredAt` (provider/source time), the `requestedModel`, `servedModel` and `provider` labels, and any provider-reported counters (`inputTokens`, `outputTokens`, `cacheReadTokens`, `cacheWriteTokens`, `reasoningTokens`, `totalTokens`); optional numeric `task`, `attribution` (`delivery`, `single_open`, `unattributed`), `pii: true` for an attributed PII task. Missing counters stay unknown. |
44
- | `task` | `id`, `event` (the board history event, e.g. `proposed`, `assigned`, `done`, `check failed`, `blocked`, `ready`), `by`, `state`, `owner`, `reviewer`, `class`, `pii`, and `reason` when the board recorded a move reason (`manual`, `budget`, `offline`, `idle`, `rejections`, `declined`, `inference_failed`, `delivery_failed`) |
44
+ | `tokens` | `peer`, `n` (tokens added since the previous report), optional `source: kimi_wire` and opaque `id` (the native row, used to keep a partial-write retry exactly once), optional numeric `task`, `attribution` (`delivery`, `single_open`, `unattributed`), `pii: true` for an attributed PII task |
45
+ | `usage` | `peer`, `source` (`omniroute`, `claude_transcript`, `claude_result`, `codex_appserver`, `kimi_wire`, `jcode_acp`, `agy_transcript`), opaque `id`, optional `measuredAt` (provider/source time), the `requestedModel`, `servedModel` and `provider` labels, and any provider-reported counters (`inputTokens`, `outputTokens`, `cacheReadTokens`, `cacheWriteTokens`, `reasoningTokens`, `totalTokens`); optional numeric `task`, `attribution` (`delivery`, `single_open`, `unattributed`), `pii: true` for an attributed PII task. Missing counters stay unknown. |
46
+ | `task` | `id`, `event` (the board history event, e.g. `proposed`, `assigned`, `done`, `check failed`, `blocked`, `ready`), `by`, `state`, `owner`, `reviewer`, `class`, `pii`, and `reason` when the board recorded a move reason (`manual`, `budget`, `offline`, `idle`, `rejections`, `declined`, `inference_failed`, `delivery_failed`). The research record (docs/research.md, #1277) reads these for every terminal task, approved or cancelled; no new event type was added |
45
47
  | `overlap` | `task`, `owner`, `others` (`task`, `owner`, `paths`, and `symbols` when plans name the same symbol; a name that matches a PII pattern is left out, so either list can be empty), the structured twin of the console notice |
46
48
  | `permission_mode` | `peer`, `from`, `to` (`ask`, `ask-when-needed`, `never-ask`): a person set a peer's permission mode (`from` equals `to` when it was already in force) or confirmed a never-ask default (issue #242) |
47
- | `settings` | `key` (a registry key such as `permission.kimi` or `routing.classes.implement.peers`), `from`, `to` (the value before and after: the one in force for a setting that applies at once, the stored one for a setting read at a start; a closed word, a boolean, a list of peer ids, a route id, or null for none), `source` (`dashboard`, `terminal`), and `undo: true` for an undo: a person changed a setting from the dashboard or `ahub settings` (issue #269). A mode change also writes its `permission_mode` event |
48
- | `permission` | `id`, `peer`, `event` (`requested`, then one of `answered`, `expired`, `cancelled`) and, on the closing event, `latencyMs`, `surface` (`console`, `dashboard`, `terminal`: where a person answered; absent when the hub closed the request) and `option` (the kind of the option chosen: `allow_once`, `allow_always`, `reject_once`, `reject_always`): one approval request relayed to the console and how it ended. `expired` is `approvals.timeout_s` without an answer. `cancelled` with a `surface` is a person's deny in the console or by `ahub permit <id> deny` (a deny on the dashboard is `answered` with a reject option); without one, the hub withdrew the request (its call or turn ended, the peer was stopped, or the hub is stopping). Never the title or the tool |
49
- | `question` | `set`, `peer`, `event` (`asked`, `answered`, `pending`, `superseded`, `cancelled`, `expired`, `unavailable`) and, where they apply, `latencyMs`, `person` (only with `surface: acon`: the console's verified identity, one bounded line), `surface` (`terminal`: `ahub answer`; `console`: the `A` key; `dashboard`: reserved, no surface sets it today; `acon`: the plugin's answer with the console's person meta), `reason` (`superseded`, `stopped`, `turn_aborted`, `session_changed`, `expired`, `unattended`), `questions` (a count) and `private`: one question a peer asked the person through `hub_ask` and how it ended (#1053). Never a prompt, an option, an answer or any other text. The attention need a question raises (`question`, in `status.needs` and `attentionItems`) is not an event: it carries the set id, the peer and the time only |
50
- | `completion` | `id`, `peer`, `outcome` (`done`, `failed`, `limit`, `interrupted`), `ms` (start of the run to settle): a run a person started settled (#1054). A run starts at the `turn_start` that consumes the person's message and settles only when the adapter's `settle` signal fired and nothing else is pending (no queued continuation, open permission or question, owned child, running check or held delivery); a restart cut short settles `interrupted`, once. An explicit person Stop and a budget pause create none. Never the prompt, the reply or any other text: the envelope ids live in `hub.db` and are read through the usual privacy path |
49
+ | `settings` | `key` (a registry key such as `permission.kimi` or `routing.classes.implement.peers`), `from`, `to` (the value before and after: the one in force for a setting that applies at once, the stored one for a setting read at a start; a closed word, a boolean, a list of peer ids, a route id, or null for none), `source` (`dashboard`, `terminal`, `conductor`), optional `peer` and `reason`, and `undo: true` for an undo: a person changed a setting from the dashboard or `ahub settings` (issue #269). A mode change also writes its `permission_mode` event |
50
+ | `permission` | `id`, `peer`, `event` (`requested`, then one of `answered`, `expired`, `cancelled`) and, on the closing event, `latencyMs`, `surface` (`console`, `dashboard`, `terminal`: where a person answered; absent when the hub closed the request) and `option` (the kind of the option chosen: `allow_once`, `allow_always`, `reject_once`, `reject_always`): one approval request relayed to the console and how it ended. `expired` is `approvals.timeout_s` without an answer. `cancelled` with a `surface` is a person's deny in the console or by `ahub permit <id> deny` (a deny on the dashboard is `answered` with a reject option); without one, the hub withdrew the request (its call or turn ended, the peer was stopped, or the hub is stopping). Never the title or the tool. From #1278 it also carries `task` (a board task id) and `attribution` (`delivery`, `single_open`, `unattributed`, the rule `turn_end` and `tokens` use; `task` is absent when unattributed), resolved when the event's subject opens (a permission when requested, a question when asked, a completion's run when it starts) and repeated on every later event of it, so an answer given after the task closed still names the task it was asked under; `pii: true` when that task is PII. Ids and a closed word only. |
51
+ | `question` | `set`, `peer`, `event` (`asked`, `answered`, `pending`, `superseded`, `cancelled`, `expired`, `unavailable`) and, where they apply, `latencyMs`, `person` (only with `surface: acon`: the console's verified identity, one bounded line), `surface` (`terminal`: `ahub answer`; `console`: the `A` key; `dashboard`: reserved, no surface sets it today; `acon`: the plugin's answer with the console's person meta), `reason` (`superseded`, `stopped`, `turn_aborted`, `session_changed`, `expired`, `unattended`), `questions` (a count) and `private`: one question a peer asked the person through `hub_ask` and how it ended (#1053). Never a prompt, an option, an answer or any other text. The attention need a question raises (`question`, in `status.needs` and `attentionItems`) is not an event: it carries the set id, the peer and the time only. From #1278 it also carries `task` (a board task id) and `attribution` (`delivery`, `single_open`, `unattributed`, the rule `turn_end` and `tokens` use; `task` is absent when unattributed), resolved when the event's subject opens (a permission when requested, a question when asked, a completion's run when it starts) and repeated on every later event of it, so an answer given after the task closed still names the task it was asked under. A question answered after the hub restarted while it was open (or after the bounded map dropped it) is `unattributed`, never the peer's task of the moment: the opening answer lives in memory only; `pii: true` when that task is PII. Ids and a closed word only. |
52
+ | `completion` | `id`, `peer`, `outcome` (`done`, `failed`, `limit`, `interrupted`), `ms` (start of the run to settle): a run a person started settled (#1054). A run starts at the `turn_start` that consumes the person's message and settles only when the adapter's `settle` signal fired and nothing else is pending (no queued continuation, open permission or question, owned child, running check, held delivery, native background task or unknown native inventory); a restart or launcher loss cut short settles `interrupted`, once. An explicit person Stop and a budget pause create none. Never the prompt, the reply, an error, a task command or any other text: the envelope ids live in `hub.db` and are read through the usual privacy path; native-person results are private stubs. From #1278 it also carries `task` (a board task id) and `attribution` (`delivery`, `single_open`, `unattributed`, the rule `turn_end` and `tokens` use; `task` is absent when unattributed), resolved when the event's subject opens (a permission when requested, a question when asked, a completion's run when it starts) and repeated on every later event of it, so an answer given after the task closed still names the task it was asked under; `pii: true` when that task is PII. Ids and a closed word only. |
51
53
  | `completion_seen` | `id`, `surface` (`terminal`, `console`, `dashboard`, `acon`): a person marked a result read (#1054). One per receipt written, never from a snapshot read or a listing, never the prompt or the reply. `surface` is where the person marked it: `dashboard` is the Results section of `ahub ui` and of the acon panel (the panel's own buttons), `acon` is the acon inbox's `result_seen` or "Mark all read" with the console's verified person meta, `terminal` is `ahub results`. Mark-unread deletes a receipt and records no event. The detail line shown beside a result (the head of the starting prompt) is built at display and is in no event |
52
54
  | `pii_screen` | `task` (absent for a budget hand-off or a note not about a task), `item` (`task`, `summary`, `review note`, `handoff`, `note`), `label` (`pii`, `clear`), `source` (`regex`: a pattern matched and no call was made; `screen`; `unknown`: no verdict, handled as PII), `category` (`name`, `student_id`, `phone`, `address`, `grade`, `health`, `other`), `miss` (why there was no verdict: `too long`, `off campus`, `timeout`, `unreadable`, `failed`), `ms` (absent for `regex`): one PII screen verdict while `signals.pii_screen = "local"` (issue #198); never the text |
53
55
  | `context_pressure` | `peer`, `source` (`claude_statusline`, `codex_token_usage`, `acp_usage_update`), `measuredAt` (epoch ms of the reading), `used` (the fraction of the context window in use, 0 to 1), `window` (its size in tokens, or null): a fresh reading of a peer's native context reached `context.gate`. Recorded once per crossing, until a reading below the gate or a new native session rearms it, and not while the peer is paused or offline or the hub is in recovery or stopping |
@@ -57,28 +59,38 @@ marked `private: true`, and PII tasks `pii: true`.
57
59
  | `quota_reset` | `peer`, `window`, `cause` (`resets_at_moved`: the window's `resetsAt` moved forward by more than 15 minutes, since a provider's `resetsAt` wobbles by seconds inside one window; `used_dropped`: `used` fell by 0.5 or more inside one window id), `resetsAt`, `previousResetsAt`, `used`, `previousUsed`, optional `measuredAt`. Derived from two readings, one entry per peer, window and `resetsAt`, also across a restart. |
58
60
  | `conflict` | `peer`, `task` (its task in progress, when it had one), `other` (the other owner's open task), `owner`, `paths` (names that match a PII pattern left out, so it can be empty), `concurrent` (another peer worked during the turn), `turns` (the two turn ids, when two overlapping turns' snapshots both hold the change) |
59
61
 
62
+ The hub also writes `release_authorization`, `role`, `config_edit`, `invocation`, `attach` and `planning` events, and optional fields not listed above; `HubEvent` in `src/hub/events.ts` is the full schema.
63
+
60
64
  Token usage by adapter:
61
65
 
62
- - Kimi (#285 phase 2): consumption is the hub's own count of Kimi's session wire log, never an ACP total. The `{used, size}`
66
+ - Kimi (#285 phase 2, delayed drain #1281): consumption is the hub's own count of Kimi's session wire log, never an ACP total. The `{used, size}`
63
67
  `usage_update` Kimi sends is context occupancy: it is shown as the peer's native context reading (source
64
68
  `acp_usage_update`, phase 1) and writes no `tokens` event. The reader (`src/adapters/kimi-wire-usage.ts`, the only code that knows
65
69
  the format) finds the session directory from `session_index.jsonl` (resolved with `realPath`, kept inside `<kimi home>/sessions`)
66
70
  and reads `agents/*/wire.jsonl` incrementally from saved offsets, sub-agents included, at a turn end, when a `usage_update`
67
- arrives and when the peer goes offline (a turn start only binds the session and fixes the history floor, it reads nothing): no
68
- watcher, no timer. One call reads at most a fixed byte bound across all of the session's files (the rest waits for the next call),
69
- and two agent entries that are one file count once. Each `usage.record` row becomes a `usage` event
71
+ arrives and when the peer goes offline. A turn start only binds the session and fixes the history floor, it reads nothing. Each cue
72
+ also schedules at most three follow-ups, after 250 ms, 1,000 ms and 2,000 ms, coalesced into one pending drain per peer with
73
+ unreferenced production timers. Stop, offline and session replacement cancel them. The offline path keeps its final synchronous
74
+ `collect -> drop`; a row durable only after that read remains uncollected, a documented ceiling. One call reads at most a fixed
75
+ byte bound across all of the session's files (the rest waits for the next call), and two agent entries that are one file count once.
76
+ A successful reader slice commits its offsets only after its rows, `seen` ids, events and window entries are committed, so a failed
77
+ event or cancellation cannot advance past an unrecorded row. Each `usage.record` row becomes a `usage` event
70
78
  (`source: kimi_wire`, `inputTokens` = Kimi's `inputOther`, `outputTokens`, `cacheReadTokens`, `cacheWriteTokens`, `totalTokens`
71
79
  including cache reads, `servedModel`, `measuredAt` = Kimi's row time) and a `tokens` event of the counted share. The id is an
72
80
  opaque hash of session, agent and byte offset; no path, session id or text reaches an event. Only the four integers, the model
73
81
  label and the time are copied from a row. The counted share is `inputOther + inputCacheCreation + output` (`kimiCountedTokens`,
74
82
  one function): cache reads are recorded and shown, never counted against `budget.kimi_tokens_5h`. The rolling 5 h sum of the
75
83
  counted share against that ceiling is the `tokens` window (`hub count, kimi wire log, of kimi_tokens_5h N`, kind `count`: #285 phase 4 names each window's kind in the budget reply, never in an event, and a person's `ahub budget set` value, kind `manual`, outranks it at the gate). Rows already in the
76
- session's log when the hub first sees it (a resumed session) are history and are not counted. An unreadable index, a missing,
84
+ session's log when the hub first sees it (a resumed session) are history and are not counted. A row's native time selects one of
85
+ the 32 most recent captured turn intervals; no unique match, an evicted interval or an ambiguous time gives `unattributed` with no
86
+ task id. Rows collected before a turn closes keep that turn's `turn_end.tokens`. Late rows update `usage`, `tokens`, the roll-up
87
+ and soft-quota window, but never rewrite an earlier `turn_end` or increment a later turn. An unreadable index, a missing,
77
88
  shrunk or replaced file (a replacement is told by a hash of the consumed head and tail kept with each offset, since Linux can reuse the inode), a truncated last line, an unknown row shape or an untested wire `protocol_version` (only 1.5 is known)
78
89
  makes the count unknown: one notice (`kimi usage unknown (<reason>)`), the `tokens` reading is dropped, and no figure is reported
79
90
  until the 5 h window the gap touched has passed (a transient read error or truncated line heals on the next read). Wire format
80
- followed: protocol 1.5 as written by Kimi Code 2.3.0 (the issue read 2.1.1; the hub verifies 2.2.0 and 2.3.0 in `compat.ts`). The
81
- live check against Kimi's own `/usage` (#285 AC11) is not done yet.
91
+ followed: protocol 1.5 as written by Kimi Code 2.3.0 (the issue read 2.1.1; the verified Kimi versions are listed in `compat.ts`). The
92
+ AC11 receipt is [2026-10-25-kimi-usage-ac11.md](verification/2026-10-25-kimi-usage-ac11.md); the current native timing and
93
+ attribution receipt is [2026-11-07-kimi-delayed-usage.md](verification/2026-11-07-kimi-delayed-usage.md).
82
94
  - Codex (app-server `thread/tokenUsage/updated`): recorded as the growth of the thread's running total, so
83
95
  compaction estimates, usage-limit refreshes and the replay to a reattaching connection add nothing. A thread
84
96
  started under the hub counts from zero; a resumed thread's first update is its history and only sets the
@@ -96,6 +108,7 @@ Token usage by adapter:
96
108
  - `ahub report` deduplicates usage records by peer, source and id. Coverage counts distinguish calls with provider usage from calls where usage was absent. Token counters are provider-reported values; the report never derives a price or treats missing spend as zero. Estimated price and measured provider spend remain unknown unless a future source reports them.
97
109
  - Usage telemetry has no prompt, completion, task text, credential, Access header, session id or transcript path.
98
110
  Jcode (#801): each prompt whose result carries a well-formed `usage` writes one `usage` event with `source: jcode_acp`, `inputTokens`, `outputTokens`, `cacheReadTokens` and `cacheWriteTokens` when present, and task attribution; never `totalTokens` (Jcode's adds the cached read to an input that already holds it for OpenAI-style providers), never a `tokens` event, and no session id, text or path. The id names the hub run, the peer and a per-run sequence.
111
+ - agy (#1280): each transcript step row with token counts, read through the hook-gated transcript readback, writes one `usage` event with `source: agy_transcript`, `inputTokens`, `outputTokens`, `cacheReadTokens` and `totalTokens` (their sum), and a `tokens` event of `totalTokens` when it is above zero. The id is an opaque hash of session and step, counted once across restarts. A row the active turn produced takes that turn's attribution; any other row is `unattributed`.
99
112
 
100
113
  ## The usage roll-up (#683)
101
114
 
@@ -113,6 +126,11 @@ deduplicated by peer, source and id; missing counters are `null` in JSON and
113
126
  `unknown` in text, with known-record counts alongside measured subsets. A
114
127
  missing task history has unknown class/outcome and belongs to the unknown class
115
128
  rollup. PII tasks have ids and a `pii: true` flag, never titles. No prices are derived.
129
+ Each task also carries `person`, the person's interactions from `permission`,
130
+ `question`, `completion` and `agent_cli` events (the research record's figures,
131
+ docs/research.md), null for a task that began before the first `hub_start` with
132
+ `personAttribution`; person events no task owns are counted apart by peer and as
133
+ `unattributed`, never folded into a task (#1278).
116
134
 
117
135
  At write time, the first applicable attribution rule wins:
118
136
 
@@ -123,7 +141,7 @@ At write time, the first applicable attribution rule wins:
123
141
  `Bus.onDeliver` observes originals immediately before `peer.deliver` starts the
124
142
  turn. Pending task identity is consumed at turn start and cleared on delivery
125
143
  admission/failure, so later user-started native turns do not inherit it. Usage
126
- and token events apply the rule at write time; `turn_end` keeps the start-time
144
+ and token events apply the rule at write time, except that a delayed Kimi row uses the unique captured turn interval selected by its native timestamp, never the later open task. `turn_end` keeps the start-time
127
145
  attribution. Local usage uses its request-bound route policy task when present.
128
146
  The existing relay has no task-bearing route usage event; this change adds no
129
147
  new usage source. Schema version 1 and the control protocol are unchanged.
package/docs/memory.md CHANGED
@@ -45,7 +45,7 @@ Notes on open tasks stay short-term. Approval settles the task and can promote d
45
45
  a cloud or GitHub token, `password: ...`) is refused.
46
46
  - The hub's own notes on a task: the done summary (finding), the review verdict and an escalation (decision), with the
47
47
  same PII and secret rules. Nothing about a PII task is written.
48
- - Notes still go to claude-mem when it is enabled, as before; the other peers get the note line on their next delivery.
48
+ - Notes go to the in-process amem store only; no note is sent to claude-mem. The other peers get the note line on their next delivery.
49
49
 
50
50
  ## Graph integration and suggestions
51
51
 
@@ -100,7 +100,7 @@ A running hub syncs 5 seconds after start and every `memory.sync_interval_min` m
100
100
  - **Session-start recall**: this project's long-term decisions, contracts and fails (and shared ones) lead the recall block; display-only filtering omits automatic approval notes, while changes-requested notes show their nonempty reasons. Lines preserve their headers and end at word boundaries with a visible marker when capped; each delivery deduplicates memory ids across prefaces and note lines. Stored notes and brief evidence are unchanged. Recent short-term amem curated notes follow; each gets half of `memory.inject_tokens` when both answer.
101
101
  - **`ahub ask`**: entries that match the question and the graph neighbourhood of what they are about are evidence, cited
102
102
  as `[mem:<8 hex>]` for existing native projections or `[mem:<32 hex>]` for full entry references. A question that carries PII skips them. `ahub ask --remember` writes a pending candidate, never curated evidence; a person must review it.
103
- - **`ahub memory`** needs no running hub. The hub CLI identity gate allows screened list/search/show reads in agent shells; graph and unscreened views are a person's, and so are changes: `promote`, `demote`, `forget`, `supersede`, `rebuild`, `machine --label` and the `goal` changes other than `link` stay person-only because the pinned amem (0.12.0) records their actor as the user (#933). The upgrade path is agent-mem 0.13.0 attribution (agent-mem#143) after the pin bump in #958, once the hub passes an agent actor. `ahub goal link` is also the configured conductor's: the hub records the peer as the link's actor. Managed peers use the bounded `hub_memory_search`, `hub_memory_show` and `hub_memory_graph` tools through the daemon, with project scope, `memory_read`, PII-turn refusal and capture exclusion:
103
+ - **`ahub memory`** needs no running hub. The hub CLI identity gate allows screened list/search/show/suggestions reads and `machine` without `--label` in agent shells; graph and unscreened views are a person's, and so are changes: `promote`, `demote`, `forget`, `supersede`, `rebuild`, `machine --label` and the `goal` changes other than `link` stay person-only because the hub passes amem no agent actor, so amem records the user (#933). The upgrade path is agent-mem attribution (agent-mem#143), once the hub passes an agent actor. `ahub goal link` is also the configured conductor's: the hub records the peer as the link's actor. Managed peers use the bounded `hub_memory_search`, `hub_memory_show` and `hub_memory_graph` tools through the daemon, with project scope, `memory_read`, PII-turn refusal and capture exclusion:
104
104
 
105
105
  ```bash
106
106
  ahub memory # this project's entries, newest first, with tier counts
@@ -184,7 +184,7 @@ A `changes_requested` review with unmet items can create one fail candidate. Tas
184
184
 
185
185
  Candidates and rendered/delivered/cited counters live only in agent-mem's machine-local `M/candidates.db` (package retention: 500 candidates/project for 30 days, 10,000 counters/project for 90 days). They are never imported or synced and are not evidence for recall, briefs, ask or graph. A person reviews them with `amem review` and accepts or rejects through that CLI's TTY and policy checks, on shared v1 and, since agent-mem 0.7.0, on a selected generation. Dashboard acceptance is a later step. Accepted results are ordinary v1 notes under the package's acceptance contract; the hub tool has no acceptance authority.
186
186
 
187
- Rendered observations use the final journal payload, including memory lines in prefaces and briefs, with the real delivery id. Delivered observations require the journal's first positive transport acknowledgement (or the pull path's completed read receipt). Failed or uncertain handoffs do not establish delivery; journal-less transports leave it unknown. Citation observations resolve `mem:<id8+>` in a peer message or task completion summary against screened project-visible entries. Citations use explicit `message:<envelope-id>` or `summary:<task>:<history-index>` observation keys when the source delivery is not proven; their rendered/delivered values remain unknown. They do not establish a per-delivery causal ratio. Duplicate observations are idempotent per entry/context/observation, not cumulative usage claims. Unavailable task, turn or session identity and unobserved metrics remain unknown, never zero. No observation is written for a private envelope, PII task or PII turn. These are delivery and citation proxies, not proof that an agent understood or used a note correctly.
187
+ Rendered observations use the final journal payload, including memory lines in prefaces and briefs, with the real delivery id. Delivered observations require the journal's first positive transport acknowledgement (or the pull path's completed read receipt). Failed or uncertain handoffs do not establish delivery; journal-less transports leave it unknown. Citation observations resolve `mem:<id8+>` in a peer message or task completion summary against screened project-visible entries. Citations use explicit `message:<envelope-id>` or `summary:<task>:<history-index>` observation keys when the source delivery is not proven; their rendered/delivered values remain unknown. They do not establish a per-delivery causal ratio. Duplicate observations are idempotent per entry/context/observation, not cumulative usage claims. Citations are also observed from a review verdict's note (`review:<task>:<history-index>`), a `hub_remember` text (`remember:<task>:<text hash>`) and a done's `spec_ack` reasons (`spec_ack:<task>:<history-index>`), under the same PII, review-observer, withheld-text and secret exclusions as a done summary (#1279). The research record's `memory` block counts them per task from the sidecar (docs/research.md): the retry signal counts exposed fail notes the plan touches that approval did not cite, and is a reading aid, not an outcome. Unavailable task, turn or session identity and unobserved metrics remain unknown, never zero. No observation is written for a private envelope, PII task or PII turn. These are delivery and citation proxies, not proof that an agent understood or used a note correctly.
188
188
 
189
189
  ## In-process recall and capture (agent-mem#13 P4)
190
190
 
@@ -207,6 +207,20 @@ Historical benchmark memory-arm labels are retained for old records. Their `clau
207
207
  Write screening examines both the JSON representation and literal structured keys/values before storage escaping. Authoritative tool input/output JSON is decoded once, from the complete original output before excerpt bounding; arbitrary nested JSON-as-text or other encodings are not interpreted. Host locators such as cwd are not capture content and are not persisted: treating the project root as content would falsely classify every event as mentioning every private subtree. Persisted capture fields and complete tool data remain screened, and complete custom deny paths are checked before token fallback. The test-only old-HTTP projection retains its old 4000-character response cap; production capture delegates its bound to CaptureStore after policy.
208
208
 
209
209
 
210
+ ## Agent-authored records (#1320)
211
+
212
+ Managed headless Codex, Kimi, Qwen, Jcode, Pi and local turns receive the package-owned Record instruction once per owned turn. Claude sessions keep their own amem hook path; isolated reviewers and person-owned TUI prompts receive no new instruction. The public `recordsEnabled` accessor from exact-pinned amem 0.23.1 applies the effective machine/repository `records: false` setting to instruction, capture and Record preference. An unavailable policy disables this optional path.
213
+
214
+ The hub imports the instruction and parser from agent-mem. Valid final-answer records become `Record` capture rows with project and peer attribution, not curated notes or approved evidence. Complete text and anchors clear current secret, PII, private-path and deny policy before storage. Private, PII, review-scoped, remote, unbound and incomplete turns are excluded. Owner, turn, session, profile and policy must remain current; unsafe steering excludes the rest of that turn. No model or network call is added.
215
+
216
+ `amem:`-prefixed record lines, including rejected forms, are removed before shared-answer publication, digests and the console envelope log. The existing local Stop capture omits them too. Native console output can still contain the original answer. Routing audience, priority, hop and delivery receipts retain their existing meaning.
217
+
218
+ Task briefs and recall may prefer complete, screened Record lines when an authoritative generated-note ID and raw-anchor registry proves coverage. The registry receives only successful public `Tasks.note` writes; manual remember, withheld/private/PII notes, failed saves, foreign-repository ambiguity and incomplete anchor metadata create no proof. Replacement must fit the old footprint and the existing byte budget. Unrelated notes, fails, contracts and priority guidance remain. The bounded registry is in memory: after restart or eviction, unproved old notes keep their bytes. This is a display preference, never a memory deletion or promotion.
219
+
220
+ Record reads use the package's read-only 32-candidate window. A partial window retains a visible coverage marker; individual proven replacements can use complete known rows, while unproved notes stay unchanged. Before/after byte counters describe actual rendered blocks and projected shared bodies. Capture acceptance includes acknowledged existing or spooled receipts, not a claim of newly inserted rows or permanent retention. Native/provider behavior remains a separate validation leg.
221
+
222
+ All consumers sharing a memory home need coordinated amem upgrades; see [operations](operations.md#agent-authored-records).
223
+
210
224
  ## P4 supplemental read and capture bounds
211
225
 
212
226
  Session-start supplemental recall is one screened short-term curated block from every author, including the receiving peer. No adapter platform whitelist or "agent-hub" pseudo-source remains. The supplemental view uses the published `readPage` keyset API: at most 16 pages of 256 exact-project candidate bodies, plus one lookahead. It never calls the materializing `list()` path. Newest project candidates are considered first; filtering private or non-short rows may leave fewer displayed rows. A remaining page produces `memory view truncated: newest 4096 project candidates considered` in recall, search and task briefs, including when all considered rows are withheld. The control status `memoryRead` reports the last read's `truncated`, `scanned` live candidate bodies and `limit`; it is not a total corpus count.
@@ -271,14 +285,14 @@ An unchanged failure emits one safe log line per episode. A complete bounded pol
271
285
 
272
286
  `ahub memory declined [--json]` is a person-only, read-only inspection. It reports physical outbound row IDs and safe policy categories, never title, body, path nodes or literal private patterns. Reads defer promotions and recheck the profile binding. Forgotten originals still matter: `forget` changes materialized visibility but leaves the source row in append-only history. Do not use it as a promise to clear a sync refusal.
273
287
 
274
- The exact-pinned agent-mem 0.22.1 supplies bounded `inspectSyncPolicy` inspection for shared-v1 and generation profiles. A complete result lists the declined IDs and safe rule categories for the inspected physical outbound history, including originals hidden by a later forget. An unavailable, stale or bounded-out inspection remains explicitly incomplete; it never proves that no declined rows exist. The hub uses the public SDK rather than private helpers, snapshots of full history or its own portable log reader.
288
+ The exact-pinned agent-mem 0.23.1 supplies bounded `inspectSyncPolicy` inspection for shared-v1 and generation profiles. A complete result lists the declined IDs and safe rule categories for the inspected physical outbound history, including originals hidden by a later forget. An unavailable, stale or bounded-out inspection remains explicitly incomplete; it never proves that no declined rows exist. The hub uses the public SDK rather than private helpers, snapshots of full history or its own portable log reader.
275
289
 
276
- The package also owns per-row local placement. The hub adopts only the projection of a successful trusted SDK placement result: `ok` with its verified withheld/exported counts. This is tested through an injected SDK-result seam, not an activated store. Agent-mem 0.22.1 requires a fresh `placementAttestation` for each v3 sync; the default hub does not supply one, so its active-v3 sync remains unsupported until legitimate host-attestation integration is added. Activation alone does not enable this hub's automatic sync, and the hub never fabricates that proof. Count projection does not delete or rewrite notes, change policy or promote a declined row; transport failures remain failures.
290
+ The package also owns per-row local placement. The hub adopts only the projection of a successful trusted SDK placement result: `ok` with its verified withheld/exported counts. Since agent-mem 0.23.0 the daemon passes `placementAttestation` on every `syncMemory` pass, built by the package's own `createPlacementAttestation` for the memory home (`hostPlacementAttestation`, `src/hub/memory-sync-attestation.ts`). A legacy or shared-v1 store ignores it. The hub supplies no writer facts of its own, never fabricates the proof and builds a new one per pass, so no measurement outlives it. A refusal (`PlacementWriterContextError`) is its own closed cause `writer` in status, the dashboard and the log: the category (`running CLI`, `host package`, `setup receipt`, `declared writer`, `active locator`, `home floor`, `writer renewal`, or `unknown` for an unrecognized SDK category), the cause class (`missing`, `changed`, `unavailable`) and the next step (repair the amem install and its host pin, then a person runs `amem migrate --sync-placement --dry-run`). The package's message, paths and versions never enter status or logs. It logs once per episode like every other cause. Count projection does not delete or rewrite notes, change policy or promote a declined row; transport failures remain failures.
277
291
 
278
- Legacy stores without active per-row placement still refuse a sync containing declined rows. The native amem CLI has person-only activation from 0.22.0 ([activation documentation](https://github.com/STAIxBWLB/agent-mem/blob/v0.22.1/README.md#initial-sync-placement-activation)). A person using the 0.22.1 CLI can preview it with every local writer installation declared, including the CLI and hub library installs:
292
+ Legacy stores without active per-row placement still refuse a sync containing declined rows. The native amem CLI has person-only activation from 0.22.0 ([activation documentation](https://github.com/STAIxBWLB/agent-mem/blob/v0.23.1/README.md#initial-sync-placement-activation)). A person using a CLI upgraded with the hub's pin (0.23.1; a 0.22.1 install sharing the home drops Record entries, see [Agent-authored records](#agent-authored-records-1320)) can preview it with every local writer installation declared, including the CLI and hub library installs:
279
293
 
280
294
  ```sh
281
295
  amem migrate --sync-placement --dry-run --writer-root '<cli-install-root>' --writer-root '<host-amem-install-root>' --json
282
296
  ```
283
297
 
284
- Declare any other local writers too, and review the package's layout and version prerequisites before a separately authorized apply. The preview writes nothing; activation does not migrate layouts, change privacy policy or automatically raise a format floor. This hub neither invokes activation nor supplies a local fallback or fabricated attestation. Complete bounded diagnostics address #1173 AC4; AC5 has result projection only. #1173 remains open for legitimate fresh host-attestation integration. Source adoption and isolated fixtures do not establish activation, deployed behavior or a successful sync of the person's memory home.
298
+ Declare any other local writers too, and review the package's layout and version prerequisites before a separately authorized apply. The preview writes nothing; activation does not migrate layouts, change privacy policy or automatically raise a format floor. This hub neither invokes activation nor supplies a local fallback or fabricated attestation. Complete bounded diagnostics address #1173 AC4; AC5 has result projection and the host attestation. Whether an activated store syncs on a person's machine is not established by the isolated fixtures. Source adoption and isolated fixtures do not establish activation, deployed behavior or a successful sync of the person's memory home.