@staix/agent-hub 0.16.0 → 0.18.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 (96) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/README.md +2 -2
  3. package/docs/agent-notes/README.md +5 -0
  4. package/docs/agent-notes/adapters.md +20 -5
  5. package/docs/agent-notes/benchmarks.md +1 -0
  6. package/docs/agent-notes/daemon.md +5 -3
  7. package/docs/agent-notes/local-worker.md +1 -0
  8. package/docs/agent-notes/tasks.md +9 -3
  9. package/docs/agent-notes/tests.md +6 -3
  10. package/docs/dogfood.md +21 -4
  11. package/docs/memory.md +1 -1
  12. package/docs/operations.md +150 -34
  13. package/docs/profiles.md +36 -0
  14. package/docs/quickstart.md +14 -4
  15. package/docs/roles.md +1 -0
  16. package/docs/sdlc.md +39 -13
  17. package/docs/security.md +41 -9
  18. package/docs/smoke.md +51 -3
  19. package/docs/specs/2026-09-19-agent-hub-design.md +56 -10
  20. package/docs/specs/2026-09-20-upgrade-recovery-design.md +3 -1
  21. package/docs/verification/2026-10-25-0.17.0.md +74 -0
  22. package/docs/verification/2026-10-25-0.18.0.md +76 -0
  23. package/docs/verification/2026-10-25-codex-0164-reviewer-tool-call.md +52 -0
  24. package/docs/verification/2026-10-25-codex-review-live-verdict.md +35 -0
  25. package/docs/verification/2026-10-25-kimi-231-reviewer-compat.md +48 -0
  26. package/docs/verification/2026-10-25-kimi-usage-ac11.md +48 -0
  27. package/docs/verification/2026-10-25-qwen-dual-output-hub-e2e.md +23 -0
  28. package/docs/verification/2026-10-25-qwen-dual-output-t0.md +20 -0
  29. package/docs/verification/2026-10-25-remote-docker-transport.md +46 -0
  30. package/docs/verification/2026-10-25-reviewer-no-verdict-diagnostics.md +35 -0
  31. package/docs/verification/profiles/YYYY-MM-DD-general.md +46 -0
  32. package/docs/verification/profiles/YYYY-MM-DD-research.md +61 -0
  33. package/docs/verification/profiles/YYYY-MM-DD-writing.md +46 -0
  34. package/docs/verified.json +28 -19
  35. package/package.json +2 -2
  36. package/plugins/agent-hub/.claude-plugin/plugin.json +1 -1
  37. package/plugins/agent-hub/server.js +1115 -192
  38. package/src/adapters/codex-review-isolation.ts +10 -1
  39. package/src/adapters/compat.ts +7 -2
  40. package/src/adapters/conformance/enrollment.ts +18 -4
  41. package/src/adapters/conformance/factories.ts +4 -1
  42. package/src/adapters/conformance/kit.ts +11 -0
  43. package/src/adapters/definitions/builtin-metadata.ts +1 -1
  44. package/src/adapters/definitions/native-cli-entry-qwen.ts +32 -4
  45. package/src/adapters/definitions/native-cli-preview-qwen.ts +9 -1
  46. package/src/adapters/definitions/native-factories.ts +8 -0
  47. package/src/adapters/definitions/native-recovery.ts +8 -0
  48. package/src/adapters/definitions/qwen.ts +7 -4
  49. package/src/adapters/local-worker.ts +5 -3
  50. package/src/adapters/qwen-dual.ts +578 -0
  51. package/src/adapters/registry-types.ts +5 -1
  52. package/src/adapters/registry.ts +9 -1
  53. package/src/adapters/reviewer-mcp.ts +12 -6
  54. package/src/adapters/reviewer-print.ts +100 -17
  55. package/src/cli/console-state.ts +9 -2
  56. package/src/cli/help.ts +29 -28
  57. package/src/cli/identity.ts +87 -6
  58. package/src/cli/main.ts +190 -69
  59. package/src/cli/output.ts +7 -2
  60. package/src/cli/sdlc-output.ts +242 -0
  61. package/src/cli/task-output.ts +212 -0
  62. package/src/cli/upgrade-output.ts +57 -0
  63. package/src/cli/upgrade.ts +4 -3
  64. package/src/hub/board.ts +17 -0
  65. package/src/hub/check-runner.ts +252 -22
  66. package/src/hub/conductor.ts +5 -0
  67. package/src/hub/config-apply.ts +16 -7
  68. package/src/hub/config-edit-host.ts +1 -1
  69. package/src/hub/config-tier.ts +1 -1
  70. package/src/hub/daemon.ts +487 -94
  71. package/src/hub/dogfood-profile.ts +248 -0
  72. package/src/hub/dogfood-read.ts +77 -14
  73. package/src/hub/dogfood.ts +5 -1
  74. package/src/hub/events.ts +1 -1
  75. package/src/hub/host-executable.ts +2 -1
  76. package/src/hub/hub-tools.ts +2 -2
  77. package/src/hub/memory-plan-guard.ts +8 -33
  78. package/src/hub/operational-authority.ts +60 -0
  79. package/src/hub/operational-view.ts +141 -0
  80. package/src/hub/orphan-process.ts +69 -0
  81. package/src/hub/permission-mode.ts +1 -1
  82. package/src/hub/read-only-shell-proof.ts +80 -0
  83. package/src/hub/read-only-shell.ts +162 -0
  84. package/src/hub/reviewer-pool-config.ts +3 -2
  85. package/src/hub/reviewer-pool.ts +3 -0
  86. package/src/hub/routing.ts +23 -6
  87. package/src/hub/sdlc-merge.ts +299 -0
  88. package/src/hub/sdlc-mirror.ts +129 -0
  89. package/src/hub/sdlc.ts +58 -12
  90. package/src/hub/settings.ts +11 -5
  91. package/src/hub/snapshots.ts +60 -0
  92. package/src/hub/task-repository.ts +31 -5
  93. package/src/hub/tasks.ts +266 -28
  94. package/src/local/tools.ts +17 -4
  95. package/src/memory/brief.ts +45 -5
  96. package/src/ui/index.html +2 -1
@@ -1,10 +1,12 @@
1
1
  # Operations guide
2
2
 
3
- This guide describes ahub 0.13.0 and control protocol 16. Live verification
3
+ This guide describes ahub 0.18.0 and control protocol 16. Live verification
4
4
  results and remaining prerequisites are recorded separately in [the smoke ledger](smoke.md).
5
5
 
6
6
  ## Agent-operated live verification
7
7
 
