@staix/agent-hub 0.12.44 → 0.13.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 (197) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/README.md +83 -116
  3. package/THIRD_PARTY_NOTICES.md +29 -0
  4. package/docs/adding-an-ai-tool.md +102 -14
  5. package/docs/agent-notes/README.md +15 -0
  6. package/docs/agent-notes/adapters.md +63 -46
  7. package/docs/agent-notes/budget.md +7 -2
  8. package/docs/agent-notes/bus.md +6 -4
  9. package/docs/agent-notes/daemon.md +15 -8
  10. package/docs/agent-notes/local-worker.md +6 -4
  11. package/docs/agent-notes/tasks.md +18 -5
  12. package/docs/agent-notes/tests.md +11 -9
  13. package/docs/dogfood.md +92 -0
  14. package/docs/events.md +14 -1
  15. package/docs/operations.md +349 -26
  16. package/docs/profiles.md +2 -2
  17. package/docs/quickstart.md +12 -2
  18. package/docs/sdlc.md +61 -13
  19. package/docs/security.md +24 -12
  20. package/docs/smoke.md +9 -4
  21. package/docs/specs/2026-09-19-agent-hub-design.md +873 -13
  22. package/docs/verification/2026-10-19-reviewer-isolation.md +2 -0
  23. package/docs/verification/2026-10-21-469-r1-dashboard-tokens.md +43 -0
  24. package/docs/verification/2026-10-21-469-r2-dashboard-shell.md +54 -0
  25. package/docs/verification/2026-10-21-469-r3-dashboard-board.md +51 -0
  26. package/docs/verification/2026-10-21-469-r4-dashboard-views.md +77 -0
  27. package/docs/verification/2026-10-21-469-r6-dashboard-motion-states.md +82 -0
  28. package/docs/verification/2026-10-22-0.12.45.md +60 -0
  29. package/docs/verification/2026-10-22-code-facts.md +78 -0
  30. package/docs/verification/2026-10-22-codex-reviewer-isolation.md +47 -0
  31. package/docs/verification/2026-10-22-kimi-qwen-compat.md +79 -0
  32. package/docs/verification/2026-10-23-0.13.0.md +89 -0
  33. package/docs/verification/assets/469-r1-board-1440-dark.png +0 -0
  34. package/docs/verification/assets/469-r1-board-1440-light.png +0 -0
  35. package/docs/verification/assets/469-r1-board-390-dark.png +0 -0
  36. package/docs/verification/assets/469-r1-board-390-light.png +0 -0
  37. package/docs/verification/assets/469-r2-agents-1440-dark.png +0 -0
  38. package/docs/verification/assets/469-r2-agents-768-dark.png +0 -0
  39. package/docs/verification/assets/469-r2-board-1024-light.png +0 -0
  40. package/docs/verification/assets/469-r2-board-1440-dark.png +0 -0
  41. package/docs/verification/assets/469-r2-board-1440-light.png +0 -0
  42. package/docs/verification/assets/469-r2-board-390-dark.png +0 -0
  43. package/docs/verification/assets/469-r2-board-390-light.png +0 -0
  44. package/docs/verification/assets/469-r2-board-768-light.png +0 -0
  45. package/docs/verification/assets/469-r3-board-1440-dark.png +0 -0
  46. package/docs/verification/assets/469-r3-board-1440-light.png +0 -0
  47. package/docs/verification/assets/469-r3-board-390-light.png +0 -0
  48. package/docs/verification/assets/469-r3-detail-1440-dark.png +0 -0
  49. package/docs/verification/assets/469-r3-detail-1440-light.png +0 -0
  50. package/docs/verification/assets/469-r3-detail-390-dark.png +0 -0
  51. package/docs/verification/assets/469-r3-plan-1440-light.png +0 -0
  52. package/docs/verification/assets/469-r3-plan-390-light.png +0 -0
  53. package/docs/verification/assets/469-r4-agents-1440-dark.png +0 -0
  54. package/docs/verification/assets/469-r4-agents-1440-light.png +0 -0
  55. package/docs/verification/assets/469-r4-agents-390-dark.png +0 -0
  56. package/docs/verification/assets/469-r4-memory-1440-dark.png +0 -0
  57. package/docs/verification/assets/469-r4-memory-1440-light.png +0 -0
  58. package/docs/verification/assets/469-r4-memory-390-dark.png +0 -0
  59. package/docs/verification/assets/469-r4-message-1440-light.png +0 -0
  60. package/docs/verification/assets/469-r4-office-1440-dark.png +0 -0
  61. package/docs/verification/assets/469-r4-office-1440-light.png +0 -0
  62. package/docs/verification/assets/469-r4-settings-1440-dark.png +0 -0
  63. package/docs/verification/assets/469-r4-settings-1440-light.png +0 -0
  64. package/docs/verification/assets/469-r4-stream-1440-light.png +0 -0
  65. package/docs/verification/assets/469-r4-stream-390-light.png +0 -0
  66. package/docs/verification/assets/469-r6-agents-empty-390-dark.png +0 -0
  67. package/docs/verification/assets/469-r6-agents-empty-390-light.png +0 -0
  68. package/docs/verification/assets/469-r6-board-1440-light.png +0 -0
  69. package/docs/verification/assets/469-r6-board-390-dark.png +0 -0
  70. package/docs/verification/assets/469-r6-board-empty-1440-dark.png +0 -0
  71. package/docs/verification/assets/469-r6-board-empty-1440-light.png +0 -0
  72. package/docs/verification/assets/469-r6-disconnected-1440-dark.png +0 -0
  73. package/docs/verification/assets/469-r6-disconnected-1440-light.png +0 -0
  74. package/docs/verification/assets/469-r6-disconnected-390-dark.png +0 -0
  75. package/docs/verification/assets/469-r6-skeleton-1440-light.png +0 -0
  76. package/docs/verification/assets/469-r6-skeleton-390-dark.png +0 -0
  77. package/docs/verification/assets/469-r6-toasts-1440-dark.png +0 -0
  78. package/docs/verification/assets/469-r6-toasts-1440-light.png +0 -0
  79. package/docs/verification/assets/469-r6-toasts-390-light.png +0 -0
  80. package/docs/verification/dogfood/2026-10-22.md +3109 -0
  81. package/docs/verified.json +19 -16
  82. package/package.json +5 -1
  83. package/plugins/agent-hub/.claude-plugin/plugin.json +1 -1
  84. package/plugins/agent-hub/server.js +10120 -9623
  85. package/src/adapters/adapter-api.ts +2 -0
  86. package/src/adapters/agy/definition.ts +3 -1
  87. package/src/adapters/agy/entry.ts +5 -4
  88. package/src/adapters/claude-channel.ts +32 -12
  89. package/src/adapters/codex-appserver.ts +19 -2
  90. package/src/adapters/codex-review-isolation.ts +12 -5
  91. package/src/adapters/compat.ts +140 -0
  92. package/src/adapters/conformance/acp.ts +114 -0
  93. package/src/adapters/conformance/codex.ts +191 -0
  94. package/src/adapters/conformance/enrollment.ts +43 -0
  95. package/src/adapters/conformance/factories.ts +17 -0
  96. package/src/adapters/conformance/fake-paths.ts +12 -0
  97. package/src/adapters/conformance/fakes/acp-server.ts +267 -0
  98. package/src/adapters/conformance/fakes/acp-watchdog-agent.ts +10 -0
  99. package/src/adapters/conformance/fakes/app-server.ts +119 -0
  100. package/src/adapters/conformance/fakes/codex-bin.ts +15 -0
  101. package/src/adapters/conformance/fakes/jcode-agent.ts +91 -0
  102. package/src/adapters/conformance/fakes/model-server.ts +39 -0
  103. package/src/adapters/conformance/fakes/pi-rpc.ts +32 -0
  104. package/src/adapters/conformance/index.ts +11 -0
  105. package/src/adapters/conformance/kit.ts +50 -0
  106. package/src/adapters/conformance/local-pi.ts +100 -0
  107. package/src/adapters/conformance/owned-acp.ts +44 -0
  108. package/src/adapters/definitions/builtin-metadata.ts +25 -7
  109. package/src/adapters/definitions/native-cli-doctor.ts +12 -5
  110. package/src/adapters/definitions/native-cli-entry-jcode.ts +9 -6
  111. package/src/adapters/definitions/native-cli-entry-kimi.ts +7 -1
  112. package/src/adapters/definitions/native-cli-entry.ts +7 -19
  113. package/src/adapters/definitions/native-cli-jcode-mcp.ts +9 -2
  114. package/src/adapters/definitions/native-cli-preview-common.ts +2 -0
  115. package/src/adapters/definitions/native-cli-preview-jcode.ts +8 -2
  116. package/src/adapters/definitions/native-cli-preview-qwen.ts +2 -1
  117. package/src/adapters/definitions/native-cli-preview.ts +2 -11
  118. package/src/adapters/definitions/qwen-native.ts +7 -3
  119. package/src/adapters/definitions/qwen.ts +5 -1
  120. package/src/adapters/external-metadata.ts +48 -0
  121. package/src/adapters/external-module-scan.ts +126 -0
  122. package/src/adapters/external-modules.ts +240 -0
  123. package/src/adapters/jcode.ts +72 -31
  124. package/src/adapters/kimi-review.ts +6 -3
  125. package/src/adapters/pi.ts +2 -0
  126. package/src/adapters/public.ts +7 -0
  127. package/src/adapters/registry-types.ts +13 -1
  128. package/src/adapters/registry.ts +52 -15
  129. package/src/cli/agents.ts +40 -0
  130. package/src/cli/console-review.ts +54 -0
  131. package/src/cli/console-state.ts +124 -29
  132. package/src/cli/console-symbols.ts +74 -0
  133. package/src/cli/console-usage.ts +89 -0
  134. package/src/cli/console.ts +26 -1
  135. package/src/cli/help.ts +36 -21
  136. package/src/cli/identity.ts +30 -7
  137. package/src/cli/init.ts +109 -11
  138. package/src/cli/main.ts +145 -16
  139. package/src/cli/output.ts +44 -1
  140. package/src/cli/preview.ts +1 -1
  141. package/src/cli/sdlc-release-guard.ts +82 -0
  142. package/src/cli/upgrade-labels.ts +1 -1
  143. package/src/cli/upgrade-presentation.ts +1 -1
  144. package/src/cli/upgrade-restore-state.ts +3 -2
  145. package/src/cli/upgrade-runtime.ts +4 -1
  146. package/src/hub/action-class.ts +362 -0
  147. package/src/hub/action-policy.ts +106 -0
  148. package/src/hub/board.ts +72 -11
  149. package/src/hub/budget.ts +71 -2
  150. package/src/hub/bus.ts +43 -3
  151. package/src/hub/checks.ts +80 -31
  152. package/src/hub/code-facts.ts +223 -0
  153. package/src/hub/config-apply.ts +28 -11
  154. package/src/hub/config-reload.ts +8 -5
  155. package/src/hub/config-trust.ts +7 -4
  156. package/src/hub/control-client.ts +4 -1
  157. package/src/hub/daemon.ts +332 -61
  158. package/src/hub/dogfood-read.ts +199 -0
  159. package/src/hub/dogfood.ts +163 -0
  160. package/src/hub/envelope.ts +1 -1
  161. package/src/hub/events.ts +11 -2
  162. package/src/hub/facts.ts +76 -13
  163. package/src/hub/hub-tools.ts +45 -7
  164. package/src/hub/inbox-polling.ts +25 -0
  165. package/src/hub/instance-config.ts +17 -5
  166. package/src/hub/instance-execution.ts +20 -8
  167. package/src/hub/instances.ts +75 -2
  168. package/src/hub/peers.ts +9 -0
  169. package/src/hub/plan-conformance.ts +83 -0
  170. package/src/hub/profiles.ts +7 -2
  171. package/src/hub/release-worktree.ts +56 -0
  172. package/src/hub/review-brief.ts +36 -0
  173. package/src/hub/review-findings.ts +104 -0
  174. package/src/hub/roster.ts +31 -5
  175. package/src/hub/sdlc-queue.ts +48 -11
  176. package/src/hub/sdlc-release-authorization.ts +173 -0
  177. package/src/hub/sdlc-release.ts +16 -1
  178. package/src/hub/sdlc.ts +71 -18
  179. package/src/hub/settings.ts +10 -3
  180. package/src/hub/snapshots.ts +101 -14
  181. package/src/hub/symbol-normalizer.ts +26 -0
  182. package/src/hub/task-code-symbols.ts +90 -0
  183. package/src/hub/task-sweep.ts +3 -2
  184. package/src/hub/tasks.ts +556 -88
  185. package/src/hub/test-integrity.ts +162 -0
  186. package/src/hub/ui.ts +2 -2
  187. package/src/hub/usage-rollup.ts +361 -0
  188. package/src/local/sandbox.ts +5 -3
  189. package/src/ui/index.html +560 -78
  190. package/src/ui/office-model.ts +3 -1
  191. package/src/ui/peer-palette.ts +44 -0
  192. package/templates/AGENTS.block.md +1 -1
  193. package/templates/profiles/dev.json +6 -1
  194. package/templates/profiles/general.json +6 -1
  195. package/templates/profiles/research.json +6 -1
  196. package/templates/profiles/writing.json +6 -1
  197. package/templates/release-guard.block.md +6 -0
package/CHANGELOG.md CHANGED
@@ -2,6 +2,46 @@
2
2
 
3
3
  Issue and pull request numbers in the entries for 0.7.7 and earlier refer to the previous repository, archived on 2026-09-30 when this repository's history was rewritten; the one exception is the open smoke-check issue, formerly #12, which moved here as #1. Numbers in newer entries refer to this repository.
4
4
 
5
+ ## Unreleased
6
+
7
+ ## 0.13.0
8
+
9
+ - Add the #636 action-policy foundation: a pure classifier, machine-local always-ask configuration, session-bound approval budgets and explicit per-peer enforcement status. Adapter pre-tool gates remain pending; status reports that limit instead of claiming protection.
10
+ - Person-only release approval binds the candidate commit, version and fresh docs; an opt-in init-written Git tag pre-push guard refuses missing or mismatched approval and preserves existing hooks (#481 S6).
11
+ - Bug-labelled tasks gain source-labelled red-first receipts and PR test-integrity readbacks. Enforce blocks review and approval when proof is missing/unknown or a pre-existing test is modified/deleted; advise shows the findings. Status and merge queues retain private metadata screening (#481 S4).
12
+ - Version policy for native agent CLIs (#691): one verified/in-line/trusted/refused decision in `src/adapters/compat.ts` for the Codex and Kimi reviewers, Jcode, agy and Qwen; `ahub agents [--json]` shows it and the person-only `ahub agents trust <id> <version> [--revoke]` accepts an untested version on this machine; refusals name the version and the trust command; a weekly workflow reports upstream drift. Receipts add Codex reviewer 0.163.0 (#697), Kimi reviewer 2.3.0 and Qwen Code 0.26.0 (#714).
13
+ - Extra Jcode instances with their own home, socket and state; hub tools are bound to an owned launch (#685).
14
+ - Usage: ledger events for Codex usage breakdown, budget pause/resume and derived quota resets (#683 U1); an incremental roll-up in `hub.db`, the `usage` control op and `ahub usage [limits|total]` (U2); the console Usage panel (tab `7`) with windows, pauses, last resets and tokens per peer and per selected task (U3).
15
+ - Code structure (#682, #684): optional bounded code facts from ripwire 0.6.7 in the review brief (observed symbols, unknown change kinds, deleted definitions not covered); head-bound task symbol observations kept apart from the task row and dropped on a head, repository or privacy change; the console task detail shows changed symbols (matching, unplanned, untouched) and screened overlaps, and a completed-change notice says `same file, different symbols` only on complete disjoint evidence; plan symbols match by normalized name across overlap notices, grooming and the review brief (#682 phase 1b).
16
+ - SDLC: the hub links lifecycle issue and PR identity from what it can verify (#694); test integrity for bug fixes with red-first receipts and modified pre-existing test detection (#481 S4); `ahub report --dogfood`, a bounded weekly scorecard of real use (#687), with CI flow measured per recorded PR head (#704); a profile-selected review checklist and hub tool descriptions (#507).
17
+ - Console review guidance (#711): `r` on a task in review asks `a approve` or `c request changes`, shows a guide line, refuses an empty changes note and shows the result; an agent shell refused a person-only action is told why; the user-reviewed done notice names the console path.
18
+ - Pull-only peers catch up (#713): `hub_inbox` drains up to 64 KiB oldest first and says how many are waiting; completed-change notices are one per recipient per done, a newer one supersedes the queued one, and none go to unaccepted work; a queued delivery can be discarded while its peer is busy; refusals name their cause; the person's `ahub queue discard --peer <id> --reason <text> [--yes]` and the console Queue `D` clear a backlog. Empty pull-only polling is detected (#681).
19
+ - Fixes: a check's exit and pipes are read through Bun.spawn so an early exit is not lost (#558); snapshot attribution survives own-commit rebases and long reflogs (#612); readiness respects the reserved owner's WIP cap (#655); host timeout kill markers are preserved in the sandbox (#700); the Codex reviewer disables legacy notify (#697).
20
+ - Retired as announced (#481): `sdlc.workflow` (gsd-lite) no longer loads, and the `phase` receipt name is refused; record a `criteria` checklist with `hub_sdlc_record` instead. `local.bash_network: "direct"` still works and still warns; its removal moves to a later release.
21
+ - Releases: a release with any feature bumps the minor version; a fix-only release bumps the patch.
22
+
23
+ ## 0.12.45
24
+
25
+ The dashboard is redesigned (#469), a machine-local, content-pinned adapter module can add an ACP agent (#451 A4), the peer lists and the CLI surface come from the adapter definitions (#625), and reviews gain structured findings with an Important gate (#481 S3) and plan conformance with a person-only departure acceptance (#481 S2).
26
+
27
+ - Load external adapter modules: `adapter_modules: [{ path, sha256 }]` in an untracked `.agenthub/config.local.json` names a self-contained ESM bundle that the daemon imports at startup from its hash-checked bytes, with `@staix/agent-hub/adapter` bound to the running hub. A module is refused on its own (bad pin, unsupported import, an import that does not settle within 2 s) while the builtins start; the CLI only sees bounded metadata. `@staix/agent-hub/adapter` and `@staix/agent-hub/conformance` are published for module authors. A pin authorizes code to run with daemon privileges; it is not a sandbox (#451 A4, #648, #653).
28
+ - The peer lists (`KNOWN_PEERS`, `OPTIONAL_PEERS`, `START_MODE_PEERS`, role, help and planner order) and each builtin's `ahub <kind>` entry, preview and help usage come from the adapter definitions; the orders shown are unchanged (#625, #656). The daemon reads optional peer capability members for session generation and permission mode instead of checking peer classes (#625, #667).
29
+ - `hub_review` and `ahub review --findings` take structured findings (id, pass, severity, disposition). In enforce, an open Important finding blocks approval and carries across later heads until a reviewer marks it fixed or false_positive or the person accepts it with a rationale; a supplied head must be the task's current head, and a finding id seen on a second task proposes one backlog card for an AGENTS.md or area-note amendment. `sdlc.max_nits` sets the nit cap (default 5) (#481 S3, #652, #657).
30
+ - Plan conformance: a task plan may carry `proof` and `risks`, and review, status and the merge queue compare the PR's changed files with the plan's literal file or directory entries (renames and copies read as unknown). In enforce, a departure needs an amended plan or the person's `ahub sdlc accept-departure <task> <head> <reason...>`, which binds the repository, PR, head, file inventory, plan and repository scope and expires on restart (#481 S2, #665).
31
+ - Review readiness keeps a lost reuse proof apart from quiet review drift, a delayed check that is refused tells its owner, and review-thread authors other than the person count as pending bot comments (#230, #641, #643, #644).
32
+ - A large file rewritten with the same size within one filesystem tick on Linux is now seen as changed: facts compare a recently written file by its bytes, within a bounded budget (#428, #646).
33
+ - When `ahub kimi --mode tui` fails because the running hub's retained `kimi_cmd` has no TUI form, the error says the command is the running hub's and that the file's value waits for `ahub settings reload` (#654, #658).
34
+ - The daemon's snapshot Git budget reads an injectable clock, a host-only `snapshotClock` option, so a test can hold it fixed and a slow CI disk cannot spend the 250 ms before a turn's end evidence is read (an exhausted budget records an unknown tree, and an unknown tree restarts the empty-turn stall count: the intermittent #661 failure of the #498 stall test). Nothing in the shipped daemon sets it, no configuration key or tool reaches it, and the share stays 250 ms.
35
+ - The dashboard board gets simpler cards (title, owner avatar, one state and priority badge, release), a task detail that opens as a right-hand sheet with its lines grouped into Status, People, Dates and Links, and a Plan sheet that holds the five board forms (plan, split, releases, delivery evidence, propose) with the fields and actions they had (#469 R3).
36
+ - The dashboard gets an app shell: from 1024px a sticky top bar and a left sidebar, below it a row of tabs that scrolls inside itself so the page never scrolls sideways; the connection status shows a coloured dot; keys `1`-`7` switch views, `?` lists the keys and `Esc` closes a sheet, ignored while typing; navigation icons come from an inline sprite of nine Tabler icons (MIT notice in `THIRD_PARTY_NOTICES.md`). View names, order, the cookie and ids are unchanged (#469 R2).
37
+ - The dashboard's style block is rewritten around one token block (colour, a 4px spacing scale, a type scale, a 6/10/full radius rule and two shadows), the dead rules are gone, the indigo accent replaces green for primary actions, focus and selection, and every peer colour has a light and a dark variant. The layout, views and behaviour are unchanged, and the contrast test now also covers the accent, dots, disabled controls and the peer palette in both themes (#469 R1).
38
+ - The dashboard's Agents rows become a summary line plus one folded details block, the Stream gets aligned event rows with its filters above the list, Memory rows and detail use the colour tokens, Settings groups are sections with a "restart pending" badge and Message uses the shared form styles. The star, arrow, checking and Office condition glyphs become Tabler icons and drawn shapes next to their words (three more icons, twelve in all), the Office scene's colours are checked through the same tokens in the contrast test, and a test now fails if a listed glyph comes back (#469 R4, R5).
39
+ - The dashboard keeps task cards, peer rows and memory rows per id across a poll, so hover, an open fold and a focused card survive an update that changed something else. It gets quiet motion on `transform` and `opacity` only (press, view fade, card arrival, toast, sheets) that is off under reduced motion, first-load skeletons for the board and the peers, empty views that name their command, a disconnected state with the time of the last snapshot, and notices as an `aria-live` toast stack where errors stay until dismissed and a success fades after 4 s (#469 R6).
40
+ - A board card's one badge now also says when the task is overdue or its check is running ("in progress P2, overdue, check running"), in its text and in the card's accessible name, instead of a second and third badge. An overdue card turns the badge warn unless the state is already an error, and the task detail keeps its own Overdue and Check running lines (#293).
41
+ - The dashboard keeps its first-load skeletons for the board and the peers after a project switch until that project's first snapshot renders (a slow or failed first snapshot no longer reads as "No project selected", which is now only for no running project), and a toast that is dismissed, expires or is pushed out no longer takes keyboard focus from another toast's Dismiss button (#469 R6 follow-ups).
42
+ - Four #450 I2 follow-ups: the interactive recovery screen and `--verbose` receipt now show a restored extra's recorded outcome after its declaration was revoked instead of throwing "invalid restore receipt"; a roster key left by an undeclared instance (`codex-2`) loads as inert and `ahub roster remove codex-2` deletes it, while any other unknown key is still an unsupported peer (only a kind that can declare an instance counts: `roster.jcode-worker` stays a typo). A key that lives only in the shared `.agenthub/config.json` is refused with "edit .agenthub/config.json" instead of reporting a removal that changes nothing, and the removal says "stale roster key removed" instead of a roster state; the `peer_instances` refusal text and the spec say it applies only while a declared instance may be live, and ask to end the extra sessions before removing a declaration; and the git calls behind an extra-instance start share one 5 s allowance instead of 5 s each (#225).
43
+ - A Claude channel tool result no longer tells a session to call `hub_inbox` while a delivery hold refuses its pulls (the counts and held rows stay), and a `hub_inbox` result states the queued count once (#221). Documented limit: mid-turn steer of a push-capable Claude session was proven only on Claude Code 2.1.302.
44
+
5
45
  ## 0.12.44
6
46
 
7
47
  A standard ACP agent can join a project from config alone (#451 A3), adapter definitions become the single dispatch point (#451 A2b), agy stops reading Claude's state files (#624), and owner turns that write nothing are flagged (#498).
package/README.md CHANGED
@@ -1,139 +1,106 @@
1
1
  # agent-hub
2
2
 
3
- A hub on one developer's machine where coding agents work as a team: Claude Code,
4
- Codex, Kimi Code, Pi and a hub-owned local worker (Qwen Code, Jcode and Antigravity
5
- optional) share a message bus and a task board per project and one memory on the
6
- machine, each attached through its own native interface.
3
+ A hub on your own machine where coding agents work together as one team. Claude
4
+ Code, Codex, Kimi Code, Pi and a hub-owned local worker (plus Qwen Code, Jcode and
5
+ Antigravity if you want them) share a message bus, a task board and a memory, each
6
+ connected through its own native interface.
7
7
 
8
- Status: 0.12.44, control protocol 16. Bun + TypeScript, one loopback daemon per
8
+ Status: 0.13.0, control protocol 16. Bun + TypeScript, one loopback daemon per
9
9
  project. Site: [agent-hub.staix.net](https://agent-hub.staix.net).
10
10
 
11
- ## What it does today
12
-
13
- - **Peers, not a pipeline.** Every agent can message the others, and the hub
14
- delivers to each through its native surface (Claude channel plugin, Codex
15
- app-server, ACP, Pi RPC or TUI). Messages are batched into digests, priorities
16
- decide what interrupts a turn, and delivery is durable across restarts.
17
- - **A shared task board.** Tasks are proposed, accepted, done and reviewed through
18
- hub tools. `routing.toml` assigns owners by task class, roles split planning,
19
- implementation and review, and a designated planner can be changed live.
20
- Cause-deduplicated stalls and unread pull-only offers need attention; cancellation
21
- closes work without approving it or releasing its dependents. Owners of
22
- overlapping work in the same repository are told what changed.
23
- - **Shared memory.** Decisions, contracts, fails and findings go to the hub's own
24
- store through the exact-pinned first-party `@staix/agent-mem` library (short-
25
- and long-term tiers, a typed graph, git sync between machines),
26
- next to optional claude-mem capture. Entries belong to their project unless
27
- saved as shared, which makes them readable from every project on the machine.
28
- Agents get memory as a recall preface, as briefs on a task, and through bounded
29
- `hub_memory_search`, `hub_memory_show` and `hub_memory_graph` tools. Agents
30
- can propose corrections; candidates stay outside evidence until a person acts.
31
- - **Local and remote models.** Pi and the local worker run on DGX or local MLX
32
- through an authenticated relay; in-process hub routes select models by task
33
- through a self-hosted OmniRoute gateway. Tasks flagged as PII stay on the on-prem
34
- worker.
35
- - **Guard rails.** The local worker and Pi run in a sandbox, and by default their
36
- writes and shell commands wait for the person's approval; a permission mode
37
- the person picks (`ask-when-needed`, `never-ask`) skips some or all prompts.
38
- Budgets pause a peer before it runs out of quota, and recovery never replays
39
- an effect whose outcome is unknown.
40
- - **Operations.** A terminal console and a local dashboard, one hub per
41
- repository or worktree with a machine-wide view, and `ahub upgrade` that carries
42
- running sessions across versions. Settings reload without a restart where their
43
- apply class allows; guarded values wait for a person's confirmed
44
- `ahub settings reload` in a terminal. The console supports revision-checked task
45
- assignment/unassignment, delivery-queue resolution, per-peer planner WIP limits
46
- and backlog management from the Tasks tab. Peers with independent
47
- tool turns can request one uncertain redelivery; the delivery-only local worker
48
- and headless ACP peers leave held deliveries for the person to resolve.
11
+ ## Quick start
49
12
 
50
- ## Where it is going
51
-
52
- - **Curated memory** ([#412](https://github.com/STAIxBWLB/agent-hub/issues/412)).
53
- The memory core now lives in [agent-mem](https://github.com/STAIxBWLB/agent-mem)
54
- (`@staix/agent-mem`, with the `amem` CLI), which agent-hub uses as its one
55
- exact-pinned first-party dependency. Next, memory becomes curated rather than
56
- captured: compression, removal, correction
57
- and failure-driven management, each shipped only after its contract and a
58
- measurement.
59
- - **Every peer able to do its share** ([#418](https://github.com/STAIxBWLB/agent-hub/issues/418)).
60
- Bounded task-spec reads and opt-in isolated checks are implemented. Installed
61
- managed-Pi verification (AC8) remains open; source and CI results do not certify
62
- that live runtime.
63
- - **Measured, not assumed.** Add-ons and memory are kept or dropped by controlled
64
- comparisons ([#248](https://github.com/STAIxBWLB/agent-hub/issues/248),
65
- [#258](https://github.com/STAIxBWLB/agent-hub/issues/258)).
13
+ You need [Bun](https://bun.sh) 1.4.2 or later on PATH.
66
14
 
67
- ## Install
15
+ ```bash
16
+ bun add -g @staix/agent-hub && ahub setup
17
+ cd <your project> && ahub init && ahub up # daemon plus the operator console
18
+ ```
68
19
 
69
- Requires [Bun](https://bun.sh) 1.4.2 or later on PATH.
20
+ Then start the agents you use, one terminal each, and talk to them:
70
21
 
71
22
  ```bash
72
- bun add -g @staix/agent-hub && ahub setup
73
- cd <your project> && ahub init && ahub up
23
+ ahub claude # Claude Code with the hub channel
24
+ ahub codex # Codex TUI, attached through the hub
25
+ ahub say "Each of you: reply with your name."
26
+ ahub ui # the web dashboard
74
27
  ```
75
28
 
76
- `ahub init --dry-run --json` shows what init would write first. While hubs run,
77
- `ahub upgrade` moves them to the latest release.
78
-
79
- After upgrading from 0.12.30 or earlier, run `ahub jcode --mode headless` once in each
80
- project that uses Jcode to refresh its owned MCP entry before conductor or dashboard
81
- starts of Jcode. The entry's format is unchanged in 0.12.37; a daemon start that still
82
- reports the entry missing or stale is fixed by the same command, which since 0.12.36
83
- writes the running hub's own plugin bundle (#502). Since 0.12.37 the hub accepts jcode
84
- 0.98.0 or later, below 1.0.0, and no longer 0.94.0 (#529).
85
- Since 0.12.39 `ahub jcode` opens Jcode's native TUI on the hub-owned ACP session by
86
- default (#464); `--mode headless` or `ahub settings set peers.jcode.start_mode headless`
87
- keeps headless startup. On 0.12.39 the TUI launcher stopped after the first hub turn;
88
- 0.12.40 opens it again (#564). On 0.12.40 `ahub codex` in a recorded Orca terminal
89
- failed with `invalid remote address`; 0.12.41 starts it again (#586). Since 0.12.42
90
- `ahub agy` accepts the Antigravity CLI 1.4.x line (1.4.2 verified; other patches warn),
91
- because agy updates itself and 0.12.41 refused 1.4.3 (#589). Since 0.12.43 agy's native reads are recorded as peer facts on 1.4.2 and 1.4.3 (#555); 1.4.3 stays unverified, and in its TUI the hub tools appear from the second turn (#267, #607). Since 0.12.44 a headless Kimi or Qwen start made by the hub also opens `ahub watch <peer>` through the terminal provider (#286), an owner turn streak with no recorded writes raises a planner notice (`task_sweep.no_writes_turns`, default 2, 0 disables; #498), a declared agy extra instance is refused at config load (#625), and a standard ACP agent can join a project as a config-only adapter declared in untracked `.agenthub/config.local.json`: headless, off roster by default and pinned to its native identity (#451).
92
- Cancellation needs a daemon advertising `task_cancel`; controlled downgrades
93
- refuse while cancelled rows exist. Live-test delegated CLI commands need a daemon
94
- advertising `cli_audit_delegated` and refuse with an upgrade remedy otherwise
95
- (#410). For local/Pi implementation, opt in to an available
96
- `checks.runner = "container"`; issue-backed owners also need authenticated
97
- spec access. PII work and designated reviewers retain their separate exemptions.
98
- See [release verification](docs/verification/2026-10-21-0.12.44.md) for the live legs
99
- still open, including #418 AC8, #438 AC7, the native console settings leg (#439 AC5),
100
- real upgrades with reattach (#463) and with a managed terminal and cancelled tasks
101
- (#478), a live headless Claude review (#223), a Claude session over 32 MiB (#517), a
102
- live fresh Codex review (#519), a live split of a real memory home (#536), the live
103
- agy TUI/account leg (#485, hub task #251), Kimi's interactive-TUI coexistence and
104
- usage checks (#533), Jcode's TUI with a personal account, a real provider and hub-tool
105
- calls (#464), a live Jcode tool call held past the inactivity watchdog (#542), a live
106
- steer of a busy Jcode turn (#572) and a real upgrade that exercises the terminal owner
107
- record (#482).
108
-
109
- Before migrating a memory home with `amem`, upgrade every hub using that home to
110
- 0.12.30 or later, check `ahub memory profile-check`, then quiesce and close all memory
111
- consumers. Shared v1 remains the default; installing this release does not migrate
112
- data. The curated shard migration (`amem migrate --shards`, agent-mem 0.4.0) needs
113
- every hub using that home to run 0.12.37 or later, which opens memory through shards
114
- (#534). An older hub (0.12.36 or earlier, agent-mem 0.3.1) does not detect the
115
- split: it keeps reading and writing the old layout, and its writes reach the shards
116
- only through `amem migrate --shards --resume`. Upgrade or stop every such hub before
117
- splitting. `ahub memory profile-check` is split-aware (#536). See [memory profiles and rollout](docs/memory.md#selected-memory-profile).
29
+ `ahub init --dry-run --json` shows what init would write. The
30
+ [Quickstart](docs/quickstart.md) walks through a first session and a working day.
31
+
32
+ ## What you get
33
+
34
+ - **Peers, not a pipeline.** Any agent can message the others. Messages are batched
35
+ into digests, priorities decide what interrupts a turn, and delivery survives
36
+ restarts.
37
+ - **A shared task board.** Work is proposed, accepted, done and reviewed through hub
38
+ tools. Roles split planning, implementation and review, `routing.toml` picks
39
+ owners by task class, and owners of overlapping work are told what changed.
40
+ - **Shared memory.** Decisions, contracts, fails and findings are kept through the
41
+ first-party [`@staix/agent-mem`](https://github.com/STAIxBWLB/agent-mem) library
42
+ (short- and long-term tiers, a typed graph, git sync between machines). Agents get
43
+ it as a recall preface, as briefs on a task, and through bounded search tools.
44
+ - **Local and on-prem models.** Pi and the local worker can run on DGX or local MLX
45
+ through an authenticated relay. Tasks marked as PII stay on the on-prem worker.
46
+ - **Guard rails.** The local worker and Pi run in a sandbox, and their writes and
47
+ shell commands wait for your approval unless you choose a looser permission mode.
48
+ Budgets pause an agent before it runs out of quota, and recovery never replays an
49
+ effect whose outcome is unknown.
50
+ - **Operations.** A terminal console and a local dashboard, one hub per repository or
51
+ worktree with a machine-wide view, live settings reload, token usage and quota
52
+ history (`ahub usage`), and `ahub upgrade`, which carries running sessions across
53
+ versions.
54
+
55
+ ## Upgrading
56
+
57
+ Run `ahub upgrade` while your hubs are running. Read the notes for your version in
58
+ the [Quickstart](docs/quickstart.md) ("Upgrading to ...") and the
59
+ [Changelog](CHANGELOG.md) first: some releases need a one-time step, such as
60
+ refreshing an agent's MCP entry.
61
+
62
+ Agent CLIs update themselves. `ahub agents` shows which installed versions the hub
63
+ accepts, and `ahub agents trust <id> <version>` accepts an untested one on this
64
+ machine.
65
+
66
+ Before you migrate a memory home with `amem`, read
67
+ [memory profiles and rollout](docs/memory.md#selected-memory-profile). Every hub that
68
+ uses the home must run a version that understands the new layout.
69
+
70
+ ## Where it is going
71
+
72
+ - **Curated memory** ([#412](https://github.com/STAIxBWLB/agent-hub/issues/412)):
73
+ compression, removal, correction and failure-driven management, each shipped only
74
+ after its contract and a measurement.
75
+ - **Every agent able to do its share** ([#418](https://github.com/STAIxBWLB/agent-hub/issues/418)).
76
+ - **Measured, not assumed.** Add-ons and memory are kept or dropped by controlled
77
+ comparisons ([#248](https://github.com/STAIxBWLB/agent-hub/issues/248),
78
+ [#258](https://github.com/STAIxBWLB/agent-hub/issues/258)).
79
+
80
+ Live checks that still need a real account or a person are listed in the
81
+ [release verification report](docs/verification/2026-10-23-0.13.0.md) and the
82
+ [smoke checklist](docs/smoke.md).
118
83
 
119
84
  ## Documentation
120
85
 
121
- - [Quickstart](docs/quickstart.md): install, the first session, a working day
122
- - [Operations guide](docs/operations.md): console, task flow, Pi and models, dashboard, projects, upgrade and recovery
123
- - [Hub memory](docs/memory.md) and [agent-mem](https://github.com/STAIxBWLB/agent-mem)
124
- - [Security notes](docs/security.md): what the hub defends and what it does not
125
- - [Design spec](docs/specs/2026-09-19-agent-hub-design.md): how it is built and why
126
- - [Smoke checklist](docs/smoke.md): what has been verified against real agents
127
- - [Changelog](CHANGELOG.md), [Contributing](CONTRIBUTING.md)
86
+ | Read | For |
87
+ | --- | --- |
88
+ | [Quickstart](docs/quickstart.md) | install, the first session, a working day, upgrade notes |
89
+ | [Operations guide](docs/operations.md) | console, task flow, Pi and models, dashboard, projects, upgrade and recovery |
90
+ | [Hub memory](docs/memory.md) | how memory is stored, shared and recalled |
91
+ | [Security notes](docs/security.md) | what the hub defends and what it does not |
92
+ | [Design spec](docs/specs/2026-09-19-agent-hub-design.md) | how it is built and why |
93
+ | [Smoke checklist](docs/smoke.md) | what has been verified against real agents |
94
+ | [Changelog](CHANGELOG.md), [Contributing](CONTRIBUTING.md) | releases and how to contribute |
128
95
 
129
- `AGENTS.md` and [`docs/agent-notes/`](docs/agent-notes/) hold the rules coding
130
- agents follow when they work on this repository.
96
+ Coding agents that work on this repository follow [`AGENTS.md`](AGENTS.md) and
97
+ [`docs/agent-notes/`](docs/agent-notes/).
131
98
 
132
99
  ## Origin
133
100
 
134
101
  The first idea came from [agent-bridge](https://github.com/raysonmeng/agent-bridge),
135
- which lets Claude Code and Codex talk to each other. agent-hub has since grown
136
- into a different system with its own goals and shares no code with it.
102
+ which lets Claude Code and Codex talk to each other. agent-hub has since grown into a
103
+ different system with its own goals and shares no code with it.
137
104
 
138
105
  ## License
139
106
 
@@ -17,3 +17,32 @@ Unless required by applicable law or agreed to in writing, software distributed
17
17
  under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
18
18
  CONDITIONS OF ANY KIND, either express or implied. See the License for the
19
19
  specific language governing permissions and limitations under the License.
20
+
21
+ ## Tabler Icons
22
+
23
+ The inline icon sprite in `src/ui/index.html` (the dashboard's navigation, help, close, star, arrow and checking icons) contains the SVG
24
+ path data of twelve icons from Tabler Icons (outline set, 24x24, stroke 2), copied unchanged from https://github.com/tabler/tabler-icons:
25
+ `layout-kanban`, `building-store`, `activity`, `users`, `message`, `brain`, `settings`, `help`, `x`, `star`, `arrow-right` and
26
+ `refresh`. No Tabler package is installed or bundled.
27
+
28
+ MIT License
29
+
30
+ Copyright (c) 2020-2026 Paweł Kuna
31
+
32
+ Permission is hereby granted, free of charge, to any person obtaining a copy
33
+ of this software and associated documentation files (the "Software"), to deal
34
+ in the Software without restriction, including without limitation the rights
35
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
36
+ copies of the Software, and to permit persons to whom the Software is
37
+ furnished to do so, subject to the following conditions:
38
+
39
+ The above copyright notice and this permission notice shall be included in all
40
+ copies or substantial portions of the Software.
41
+
42
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
43
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
44
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
45
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
46
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
47
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
48
+ SOFTWARE.
@@ -10,7 +10,7 @@ Under **Adapter API 1** (issue #451), every tool is integrated as an `AdapterDef
10
10
 
11
11
  1. **One Definition per Kind**: Each tool is identified by a unique `kind` (e.g., `codex`, `kimi`, `agy`, `claude`, `jcode`, `pi`, `local`, `qwen`). Its capabilities, transport, launch argv, permission mappings, and recovery contracts are encapsulated in an `AdapterDefinition`.
12
12
  2. **Core Independence**: Core daemon logic (`src/hub/daemon.ts`), task management (`src/hub/tasks.ts`), and routing (`src/hub/routing.ts`) inspect definition fields (such as `transport`, `identity`, `attach`, `budget`), never raw vendor names.
13
- 3. **Strict Conformance**: Every builtin adapter must run the conformance test kit (`test/conformance/`). Unsupported legs must provide explicit, documented reasons rather than silent test skips. (External adapter enrollment lands with A4.)
13
+ 3. **Strict Conformance**: Every builtin adapter must run the conformance test kit (`test/conformance/`). Unsupported legs must provide explicit, documented reasons rather than silent test skips. (A4 exports the same callable contracts for external package CI.)
14
14
  4. **Trust & Security Boundaries**:
15
15
  - **On-prem vs. Cloud**: `trust.onPrem` controls whether private/PII tasks may be routed to the agent. A cloud agent (`trust.onPrem: false`) never receives PII task text or memory entries.
16
16
  - **Path Protection**: Any workspace configuration directory owned by the agent (e.g., `.agents/`, `.codex/`) must be listed in `AGENT_CONFIG_SEGMENTS` (`src/hub/permission-mode.ts`) so agents cannot self-modify their own hooks or plugins.
@@ -24,7 +24,7 @@ agent-hub supports five transport architectures (`transport` in `AdapterDefiniti
24
24
 
25
25
  | Transport | Description | Best Suited For | Examples |
26
26
  | :--- | :--- | :--- | :--- |
27
- | **`acp`** | Agent Client Protocol over stdio JSON-RPC | Agents implementing the standard ACP specification | Kimi, Qwen |
27
+ | **`acp`** | Agent Client Protocol over stdio JSON-RPC | Agents implementing the standard ACP specification | Kimi, Qwen, Jcode |
28
28
  | **`codex-appserver`** | Bidirectional JSON-RPC with proxy intercept and thread tracking | Tools with structured thread resume and proxy-injectable RPC | Codex |
29
29
  | **`claude-channel`** | MCP plugin running inside the host agent with WebSocket control link | Agents with native plugin systems that push notifications | Claude Code |
30
30
  | **`ws-pull`** | Workspace MCP plugin connecting to daemon WebSocket; pull-only message inbox | Agents with local plugin discovery and interactive TUIs | Google Antigravity (`agy`) |
@@ -65,9 +65,11 @@ Defines how the hub MCP server identity reaches the tool:
65
65
 
66
66
  #### `permission`
67
67
  Maps hub permission modes (`ask`, `ask-when-needed`, `never-ask`) to native flags or ACP mode IDs:
68
- * `grants`: Record mapping `PermissionMode` to native argument/mode string.
69
- * `unmanaged`: String explanation if native permissions are unmanaged by the hub.
70
- * `unmanagedForms`: Start forms where permissions remain unmanaged (e.g. `["tui"]`).
68
+ * `grants`: the text that says what each hub mode does for this kind (`ahub permission` and the settings preview show it). It is a description, not the native flag: the native mode id or policy is applied by the adapter (an ACP mode id, Codex's `approvalPolicy`).
69
+ * `genericAcp`: for a configured ACP kind, the validated `modes` (hub mode to ACP mode id) and `readOnly` id that the runtime and the instance ceiling both read.
70
+ * `unmanaged`, `unmanagedNote`, `unmanagedStatusNote`: why the hub cannot manage native permissions, when it cannot.
71
+ * `unmanagedForms`: start forms where permissions remain unmanaged (e.g. `["tui"]`).
72
+ * `trackUnattended`: the daemon records whether a start was `--unattended` and refuses a second start with a different setting while one is in progress (Codex).
71
73
 
72
74
  #### `session`
73
75
  Controls session restoration, thread continuity, and crash recovery:
@@ -76,6 +78,18 @@ Controls session restoration, thread continuity, and crash recovery:
76
78
  * `resumeArgv(binding, fresh)`: Builds CLI arguments to resume a persisted session.
77
79
  * `transcriptPath(binding)`: Resolves local transcript file path for audit/usage tracking.
78
80
 
81
+ #### `projection`
82
+ Where the kind sits in the host's derived lists: `roleRank`, `startRank`, `helpRank` and `plannerEligible`. `KNOWN_PEERS`, `OPTIONAL_PEERS`, `START_MODE_PEERS`, `ROLE_ORDER`, `HELP_ORDER` and `PLANNER_PEERS` are derived from `ADAPTERS` and these ranks (`deriveAdapterLists`). The only hand-kept lists are the cross-release copies in `src/hub/peer-catalog.ts` (`KNOWN_PEERS`, `OPTIONAL_PEERS`) and `src/hub/start-mode.ts` (`START_MODE_PEERS`, for a dual-form kind): a new native kind is added there too, and `test/registry-guard.test.ts` fails until those copies equal the derived lists. A configured or external definition cannot set `projection`.
83
+
84
+ #### `cli`
85
+ The `ahub <kind>` surface: `command`, `startWords(form)`, and for a fixed builtin `entry` (the launcher and whether it needs lifecycle admission), `preview`, `usage` (help lines) and `launchConfigKeys`. `builtinCliEntries(definitions)` projects the entries; no configuration or module can register one.
86
+
87
+ #### `instances` and `attach`
88
+ `instances.mode` is `headless` (needs a headless `start.create` factory) or `external` (a channel instance started from the person's terminal). A kind with no `instances` policy (Jcode) takes no extra instance, and `validateInstances` refuses a declaration of one. `attach` holds the pull-only forms, external-hello admission and the refusal texts for a TUI that attaches without a driven peer.
89
+
90
+ #### Peer capability members
91
+ The runtime peer (`PeerAdapter`, `src/hub/peers.ts`) exposes optional members that the daemon reads instead of checking its class (#625 phase 6): `sessionGeneration` (native session identity: absent keeps the owner-token fallback, present but undefined is unknown and refuses bounded checks), `checkpointUsesSessionGeneration` (opt out of generation-fenced checkpoints, as Pi does), `permissionModeState` (the effective native approval state, or `unknown` / `unmanaged`) and `setPermissionMode(mode)` (resolves only after the native side acknowledges). Native safety proofs (Codex proxy and restoration, Claude launch generation) stay in the daemon.
92
+
79
93
  #### `budget`
80
94
  Defines quota and context window consumption readers:
81
95
  * `account`: Account identifier for quota grouping.
@@ -94,20 +108,94 @@ Grok declarations require explicit `--no-leader`, since native defaults can inhe
94
108
 
95
109
  ---
96
110
 
97
- ## 5. Planned: External Adapter Modules (#451 A4)
111
+ ## 5. External Adapter Modules (#451 A4)
112
+
113
+ A person can authorize a bundled adapter in an untracked
114
+ `.agenthub/config.local.json`:
115
+
116
+ ```json
117
+ {
118
+ "adapter_modules": [
119
+ { "path": ".agenthub/adapters/my-tool.mjs", "sha256": "<64 hex digits from the exact bundle>" }
120
+ ]
121
+ }
122
+ ```
123
+
124
+ The daemon imports the module at startup. Settings, reload, previews and ordinary
125
+ CLI reads never import it. A changed declaration requires restart; it cannot be
126
+ written through a hub tool or Settings. The CLI sees only the running daemon's
127
+ bounded kind and display name. Tracked/shared/cloned configuration cannot enable
128
+ code. A wrong hash, API mismatch, builtin collision, symlink component, path
129
+ outside the project, nonregular/world-writable file, oversized file or unsupported
130
+ module construct refuses loading without exposing source text in the error.
131
+
132
+ Publish a single self-contained ESM JavaScript bundle. Bundle third-party
133
+ implementation into that file; do not add runtime dependencies to the hub.
134
+ Runtime imports may use Node/Bun builtins except `bun:ffi` and `bun:test`, plus
135
+ `@staix/agent-hub/adapter`, bound to the running daemon's own SDK rather than
136
+ project packages. `/conformance` is available to module CI, not runtime modules.
137
+ Relative or other package imports, dynamic imports, require (including
138
+ `import.meta.require`), eval and Function-based loading
139
+ are refused. The scanner also refuses any `require`, `eval` or `Function` word token, including non-loading uses such as `o.require` or `instanceof Function`. String literal contents are not word tokens. The scan is conservative, not a sandbox. Authorized module code runs
140
+ with daemon privileges; inspect the full bundle before recording its hash. Each import must settle within two seconds or that module is refused while startup continues. This deadline stops waiting; it does not cancel module code or undo its side effects.
141
+ Dependencies must be ESM-only. The loader verifies the captured original bytes,
142
+ rewrites only scanned SDK imports to host-owned file URLs, and imports that result
143
+ rather than reopening a mutable source path after the hash check. A refused
144
+ module appears in bounded status diagnostics while other adapters keep working.
145
+ Its roster row stays inert; CLI config reads also retain inert unknown rows when
146
+ trusted module declarations exist but daemon metadata is unavailable.
147
+
148
+ The module exports `definition` with `api: ADAPTER_API`. Import the version,
149
+ `AcpPeer`, `BasePeer` and definition/context types from
150
+ `@staix/agent-hub/adapter`. The initial executable subset uses a headless ACP
151
+ factory, its own kind/family, `optional: true`, `defaultOnRoster: false` and
152
+ `trust: { onPrem: false, hubSandboxed: false }`. Preserve the host's factory
153
+ options and instance id when constructing the transport. Supply a launch plan,
154
+ start/identity/session/CLI/display metadata and only supported native mode
155
+ mappings; no mapping means unmanaged. By default the host disables native
156
+ hub-tool title auto-approval for external kinds. A cooperating module must preserve
157
+ that factory option; approved module code runs with daemon privileges, so this is
158
+ a host default rather than isolation from a module that overrides its options. The loader refuses fixed-builtin capabilities and unsupported
159
+ fields rather than silently ignoring them. See `validateExternalDefinition` for
160
+ the exact accepted subset.
161
+
162
+ External kind instances are explicitly unsupported in A4. Follow-up board task
163
+ #287 owns execution roots, CLI identity and recovery for them. Broadening the
164
+ module transport beyond the existing headless ACP host port also needs a reviewed
165
+ host contract (#625 phase 6); selecting a different native engine is not a generic extension.
166
+
167
+ For example, bundle an ESM definition with its dependencies and record its digest:
98
168
 
99
- Support for loading adapter definitions from external modules outside the core repository is planned as board task #135. As decided in issue #451 (P3), external modules will be governed by strict trust rules:
169
+ ```bash
170
+ bun build ./adapter.ts --target bun --format esm --external @staix/agent-hub/adapter --outfile .agenthub/adapters/my-tool.mjs
171
+ shasum -a 256 .agenthub/adapters/my-tool.mjs
172
+ ```
100
173
 
101
- * **Machine-Local Only**: Loaded exclusively from local files specified in local configuration; never from repository tracking or network URLs.
102
- * **Content-Hash Pinning**: Explicit SHA-256 hash pinning to prevent unauthorized tampering.
103
- * **Person Authority**: Enabling external modules requires explicit human authorization.
104
- * **Conformance Requirement**: External modules must pass the conformance kit before admission.
174
+ Enable its roster row only after loading it and exercising the applicable
175
+ conformance contracts. Source and target recovery runtimes must advertise
176
+ `external_adapter_modules`; old runtimes cannot preserve the verified catalog.
105
177
 
106
178
  ---
107
179
 
108
180
  ## 6. The Conformance Kit
109
181
 
110
- The conformance kit (`test/conformance/`) validates that an adapter satisfies hub invariants:
182
+ The exported Bun kit (`@staix/agent-hub/conformance`) supplies callable transport
183
+ registrations, `createFromDefinition`, `registerConformance`, explicit unsupported
184
+ leg validation and immutable `fakePaths`. Importing it starts no fake transport;
185
+ call a registration in your own Bun test file. The hub's `test/conformance/`
186
+ wrappers run the same implementation against every applicable builtin.
187
+
188
+ An external adapter test imports its definition and calls
189
+ `registerConformance` with its real factory and a fake transport fixture. ACP
190
+ adapters also call `registerAcpConformance({ definition, ... })`; unsupported native
191
+ approval, mode or quota legs require concrete reasons, never silent skips. Other
192
+ exports cover Codex, owned ACP, Pi, local and external-channel fixture contracts.
193
+ Those exports do not grant an external runtime access to a builtin-only engine.
194
+ The shipped fake assets live under `src/adapters/conformance/fakes`, so package CI needs
195
+ no development-tree files. Native account/TUI probes remain separate from these
196
+ synthetic protocol contracts.
197
+
198
+ The kit validates that an adapter satisfies hub invariants:
111
199
 
112
200
  ```bash
113
201
  # Run the complete conformance suite
@@ -120,7 +208,7 @@ bun test test/conformance/agy.test.ts
120
208
 
121
209
  ### Invariants Verified by the Kit:
122
210
  1. **Enrollment & Coherence (`enrollment.test.ts`)**: Every definition in `ADAPTERS` and reviewer variant must be enrolled. A kind without kit coverage needs a reason in `UNSUPPORTED` (`test/conformance/enrollment.ts`), and an ACP kind that skips one of the shared `ACP_LEGS` needs a reason per leg in `UNSUPPORTED_LEGS`.
123
- 2. **Delivery Occupancy**: Sending messages updates driven peer state to `busy` synchronously, delivering digests reliably.
211
+ 2. **Delivery Occupancy**: Sending messages updates driven peer state to `busy` synchronously, delivering digests reliably. A channel peer whose native hooks own occupancy (Claude) stays idle on insertion by design.
124
212
  3. **Recovery Metadata Hygiene**: No prompt text or credentials leaked into `recoveryMetadata`.
125
213
  4. **Watchdog Cancellation & Generation Fencing**: Expiry of the turn watchdog cancels prompts cleanly and generation fences prevent stale late answers from publishing.
126
214
  5. **Teardown & Cleanup**: When an adapter is stopped (`peer.stop()`), all owned child processes in the process group stop with it (the peer reaches offline).
@@ -132,7 +220,7 @@ bun test test/conformance/agy.test.ts
132
220
  When adding or updating an adapter, verify each item before opening a PR:
133
221
 
134
222
  - [ ] **T0 Receipt Recorded**: Document native CLI version, observed hook payloads, and protocol outputs in `docs/verification/YYYY-MM-DD-<kind>-t0.md`.
135
- - [ ] **Registered in ADAPTERS**: Added to `src/adapters/registry.ts` with explicit `displayName`, `family`, `transport`, and `trust`.
223
+ - [ ] **Registered in ADAPTERS**: the definition is declared under `src/adapters/definitions/` (or its own directory) with explicit `displayName`, `family`, `transport`, `trust` and `projection`, and listed in `ADAPTERS` (`src/adapters/registry.ts`). The peer lists are derived from it. The hand-kept cross-release copies in `src/hub/peer-catalog.ts` and `src/hub/start-mode.ts` and the pinned tests listed in `docs/agent-notes/adapters.md` change with it, and the PR names them as expected test changes.
136
224
  - [ ] **Config Path Protection**: Agent configuration directories added to `AGENT_CONFIG_SEGMENTS` in `src/hub/permission-mode.ts`.
137
225
  - [ ] **PII Safety Verified**: Cloud models have `trust.onPrem: false`; verify PII markers refuse routing to this peer.
138
226
  - [ ] **Process Group Teardown**: Daemon-spawned processes use process groups and exit cleanly on stop.
@@ -20,3 +20,18 @@ The #451 predicate and identity-lookup moves exposed unbound names in a VM fixtu
20
20
  that extracts daemon closures. Reconnecting imported helpers and deterministic
21
21
  identity ports preserved the fixture's existing assertions; changing the asserted
22
22
  behavior would have hidden the missing dependency.
23
+
24
+ Background moved out of the area notes for 0.12.45:
25
+
26
+ - Instance execution git budget (#225, daemon.md): `resolveInstanceExecutionCwd` runs synchronously on the daemon's event loop (an extra-instance start, `turn_revert`) with up to four git calls, measured at about 15 ms on a warm local repository. One shared 5 s allowance holds the loop at most 5 s, not 4 x 5 s. It stays synchronous because the CLI and recovery callers are; an async twin for the two daemon call sites is the upgrade if a typical resolution ever costs more than a few ms.
27
+ - Claude steer version gate (#493, #221, daemon.md): mid-turn consumption of a steered important message was proven only on Claude Code 2.1.302 (`docs/verification/2026-10-18-493-claude-busy-channel.md`); on an older client a dropped mid-turn notification stays `accepted` until a person resolves it. The hello does not carry the client version, and the oldest working version is unknown, so a gate would be a guess that could disable a working path.
28
+ - Planner reservation and done gates (tasks.md): in #378 a same-value planner write laundered a person's reservation; in #382 advise recorded overlapping dones, and an owner could neither relink a PR nor be stopped from carrying a head to a new PR.
29
+ - Process-tree stops (adapters.md): three review rounds of #113 found snapshot gaps while the tree ran (groups of its own, an unreadable first read, a child started during the grace period).
30
+ - Local worker (local-worker.md): a bare `private/` deny entry once denied all of `/private/var`; `existsSync` made a dangling link look like a new file, so a write landed at its target.
31
+ - Suite watchdog (tests.md): macOS CI hit `AHUB_CHECK_HANG_S` while tests still passed (#378, #593).
32
+
33
+ Background moved out of the area notes for 0.13.0:
34
+
35
+ - Jcode MCP entry (#685, adapters.md): jcode gives an MCP entry's own env precedence over the process env (probed on 0.99.0), so a peer id in the shared `.jcode/mcp.json` entry would make every extra instance act as `jcode`.
36
+ - Bulk queue discard (#713, bus.md): a queued row with no journal record of its own carries the journal's global revision, which every discard moves, so a revision read once at the start goes stale after the first discard.
37
+ - Usage roll-up (#683 U2, budget.md): a pass cap smaller than one log line once hung the fold.