8
+ Every open live leg in [smoke.md](smoke.md#open-live-legs-by-class) is classed `agent-executable`, `agent-evidence / person-verdict`, `person-only` or `external-blocked` (#784); this section is how an agent runs the first two.
9
+
8
10
  When the user explicitly authorizes a live test, its agent may run console
9
11
  commands using `ahub --live-test [--project <path|id>] <command> [args...]`.
10
12
  For example, `ahub --live-test --project <scratch-path> ui --no-open` starts the
@@ -65,6 +67,9 @@ smoke ledger; the presence of this option proves no outstanding #273 live leg.
65
67
  `status --all` uses the projects table. `queue show`, `models status` and `budget execution status` show labelled fields; add `--json` for the raw fetched document.
66
68
  `report --by task` keeps the attribution and coverage sentences with section headings and aligned counters.
67
69
  Use `--json` for scripts; it returns the fetched data without color, and `status --json` keeps its existing document.
70
+ `sdlc status`, `sdlc explain`, `sdlc queue`, `sdlc release`, `sdlc metrics`, `sdlc costs` and `sdlc authorize-release` print readable output by default (#814: aligned columns, wrapped text, readable times, `--color=auto|always|never`). A script that parsed their JSON must pass `--json`, which prints exactly the document they printed before. `sdlc export` is a data format and stays JSON, as do `export`, `research export` and `bench export`.
71
+ `restart` and `upgrade` off an interactive terminal (a pipe, `--dry-run`), `recovery status` and the results of `recovery reattach`, `resume`, `abort` and `dispose`, `models setup` and `start`, `queue resolve`, and `budget execution configure` and `disable` print readable text by default (#814); a script that parsed their JSON must pass `--json`, which prints exactly the document they printed before, including `restart --json --yes`. A readable plan lists each project, each peer with how it runs and what happens to it, every blocker, every reconnect-only session and every fresh start, and says nothing was changed; `--json` keeps those as stderr lines. A pipe wraps at `COLUMNS` when it is set, else at 80 columns.
72
+ `task show`, `task cancel`, `backlog groom`, `backlog return|plan|pin|split|undo|pull-ready` and the `release` commands (`list`, `show`, `new`, `plan`, `activate|freeze|ship|drop`) print a readable block by default (#814): the task or release as the hub holds it, a table for lists, every identifier whole, long text wrapped to the terminal. A script that parsed their JSON must pass `--json`, which prints the hub tool's text exactly as before. A private task arrives from the hub as its stub and is shown as that stub. Because these commands also take free text, `--json` and `--color=` count as flags only at the start or the end of the arguments: `--json` in the middle of a reason is part of the reason, and a value flag's value (`task cancel --reason --json`) is never a flag. A reason that ends in a bare `--json` loses it to the flag. `backlog add|pull`, `task escalate|assign|unassign` already answered one sentence and are unchanged.
68
73
  In `projects --json` and `status --all --json`, an unavailable hub that explicitly refuses an inspection for SQLite contention also carries `failure: { "code": "database_busy" }`; it is additive metadata alongside the neutral `error` sentence.
69
74
  Text columns are a human interface, not a scripting contract. An identifier accepted as a command argument is whole wherever its available column can hold its own length:
70
75
  turn ids, queue ids, project ids, execution budget ids and ids in labelled views. Only status's informational settlement and hold ids are shortened;
@@ -134,6 +139,12 @@ asking, under the same path guard and sandbox; a Pi restart or replacement, or a
134
139
  hub restart, drops it. The hub log records each granted call by tool name only.
135
140
  The dashboard can only deny Pi's requests.
136
141
 
142
+ In `ask-when-needed`, Pi and the local worker also grant bounded read-only shell calls at the host permit boundary (#816). The command must parse as one literal command and satisfy a closed program/flag table, trusted executable lookup and the existing root/path guard. Unknown flags, operators, expansions, pipelines, output files, unsafe helper/follow/file-list options and outside-root paths keep the ordinary approval path. Single quotes preserve literal data; double quotes containing `$`, backticks or backslashes are not automatically granted.
143
+
144
+ The fixed program set is `ls`, `cat`, `head`, `tail`, `wc`, `rg`, `grep`, `stat`, `file`, `tree`, `pwd`, `find` and supported read-only `git` forms. Git patch forms need both `--no-ext-diff` and `--no-textconv` where supported; a configured helper-bearing key (`core.fsmonitor`, `log.showSignature`, `gpg.program`, `gpg.<format>.program`, `diff.external`, `diff.<driver>.command` or `diff.<driver>.textconv`, `format.pretty` or `pretty.<name>`) outside the hub's own command scope keeps every git form asking. Custom `--format` and `--pretty` options also ask because signature placeholders can invoke the default GPG program. The host revalidates executable and path proof after each await, immediately before execution. A changed proof requires an explicit approval, including in unattended mode; persistent instability runs nothing. Neither argv nor environment is rewritten. Scoped read-only grants log the tool and class without command arguments.
145
+
146
+ `ask` retains shell approval behavior; `never-ask`, existing Pi tool-wide grants and the always-ask action policy retain their precedence. Seatbelt, the path guard, read allowlists, home and network access are unchanged. The person's Pi setting and live triage receipt are separate AC4 work; this feature's tests do not certify that rollout.
147
+
137
148
  Tab toggles stream and panels; `ahub console --panels` starts in panels. A panel
138
149
  screen has a header (the project's directory name, then the tabs), the panel and
139
150
  a three-line footer, separated by ASCII `-` rules; the stream has one rule above
@@ -516,6 +527,41 @@ resume, budget, queue, permit, permission, ask, remember, route, turns, undo,
516
527
  check-path and report operations. It executes an argument vector with closed stdin. Lifecycle,
517
528
  launch, nested console, setup, UI, logs and tail commands are refused.
518
529
 
530
+ ## Authority by command
531
+
532
+ `classifyPeerCommand` (src/cli/identity.ts) is the gate for an `ahub` command
533
+ run from an agent shell. It gives every command one of three classes:
534
+ **Allowed** means any agent may run it; **Conductor** means only the
535
+ configured conductor peer may (actor-preserving and audited); **Console** means
536
+ only the person's own terminal. A command the gate does not name is Console,
537
+ and so is every help entry the gate has no class for yet;
538
+ `test/identity.test.ts` pins each classed form below.
539
+
540
+ ### Allowed (any agent)
541
+
542
+ | Command | Class | Why |
543
+ | --- | --- | --- |
544
+ | `ahub doctor [--json] [--full] [--color=...]` | Allowed | a read-only check of tools, daemon, plugin, gateway, models and memory |
545
+ | `ahub doctor --stale-anchors [--json]` | Allowed | a bounded read-only report of memory symbol anchors at current HEAD |
546
+ | `ahub queue list [--peer <id>] [--json] [--full] [--color=...]` | Allowed | public queue metadata only; held bodies and resolution remain conductor operations |
547
+ | `ahub roster [--json] [--color=...]` | Allowed | public roster status; add/remove retain conductor admission |
548
+ | `ahub settings [list] [--json]`, `ahub settings get <key> [--json]` | Allowed | public registry values; secret-locating values, paths, undo records and config-editor details are withheld |
549
+ | `ahub sdlc status\|explain [<task>] [--json] [--color=...]` | Allowed | public lifecycle status; private tasks stay stubs, without private evidence or receipts |
550
+ | `ahub sdlc queue <owner/repo> [--json] [--color=...]`, `ahub sdlc release <owner/repo> [live-issue...] [--json] [--color=...]` | Allowed | public delivery/release readback for the checkout's GitHub origin, explicit SDLC config repos or person-imported public external records; no release authorization or mutation |
551
+ | `ahub release show <name>` | Allowed | public release metadata; private scope and internal history remain withheld |
552
+ | `ahub projects [--json] [--color=...]` | Allowed | lists registered projects; `projects remove` stays Console |
553
+ | `ahub models status [--json] [--color=...]` | Allowed | reads local model state; `setup\|start\|stop` stay Console |
554
+ | `ahub recovery status [<op-id>] [--json]` | Allowed | reads a preflight operation; the bare interactive screen, `resume`, `abort` and `reattach` stay Console |
555
+ | `ahub upgrade ... --dry-run` (no `--yes`) | Allowed | reviews the upgrade plan and applies nothing; `--yes` stays Console |
556
+ | `ahub restart --dry-run [--json]` (no `--yes`) | Allowed | reviews the restart plan and applies nothing; `--yes` stays Console |
557
+
558
+ `backlog list`, `release list` and `sdlc costs|metrics` retain their existing
559
+ planner/person policy. Their CLI forms stay Console for ordinary agents; a
560
+ configured planner can use the existing planner tools without borrowing console
561
+ authority. All newly admitted reads use the ordinary tools connection and public
562
+ views, never console identity. The person's full readback stays unchanged.
563
+ Conductor operations are listed in [the operational command table](#conductor-operations-812-t2).
564
+
519
565
  ## Conducting a team from Claude Code or Codex
520
566
 
521
567
  Start the daemon with `ahub up --no-console`, set exactly one conductor in the
@@ -621,13 +667,17 @@ does not automatically hand its task to a cloud peer.
621
667
  For assigned, non-private work, `hub_task_spec` reads the named GitHub issues
622
668
  through the hub's authenticated, bounded read path. `hub_check_start` runs an
623
669
  exact Git ref's permitted tests or typecheck in the opt-in isolated container
624
- runner (`checks.runner: "container"`); `hub_check_result` and `hub_check_cancel`
670
+ runner (`checks.runner: "container"`, or the optional `"remote"` backend); `hub_check_result` and `hub_check_cancel`
625
671
  read or cancel that owned run. Missing spec/check capability refuses the
626
672
  assignment early; it never grants host commands, credentials or broader sandbox
627
673
  access. Receipts distinguish exact source/tree/lockfile, platform, exit and
628
674
  uncertain or cancelled outcomes. See [bounded spec and check access](security.md#bounded-task-specs-and-isolated-checks-418)
629
675
  for the authorization and resource bounds.
630
676
 
677
+ Remote runner configuration (#793) is permitted only in the person's untracked `config.local.json`: select `checks.runner = "remote"` and supply `checks.remote.host`, `checks.remote.image` (immutable SHA-256 image reference) and `checks.remote.root` (reserved absolute metadata for the later dependency-preparation slice). No remote destination belongs in tracked project files. The runner uses the person's host SSH capability (including the hub's authentication agent socket) in BatchMode, with TTY allocation, agent/X11 forwarding, configured forwardings and local SSH commands disabled, and fixed Docker argv; it never installs host tools, mounts host paths or falls back to this Mac. A failed SSH, Docker, image or hardened network-none/transfer probe marks sandboxed test capability unavailable with a generic remote-runner reason. A successful platform line names only Linux architecture and numeric Docker version.
678
+
679
+ The remote source is the recorded Git commit, streamed into a hardened non-root container. Mac dependencies are excluded; the project-scoped read-only named dependency volume is currently an unprepared placeholder, so the runner reports `remote dependencies unprepared` and withholds tests capability until the separate admitted preparation slice lands, even when its transport probe succeeds. That future step must key the volume by lockfile and Bun version; the run itself performs no install. Remote `root` is validated but unused in this transport-only slice because no host path operation is needed. The bounded [local Docker transport receipt](verification/2026-10-25-remote-docker-transport.md) records the extraction and cleanup leg. Actual remote-host opt-in, SSH and pi's live check receipt remain unverified follow-up work. Existing local Apple-container behavior remains available by explicit selection.
680
+
631
681
  Retention bounds inactive valid check receipts to 200 records and the newest 20
632
682
  full outputs, excluding active runs. Full output is also consumed by the owner
633
683
  result read or expires after 24 hours.
@@ -794,9 +844,12 @@ initialization pair `AGENTHUB_PROJECT_DIR` / `AGENTHUB_STATE_DIR`.
794
844
 
795
845
  Manager-started hubs use attended mode and project configuration, including
796
846
  credential-file references. They do not inherit the launching project's gateway
797
- URL/key overrides. Native memory remains shared according to claude-mem aliases;
798
- worktrees recall their parent and composite identity. A shared-alias notice does
799
- not mean that task boards or agent sessions are shared. Provider quota readings
847
+ URL/key overrides. Native memory is shared by memory project key: the project's
848
+ normalized `origin` remote (without one, its git chain and main working root),
849
+ mapped through the person's `amem alias` log, so a worktree or subdirectory uses
850
+ its main checkout's key. The manager's shared-alias notice compares project-name
851
+ chains instead (superprojects down to the repository, `<parent>/<worktree>` for a
852
+ worktree). Neither means that task boards or agent sessions are shared. Provider quota readings
800
853
  may describe the same account and should not be added across projects.
801
854
 
802
855
  Before upgrading an older hub, inspect the plan with the matching CLI.
@@ -828,7 +881,8 @@ what the hub runs, which files it sends as credentials, where task text goes,
828
881
  how far the local worker's sandbox reaches, or how often a peer asks before it
829
882
  acts (`kimi_cmd`, `permission_modes`, `codex_bin`,
830
883
  `pi.cmd`, `checks`, `mlx.bin`, `mlx.runtimeDir`, `mlx.modelPath`, `omniroute.urls`,
831
- `omniroute.access_hosts`, the `omniroute` key files, `memory.worker_url`,
884
+ `omniroute.access_hosts`, the `omniroute` key files, `memory.worker_url` (still
885
+ accepted, ignored since 0.16.0),
832
886
  `local.read_allow`, `local.bash_network`, `local.network_allow`) are machine-local:
833
887
  they apply only from a file git confirms nobody committed. Put them in
834
888
  `.agenthub/config.local.json` (`ahub init` adds it to `.gitignore`), which is
@@ -1022,7 +1076,9 @@ includes), read the check result, and list what is
1022
1076
  unmet (`hub_review` takes `unmet`, `ahub review ... --unmet <item>`). A reviewer
1023
1077
  that missed the request, and the owner, read the done summary and check result
1024
1078
  with `hub_task_show {id}`: the task's public view with its history, as the
1025
- conductor sees it, and only a stub for a PII task. Other peers are refused. Each
1079
+ conductor sees it, and only a stub for a PII task. The configured planner reads any
1080
+ task outside the backlog the same way (#812); a staged backlog row stays hidden from agent
1081
+ task tools and is read through the planner tools. Other peers are refused. Each
1026
1082
  request also carries the hub's review brief for the task's commit: reviewable and
1027
1083
  excluded files with reasons, the `REVIEW.md` and `ahub-review-rules` rules read at
1028
1084
  the merge base, and a cross-check list; `ahub review brief <id>` prints it.
@@ -1298,7 +1354,7 @@ ahub memory forget 1a2b3c4d # a person's; also promote, demote, sup
1298
1354
 
1299
1355
  `"memory": { "native": false }` in `.agenthub/config.json` turns it off for a project.
1300
1356
 
1301
- The exact-pinned `@staix/agent-mem` 0.7.0 resolves `AMEM_HOME`, then `$AGENTHUB_HOME/memory`, then `~/.agenthub/memory`. An absent `M/profile.json` selects shared v1; an explicit generation selects `M/generations/G` with the package's readonly legacy bridge. All daemon memory consumers and the hub memory/goal CLI use that selected profile. Invalid metadata or a missing selected generation makes native memory unavailable while the bus and board continue; there is no fallback to legacy writes. Inspect the daemon's memory binding/availability before interpreting missing memory as an empty store.
1357
+ The exact-pinned `@staix/agent-mem` 0.8.0 resolves `AMEM_HOME`, then `$AGENTHUB_HOME/memory`, then `~/.agenthub/memory`. An absent `M/profile.json` selects shared v1; an explicit generation selects `M/generations/G` with the package's readonly legacy bridge. All daemon memory consumers and the hub memory/goal CLI use that selected profile. Invalid metadata or a missing selected generation makes native memory unavailable while the bus and board continue; there is no fallback to legacy writes. Inspect the daemon's memory binding/availability before interpreting missing memory as an empty store.
1302
1358
 
1303
1359
  The daemon checks its selector at hub operation entry and before candidate/counter writes. It does not hot-switch handles or provide an atomic fence against selection changes during an in-flight core call. Quiesce consumers and close their handles before migration or selection changes; reopen through the supported session-preserving lifecycle afterward. Candidate/counter storage remains `M/candidates.db`, independent of `G`; since agent-mem 0.7.0 `amem review` also lists and accepts candidates on a selected generation. Every running hub using this home needs an authenticated receipt: a matching ready binding, or a generation-capable unbound receipt (`disabled` when native memory is off, `unavailable` when opening failed) proving it holds no memory handle. An unbound daemon and zero running hubs are quiesced for memory; a stale bound handle, unreadable registry or unknown runtime is not ready. Existing JSON memory/goal results remain unchanged; the additive binding receipt belongs to daemon status, profile-check and the decay object. This source integration does not authorize installing a new runtime, migrating real memory, restarting sessions or claiming real-machine sync/capture receipts. Migration/deactivation and their limits belong to [agent-mem](https://github.com/STAIxBWLB/agent-mem); see [the hub profile contract](memory.md#selected-memory-profile).
1304
1360
 
@@ -1323,6 +1379,8 @@ ahub goal # open ones
1323
1379
  ahub goal take 1a2b3c4d --force # take one over from another machine
1324
1380
  ```
1325
1381
 
1382
+ Without a remote the periodic sync stays quiet; any other sync failure writes `hub memory sync failed: <reason>` to `hub.log` (#401).
1383
+
1326
1384
  ## Benchmarks
1327
1385
 
1328
1386
  In a git repository kept for benchmarks (`"bench": { "enabled": true }` in its `.agenthub/config.json`, a clean tree),
@@ -1646,7 +1704,7 @@ denylist (Pi and local), or native vendor boundaries (Claude and Codex).
1646
1704
  | Kimi Code CLI | ACP yolo | ACP auto | ACP default |
1647
1705
  | Codex | on-request for every outgoing turn/start | never for every outgoing turn/start | Restore the known native policy once, then stop overriding |
1648
1706
  | Claude | Allow resolving project file tools outside .agenthub/.git/.claude/.codex/.qwen/.kimi/.kimi-code/.jcode/.pi/.mcp.json/.agents/.agent/_agents/_agent/.gemini/.grok/.claude.json | Hook allow for every tool | No hook decision |
1649
- | Pi and local | Grant write/edit outside native agent configuration paths; read never asks; shell/git writes ask | Grant each tool once within the existing sandbox/guard | Normal approval handling |
1707
+ | Pi and local | Grant write/edit outside native agent configuration paths and proven read-only shell calls; other shell/git writes ask | Grant each tool once within the existing sandbox/guard | Normal approval handling |
1650
1708
 
1651
1709
  Kimi's map applies only to the actual Kimi Code CLI identity, not another ACP
1652
1710
  agent configured in kimi_cmd. Qwen and other ACP agents start fresh/resumed
@@ -1915,7 +1973,7 @@ Instances, the review and approval blocks and the lifecycle can be edited withou
1915
1973
  1. **Registry settings** (everything above) are unchanged.
1916
1974
  2. **Structural keys**, editable in the console and in a dashboard settings session:
1917
1975
  - `instances.<id>` with `kind`, `roles`, `start_mode`, `review_mode`, `readOnly`, `worktree` and `permission_mode`, in `config.local.json`;
1918
- - `review.adaptive`, `review.min_reviews`, `review.pool`, `review.rerotate`, `snapshots.keep`, `approvals.timeout_s` and `context.gate`, in `config.local.json`;
1976
+ - `review.adaptive`, `review.min_reviews`, `review.pool`, `review.rerotate`, `review.same_family`, `snapshots.keep`, `approvals.timeout_s` and `context.gate`, in `config.local.json`;
1919
1977
  - `mode` and `required_checks` in `.agenthub/sdlc.toml`. Only those two lines change: comments and every other table stay as written, and a layout the editor cannot change faithfully (a key repeated, or one inside a multi-line string) is refused with its own reason.
1920
1978
 
1921
1979
  `roster.*`, `tasks.wip_limits.*`, `permission_modes`, `peers` and the rest of the registry keep their own `ahub settings set` path.
@@ -2451,7 +2509,7 @@ Rows without a live process are stale registrations; forget them with
2451
2509
 
2452
2510
  ## Agent CLI versions
2453
2511
 
2454
- Agent CLIs update themselves often, and a hub release cannot follow every one. One policy decides each gated CLI: the Codex and Kimi fresh reviewers, Jcode, agy and Qwen (#691).
2512
+ Agent CLIs update themselves often, and a hub release cannot follow every one. One policy decides each gated CLI: the Codex and Kimi fresh reviewers, Jcode, agy and Qwen (#691). Qwen has two entries: `qwen` for headless ACP and `qwen-dual` for the dual-output TUI (#286).
2455
2513
 
2456
2514
  - `ahub agents [--json]` lists each gated CLI with its version, verdict and verified versions.
2457
2515
  - **verified:** a receipt exists.
@@ -2463,7 +2521,7 @@ Agent CLIs update themselves often, and a hub release cannot follow every one. O
2463
2521
  - For the reviewers, trust lifts only the version pin. The MCP inventory, Apps/plugins/hooks readback, sandbox denial fixtures and binary fence still run before every child, and a failed leg still refuses.
2464
2522
  - What trust cannot prove is printed when you trust.
2465
2523
  - `ahub doctor` shows one line for each installed CLI that is not on a verified version.
2466
- - A weekly workflow (`.github/workflows/agent-compat.yml`) compares the latest npm versions of Codex, Kimi Code and Qwen Code with the verified sets, keeps one `agent-compat` issue up to date while one is ahead and closes it when none is. The next step for each listed version is a model-free receipt in `docs/verification/`, then adding it to `verified` in the same PR. Jcode and agy are not watched.
2524
+ - A weekly workflow (`.github/workflows/agent-compat.yml`) compares the latest npm versions of Codex, Kimi Code and Qwen Code with the verified sets, keeps one `agent-compat` issue up to date while one is ahead and closes it when none is. The next step for each listed version is a model-free receipt in `docs/verification/`, then adding it to `verified` in the same PR. Jcode, agy and `qwen-dual` are not watched.
2467
2525
 
2468
2526
  ## Upgrade and crash recovery
2469
2527
 
@@ -2484,7 +2542,7 @@ section is what they run.
2484
2542
 
2485
2543
  Upgrade running projects with the target release's own coordinator. It accepts
2486
2544
  a running source on control protocol 9 (0.6.x), 10 (0.7.0 through 0.12.0),
2487
- 11 (0.12.1 and 0.12.2), 12 (0.12.3), 13 (0.12.4 through 0.12.15), 14 (0.12.16), 15 (0.12.17 through 0.12.19) or 16 (0.12.20 through 0.12.43), and only
2545
+ 11 (0.12.1 and 0.12.2), 12 (0.12.3), 13 (0.12.4 through 0.12.15), 14 (0.12.16), 15 (0.12.17 through 0.12.19) or 16 (0.12.20 through 0.18.0), and only
2488
2546
  a target on its own protocol, so the target's coordinator fits every supported
2489
2547
  source and carries every recovery fix released up to it. Protocol 8 and older
2490
2548
  (0.5.x and earlier) are refused as `manual-bootstrap-required`. Run from the
@@ -2498,7 +2556,7 @@ bunx --package @staix/agent-hub@0.12.43 ahub upgrade --to 0.12.43 --yes
2498
2556
  | Running now | Coordinator to use |
2499
2557
  | --- | --- |
2500
2558
  | 0.6.x (protocol 9) | the target's, through `bunx` as above |
2501
- | 0.7.0 through 0.12.0 (protocol 10), 0.12.1 and 0.12.2 (protocol 11), 0.12.3 (protocol 12), 0.12.4 through 0.12.15 (protocol 13), 0.12.16 (protocol 14), 0.12.17 through 0.12.19 (protocol 15), 0.12.20 through 0.12.43 (protocol 16) | the target's, through `bunx` as above |
2559
+ | 0.7.0 through 0.12.0 (protocol 10), 0.12.1 and 0.12.2 (protocol 11), 0.12.3 (protocol 12), 0.12.4 through 0.12.15 (protocol 13), 0.12.16 (protocol 14), 0.12.17 through 0.12.19 (protocol 15), 0.12.20 through 0.18.0 (protocol 16) | the target's, through `bunx` as above |
2502
2560
  | any supported source, with the installed CLI already at the target | `ahub upgrade` below, which is the same coordinator |
2503
2561
  | 0.5.x or earlier (protocol 8 and older) | not supported: bootstrap by hand with the matching CLI |
2504
2562
 
@@ -2647,15 +2705,14 @@ plugin, daemon, or terminal mutation.
2647
2705
 
2648
2706
  `ahub upgrade` and `ahub restart` are interactive when standard input and output
2649
2707
  are a terminal and neither `--dry-run` nor `--yes` is given. With either flag, or
2650
- through a pipe, the JSON plan, the `ahub: blocker:` lines and the exit codes are
2651
- unchanged. The screens add no way to change an operation: every choice runs one
2708
+ through a pipe, the plan is printed as readable text (#814) and `--json` keeps the JSON plan and the `ahub: blocker:` lines; the exit codes are unchanged. The screens add no way to change an operation: every choice runs one
2652
2709
  of the commands in this section for you, so that command's refusals decide.
2653
2710
 
2654
2711
  The screens use the console palette and `--color=auto|always|never`, with the
2655
2712
  same `NO_COLOR` and `TERM=dumb` precedence. Auto colours a suitable TTY; explicit
2656
2713
  always has the console's override behaviour. Raw JSON bypasses colour and width
2657
- handling. Default and never preserve the existing pipe, dry-run, status and
2658
- dispose output byte for byte. Presentation flags go after the command, for
2714
+ handling. Default and never print the same readable pipe, dry-run, status and
2715
+ dispose text, and `--json` keeps the previous documents byte for byte. Presentation flags go after the command, for
2659
2716
  example `ahub recovery --color=never` or
2660
2717
  `ahub recovery status <operation-id> --json`. An explicit `--json` returns only
2661
2718
  the raw document, without a human suffix. `upgrade --json` reviews a JSON plan;
@@ -2989,7 +3046,9 @@ next actions").
2989
3046
  AND pid = <pid>"` (`ahub projects --json` shows the id). A
2990
3047
  project whose directory is
2991
3048
  gone is only recorded (`ahub doctor --orphans` lists a hub left running
2992
- there). It records its decision before it acts. It releases a source hold of
3049
+ there). It records its decision before it acts; that audit entry keeps the
3050
+ operation's error at that moment as `cause`, because disposal clears the
3051
+ error itself (#776). It releases a source hold of
2993
3052
  its own (that hub keeps running), stops a target hub it started and has not
2994
3053
  released (one an older coordinator started is stopped at that release's
2995
3054
  control protocol), moves that operation's
@@ -3261,7 +3320,7 @@ The person can retain superseded work as closed history:
3261
3320
  ahub task cancel <id> --reason <text> [--superseded-by <ref>] [--revision N]
3262
3321
  ```
3263
3322
 
3264
- The console also offers cancellation with the selected task's flow revision. Approved tasks cannot be cancelled. The planner's `hub_task_cancel` tool is limited to its own unaccepted backlog/proposed work; previously accepted work requires the person. Cancellation sends the former owner/reviewer a stop notice, releases overlap/reservation participation and keeps dependents blocked with a cancelled-dependency notice. It does not stop a native turn, delete a worktree or write an outcome memory note. Cancelled work is closed history, counted separately from approved work; it does not satisfy an approval dependency. A still-running private turn keeps its privacy fence after cancellation. Use the displayed revision to avoid acting on a task that changed while it was selected.
3323
+ The console also offers cancellation with the selected task's flow revision. Approved tasks cannot be cancelled. The planner's `hub_task_cancel` tool is limited to work it proposed that is in backlog or proposed with no execution evidence: never started, or accepted by an owner and then declined or returned untouched (no branch, commit, PR, local check, done, verdict or reopen, the same test as `hub_backlog_return_untouched`, #812). Work with any such evidence requires the person. Cancellation sends the former owner/reviewer a stop notice, releases overlap/reservation participation and keeps dependents blocked with a cancelled-dependency notice. It does not stop a native turn, delete a worktree or write an outcome memory note. Cancelled work is closed history, counted separately from approved work; it does not satisfy an approval dependency. A still-running private turn keeps its privacy fence after cancellation. Use the displayed revision to avoid acting on a task that changed while it was selected.
3265
3324
 
3266
3325
  The daemon advertises `task_cancel`; a current CLI refuses cancellation against older daemons. Recovery retains verified target features beside its immutable root/digest, reuses them on resume and on each lease renewal before a terminal is closed, and checks only sources not yet past commit; a legacy receipt without that evidence needs a target probe only before commit. Upgrade/restart refuses a target without this feature while cancelled rows exist and names their ids. No cancelled row is rewritten as approved. An old binary launched by hand remains unsupported: it can count cancelled work as open or fail to move it. Use a compatible coordinator instead. Live task cancellation and sweep enablement are separate post-release operations.
3267
3326
 
@@ -3365,7 +3424,11 @@ protection (sandbox, text projection) is covered by its regression test. Each na
3365
3424
  checkout bytes, then must fail an assertion with the corresponding guard weakened.
3366
3425
  Seed rot (anything other than one exact replacement), a surviving seed and an
3367
3426
  invalid detection have distinct errors. Compiler, setup, unrelated-test and timeout
3368
- failures never count as detection.
3427
+ failures never count as detection. When the anchor text is missing, the seed-rot
3428
+ error also names the base commit, the symbol that held the anchor there and that
3429
+ symbol's current file and line, or says which part is unknown (#778). This is
3430
+ evidence only: the exact-match rule still fails the pair. `--base <commit>` names
3431
+ the base; without it the runner uses the merge base with `origin/main`.
3369
3432
 
3370
3433
  Each seed has a private temporary checkout without Git metadata, state, output
3371
3434
  directories or user untracked files. Installed dependency packages are linked,
@@ -3375,8 +3438,9 @@ registry directories and a scrubbed environment. The normal 20-second test timeo
3375
3438
  both legs. Successful fixtures are removed; a failed pair prints its preserved
3376
3439
  fixture location with test and leak evidence for inspection.
3377
3440
 
3378
- CI runs the pairs as four Linux shards (`bun scripts/seeded-check.ts --shard i/4`,
3379
- every fourth pair, still sequential within a shard) beside the ordinary checks; the
3441
+ CI runs the pairs as four Linux shards (`bun scripts/seeded-check.ts --shard i/4 --base <ref>`,
3442
+ every fourth pair, still sequential within a shard; the base is the PR's base commit
3443
+ or the push's previous one, on a full-history checkout) beside the ordinary checks; the
3380
3444
  required job `seeded guards` passes only when all four shards passed (#457). The pairs
3381
3445
  do not repeat on macOS or run recursively inside `bun test`. The runner reports every
3382
3446
  pair's elapsed seconds and the total runtime. A green ordinary check alone does
@@ -3640,10 +3704,22 @@ The playbook lifecycle (#257, #481) is off without `.agenthub/sdlc.toml`. When e
3640
3704
  ## Optional Qwen Code peer
3641
3705
 
3642
3706
  Select Qwen per project with `ahub roster add qwen`; it defaults off and is absent
3643
- from default class preferences. `ahub qwen [--mode headless] [--model <alias>]`
3644
- starts its ACP peer. `--print-command` previews; TUI is refused until #286's
3645
- verification. `ahub stop qwen` stops the owned process group. A conductor may start
3646
- it only through the selected roster and existing capabilities.
3707
+ from default class preferences. `ahub qwen [--mode headless|tui] [--model <alias>]`
3708
+ starts its ACP peer (headless) or Qwen's own TUI in your terminal (below).
3709
+ `--print-command` previews either. `ahub stop qwen` stops the owned process group
3710
+ of a headless Qwen. A conductor may start the headless form only through the
3711
+ selected roster and existing capabilities; the TUI is always a person's start.
3712
+
3713
+ ### Qwen's own TUI, driven through dual output (#286 Part 3)
3714
+
3715
+ `ahub qwen --mode tui` runs `qwen --input-file <in> --json-file <out> --mcp-config <hub server> --approval-mode default` in the terminal you ran it from. The daemon prepares the two files (mode 0600, under `<state dir>/qwen/qwen-dual/`) and returns the launch; the hub then appends one `submit` line per delivery and tails the event file from a saved offset. It needs a Qwen the dual-output compat entry verifies (`ahub agents` shows `qwen-dual`, verified 0.26.1 only; the headless `qwen` entry is separate and unchanged) and refuses another version before it creates a file. The TUI is explicit only: `ahub qwen` without `--mode` is still headless, Qwen is not a start-mode peer, and the hub never opens this terminal by itself. The TUI start is refused for an extra Qwen instance, off roster, outside a terminal, and while a headless Qwen runs (`ahub stop qwen` first); a headless start is refused while the TUI holds its terminal.
3716
+
3717
+ - What the hub does: a delivery becomes a `submit`; the last assistant message of the turn (an `assistant` event whose `stop_reason` is not `tool_use`, then `message_stop`) is shared as the answer; busy and idle follow the events. A `can_use_tool` request goes to the console approval path (`ahub permit`, the dashboard), and the hub's own tools are approved only by their exact `mcp__agent-hub__<tool>` name. If you answer a prompt in the Qwen terminal first, the hub's pending approval is withdrawn.
3718
+ - **Limit 1, a deny ends the turn without an answer.** Qwen emits nothing when the hub denies: it cancels the whole turn. The hub ends the turn itself, shares no answer, settles the delivery as `completed` (a deny is a known outcome, and a `needs_review` would hold every later message to Qwen until a person resolved it) and says so in a notice. A turn whose outcome is not known (Qwen exited, an Esc followed by a new prompt, an event file that became unreadable) is the one that settles `needs_review`.
3719
+ - **Limit 2, the hub cannot stop a Qwen turn.** The input protocol has only `submit` and `confirmation_response`, and a signal does not stop a running turn. The inactivity watchdog therefore never cancels: after `watchdog_ms` of silence it marks the turn stalled (`ahub status`, the console and the dashboard say "press Esc in the Qwen terminal") and keeps the peer busy. The hub never types into your terminal and never signals Qwen to stop a turn.
3720
+ - A Qwen write or shell command that names the hub state directory is refused (see [security](security.md): the input file is a prompt channel).
3721
+ - If the hub cannot read the event file the peer is `detached`, shown as offline with a notice, never idle: Qwen itself keeps working, and the hub reattaches when the file is readable again.
3722
+ - Restart: if the hub restarts while your Qwen keeps running, it reads on from its saved offset (no event twice, no launch). If Qwen is gone, `ahub qwen --mode tui` starts `qwen -r <session id>` on the same two files; the earlier submits are not replayed and the recorded answers are not shared again. Recovery never restores this terminal as a headless worker, and `ahub stop qwen` refuses: end Qwen in its own terminal.
3647
3723
 
3648
3724
  Receipt-verified native ACP identities are qwen-code 0.25.0 and 0.26.0 ([dated receipt](verification/2026-10-22-kimi-qwen-compat.md)). A CLI version label alone
3649
3725
  is insufficient: startup verifies its native identity/version and advertised mode
@@ -3740,7 +3816,7 @@ A bundled adapter module is authorized by the person with `adapter_modules` (at
3740
3816
 
3741
3817
  - A person opens `ahub watch kimi` or `ahub watch qwen` in a second terminal. `--no-thoughts` hides thought items; `--color=auto|always|never` controls colour. `q` or Ctrl+C leaves the view, keeping the peer running. Answer approvals in `ahub console` or with `ahub permit`.
3742
3818
  - Watch replays bounded memory history from this daemon, then displays live updates. It is the hub's read-only view, with no prompt input. It does not read native session files.
3743
- - Kimi's default is its own pull-only TUI (#316). Watch requires `ahub kimi --mode headless`; its own TUI remains visible in its native terminal. Qwen requires roster participation and a receipt-verified ACP identity. `ahub qwen --mode tui` remains refused.
3819
+ - Kimi's default is its own pull-only TUI (#316). Watch requires `ahub kimi --mode headless`; its own TUI remains visible in its native terminal. Qwen requires roster participation and a receipt-verified ACP identity. Watch is for headless Qwen; `ahub qwen --mode tui` is Qwen's own terminal (see Optional Qwen Code peer) and has no watch view.
3744
3820
  - Protocol stays 16; a same-protocol older daemon answers the new request as unknown, which the CLI reports. Since 0.12.44 a headless start that the hub itself makes for Kimi or Qwen opens this view automatically through the terminal provider (see Start modes; #286).
3745
3821
  - Native T0 limits: [ACP watch verification](verification/2026-10-11-acp-watch-t0.md).
3746
3822
 
@@ -3925,7 +4001,12 @@ Capacity defaults to one per peer. Each declared instance has its own `tasks.wip
3925
4001
  uses the existing machine-local registry path; integers 0..32 apply live (the next
3926
4002
  admission reads the current value), with 0 disabling planner admission for that
3927
4003
  peer. Status and the agent legend count
3928
- owned unfinished work plus unowned planner-pull reservations. The same limit gates
4004
+ owned unfinished work plus unowned planner-pull reservations, and show how that
4005
+ count splits (#784): `ahub status` prints `<peer> planner WIP 3/3 (active 2, review-wait 1, reserved 0)`,
4006
+ the console Peers detail (Enter) has a `planner WIP` line, and the dashboard legend shows the same split.
4007
+ `active` is owned work that is not waiting for review, `review-wait` is owned work in review (it still
4008
+ holds its slot), `reserved` is a planner-pull reservation nobody owns yet; the three add up to the count
4009
+ admission reads, and the split changes no admission decision. An older hub shows the plain count. The same limit gates
3929
4010
  acceptance and self-claim in every lifecycle mode, so 0 refuses new acceptances; a
3930
4011
  current owner's redo of sent-back work keeps its slot (#481 S9).
3931
4012
 
@@ -4182,6 +4263,15 @@ restart the hub. For example, a reviewer can use:
4182
4263
  Start them with `ahub codex --as codex-review` and
4183
4264
  `ahub kimi --as kimi-review`. Codex keeps its native TUI and its own hub-owned
4184
4265
  app-server proxy; extra Kimi, Qwen, Jcode, Pi and local instances use headless starts.
4266
+
4267
+ An extra instance of any kind that holds the `implementer` role needs its own
4268
+ registered worktree on an attached branch, at exactly `.worktrees/<id>`
4269
+ (`"worktree": ".worktrees/<id>"`). Configuration validation refuses a missing one
4270
+ only for Claude channel instances and headless writers. For other kinds, Codex and
4271
+ Jcode included, the hub accepts the declaration at startup and then refuses the start
4272
+ with `an extra implementer requires an explicit managed worktree`. Create and
4273
+ register the worktree before the start; the hub never creates it.
4274
+
4185
4275
  Extra Jcode instances are supported (#685), in `.agenthub/config.local.json` only:
4186
4276
 
4187
4277
  ```json
@@ -4281,21 +4371,23 @@ From 0.12.37 reviews can rotate across fresh headless Claude and Codex reviewers
4281
4371
  "codex-review": { "kind": "codex", "roles": ["reviewer"], "start_mode": "headless", "review_mode": "fresh" },
4282
4372
  "kimi-review": { "kind": "kimi", "roles": ["reviewer"], "start_mode": "headless", "review_mode": "fresh" }
4283
4373
  },
4284
- "review": { "pool": ["claude", "codex", "kimi"], "rerotate": false }
4374
+ "review": { "pool": ["claude", "codex", "kimi"], "rerotate": false, "same_family": "fallback" }
4285
4375
  }
4286
4376
  ```
4287
4377
 
4378
+ `review.same_family` (#820) is `"fallback"` (the default) or `"never"`. With `"fallback"` a reviewer of the owner's family is chosen only when no other family is eligible, and the board records a same-family fallback. With `"never"` routing never selects one, in the pool and in the legacy path: the planner reviews when it holds the reviewer role, is not the owner, is of another family and is not blocked, otherwise the person does (`reviewer = "user"`, recorded as blocked), including when every reviewer is offline: an approval without review never happens under `"never"`. A manual `ahub task assign <id> <peer> --role reviewer` of a same-family peer is refused with `same family as <owner>; review.same_family is never`. `ahub route explain <id>` names the rule in its trace. Use `"never"` when the workspace review gate needs the reviewer to be a different AI than the implementer; a Jcode running a Claude model is still family `jcode`.
4379
+
4288
4380
  Start them with `ahub claude --as claude-review`, `ahub codex --as codex-review` and `ahub kimi --as kimi-review`; stop with `ahub stop <id>`. For the Claude and Codex reviewers the command asks the running hub to start the reviewer and returns: nothing runs in that terminal, it takes no launch arguments, and `--print-command` or `--dry-run` prints a hub-start note instead of a launch (#720). Fresh Claude and Codex variants share the project checkout; the Kimi variant runs in a clean temporary working directory and reviews only the screened brief and host facts. All fresh variants refuse a custom worktree or permission mode. Codex and Kimi require `review_mode: "fresh"`; without it, an existing headless instance with the reviewer role keeps its native app-server/ACP behavior, worktree and permission options and does not join this pool. Claude retains its #223 automatic headless-reviewer declaration. The agy reviewer slot remains automatically unavailable (`agy is an implementer peer (#485)`). A failed or unsupported fresh start never downgrades to a native continuing session. Ordinary implementer instances retain their own adapters. The default logical pool order is Claude, Codex, Kimi. Only configured kinds with at least one declared reviewer count as slots, including declared ones that are offline, paused, quota-limited or failing, so availability never renumbers them; configured kinds with no declaration are listed after the walk as `no declared reviewer`. `review.rerotate` defaults to false. Pool selection starts at PR number modulo the number of declared kind slots, or task id when there is no PR, then skips the implementer's family and unavailable candidates. Delta review prefers the preceding eligible independent family in a fresh child. A preceding same-family fallback does not outrank a newly available independent family. `ahub route explain` shows the same pure walk.
4289
4381
 
4290
- Codex requires a verified `codex-cli` (0.146.0, 0.163.0 or 0.164.0) or one the person trusts on this machine, and a passing bounded runtime receipt before its model child starts. 0.146.0 and 0.163.0 passed the [2026-10-22 model-free production admission](verification/2026-10-22-codex-reviewer-isolation.md) and 0.164.0 the [2026-10-24 one](verification/2026-10-24-codex-0164-reviewer-isolation.md). A refusal names the installed and verified versions. Either set `codex_bin` to a verified executable, or run `ahub agents trust codex-review <version>`: trust lifts only the version pin, and every proof below still runs before each child (#691). The producer checks native binary/config stability, configured MCP inventory with only the two hub tools, effective Apps/plugins/hooks disablement, an explicit empty legacy `notify` command and a named filesystem profile. Apps needs separate feature readback because configured inventory omits runtime connectors. Web search is requested disabled; its effective turn mode is not read back and managed requirements can select Cached (see the verification ceiling). Each launch proves public-read, exact/glob/symlink private-denial, standard host credential denial and write-denial in temporary fixtures. Standard credential and configured tool-home/XDG subtrees are denied independently of project `local.deny`. Its sandboxed shell is filesystem read-only with private paths denied and network configured disabled; it is not Claude's Read/Grep/Glob-only tool whitelist. No credential home is copied.
4382
+ Codex requires a verified `codex-cli` (0.146.0, 0.163.0 or 0.164.0) or one the person trusts on this machine, and a passing bounded runtime receipt before its model child starts. 0.146.0 and 0.163.0 passed the [2026-10-22 model-free production admission](verification/2026-10-22-codex-reviewer-isolation.md) and 0.164.0 the [2026-10-24 one](verification/2026-10-24-codex-0164-reviewer-isolation.md). A refusal names the installed and verified versions. Either set `codex_bin` to a verified executable, or run `ahub agents trust codex-review <version>`: trust lifts only the version pin, and every proof below still runs before each child (#691). Each launch approves exactly `hub_review` and `hub_task_show` per tool (`approval_mode = "approve"`), never through a server-wide default: without it Codex 0.164.0 listed the tools but refused the call, so reviews ended with no verdict (#783). A model-free receipt proves the inventory, not that a verdict reaches the hub; a [model-backed 0.164.0 run](verification/2026-10-25-codex-0164-reviewer-tool-call.md) recorded one verdict through that path. The producer checks native binary/config stability, configured MCP inventory with only the two hub tools, effective Apps/plugins/hooks disablement, an explicit empty legacy `notify` command and a named filesystem profile. Apps needs separate feature readback because configured inventory omits runtime connectors. Web search is requested disabled; its effective turn mode is not read back and managed requirements can select Cached (see the verification ceiling). Each launch proves public-read, exact/glob/symlink private-denial, standard host credential denial and write-denial in temporary fixtures. Standard credential and configured tool-home/XDG subtrees are denied independently of project `local.deny`. Its sandboxed shell is filesystem read-only with private paths denied and network configured disabled; it is not Claude's Read/Grep/Glob-only tool whitelist. No credential home is copied.
4291
4383
 
4292
- Kimi requires a compat-admitted Kimi Code on the hub's PATH (receipt-verified 2.2.0 and 2.3.0), signed in through its managed OAuth provider, and a passing runtime preparation before each child; an unverified/untrusted version or a failed preparation is unavailable with its reason. The [2.3.0 receipt](verification/2026-10-22-kimi-qwen-compat.md) is model-free and does not verify real login/provider readiness. Each review runs a new `kimi -p` child without Seatbelt, in a private `KIMI_CODE_HOME` with managed-provider-only config, a clean temporary working directory and an empty skills directory. Its agent may call only `hub_review` and `hub_task_show`, through a task-bound loopback MCP session that never carries the hub's control token, and has no native read, file or shell tool: it reviews the screened brief and host facts only. Its `credentials/`, `oauth/` and `device_id` link to the person's native Kimi files, so it shares the native login, refresh lock and the Kimi account's budget; no token is copied. A stop revokes its verdict authority first, then waits briefly while an OAuth refresh holds the lock; a forced stop mid-refresh may require a native re-login. The Kimi backend records no measured token counts here, so its usage stays unknown; the 2.3.0 receipt makes no usage claim. This is a native tool-authority boundary, not filesystem or network isolation.
4384
+ Kimi requires a compat-admitted Kimi Code on the hub's PATH (receipt-verified 2.2.0, 2.3.0 and 2.3.1), signed in through its managed OAuth provider, and a passing runtime preparation before each child; an unverified/untrusted version or a failed preparation is unavailable with its reason. The [2.3.0](verification/2026-10-22-kimi-qwen-compat.md) and [2.3.1](verification/2026-10-25-kimi-231-reviewer-compat.md) receipts are model-free and do not verify real login/provider readiness. Each review runs a new `kimi -p` child without Seatbelt, in a private `KIMI_CODE_HOME` with managed-provider-only config, a clean temporary working directory and an empty skills directory. Its agent may call only `hub_review` and `hub_task_show`, through a task-bound loopback MCP session that never carries the hub's control token, and has no native read, file or shell tool: it reviews the screened brief and host facts only. Its `credentials/`, `oauth/` and `device_id` link to the person's native Kimi files, so it shares the native login, refresh lock and the Kimi account's budget; no token is copied. A stop revokes its verdict authority first, then waits briefly while an OAuth refresh holds the lock; a forced stop mid-refresh may require a native re-login. The Kimi backend records no measured token counts here, so its usage stays unknown; the 2.3.0 receipt makes no usage claim. This is a native tool-authority boundary, not filesystem or network isolation.
4293
4385
 
4294
4386
  A dangling or unreadable standard/configured credential root makes the Codex reviewer unavailable with only its path class in the reason (for example `~/.docker` or `$DOCKER_CONFIG`, never an expanded path or contents); repair the root and start the reviewer again.
4295
4387
 
4296
4388
  agy is not a reviewer (person decision, 2026-10-19): it is an optional implementer peer (see [Optional Antigravity peer](#optional-antigravity-agy-peer)), and its retained reviewer slot is outside the default pool and always unavailable with `agy is an implementer peer (#485)`. A manual pool accepts only registered reviewer kinds (Claude, Codex, Kimi, agy), so local/Pi are refused. An explicit pool without declared candidates blocks for person action; an omitted pool retains legacy routing without declarations and falls back to an eligible planner when fresh candidates are exhausted. The exhausted pool walk remains recorded; without an eligible planner, the person reviews. A manual pool may name agy, or a Kimi reviewer whose preparation fails; the reason appears as an unavailable skip, and they never run or count as approval. Do not substitute plan mode for isolation.
4297
4389
 
4298
- A failed start or any child ending without a saved verdict advances to the remaining eligible candidates; no quota meaning is guessed from text. A same-family fallback is a distinct fresh reviewer session. Exhaustion records `blocked: no reviewer can run`; with no explicit pool the eligible planner fallback is retained, while an explicit pool or absent eligible planner leaves person action. It never auto-approves. A per-review isolation preparation failure excludes that peer from later tasks until a verified restart. Its reason names one cause from a closed list (`version`, `binary`, `mcp_inventory`, `plugins_hooks_apps`, `sandbox_proof`, `credential_root`, `timeout`, `unknown`) with a fixed hint, on the peer's `reviewer` line in `ahub status` and in a `hub.log` line, and never a path, native CLI text or token (#722). Only the Codex preparation classifies its failures; other reviewers report `unknown`. Recovery targets must advertise `reviewer_pool` when a pool is explicitly configured or fresh reviewer instances are declared. Verdict history retains `reviewContext` and adds `reviewerFamily` and `reviewerReason` from the host.
4390
+ A failed start or any child ending without a saved verdict advances to the remaining eligible candidates; no quota meaning is guessed from text. A request that went stale before its child started (a new head, review revision or reviewer) is skipped with one `hub.log` line; a still-current request whose review policy changed moves on as `no_verdict`. Neither marks the reviewer unavailable (#781). A child that ends without a verdict leaves one bounded `hub.log` line: its exit code and the hub tools it called, screened like any refusal, never tool arguments or model text. Its delivery completes only once the re-offer is confirmed; an unconfirmed re-offer stays `needs_review`. A manually named reviewer's no-verdict, and one with no declared pool, goes to the person, never to an agent the person did not choose (#453). A same-family fallback is a distinct fresh reviewer session. Exhaustion records `blocked: no reviewer can run`; with no explicit pool the eligible planner fallback is retained, while an explicit pool or absent eligible planner leaves person action. It never auto-approves. A per-review isolation preparation failure excludes that peer from later tasks until a verified restart. Its reason names one cause from a closed list (`version`, `binary`, `mcp_inventory`, `plugins_hooks_apps`, `sandbox_proof`, `credential_root`, `timeout`, `unknown`) with a fixed hint, on the peer's `reviewer` line in `ahub status` and in a `hub.log` line, and never a path, native CLI text or token (#722). Only the Codex preparation classifies its failures; other reviewers report `unknown`. Recovery targets must advertise `reviewer_pool` when a pool is explicitly configured or fresh reviewer instances are declared. Verdict history retains `reviewContext` and adds `reviewerFamily` and `reviewerReason` from the host.
4299
4391
 
4300
4392
  Fake-CLI tests and CI cover these host contracts. [Offline isolation evidence](verification/2026-10-19-reviewer-isolation.md) and fake-CLI tests do not prove an account/model review or observed network denial. Native acceptance remains a separate [manual smoke leg](smoke.md#reviewer-pool-native-legs-519-2026-10-19); existing #223 Claude behavior has no new live proof here. Kimi's authenticated fresh-verdict receipts, and its still-open interactive-TUI coexistence and usage checks, are tracked in [Kimi smoke legs](smoke.md#kimi-reviewer-and-task-bound-mcp-533).
4301
4393
 
@@ -4370,7 +4462,7 @@ Native launcher connections retry transport timeouts/unclean closes with bounded
4370
4462
 
4371
4463
  ## amem runtime (agent-mem#13 P4)
4372
4464
 
4373
- The hub exact-pins @staix/agent-mem 0.7.0 for recall, curated evidence and local deterministic capture. No runtime call reaches a claude-mem worker; `memory.worker_url` is ignored. The person's `ahub memory import claude-mem` remains explicit and off by default. Existing profile, alias, PII and private-turn fences still apply. `ask --remember` and context checkpoints propose machine-local candidates, never automatic curated evidence. See [memory integration](memory.md#in-process-recall-and-capture-agent-mem13-p4) for changed behavior and bounded-view ceilings.
4465
+ The hub exact-pins @staix/agent-mem 0.8.0 for recall, curated evidence and local deterministic capture. No runtime call reaches a claude-mem worker; `memory.worker_url` is ignored. The person's `ahub memory import claude-mem` remains explicit and off by default. Existing profile, alias, PII and private-turn fences still apply. `ask --remember` and context checkpoints propose machine-local candidates, never automatic curated evidence. See [memory integration](memory.md#in-process-recall-and-capture-agent-mem13-p4) for changed behavior and bounded-view ceilings.
4374
4466
 
4375
4467
  ## Backlog issue identity and notes
4376
4468
 
@@ -4399,3 +4491,27 @@ In the dashboard Memory view (#684 phase 4), select a symbol and enable Code nei
4399
4491
  `hub_memory_graph` includes the same bounded derived context for symbol starts within its existing 6 KB output budget. Task briefs prioritize attached fails and decisions within `brief_items`; the console related-note count refers to that bounded selection. Code facts remain optional: no index is copied into memory, no graph edges are persisted and no PII task/turn starts a query.
4400
4492
 
4401
4493
  Optional code work runs only while Memory is open and visible. A cold console count reports unknown immediately; it does not prepare code facts. Direct task memory remains available when optional code facts are ineligible, interrupted or unavailable. Review/completion queries pre-empt optional native work after its owned process/tree cleanup. Unknown lookups have a five-second retry floor; topology caches are commit-bound and note bodies are refreshed under current policy. These are advisory coverage bounds, not empty-result proofs.
4494
+
4495
+ ## Authority by command
4496
+
4497
+ ### Conductor operations (#812 T2)
4498
+
4499
+ The selected project's configured conductor may run the commands below through its ordinary peer identity. Other peers retain the guidance "the person runs it in ahub console or a terminal". A daemon round trip is permitted, but an unreachable hub refuses promptly rather than waiting for the ordinary connection timeout. Refused operations are audited as refused. The daemon checks the authenticated connection, current role and project membership before effects and after asynchronous boundaries. Roster handoffs carry that same authority check through plan admission, owner delivery and each later task; a saved assignment is never rolled back when delivery is interrupted. It records an `agent_cli` admission with the initiating peer before proceeding; audit failure refuses the operation. Admission records are not a unique invocation counter.
4500
+
4501
+ | Command | Conductor scope |
4502
+ | --- | --- |
4503
+ | roster add/remove | Existing roster lifecycle and confirmations; no role or permission-mode grant |
4504
+ | stop peer | Existing hub-owned peer stop, ownership and recovery guards |
4505
+ | queue show/resolve/discard | Public queue projection and existing revision/confirmation guards |
4506
+ | task cancel | Existing hub_task_cancel with the real peer; eligibility follows the task-board policy |
4507
+ | doctor --orphans --kill | Selected project's positively identified hub-owned process only; no cross-project registrations or unsigned process files |
4508
+ | logs / export | Bounded daemon projections, with unsupported/private records withheld; logs -f ends when authority ends |
4509
+ | settings set | Only the twelve existing live registry keys listed below |
4510
+
4511
+ The exact settings keys are `task_sweep.enabled`, `task_sweep.auto_reassign`, `task_sweep.no_writes_turns`, `task_sweep.interval_s`, `task_sweep.unaccepted_min`, `task_sweep.idle_min`, `task_sweep.review_min`, `task_sweep.ready_min`, `task_sweep.ladder_min`, `snapshots.enabled`, `research.enabled` and `approvals.notify`. New keys receive no authority by prefix. Generic roster setting writes still use the dedicated roster lifecycle. Conductor setting records name the initiating peer, and conductor writes preserve the person's pending undo record. An intervening write can still invalidate that undo through the existing file-digest guard; preserving the record does not bypass that guard. Permission modes, roles, `pet.window`, arbitrary configuration reload and undo remain person commands.
4512
+
4513
+ Log history is limited to the last 100 retained lines and export to the last 1000 retained events, each within a 128 KiB read. Truncation is explicit. Export accepts closed metadata shapes; unknown fields and nested records are withheld rather than copied. Task titles, paths and private delivery bodies are not part of this projection. It does not change the person's ordinary logs/export output.
4514
+
4515
+ Orphan cleanup requires a missing selected root, signed process identity and the host-known hub executable/entrypoint and argv. An inaccessible root or unavailable proof remains unknown; there is no offline config-based role grant. The daemon rechecks authority and process ownership before signals. A confirmed self candidate uses the existing lifecycle stop after its reply. A roster write already committed before authority ends is acknowledged as saved, without authorizing further lifecycle work or commands.
4516
+
4517
+ `restart --yes` and `recovery resume/abort` await a project-scoped continuation proof. `task unassign` follows #481, and legacy models start/stop awaits a project that needs it. This slice adds no task eligibility rule and no MLX/recovery-driver changes. Person authority and the separately authorized `--live-test` path retain their existing behavior.
package/docs/profiles.md CHANGED
@@ -56,3 +56,39 @@
56
56
  - `role_text` is bounded guidance for existing flow roles (2000 characters each); it grants no authority. `catalog_roles` supplies bounded compatible guidance ids; the existing explicit catalog selections take precedence. Actual flow maps remain in `roles` and retain their existing validation.
57
57
  - `agents` replaces only the managed AGENTS block (16000 characters maximum); surrounding instructions remain. Init previews contain paths/actions only. `example_checks` is at most 16 display strings of 2000 characters, shown as advisory examples by init and never selected as executable checks. `review_checklist` is at most 16 non-empty strings of 500 characters, customizing the checklist items in review requests with `{target}` and `{check}` interpolations. Existing `checks` trust remains authoritative.
58
58
  - No override mutates shipped profile data or another project. Unknown fields, base remapping and invalid/oversized data are refused. Headers are quoted. Daemon/MCP restart is required for config changes; no native model consumption or research measurement is claimed.
59
+
60
+ # Profile scorecard (#799)
61
+
62
+ The existing ahub report --dogfood command adds a profile section when the selected profile is non-dev, or bound non-dev tasks have evidence in the requested window. Dev-only JSON and readable output retain their prior bytes. Existing flow, quality, cost and other fields keep their meanings; the profile section does not require merged PRs.
63
+
64
+ Rows include profile totals and class-alias groups with the stored base class. A task keeps its recorded profile across later configuration changes. Public custom aliases remain bounded identifiers; private custom aliases are withheld. Task titles, paths, notes, checklist prose and model text are not exported. Private pii/pii_path tasks are counted by id and number.
65
+
66
+ A missing, incomplete or unsupported source produces JSON null, rendered as unknown in the readable report. A complete source can prove zero recorded events; it cannot prove zero events for a category that has no recorder. Source completeness and flow scope distinguish history-backed totals from recorded-window observations. Profile bindings, including event-only fallback, are capped at 500; a capped window reports incomplete/unknown totals rather than extrapolating. Automatic approvals are flow transitions, not reviewer rounds or first-pass review samples.
67
+
68
+ | Row group | Existing evidence | Unmeasured ceiling |
69
+ | --- | --- | --- |
70
+ | Flow | Bound task history and complete task-event windows; observed automatic approvals | Undated approvals, incomplete history and first-pass review without history remain unknown |
71
+ | Review | Explicit verdicts and structured public unmet-criteria ids | Profile checklist prose has no item-id recorder; private criterion ids are withheld |
72
+ | Overlap | Recorded path/section notices and later matching pair/path edit facts | Observed path-edit pairs imply no authorship or causation; section edit confirmation remains unknown |
73
+ | Deliverables | Deduplicated ids in recorded deliverable histories | No new file reads; changed-since-approval and current unknown states remain unknown |
74
+ | Privacy | Private task flags and generic attributed PII note-screen records | Screen records do not identify the operation; memory drops, refusals and capture totals remain unknown without operation-specific counters |
75
+ | Undo | No additional recorder introduced | Request, completion and guard-refusal totals remain unknown |
76
+ | Snapshots | Already-recorded, attributed snapshot durations | No new recording; budget exhaustion and absent durations remain unknown |
77
+ | Profile errors | No additional recorder introduced | Unknown/foreign alias-refusal totals remain unknown |
78
+ | Cost | Existing task-attributed token/usage summaries | Missing usage and attribution remain unknown; no provider/model prose is exported |
79
+
80
+ Research rows also expose bounded current-plan source and claim counts per task. Claim slots are anonymous ordinal numbers; declaration text and identifiers are never exported. In a stored board plan a key the plan omits counts as zero declarations, as an explicit empty list does; a cut or malformed plan leaves that one task's declarations unknown without affecting the rest of the board. These are current-plan counts, not a reconstruction of past plans.
81
+
82
+ Each research class alias retains its own recorded task-check pass/fail counts under `observedCheckOutcomes`. Those history events do not record which check key ran. Consequently `factCheck` pass/fail, check selection and missing-key counts per run remain unknown until that provenance is recorded. No new telemetry is collected. Model labels, person verdicts, claims reaching a person verdict and per-label agreement also remain unknown because no claim-level verdict source exists. Task approval never supplies a claim verdict. Research uses the same recorded section-overlap rows as writing.
83
+
84
+ The weekly writing, general and research receipt templates are in the verification/profiles directory. Copy only the emitted profile subsection, preserve null values, and include no project/person names or paths. A template is not a completed measurement or a live acceptance claim.
85
+
86
+ The following verification claim ids collect the still-unverified statements above. A weekly receipt gives each a verdict of supported, partly supported or not supported, tied to recorded ids and remaining unknowns. Profile counts alone do not prove native ingestion, context retention or account acceptance; those verdicts need corresponding native/account receipt ids and independent judgment. None becomes verified merely because this reporting section exists:
87
+
88
+ - writing-live-example: an observed writing workflow.
89
+ - general-live-example: an observed general workflow.
90
+ - research-live-example: the live three-source/two-agent research example.
91
+ - native-model-ingestion: native peers consuming profile guidance and tasks.
92
+ - context-retention: profile/task context retained through the relevant native turns.
93
+ - native-account-research: a real native/model/account research workflow.
94
+ - research-measurement: observed research-profile measurements.
@@ -17,7 +17,7 @@ ahub setup # installs the Claude Code channel plu
17
17
  Or use the matching GitHub release:
18
18
 
19
19
  ```bash
20
- bun add -g github:STAIxBWLB/agent-hub#v0.16.0
20
+ bun add -g github:STAIxBWLB/agent-hub#v0.18.0
21
21
  ahub setup
22
22
  ```
23
23
 
@@ -30,6 +30,16 @@ and upgrade or crash recovery, see the [operations guide](operations.md). To
30
30
  move running projects to a newer release later, run `ahub upgrade` in a
31
31
  terminal: it reviews the plan with you, applies it and follows it.
32
32
 
33
+ ## Upgrading to 0.18.0
34
+
35
+ The `ahub sdlc` read commands (`status`, `explain`, `queue`, `release`, `metrics`, `costs`, `authorize-release`) now print readable output by default, no longer a JSON document (#814). A script that parses their output must pass `--json`: it prints exactly what the command printed before. `sdlc export` stays JSON. `restart` and `upgrade` off a terminal (a pipe or `--dry-run`), `recovery status` and its results, `models setup|start`, `queue resolve` and `budget execution configure|disable` follow (#814): pass `--json` for the old document. `task show|cancel`, `backlog groom|return|plan|pin|split|undo|pull-ready` and `release list|show|new|plan|activate|freeze|ship|drop` follow (#814): pass `--json` for the hub tool's text. More commands follow in later releases.
36
+
37
+ Agents can now run the read-only `ahub` forms themselves (`doctor`, `projects`, `models status`, `recovery status`, `queue list`, `roster`, `settings` reads, `sdlc status|explain|queue|release`, `release show` and the `--dry-run` previews of `upgrade` and `restart`), and the configured conductor can run `stop`, `queue show|resolve|discard`, `task cancel`, `roster add|remove`, `logs`, `export`, `doctor --orphans --kill` and `settings set` on twelve live keys (#812). Nothing changes for a person's terminal. `sdlc.toml` gains `auto_merge` (`off` by default): set `dry-run` to see what the guarded merge and the one-per-verdict GitHub COMMENT review would do before setting `on` (#786). `review.same_family = "never"` keeps a same-family reviewer from being assigned (#820). In `ask-when-needed`, Pi and the local worker run proven bounded read-only shell commands without asking (#816). The isolated remote Docker check runner is opt-in through `checks.runner = "remote"` in the person's untracked `config.local.json` (#793). `@staix/agent-mem` is pinned at 0.8.0.
38
+
39
+ ## Upgrading to 0.17.0
40
+
41
+ `ahub qwen --mode tui` runs Qwen Code's own TUI in your terminal, driven by the hub through its dual-output files (#286). It is opt-in: the hub never opens it by itself, `roster.qwen` stays off by default, and headless Qwen works as before. It needs Qwen Code 0.26.1 (a new `qwen-dual` compat entry; the headless entry is not widened), refuses an extra instance (`--as`) and refuses while a headless Qwen runs (`ahub stop qwen` first). It has two limits: a hub deny ends the turn without an answer (the delivery completes, so later messages still reach Qwen), and a stalled turn is never cancelled; the hub reports it and you press Esc in the Qwen terminal. `ahub stop qwen` does not end the TUI, and `ahub upgrade` and recovery do not restore it: end it in its terminal before you upgrade, then run `ahub qwen --mode tui` again, which resumes its session. The `codex-review` reviewer now approves exactly `hub_review` and `hub_task_show`, per tool: on Codex 0.164.0 `exec` refused every MCP tool call, so its reviews ended without a verdict (#783). A reviewer turn that still ends without a verdict leaves one screened `hub.log` line (exit code and the hub tools it called) and is offered on, or to you when you named that reviewer (#453). A stale review request that the hub refuses at admission no longer marks the reviewer unavailable: a request whose binding changed is skipped, and one whose policy changed is rerouted as no verdict (#781). An unavailable reviewer slot no longer stops the agy TUI from reading its own task (#794). An `ahub recovery dispose --stop-and-archive` audit entry now keeps the error that blocked the upgrade as `cause` (#776). A task counts toward a recurring finding only where that finding was recorded open or accepted, so a fix-only record no longer files a "Review policy amendment" card (#328), and a missing generation sync remote no longer logs a failure every sync interval (#401). Upgrade running hubs with `ahub upgrade` and restart Claude sessions so they load the 0.17.0 plugin. Coming from 0.15.0 or older, the notes below apply too.
42
+
33
43
  ## Upgrading to 0.16.0
34
44
 
35
45
  Always-ask now covers the local worker, Pi and Codex too (#636 slice 3): a local or Pi model tool call is classed before its permission mode, a `never-ask` grant, Pi's `Always allow` or `--unattended`, and a classed command approval request that Codex sends offers only allow-once, deny and the class budget. Unattended local or Pi work that publishes, installs or deletes now waits for you: answer it in the console, or change `action_policy` as in the 0.15.0 notes below. `ahub status` still lists Codex as not enforceable, because its native policy can run a command without sending a request, and Jcode as having no hub approval path. An approval whose command is cut or withheld (an ACP peer's private turn, for one) can only be denied, and a local `action_policy` that weakens the defaults is flagged on every status policy row. The classifier now reads the literal words around a shell expansion (`git push origin $B` asks) and takes the strictest class where the expansion can change it, while a `gh api graphql` call with one literal query no longer asks (#762, #756; see [security notes](security.md)). The hub no longer calls a claude-mem worker (agent-mem#13 P4): recall, briefs, `ahub ask` and the local worker's capture run in process on the exact-pinned `@staix/agent-mem` 0.7.0, `memory.worker_url` is ignored, `ahub doctor` reports the library, and `ahub ask --remember` and context checkpoints save pending candidates that only a person accepts; `ahub memory import claude-mem` stays the explicit way to copy old notes. The planner setting takes up to eight peers (`ahub settings set planner claude,codex`): each new task records one of them, only that planner or you change its planning, an agent's own plan is reviewed by another holder whenever one is online, and `ahub task assign <id> <peer> --role planner` moves it (#525-2; see [the planner](operations.md#the-planner-455)). Once a planner list is set or any task records a planner, `ahub upgrade` and recovery refuse a target release without `task_planners`, so the project cannot be moved back to 0.15.0 that way. `ahub deliverables [--task <id>] [--approved] [--check]` lists what each task delivered and a reviewer approved, and a dashboard card shows a `Deliverables n` chip (#509b). `ahub budget` prints each window's kind and source and says why a peer has no number (#285). The dashboard Memory view gains a Code neighbours toggle for a selected symbol, and `ahub doctor --stale-anchors` is a read-only report of memory symbol anchors at the current head (#684). The `codex-review` reviewer on Codex 0.164.0 no longer needs `ahub agents trust` (#757). Upgrade running hubs with `ahub upgrade` and restart Claude sessions so they load the 0.16.0 plugin. Coming from 0.14.0 or older, the notes below apply too.
@@ -92,7 +102,7 @@ The 0.12.38 plugin reports a reply stopped by the hop cap as not delivered inste
92
102
 
93
103
  Antigravity (`agy`) can join as an optional pull-only implementer (#485). It is off roster by default: install the Antigravity CLI 1.4.x (1.4.2 verified; other 1.4.x patches launch with a warning; on 1.4.3 the hub tools appear from the second TUI turn), run `ahub roster add agy`, then run `ahub agy` in a terminal. Its native permissions are unmanaged and it has no hub sandbox. See [Antigravity operations](operations.md#optional-antigravity-agy-peer).
94
104
 
95
- Reviews can rotate across fresh Claude, Codex and Kimi reviewer sessions (#519, #533). Declare headless reviewer-only instances in `.agenthub/config.local.json`; Codex and Kimi join only with `review_mode: "fresh"`. Codex also needs a compat-admitted Codex (receipt-verified 0.146.0 and 0.163.0; select it with `codex_bin` when needed), and Kimi needs a compat-admitted Kimi Code on PATH (receipt-verified 2.2.0 and 2.3.0), signed in with its own OAuth login. Run `ahub agents` for the current version policy; every fresh reviewer still needs a passing runtime preparation. The [2.3.0 receipt](verification/2026-10-22-kimi-qwen-compat.md) is model-free and does not establish real login or model readiness. A headless reviewer instance without `review_mode` keeps its native behavior and stays out of the pool. agy is not a reviewer: naming it in `review.pool` shows an unavailable skip in `ahub route explain`, never a review. Once a train is active or frozen, or `review.pool` is set or fresh reviewer instances are declared, `ahub upgrade` refuses a target release without that support, so an older release cannot take the project over. See [fresh reviewer pool](operations.md#fresh-reviewer-pool-519).
105
+ Reviews can rotate across fresh Claude, Codex and Kimi reviewer sessions (#519, #533). Declare headless reviewer-only instances in `.agenthub/config.local.json`; Codex and Kimi join only with `review_mode: "fresh"`. Codex also needs a compat-admitted Codex (receipt-verified 0.146.0 and 0.163.0; select it with `codex_bin` when needed), and Kimi needs a compat-admitted Kimi Code on PATH (receipt-verified 2.2.0, 2.3.0 and 2.3.1), signed in with its own OAuth login. Run `ahub agents` for the current version policy; every fresh reviewer still needs a passing runtime preparation. The [2.3.0](verification/2026-10-22-kimi-qwen-compat.md) and [2.3.1](verification/2026-10-25-kimi-231-reviewer-compat.md) receipts are model-free and do not establish real login or model readiness. A headless reviewer instance without `review_mode` keeps its native behavior and stays out of the pool. agy is not a reviewer: naming it in `review.pool` shows an unavailable skip in `ahub route explain`, never a review. Once a train is active or frozen, or `review.pool` is set or fresh reviewer instances are declared, `ahub upgrade` refuses a target release without that support, so an older release cannot take the project over. See [fresh reviewer pool](operations.md#fresh-reviewer-pool-519).
96
106
 
97
107
  A guarded config edit that the hub keeps at its running value now shows as `config retained: <keys>; run ahub settings reload` in status, the console and the dashboard's Settings, and starting a peer whose launch keys are retained says it uses the running value (#542). See [settings](operations.md#settings-from-the-dashboard-and-the-terminal).
98
108
 
@@ -102,7 +112,7 @@ The restarted Claude planner gets the release-train tools (`hub_release_new`, `h
102
112
 
103
113
  Jcode must be 0.98.0 or later, below 1.0.0; 0.94.0 is no longer accepted, so `ahub doctor` fails its Jcode row for an older install and the peer does not start (#529). Every owned jcode process runs with `JCODE_NO_TELEMETRY=1`.
104
114
 
105
- Since 0.12.37 the hub opens a split memory home through its shards (#534); the current exact `@staix/agent-mem` pin is 0.7.0. Before anyone runs `amem migrate --shards` on a memory home, every hub using that home must run 0.12.37 or later: an older hub does not see the split and keeps writing the old layout. `ahub memory profile-check` is split-aware and compares each hub with its own project's shard (#536). See [memory profiles and rollout](memory.md#selected-memory-profile).
115
+ Since 0.12.37 the hub opens a split memory home through its shards (#534); the current exact `@staix/agent-mem` pin is 0.8.0. Before anyone runs `amem migrate --shards` on a memory home, every hub using that home must run 0.12.37 or later: an older hub does not see the split and keeps writing the old layout. `ahub memory profile-check` is split-aware and compares each hub with its own project's shard (#536). See [memory profiles and rollout](memory.md#selected-memory-profile).
106
116
 
107
117
  From 0.12.30 or earlier, existing Jcode project MCP entries need one refresh before conductor or dashboard starts. Once per project, the person runs:
108
118
 
@@ -169,7 +179,7 @@ More: `ahub help`. How it is built and why: [`docs/specs/2026-09-19-agent-hub-de
169
179
 
170
180
  ## Shared memory
171
181
 
172
- The hub exact-pins the first-party `@staix/agent-mem` 0.7.0 core, including deterministic capture; no claude-mem worker is needed. Existing shared-v1 memory remains the default; upgrading does not migrate it. Managed agents use screened `hub_memory_search`, `hub_memory_show` and `hub_memory_graph` tools, or propose a correction with `hub_memory_correct`; only a person accepts candidates through the supported `amem review` path. Since agent-mem 0.7.0, `amem review` also accepts candidates on a selected generation.
182
+ The hub exact-pins the first-party `@staix/agent-mem` 0.8.0 core, including deterministic capture; no claude-mem worker is needed. Existing shared-v1 memory remains the default; upgrading does not migrate it. Managed agents use screened `hub_memory_search`, `hub_memory_show` and `hub_memory_graph` tools, or propose a correction with `hub_memory_correct`; only a person accepts candidates through the supported `amem review` path. Since agent-mem 0.7.0, `amem review` also accepts candidates on a selected generation.
173
183
 
174
184
  Before any real generation migration, upgrade every hub sharing that memory home to 0.12.30 or later and check its authenticated binding with `ahub memory profile-check` in each custom registry. Ready bindings prove compatibility, not an atomic live cutover: quiesce consumers and close their handles before migrating, then reopen through the supported session-preserving lifecycle. Invalid or changed profiles disable native memory without falling back to legacy writes; the bus and board continue. See [memory operations](operations.md#hub-memory) for the remaining rollout gates.
175
185
 
package/docs/roles.md CHANGED
@@ -1,6 +1,7 @@
1
1
  # Role catalog (#295)
2
2
 
3
3
  - Flow roles remain conductor, planner, implementer, verifier and reviewer. Only the existing `roles` block controls their authority and routing. Catalog roles are bounded guidance selected through `catalog_roles`; they add no tool, capability, permission mode, sandbox reach or routing preference.
4
+ - Reviewer completion (#784, this repository): the reviewer that approves a PR at its head merges it once exact-head CI is green, no review thread is unresolved and no change request is pending, then removes the branch and worktree, or names the open gate. A release PR waits for the person's release consent. This is this repository's convention (its `AGENTS.md`, outside the managed block), not a shipped default: the AGENTS block template, the catalog roles and the flow role contracts are unchanged, so another project keeps merge with the person unless its own AGENTS.md delegates it.
4
5
  - Default catalog assignments are absent. Existing flow contracts are byte-identical to main d83cb8dd when no catalog role is selected.
5
6
 
6
7
  # Definitions and layers