@staix/agent-hub 0.12.30 → 0.12.32

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 (102) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/README.md +29 -9
  3. package/docs/agent-notes/adapters.md +9 -5
  4. package/docs/agent-notes/budget.md +1 -1
  5. package/docs/agent-notes/bus.md +5 -0
  6. package/docs/agent-notes/daemon.md +14 -8
  7. package/docs/agent-notes/local-worker.md +3 -1
  8. package/docs/agent-notes/tasks.md +7 -1
  9. package/docs/agent-notes/tests.md +6 -2
  10. package/docs/cooperbench.md +1 -1
  11. package/docs/gsd-collaboration-analysis.md +1 -1
  12. package/docs/memory.md +2 -2
  13. package/docs/operations.md +236 -37
  14. package/docs/quickstart.md +24 -5
  15. package/docs/security.md +42 -10
  16. package/docs/smoke.md +34 -0
  17. package/docs/specs/2026-09-19-agent-hub-design.md +241 -3
  18. package/docs/specs/2026-09-20-upgrade-recovery-design.md +275 -10
  19. package/docs/verification/2026-10-17-0.12.31.md +71 -0
  20. package/docs/verification/2026-10-17-418-probes.md +21 -0
  21. package/docs/verification/2026-10-18-0.12.32.md +54 -0
  22. package/docs/verified.json +20 -15
  23. package/package.json +2 -2
  24. package/plugins/agent-hub/.claude-plugin/plugin.json +1 -1
  25. package/plugins/agent-hub/server.js +1361 -44
  26. package/src/adapters/acp.ts +5 -6
  27. package/src/adapters/claude-channel.ts +29 -11
  28. package/src/adapters/definitions/builtin-metadata.ts +121 -0
  29. package/src/adapters/definitions/kimi-native.ts +4 -0
  30. package/src/adapters/definitions/qwen-native.ts +24 -0
  31. package/src/adapters/definitions/qwen.ts +71 -0
  32. package/src/adapters/local-worker.ts +2 -2
  33. package/src/adapters/pi.ts +11 -2
  34. package/src/adapters/registry-types.ts +174 -0
  35. package/src/adapters/registry.ts +36 -0
  36. package/src/cli/attention.ts +5 -1
  37. package/src/cli/console-state.ts +130 -17
  38. package/src/cli/console.ts +54 -8
  39. package/src/cli/help.ts +3 -1
  40. package/src/cli/identity.ts +16 -5
  41. package/src/cli/jcode-mcp.ts +1 -1
  42. package/src/cli/launch.ts +1 -6
  43. package/src/cli/main.ts +208 -40
  44. package/src/cli/output.ts +15 -2
  45. package/src/cli/preview.ts +8 -5
  46. package/src/cli/recovery-guidance.ts +137 -0
  47. package/src/cli/recovery-presentation-options.ts +8 -0
  48. package/src/cli/recovery-session-file.ts +18 -0
  49. package/src/cli/terminal-recovery.ts +48 -0
  50. package/src/cli/upgrade-interactive.ts +129 -74
  51. package/src/cli/upgrade-labels.ts +30 -0
  52. package/src/cli/upgrade-presentation-data.ts +41 -0
  53. package/src/cli/upgrade-presentation-flags.ts +31 -0
  54. package/src/cli/upgrade-presentation.ts +217 -0
  55. package/src/cli/upgrade-restore-state.ts +137 -0
  56. package/src/cli/upgrade-runtime.ts +430 -175
  57. package/src/cli/upgrade.ts +325 -49
  58. package/src/hub/board.ts +82 -24
  59. package/src/hub/bus.ts +89 -29
  60. package/src/hub/check-runner.ts +514 -0
  61. package/src/hub/child-process.ts +1 -0
  62. package/src/hub/cohorts.ts +2 -2
  63. package/src/hub/config-apply.ts +242 -0
  64. package/src/hub/config-reload.ts +120 -0
  65. package/src/hub/config-trust.ts +11 -2
  66. package/src/hub/control-client.ts +5 -1
  67. package/src/hub/crash.ts +8 -6
  68. package/src/hub/daemon.ts +931 -209
  69. package/src/hub/delivery-hints.ts +30 -0
  70. package/src/hub/delivery-journal.ts +185 -12
  71. package/src/hub/delivery-superseded.ts +52 -0
  72. package/src/hub/envelope.ts +1 -1
  73. package/src/hub/events.ts +2 -2
  74. package/src/hub/host-executable.ts +11 -0
  75. package/src/hub/hub-tools.ts +9 -1
  76. package/src/hub/manager.ts +1 -1
  77. package/src/hub/peer-catalog.ts +13 -13
  78. package/src/hub/peers.ts +12 -2
  79. package/src/hub/permission-mode.ts +5 -3
  80. package/src/hub/recovery-continuity.ts +152 -0
  81. package/src/hub/recovery-store.ts +10 -4
  82. package/src/hub/routing.ts +35 -16
  83. package/src/hub/sdlc.ts +5 -1
  84. package/src/hub/settings.ts +52 -37
  85. package/src/hub/settled-roles.ts +35 -0
  86. package/src/hub/spec-read.ts +120 -0
  87. package/src/hub/supervision.ts +24 -8
  88. package/src/hub/task-sweep.ts +7 -6
  89. package/src/hub/tasks.ts +199 -40
  90. package/src/hub/ui.ts +1 -1
  91. package/src/memory/brief.ts +6 -5
  92. package/src/memory/capture.ts +2 -1
  93. package/src/pi/session.ts +23 -4
  94. package/src/ui/index.html +35 -16
  95. package/src/ui/needs.ts +7 -5
  96. package/src/ui/office-model.ts +4 -1
  97. package/src/ui/task-board.ts +1 -1
  98. package/src/ui/task-progress.ts +6 -2
  99. package/templates/AGENTS.block.md +1 -1
  100. package/templates/profiles/general.json +1 -1
  101. package/templates/profiles/research.json +1 -1
  102. package/templates/profiles/writing.json +1 -1
@@ -1,6 +1,6 @@
1
1
  # Operations guide
2
2
 
3
- This guide describes ahub 0.12.30 and control protocol 16. Live verification
3
+ This guide describes ahub 0.12.32 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
@@ -120,17 +120,22 @@ sounds on an action-count transition from zero, at most once per minute, never
120
120
  for a message alone. Plain mode prints the line only when the action count changes.
121
121
  Messages addressed to `user` remain attention items until the next key. Drawing
122
122
  adds no timer, network request or writable settings path.
123
- Tabs change with the digits 1 to 5 or with Left and Right (wrapping at both
123
+ The operational tabs change with digits 1 to 5 or Left and Right (wrapping at both
124
124
  ends), never while a command is being edited or a choice is open; under a
125
125
  confirmation an arrow dismisses it like any key but y, without moving a tab. A pasted
126
- chunk can only edit the command line, but a read that holds nothing but arrow
127
- sequences is that many key presses, so a held key repeats its tab move. In the Events
126
+ chunk can only edit the command line, but a read that holds nothing but arrow or
127
+ Home/End sequences is that many key presses, so a held key repeats its move. Home
128
+ or `<` jumps to a panel's first row and End or `>` to its last; the Events tab
129
+ follows new events while the last row is selected and stays on a row you moved to.
130
+ `w` opens the dashboard and `o` the pet window; `:ui --all` and `:pet --window --close`
131
+ work on the command line too. In the Peers tab the planner's row reads `(planner)`, and
132
+ `l` then `y` makes the selected peer the planner (`ahub settings set planner <peer>`). In the Events
128
133
  tab a row's header line is tokenized and coloured exactly as the same event in
129
134
  the stream; only the header is tab-flattened before tokenizing. Body lines retain
130
135
  the previous rendering and stay plain, as does command output; colour never changes
131
136
  what the panel's text says.
132
137
 
133
- Peers, Approvals, Tasks and Queue are tables with a header row. A column is as
138
+ Peers, Approvals, Tasks, Queue and Settings are tables with a header row. A column is as
134
139
  wide as its widest cell, up to a third of the terminal; the last column takes
135
140
  the rest and is cut with `...`. In Tasks, TITLE takes the rest and the STAGE
136
141
  meter keeps a fixed column at the right edge.
@@ -141,6 +146,7 @@ meter keeps a fixed column at the right edge.
141
146
  | Approvals | ID PEER LEFT TITLE |
142
147
  | Tasks | ID STATE OWNER REVIEWER CLASS AGE TITLE STAGE |
143
148
  | Queue | ID PEER STATE REV AGE |
149
+ | Settings | GROUP KEY VALUE SOURCE APPLIES |
144
150
 
145
151
  The MODE column appears only when at least one peer has a non-`ask` mode.
146
152
  Zero counters and unknown values read `-`. Durations read `45s`, `12m`, `3h05m`
@@ -189,7 +195,27 @@ In Tasks, `a` assigns the owner in ordinary open states and the reviewer in
189
195
  the corresponding role, and `r` reviews only in `in_review`. In Queue, `r`
190
196
  prefills `discard` for a queued row and `retry` for a needs_review row, with the
191
197
  action still editable before confirmation. `completed` is never the default.
192
- Every resolution needs a reason. Queue `discard` removes queued originals or
198
+ Status, console notices and `route explain` show every held row with its id, sender, kind and age. The hub completes rows made entirely of superseded hub workflow notices or presence items, recording an ids-only reason and the hub actor. Mixed messages, live task notices and unknown references remain held. A Claude session without channel support safely returns unseen pushes for `hub_inbox`; a thrown notification write remains uncertain.
199
+
200
+ Claude channel/pull sessions, Codex and Pi may call `hub_delivery_retry { delivery_id }` for their own
201
+ `needs_review` row once. Its tool results show held-row count, ids, senders,
202
+ kinds and age, never message bodies or task text (up to 32 rows/4 KiB, with an
203
+ explicit truncation notice). The redelivery starts with a fixed warning that
204
+ the earlier attempt is uncertain and its effects must be checked before acting.
205
+ The warning fits within the existing journal body limit. If needed, only the rendered copy is clipped at a Unicode character boundary and ends with an explicit cut marker; the original message is retained. Consumed-retry proof follows every coalesced original atomically with a successful checkpoint, surviving safe failure, stale removal, pruning and restart.
206
+
207
+ Any earlier explicit retry in the same recipient's lineage, including a person's
208
+ retry, leaves a later hold for the person. A busy peer's request only requeues
209
+ the originals; delivery waits for idle and retains all pauses and recovery holds.
210
+ Hub presence prefaces are mutable context, so they do not consume or inherit a
211
+ message's retry allowance and never receive the uncertain-retry warning.
212
+ The tool cannot complete or discard a row. If a recovery snapshot lacks retry
213
+ history, or older pruned retry records cannot be mapped, the affected message
214
+ lineages require a person; unrelated new messages retain the one-retry option.
215
+
216
+ The local worker and headless ACP peers, including Jcode, receive tools only inside a delivered turn. A hold prevents that turn, so these delivery-only transports do not offer recipient retry; their held hints ask the person to resolve the row. Ordinary messages stay queued. This restriction follows the current transport, not the vendor name: Kimi TUI remains pull-only and can request its one retry.
217
+
218
+ Every console resolution needs a reason. Queue `discard` removes queued originals or
193
219
  settles a needs_review receipt; it never cancels a task or native turn.
194
220
 
195
221
  `ahub task unassign <id> [--role owner|reviewer] [--revision N]` is the terminal
@@ -464,6 +490,26 @@ Tool-call receipts survive daemon restart; an interrupted operation with an
464
490
  unknown outcome must be reconciled before repeating it. Cancelling a Pi turn
465
491
  does not automatically hand its task to a cloud peer.
466
492
 
493
+ For assigned, non-private work, `hub_task_spec` reads the named GitHub issues
494
+ through the hub's authenticated, bounded read path. `hub_check_start` runs an
495
+ exact Git ref's permitted tests or typecheck in the opt-in isolated container
496
+ runner (`checks.runner: "container"`); `hub_check_result` and `hub_check_cancel`
497
+ read or cancel that owned run. Missing spec/check capability refuses the
498
+ assignment early; it never grants host commands, credentials or broader sandbox
499
+ access. Receipts distinguish exact source/tree/lockfile, platform, exit and
500
+ uncertain or cancelled outcomes. See [bounded spec and check access](security.md#bounded-task-specs-and-isolated-checks-418)
501
+ for the authorization and resource bounds.
502
+
503
+ Retention bounds inactive valid check receipts to 200 records and the newest 20
504
+ full outputs, excluding active runs. Full output is also consumed by the owner
505
+ result read or expires after 24 hours.
506
+ Malformed or unreadable receipts are a retention exception: their receipt bytes,
507
+ output and staging stay for inspection, with ID-only warnings separate from
508
+ unknown container-owner warnings. Maintenance skips them while continuing valid
509
+ retention; it never deletes an unknown container. See the security contract for
510
+ the same-user parent-swap cleanup limitation. These source guarantees do not
511
+ establish the separate native macOS acceptance leg.
512
+
467
513
  The `mlx/fast` alias now defaults to an externally managed Ollama MLX backend.
468
514
  Install and start Ollama separately, with `OLLAMA_NO_CLOUD=1`,
469
515
  `OLLAMA_NUM_PARALLEL=1`, `OLLAMA_MAX_LOADED_MODELS=1`, and a finite
@@ -559,7 +605,8 @@ PID-name matching. See the operations guide and the
559
605
 
560
606
  ## Install and start
561
607
 
562
- Use Bun 1.4.2 or newer. Install the released package and install its Claude
608
+ Use Bun 1.4.2 or newer. Source checks and CI use the version pinned in
609
+ `.bun-version` (currently 1.4.2). Install the released package and install its Claude
563
610
  channel plugin:
564
611
 
565
612
  ```bash
@@ -923,7 +970,7 @@ The daemon checks its selector at hub operation entry and before candidate/count
923
970
 
924
971
  Run `ahub memory profile-check [--json]` from the person's terminal for the read-only preflight. It identifies live registry owners by signed process identity and authenticated daemon replies, then reports their loaded memory package and bound home/profile. The receipt names the current `AGENTHUB_HOME` registry scope; zero results establish no live daemon in that inventory, not system-wide process absence. Inventory and check separate custom registries too when they share `AMEM_HOME`. A missing or unreadable runtime receipt never counts as a different home or permission to migrate.
925
972
 
926
- Before real migration, first upgrade every hub sharing the home to 0.12.30. Obtain positive ready or unbound/quiesced receipts in every relevant registry; then quiesce consumers and close bound handles before changing the selector. A matching ready handle proves compatibility but is still an open handle. Verify synthetic cross-writes before the separately approved real migration, then reopen through the supported session-preserving lifecycle afterward. Merely installing this release does not authorize migration or provide live capture/device-sync evidence.
973
+ Before real migration, first upgrade every hub sharing the home to 0.12.30 or later. Obtain positive ready or unbound/quiesced receipts in every relevant registry; then quiesce consumers and close bound handles before changing the selector. A matching ready handle proves compatibility but is still an open handle. Verify synthetic cross-writes before the separately approved real migration, then reopen through the supported session-preserving lifecycle afterward. Merely installing this release does not authorize migration or provide live capture/device-sync evidence.
927
974
 
928
975
  Managed agents read through `hub_memory_search`, `hub_memory_show` and `hub_memory_graph`, with the server's project identity, the `memory_read` capability and current privacy screening. They cannot supply another project; private turns are refused. The tools bound UTF-8 input/output, screen before counts and truncation, and exclude their arguments/results from hub-managed capture. `hub_memory_correct` has its own `memory_correct` capability and records a screened correction candidate, not a note change. See [the complete memory contract](memory.md) for caps and refusal semantics.
929
976
 
@@ -1390,6 +1437,16 @@ override them.
1390
1437
 
1391
1438
  ## Settings from the dashboard and the terminal
1392
1439
 
1440
+ In `ahub console`, press `6` for Settings. Existing operational-tab arrow cycling
1441
+ is unchanged; from Settings, Left returns to Events and Right to Peers. Select a
1442
+ row and press `e` to edit: value, daemon preview, nonempty reason, then `y`. Press
1443
+ `u` to preview and confirm undo. Undo binds the key and exact undo-record digest;
1444
+ if another write replaces that record, preview again. For busy roster removal,
1445
+ the panel names `ahub roster remove <peer> --now`, which explicitly stops an owned
1446
+ runtime or detaches a native session during its active turn; the panel does not force it.
1447
+ Esc cancels, and pasted confirmation text cannot
1448
+ write. This panel uses the current authenticated daemon connection.
1449
+
1393
1450
  The dashboard's Settings section and `ahub settings` show and change the same
1394
1451
  closed list of settings (issue #269). Run them from a plain terminal:
1395
1452
 
@@ -1401,17 +1458,22 @@ ahub settings set routing.classes.implement.peers codex,kimi,pi
1401
1458
  ahub settings set permission_modes.kimi ask-when-needed
1402
1459
  ahub settings set research.enabled inherit # remove the machine-local value
1403
1460
  ahub settings undo # put back the file the last write changed
1461
+ ahub settings reload # validate and apply the complete four-file candidate
1404
1462
  ahub ui --settings # dashboard with a 15-minute settings session
1405
1463
  ```
1406
1464
 
1407
1465
  | Group | Keys | Stored in | Applies |
1408
1466
  | --- | --- | --- | --- |
1409
1467
  | Permissions | `permission.<peer>` (the mode now) | the running hub only | at once |
1410
- | Permissions | `permission_modes.<peer>` (the mode at hub start) | `config.local.json` | next hub start |
1468
+ | Permissions | `permission_modes.<peer>` (the default mode) | `config.local.json` | next peer start |
1411
1469
  | Start | `peers.pi.start_mode`, `peers.codex.start_mode`, `peers.kimi.start_mode` (`tui` or `headless`) | `config.local.json` | that peer's next start |
1412
- | Start | `pi.auto_start` | `config.local.json` | next hub start |
1470
+ | Start | `pi.auto_start` | `config.local.json` | next startup/recovery auto-start decision; never starts a peer merely on reload |
1413
1471
  | Routing | `routing.stay_switch`, `routing.classes.<class>.peers`, `.escalate_to`, `.route`, `.pi_backend` | `routing.local.toml` | at once |
1414
- | Switches | `research.enabled`, `approvals.notify`, `snapshots.enabled`, `coordination` | `config.local.json` | next hub start |
1472
+ | Switches | `research.enabled`, `approvals.notify`, `snapshots.enabled` | `config.local.json` | live, without disturbing an active turn |
1473
+ | Switches | `coordination` | `config.local.json` | newly created tasks only |
1474
+ | Switches | `task_sweep.enabled`, `.auto_reassign`, `.interval_s`, `.unaccepted_min`, `.idle_min`, `.review_min`, `.ready_min`, `.ladder_min` | `config.local.json` | live; reschedules the sweep timer |
1475
+ | Routing | `tasks.wip_limits.<peer>` | `config.local.json` | live |
1476
+ | Roles | `planner` (the one peer that plans) | `config.local.json` | at once |
1415
1477
 
1416
1478
  - Writes go only to `.agenthub/config.local.json` and `.agenthub/routing.local.toml`,
1417
1479
  the machine-local files (`ahub init` ignores both in git). The shared
@@ -1423,8 +1485,28 @@ ahub ui --settings # dashboard with a 15-minute settings session
1423
1485
  file each value comes from. `--preview`, and the dashboard's Preview button,
1424
1486
  show `ahub route explain` for the open tasks before and after, or what a
1425
1487
  permission mode grants, and save nothing.
1426
- - A row shows the value in force, its source file, when it applies, and for a
1427
- value read at hub start what the next start will read (`Pending restart`).
1488
+ - A row shows running and file values, source and apply class (`live`, `next use`,
1489
+ or `restart`). Pending restart keys and reasons also appear in status, console
1490
+ and dashboard, including startup-only blocks outside the editable registry.
1491
+ - Settings writes and undo, the dashboard Reload configuration button and
1492
+ `ahub settings reload` use one complete validation/apply path. Debounced changes
1493
+ of config.json, config.local.json, routing.toml and routing.local.toml use it too,
1494
+ including atomic file replacement. Invalid candidates apply nothing and emit
1495
+ one bounded error notice. Valid but unauthorized keys retain their accepted value and are reported per key; other eligible changes still apply. Recovery/shutdown hold reloads.
1496
+ - Individual writes and undo publish only the named setting. Other file edits remain unapplied.
1497
+ - `ahub settings reload` lists guarded keys with complete before -> after values (including full argv) and any planner/conductor holder effect. It requires an interactive terminal and exact `y` within 30 seconds before adopting them. Oversized previews remain unapplied and must be split or reduced. Candidate bytes or accepted state changes invalidate that confirmation. Watchers and ordinary dashboard reloads never confirm a raise.
1498
+ - Privacy tightening (local PII constraints/screening, added PII patterns, nonholder role reductions and explicit capability-list narrowing) is automatic, including tracked files. A planner/conductor holder change is guarded even when a role list shrinks; deleting a restricted capability entry restores all capabilities and is guarded. Reload checks the actual files' Git provenance. Changed machine-local or raising
1499
+ values from tracked/unverifiable files are refused; an ordinary dashboard or
1500
+ watcher cannot adopt unrelated raising local edits. A settings session cannot
1501
+ adopt routing fields outside its editable registry. Existing confirmation and
1502
+ roster lifecycle fences remain; use the confirmed roster setting for membership.
1503
+ Pi relay model aliases (`pi.dgx_coding`, `pi.dgx_fast`) and `routing.pi` retain their running values until restart, because existing native sessions use the published relay catalogue and context contract. Routing policy changes apply to future decisions; local model/target changes apply at the next peer or sidecar creation.
1504
+
1505
+ - Runtime/client ownership still requires restart for memory handles and sync,
1506
+ gateway/MLX, runner/check commands, profile/tool contracts, converters, existing
1507
+ session privacy/sandbox policies, the terminal provider and benchmark environment.
1508
+ The exhaustive reasons are in the issue #439 spec amendment. A pending file value
1509
+ is not applied to the running consumer. Coordination creation pins last for the daemon lifetime; a restart re-pins retained rows to its startup mode.
1428
1510
  - `ahub settings undo` (the dashboard's "Undo last write") puts back the one
1429
1511
  previous version of the file the last write changed. It refuses when that
1430
1512
  file was edited since, and when it would put a stored never-ask back (set it
@@ -1437,10 +1519,11 @@ ahub ui --settings # dashboard with a 15-minute settings session
1437
1519
  `.agenthub/routing.local.toml`: run `ahub init` again, or add it. A
1438
1520
  `permission_modes` value is read only from a file git confirms nobody
1439
1521
  committed (config trust); where the hub will not read what was written, the
1440
- reply and the Settings row say so.
1522
+ reload refuses the guarded candidate and the Settings row identifies the file.
1441
1523
  - Authority: a dashboard opened with `ahub ui` reads settings, lowers a mode to
1442
- `ask`, turns `pi.auto_start` off, sets a start mode back to `tui` and changes
1443
- the Switches group. Everything
1524
+ `ask`, turns `pi.auto_start` off, sets a start mode back to `tui`, sets a WIP
1525
+ limit to 0, turns `task_sweep.enabled` or `.auto_reassign` off and changes
1526
+ the other Switches. Everything
1444
1527
  else needs `ahub ui --settings`, whose session may raise for 15 minutes, or
1445
1528
  `ahub settings` in a terminal. `never-ask` needs the peer id typed in the
1446
1529
  dashboard, or `--yes` in the terminal, and a stored never-ask default still
@@ -1505,8 +1588,10 @@ The configured `kimi_cmd` must be a single executable or end in exactly `acp`;
1505
1588
  the TUI uses the executable or drops that final word. Other wrappers are refused
1506
1589
  with the headless command rather than guessed.
1507
1590
 
1508
- The TUI is pull-only. Its model reads `hub_inbox` at the start of work and before
1509
- reporting, and shares results explicitly with `hub_send`. Status, the console and
1591
+ The TUI is pull-only. Its model reads `hub_inbox` at the start of work, between
1592
+ steps of longer work and before reporting, and shares results, and mid-work
1593
+ blockers or changed contracts, explicitly with `hub_send` addressed with `to`
1594
+ (progress-only notes `[FYI]`). Status, the console and
1510
1595
  the dashboard show `pull-only`, the waiting count and the last inbox read. Messages
1511
1596
  and important markers do not push or interrupt it. There is no hub busy state,
1512
1597
  watchdog, console approval, hub permission mode, context reading, automatic quota
@@ -1710,6 +1795,28 @@ so a restarted hub never launches beside a survivor. A hub whose project root
1710
1795
  or state directory was deleted stops itself within about 10 seconds; the
1711
1796
  dashboard manager does the same when its home directory vanishes.
1712
1797
 
1798
+ ## The planner (#455)
1799
+
1800
+ One peer plans: it proposes and splits tasks, grooms the backlog and gets the
1801
+ backlog and sweep notices. `ahub status` prints it with its source, the
1802
+ dashboard's Agents view shows a Planner badge, and the console marks its row.
1803
+
1804
+ - `setting`: `planner` in `.agenthub/config.json` or `config.local.json` (the
1805
+ machine's file wins). That peer is the only planner; every other peer loses
1806
+ the role. It is one of `claude`, `codex`, `kimi`, `qwen` or `jcode`: the
1807
+ hub-sandboxed `pi` and `local` never plan.
1808
+ - `roles`: with no `planner` key, the `roles` planners stand. That is `claude`
1809
+ by default.
1810
+ - `automatic`: when no rostered peer holds the role, the hub gives it to the
1811
+ first rostered peer of that list. It recomputes this at start and after
1812
+ each roster change, and writes nothing to disk.
1813
+
1814
+ Change it with `ahub settings set planner codex`, the dashboard Settings row
1815
+ (a settings session, `ahub ui --settings`) or `l` in the console. Planning
1816
+ authority and the backlog notices move at once. The new planner's role text
1817
+ updates at its next start. `ahub settings undo` puts the previous planner
1818
+ back. Agents cannot change it.
1819
+
1713
1820
  ## Resetting a project's hub
1714
1821
 
1715
1822
  `ahub reset` returns a project's hub to a clean state. Without `--yes` it is a
@@ -1842,21 +1949,21 @@ section is what they run.
1842
1949
 
1843
1950
  Upgrade running projects with the target release's own coordinator. It accepts
1844
1951
  a running source on control protocol 9 (0.6.x), 10 (0.7.0 through 0.12.0),
1845
- 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.30), and only
1952
+ 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.32), and only
1846
1953
  a target on its own protocol, so the target's coordinator fits every supported
1847
1954
  source and carries every recovery fix released up to it. Protocol 8 and older
1848
1955
  (0.5.x and earlier) are refused as `manual-bootstrap-required`. Run from the
1849
1956
  project directory, without replacing the global CLI first:
1850
1957
 
1851
1958
  ```bash
1852
- bunx --package @staix/agent-hub@0.12.30 ahub upgrade --to 0.12.30 --dry-run
1853
- bunx --package @staix/agent-hub@0.12.30 ahub upgrade --to 0.12.30 --yes
1959
+ bunx --package @staix/agent-hub@0.12.32 ahub upgrade --to 0.12.32 --dry-run
1960
+ bunx --package @staix/agent-hub@0.12.32 ahub upgrade --to 0.12.32 --yes
1854
1961
  ```
1855
1962
 
1856
1963
  | Running now | Coordinator to use |
1857
1964
  | --- | --- |
1858
1965
  | 0.6.x (protocol 9) | the target's, through `bunx` as above |
1859
- | 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.30 (protocol 16) | the target's, through `bunx` as above |
1966
+ | 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.32 (protocol 16) | the target's, through `bunx` as above |
1860
1967
  | any supported source, with the installed CLI already at the target | `ahub upgrade` below, which is the same coordinator |
1861
1968
  | 0.5.x or earlier (protocol 8 and older) | not supported: bootstrap by hand with the matching CLI |
1862
1969
 
@@ -1888,17 +1995,18 @@ projects first:
1888
1995
 
1889
1996
  ```bash
1890
1997
  ahub restart --dry-run
1891
- ahub upgrade --to 0.12.30 --dry-run
1998
+ ahub upgrade --to 0.12.32 --dry-run
1892
1999
  ```
1893
2000
 
1894
2001
  Apply only after reviewing the plan:
1895
2002
 
1896
2003
  ```bash
1897
2004
  ahub restart --yes
1898
- ahub upgrade --to 0.12.30 --yes
2005
+ ahub upgrade --to 0.12.32 --yes
1899
2006
  ahub recovery status [<operation-id>]
1900
2007
  ahub recovery resume [<operation-id>]
1901
2008
  ahub recovery abort [<operation-id>]
2009
+ ahub recovery reattach <operation-id> codex|claude|pi
1902
2010
  ahub recovery dispose [<operation-id>] --fresh-session <peer> --reason <text>
1903
2011
  ahub recovery dispose [<operation-id>] --stop-and-archive --reason <text>
1904
2012
  ```
@@ -1962,7 +2070,9 @@ A lost commit or start reply is reconciled against the actual daemon identity,
1962
2070
  package digest, terminal binding, and phase receipt. An uncertain terminal
1963
2071
  creation is never repeated blindly. Recovery retains the exact-pinned first-party memory package with the preserved runtime, includes its identity and bytes in the digest, and refuses missing, symlinked or changed retained dependencies instead of resolving a mutable ancestor/global installation. It does not copy the full dependency tree.
1964
2072
 
1965
- After creating a managed terminal, the coordinator saves its binding before waiting up to 90 seconds for authenticated attachment to the expected target hub and conversation. An idle terminal alone is not attachment proof. Timeout retains the terminal and its diagnostic receipt; resume waits on that same binding rather than opening a duplicate. The zero-turn Claude exception still applies only when no original transcript exists. If Claude shows its development-channel confirmation screen, confirm it in
2073
+ After creating a managed terminal, the coordinator saves its exact handle, incarnation and worktree before waiting up to 600 seconds (10 minutes) for authenticated attachment to the expected target hub and conversation. A pending or failed creation receipt also waits when the current target has a verified live launcher; its saved binding retains the pending/failed origin across interruption. An idle terminal alone is not attachment proof. Without a current launch record, a confirmed-ended row for another terminal and an attached session still reporting no id keep the chosen terminal waiting within the same bound; a late matching record continues that wait. Live replacement and unreadable records still block. Only non-offline session ids count, and older-instance launchers are checked before declaring a launch gone. Timeout retains the binding and diagnostic receipt; resume waits on that same binding rather than opening a duplicate.
2074
+
2075
+ The wait checks the selected launcher's signed identity on each poll. When that exact launcher exits and the target confirms no session or other live launcher, a pending-origin wait (including a new terminal) records failure and offers the failed-restoration choices, including fresh-session for Codex or Claude. A failed-origin wait returns to its existing retry path. A replacement terminal, missing or unreadable launcher identity, unreadable target or different attached conversation blocks without treating unknown as gone. Success clears the waiting origin and preserves exact terminal/session revalidation. A launcher from an older target instance still blocks without another terminal. The 10-minute limit matches terminal creation readiness; terminal idle can precede native resume and MCP handshake completion. The zero-turn Claude exception still applies only when no original transcript exists. If Claude shows its development-channel confirmation screen, confirm it in
1966
2076
  the captured terminal, then run `ahub recovery resume <operation-id>`; resume must not open a duplicate terminal.
1967
2077
  Kimi and local sessions may start fresh with preserved routing and task context.
1968
2078
  A Claude session that never persisted a transcript (zero turns) also starts fresh:
@@ -1997,6 +2107,16 @@ through a pipe, the JSON plan, the `ahub: blocker:` lines and the exit codes are
1997
2107
  unchanged. The screens add no way to change an operation: every choice runs one
1998
2108
  of the commands in this section for you, so that command's refusals decide.
1999
2109
 
2110
+ The screens use the console palette and `--color=auto|always|never`, with the
2111
+ same `NO_COLOR` and `TERM=dumb` precedence. Auto colours a suitable TTY; explicit
2112
+ always has the console's override behaviour. Raw JSON bypasses colour and width
2113
+ handling. Default and never preserve the existing pipe, dry-run, status and
2114
+ dispose output byte for byte. Presentation flags go after the command, for
2115
+ example `ahub recovery --color=never` or
2116
+ `ahub recovery status <operation-id> --json`. An explicit `--json` returns only
2117
+ the raw document, without a human suffix. `upgrade --json` reviews a JSON plan;
2118
+ `--yes` is still needed to apply it without the interactive review.
2119
+
2000
2120
  The plan screen lists each project with its hub version and, per attached peer,
2001
2121
  its state, how it runs (`TUI` in a terminal the plan bound to its session,
2002
2122
  `headless` as the hub's own process, `own` for a session the hub did not
@@ -2029,23 +2149,35 @@ plan shows the ended agents as offline.
2029
2149
 
2030
2150
  After apply the command stays attached and prints each step as the receipt
2031
2151
  records it, and while a source is being prepared, what it still waits for.
2152
+ Each reported step has a status mark and elapsed observation time. Resume lists
2153
+ only steps observed on that attempt and says `resuming from ...` once. Its stage
2154
+ step really runs again and is labelled `checking retained release`. Waits use
2155
+ the coordinator's actual recorded start and deadline, for example
2156
+ `[waiting] alpha: restoring Codex and Pi sessions (waiting 2m10s of 10m)`.
2157
+ Older receipts without timing metadata say `timing unknown`; updatedAt is never
2158
+ used as a substitute. Timing-only save failures log a warning and do not fail
2159
+ the operation. Stable waits print only on change and at most once per minute.
2160
+ Approval waits point to `ahub console`; native attachment waits point to the
2161
+ recorded launch and conversation. Korean text and
2162
+ long paths wrap to the measured width on plan, progress and menu screens.
2032
2163
  Enter opens the operation's screen while the runner works on. Ctrl+C leaves the
2033
2164
  command, at any prompt and while following, and never stops the runner: the
2034
- `left:` line names the command that comes back to the screen, with the
2035
- operation's own coordinator, because the installed `ahub` is the older release
2036
- until the upgrade ends. A Ctrl+C between `a` and the start of the operation
2165
+ `left:` line names `ahub recovery status <operation-id>`. Use `--verbose` for
2166
+ the internal command with the operation's retained coordinator, because the
2167
+ installed `ahub` may still be the older release until the upgrade ends. A Ctrl+C between `a` and the start of the operation
2037
2168
  starts nothing. A prompt for a reason that is answered with
2038
2169
  Ctrl+C or the end of input ends nothing.
2039
2170
 
2040
2171
  The operation's screen also opens first whenever an operation holds the lock,
2041
2172
  and for bare `ahub recovery`. It shows the phase and step, each project's phase
2042
- and effect receipts and the error, then the choices that `status` lists under
2173
+ and human outcome labels, then What happened / Why / What to do and the choices that `status` lists under
2043
2174
  `next` for the same receipt and live state:
2044
2175
 
2045
2176
  | Key | Runs | Offered when |
2046
2177
  | --- | --- | --- |
2047
2178
  | `r` | `recovery resume`, then follows | resume can get past what is live |
2048
2179
  | `c` | `recovery abort` | no runtime was stopped and no terminal effect or commit request is recorded |
2180
+ | `a` | `recovery reattach <id> <peer>` | the recorded detached session is eligible for reattachment |
2049
2181
  | `f` | `recovery dispose --fresh-session <peer>`, after a reason | a Codex or Claude restoration failed |
2050
2182
  | `e` | `recovery dispose --stop-and-archive`, after a confirmation and a reason | every unverified project reads as running, stopped or missing |
2051
2183
  | `x` | `e`, then the reset below | as `e` |
@@ -2055,6 +2187,26 @@ When more than one restoration failed, the second and later peers get
2055
2187
  `f-<peer>`. `s` refreshes the screen, `j` prints the receipt as JSON and `q`
2056
2188
  leaves the operation as it is.
2057
2189
 
2190
+ The marked recommendation is a read-only Enter default: refresh the plan, follow
2191
+ an active runner, read the receipt or refresh the operation. Apply, resume and
2192
+ reattach require their explicit keys; buffered Enter never starts them. Unknown failures recommend
2193
+ reading `j` before retrying effects. A wait whose runner cannot be verified is
2194
+ shown disabled with its reason, and cannot run a command. Stop, archive, reset
2195
+ and fresh-session choices carry a warning and name the consequence before the
2196
+ person confirms. Raw receipt keys and the original recorded error are available
2197
+ with `j` or `--verbose`. The four preservation failures name the actual failed
2198
+ queue, manual-pause, board or budget comparison; an older untyped cause remains
2199
+ unknown rather than being guessed from its text.
2200
+
2201
+ Completion and stop-and-archive use a human summary on a TTY. It separates the
2202
+ outcome, recorded plugin/global installation effects, remaining work and the
2203
+ per-peer session commands. An optional fresh read-only inspection names the
2204
+ current hub version; a failed reading says `runtime unknown`, never a guessed
2205
+ version from the plan. The summary performs no lifecycle action. Use `j` or
2206
+ `--json` for the full receipt; JSON is intentionally exempt from human wrapping.
2207
+ For a long command, copy the exact single-line value from `j` or the status JSON;
2208
+ the width-wrapped human preview is for reading.
2209
+
2058
2210
  While a runner is only waiting for its source to get quiet (step `prepare`, no
2059
2211
  effect recorded), `c` stops that runner and then aborts. It is offered only for
2060
2212
  a runner whose claim carries a process signature that still matches; a claim
@@ -2082,7 +2234,8 @@ or cancel and upgrade later.
2082
2234
  its phase, step and error; `runner`, which says whether a runner process holds
2083
2235
  the operation now (`running` with its pid, or `none`; `stale` marks a receipt
2084
2236
  that says running with no runner behind it); each project's phase and effect
2085
- receipts (`closed:<peer>`, `restored:<peer>` as `done`, `pending` or `failed`);
2237
+ receipts (`closed:<peer>` as `done` or `pending`; `restored:<peer>` as
2238
+ `pending`, `waiting:pending`, `waiting:failed`, `done` or `failed`);
2086
2239
  whether the shared plugin and the global CLI were installed; and `next`, the
2087
2240
  commands that apply now, read from every source the operation has not stopped
2088
2241
  yet (every error of `resume` ends with the same list). `resume` is left out
@@ -2092,7 +2245,11 @@ message text. `resume` does not
2092
2245
  start a second runner while one is alive. Every `next` entry and error names the
2093
2246
  operation's own coordinator, `bun <preserved source>/src/cli/main.js recovery
2094
2247
  ...`: in the middle of an upgrade the global `ahub` may still be the older
2095
- release, whose `recovery` lacks these commands. Copy that command line. When
2248
+ release, whose `recovery` lacks these commands. The published 0.12.30 CLI also
2249
+ mislabels tagged waiting receipts as done and can hide the fresh-session choice,
2250
+ even when its status command exists. Use the printed preserved-source
2251
+ coordinator for status, resume and disposition; do not decide from that older
2252
+ CLI's receipt display. Copy that command line. When
2096
2253
  an older coordinator started the operation, `dispose` is named from the running
2097
2254
  release, which has it. What
2098
2255
  each receipt allows, given what is live, is tabulated in the recovery spec
@@ -2130,6 +2287,11 @@ next actions").
2130
2287
  use its offered `ahub recovery resume <id>`. Resume rechecks the source and
2131
2288
  reconciles a commit that may already have been requested. A busy read while
2132
2289
  that committed source is stopping stays inside the existing shutdown wait.
2290
+ A resumed prepared receipt with `commitSent` also polls an unavailable source
2291
+ within the 30-second shutdown bound, including initial database contention,
2292
+ without sending another commit, re-preparing or closing terminals again. Only
2293
+ confirmed `stopped` permits target startup; a replacement instance refuses, and
2294
+ expiry retains the prepared receipt and the same operation for another resume.
2133
2295
  A stop-and-archive that meets contention instead says to retry that
2134
2296
  disposition; resume remains refused while abandonment is partway. Successful
2135
2297
  abort, fresh-session choice and disposal clear the earlier failure annotation.
@@ -2198,11 +2360,23 @@ next actions").
2198
2360
  unpinned signature too, so it counts as running when this command runs in
2199
2361
  the same time zone and locale as the launcher did. `resume` is refused while a stop-and-archive is partway. A lifecycle command refused by the lock names
2200
2362
  the operation's own `status` command, which lists what to do next.
2363
+ - `ahub recovery reattach <operation-id> codex|claude|pi` is person-only, including during live verification: an agent shell cannot delegate it. Name the operation and exactly one peer; session, backend, model and terminal overrides are not accepted. Use the exact operation-coordinator command printed by status or its blocked guidance. It repairs only that peer and leaves the operation blocked; run the offered `recovery resume` command to continue the remaining steps.
2364
+ The CLI delegates only when the retained coordinator supports reattach. An existing older coordinator without that action uses this release's implementation instead; a missing receipt, retained coordinator path or coordinator file prints inspection/recovery guidance and starts no session.
2365
+ A peer that attached and later went offline can be re-restored once when its saved terminal is positively orphaned or missing and no current or older operation launcher may still run. The recorded session id and Pi session file stay fixed; the new terminal binding is saved before waiting for authenticated attachment. A second detach blocks. An unreadable terminal, changed incarnation or worktree, disconnected-only evidence, truncated inventory or live/unknown launcher does not authorize another terminal.
2366
+ Recovery status names the saved Codex thread, Pi session file and Claude session, the terminal evidence, and the applicable reattach command. A different attached conversation remains a strict refusal.
2201
2367
  - `ahub recovery dispose <operation-id> --fresh-session <peer> --reason <text>`
2202
2368
  applies to a Codex or Claude peer whose restoration failed (Pi is refused: a
2203
2369
  restored hub resumes Pi's recorded session). It records the lost session or
2204
2370
  thread id (status shows it under `lostContinuity`) and resumes: the peer
2205
2371
  starts without its old conversation, and the rest is verified as usual.
2372
+ A session the operation already reattached keeps that repaired provenance
2373
+ across target restarts and is never replaced automatically. Its
2374
+ loss can be accepted only after the restoration reported the recorded Claude
2375
+ transcript or Codex rollout as positively missing, naming the checked path;
2376
+ dispose checks that path again before saving the choice and otherwise refuses
2377
+ with "recorded conversation is not positively missing". Under `--live-test`
2378
+ this repaired-session choice is refused even where an ordinary fresh session
2379
+ may be delegated.
2206
2380
  - `ahub recovery dispose <operation-id> --stop-and-archive --reason <text>`
2207
2381
  abandons the operation. It checks every project first and refuses while a
2208
2382
  hub is unreachable, starting, stopping or of another control protocol; `next`
@@ -2249,7 +2423,8 @@ next actions").
2249
2423
  again.
2250
2424
  Start a project whose target ran with that release's CLI (`bunx --package
2251
2425
  @staix/agent-hub@<version> ahub up`), since it may have changed the task
2252
- database. The global CLI was not promoted.
2426
+ database. The global CLI was not promoted. The archive summary distinguishes completed target startup and plugin installation from remaining global CLI installation, and prints recorded-session commands: `ahub codex resume <thread-id>`, `ahub pi --session-file <path>`, and the Claude reconnect command. On the next `ahub up`, `pi.auto_start` resumes the archived operation's recorded Pi session rather than choosing a fresh conversation. Unknown or conflicting archived identity refuses that automatic resume.
2427
+ That session is kept as a bookmark, `.agenthub/state/recovery-continuity.json`. When its session file can no longer be resumed or does not match it, the hub archives the bookmark and starts no fresh session in that start; the error names `ahub pi --mode <mode> --session-file <managed-file>` for choosing one. An invalid or unreadable bookmark, or session storage that cannot be verified, starts nothing, keeps the bookmark and prints the `mv -n` command that archives it after inspection. The bookmark is retired once Pi attaches with a different authenticated session.
2253
2428
  - Both choices are for a person in a terminal; an agent shell is refused, and
2254
2429
  the reason is kept in the operation's audit. Run each with the command
2255
2430
  `next` or the error prints: the operation's own coordinator, or the release
@@ -2459,6 +2634,22 @@ the capability is absent. It never rewrites these settings. Explicit
2459
2634
  refused before any local startup. Re-enable MLX or explicitly migrate the
2460
2635
  recorded launch before recovery.
2461
2636
 
2637
+ ## Task stalls and cancellation
2638
+
2639
+ A ready task with an ineligible reservation, no eligible peer or a cancelled dependency shows an ids-only stall cause in status and the Tasks panel. The hub reports a cause once, repeating only when the cause changes or the task is re-planned. It directs ownerless advice to the designated planner's next bounded preface and the configured supervision stream, otherwise the person's attention list; it does not create an extra ordinary turn beside backlog batching. Configure the missing capability, assign another eligible peer, re-plan or cancel the task as appropriate; a reservation never bypasses routing guards.
2640
+
2641
+ An offer to a pull-only peer adds an advisory "open <peer>: task #N is waiting for it" attention item. It clears when that exact offer is accepted, declined, superseded or genuinely delivered and settled to the addressed peer. Another inbox read, an accepted-only receipt or a person's queue completion does not prove it was read. The attention item survives peer detach and daemon restart using the saved offer's pull-only flag; it does not alter delivery state.
2642
+
2643
+ The person can retain superseded work as closed history:
2644
+
2645
+ ```sh
2646
+ ahub task cancel <id> --reason <text> [--superseded-by <ref>] [--revision N]
2647
+ ```
2648
+
2649
+ 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.
2650
+
2651
+ 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 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.
2652
+
2462
2653
  ## Task idle sweep
2463
2654
 
2464
2655
  The between-turn task sweep (#186) is disabled by default. Set `task_sweep` in
@@ -2472,6 +2663,7 @@ The between-turn task sweep (#186) is disabled by default. Set `task_sweep` in
2472
2663
  "unaccepted_min": 60,
2473
2664
  "idle_min": 120,
2474
2665
  "review_min": 120,
2666
+ "ready_min": 60,
2475
2667
  "ladder_min": 30,
2476
2668
  "auto_reassign": false
2477
2669
  }
@@ -2483,6 +2675,8 @@ at least 1; timeouts are bounded to the platform timer limit. Each threshold
2483
2675
  measures time since the last real task history event. A ladder record does not
2484
2676
  refresh that activity; a new event resets the ladder even at the same timestamp.
2485
2677
 
2678
+ Ready proposed tasks without an owner use `ready_min` and the `ready-unassigned` ladder; unresolved or cancelled dependencies do not become ready. A person's unassignment suppresses this automatic ladder until a later explicit assignment or reservation. Planner-pulled work keeps its reserved peer and current WIP/hold admission; an unavailable or full reservation never selects another worker.
2679
+
2486
2680
  The first overdue sweep sends the assigned owner or reviewer one normal task
2487
2681
  reminder. After `ladder_min`, the next sweep notifies the console and available
2488
2682
  planner-role peers. After another interval it reports a reassignment suggestion
@@ -2564,13 +2758,15 @@ registry directories and a scrubbed environment. The normal 20-second test timeo
2564
2758
  both legs. Successful fixtures are removed; a failed pair prints its preserved
2565
2759
  fixture location with test and leak evidence for inspection.
2566
2760
 
2567
- The required Linux CI job `seeded guards` follows the ordinary checks; it does not
2568
- repeat on macOS or run recursively inside `bun test`. The runner reports every
2761
+ CI runs the pairs as four Linux shards (`bun scripts/seeded-check.ts --shard i/4`,
2762
+ every fourth pair, still sequential within a shard) beside the ordinary checks; the
2763
+ required job `seeded guards` passes only when all four shards passed (#457). The pairs
2764
+ do not repeat on macOS or run recursively inside `bun test`. The runner reports every
2569
2765
  pair's elapsed seconds and the total runtime. A green ordinary check alone does
2570
2766
  not prove these pairs.
2571
2767
 
2572
- The full CI gate tests the PR head tree on Linux and macOS, followed by the
2573
- sequential seeded-guard job. Main and release jobs reuse only a successful full
2768
+ The full CI gate tests the PR head tree on Linux and macOS, with the seeded-guard
2769
+ shards running at the same time. Main and release jobs reuse only a successful full
2574
2770
  PR or push check with the identical Git tree and all three successful jobs. An absent or
2575
2771
  unreadable result runs the main gate again and refuses release. A manual
2576
2772
  `prepare_bundle` dispatch builds reviewable plugin assets without publishing;
@@ -2847,6 +3043,9 @@ Qwen controlled recovery and automatic crash resume load the recorded conversati
2847
3043
 
2848
3044
  Use ahub roster add jcode, then ahub jcode --mode headless [--model <alias>] [--provider-profile <name>]. The person launcher configures only agent-hub-jcode in .jcode/mcp.json; run ahub init afterwards to ignore the untracked machine-path file. Conductor/dashboard starts read that entry without editing it. Preview starts nothing, and ahub stop jcode stops only the owned private daemon/ACP groups. jcode_cmd, jcode_home and jcode_provider_profile are machine-local and never editable from settings.
2849
3045
 
3046
+ After upgrading to the recipient-retry release, a Jcode project MCP entry written before `AGENTHUB_DELIVERY_ONLY` was added is intentionally stale. Once per project, the person runs `ahub jcode --mode headless` before using conductor/dashboard starts. The launcher rewrites only the owned entry with the delivery-only marker, preserving foreign entries and refusing collisions; recovery relaunches already use this CLI path. Readiness checks never rewrite the file, and an explicit false marker or any other drift remains refused. Until that rewrite, daemon starts keep their actionable stale-entry refusal rather than advertising a retry tool Jcode cannot use.
3047
+
3048
+
2850
3049
  Native policy is unmanaged and has NO hub sandbox; no permission_modes.jcode or runtime mode mapping is invented. Quota and consumption remain unknown. Version 0.94.0 cannot prove native session/load identity, so attached Jcode blocks controlled recovery before effects and crash recovery asks for deliberate native reopening. A requested load without an echoed identity refuses; no fresh session is presented as restored. Provider/tool/native teardown receipts remain unverified in the pinned contract report.
2851
3050
 
2852
3051
  # Headless ACP watch (#286)
@@ -2975,7 +3174,7 @@ Create a phase with `ahub release new <name> <goal> <order>`, inspect `list` or
2975
3174
  `show`, and set planned start/cut/ship with `plan <name> <revision> <dates-json>`.
2976
3175
  `activate`, `freeze`, `ship` and `drop` need its current revision. Only a person
2977
3176
  freezes, ships, drops or edits frozen scope. Ship records the first ship time
2978
- only after every member is approved or moved out; it runs no tag or publish.
3177
+ only after every member is approved, cancelled or moved out; it runs no tag or publish.
2979
3178
  The dashboard shows phase progress, blocking dependencies, dates and remaining
2980
3179
  work. Actual task dates come from execution/review/approval history, never input.
2981
3180
 
@@ -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.12.30
20
+ bun add -g github:STAIxBWLB/agent-hub#v0.12.32
21
21
  ahub setup
22
22
  ```
23
23
 
@@ -30,6 +30,21 @@ 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.12.32
34
+
35
+ The upgrade runs with the target release's own coordinator. If the operation blocks because a restored Codex, Claude or Pi terminal disappeared, the person runs `ahub recovery reattach <operation-id> codex|claude|pi` to relaunch that peer with its recorded session (one relaunch per receipt), then `ahub recovery resume` to finish.
36
+
37
+ 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:
38
+
39
+ ```bash
40
+ ahub jcode --mode headless
41
+ ahub init
42
+ ```
43
+
44
+ The first command starts Jcode and rewrites only the hub-owned `agent-hub-jcode` entry in `.jcode/mcp.json`, adding its delivery-only marker. Foreign or overriding entries refuse instead of being overwritten. `ahub init` keeps an untracked machine-path file out of git; review a tracked file deliberately. Daemon readiness checks never rewrite this entry. See [Jcode operations](operations.md#optional-jcode-peer).
45
+
46
+ Task owners running as Pi or `local` need the isolated test capability for non-PII `implement`, `test` and `bulk_edit` work. A person sets `checks.runner` to `"container"` in untracked `.agenthub/config.local.json`; the Apple container service and pinned image must also be available. Issue-backed owners additionally need spec access. Manual messages remain available, and PII work retains its local-only routing. See [bounded check requirements](security.md#bounded-task-specs-and-isolated-checks-418) before enabling the runner.
47
+
33
48
  ## First session
34
49
 
35
50
  In your project directory, one terminal each:
@@ -68,6 +83,9 @@ or set `OMNIROUTE_API_KEY`. Name the model in `.agenthub/routing.toml` (`[local]
68
83
  | `ahub say [@peer] <text>` | talk; start with `[STATUS]` to let it batch, `[FYI]` for the record only |
69
84
  | `ahub task propose [--class <c>] <title>` | put work on the board; the hub picks an owner and a reviewer, and the class if you name none |
70
85
  | `ahub board` | who has what; `ahub task show <id>` for one task |
86
+ | `ahub task cancel <id> --reason <text>` | close obsolete work without approving it or stopping a native turn |
87
+ | `ahub settings set planner <peer>` | pin the planner; status reports whether it came from settings, roles or the automatic choice |
88
+ | `ahub settings reload` | apply edited config files without a restart; guarded values wait for your `y` in this terminal, and restart-only keys stay pending |
71
89
  | `ahub status` | peers, queues, pauses; `ahub budget` for quota windows |
72
90
  | `ahub memory profile-check` | a person's read-only check of running memory bindings in the current registry |
73
91
  | `ahub ask <question>` | what the board, shared memory and the log say, with the ids the answer rests on |
@@ -78,9 +96,9 @@ More: `ahub help`. How it is built and why: [`docs/specs/2026-09-19-agent-hub-de
78
96
 
79
97
  ## Shared memory
80
98
 
81
- The hub exact-pins the first-party `@staix/agent-mem` 0.3.0 core. 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. Generation candidate acceptance is still refused.
99
+ The hub exact-pins the first-party `@staix/agent-mem` 0.3.1 core. 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. Generation candidate acceptance is still refused.
82
100
 
83
- Before any real generation migration, upgrade every hub sharing that memory home to 0.12.30 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.
101
+ 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.
84
102
 
85
103
  ## Browser dashboard
86
104
 
@@ -95,8 +113,9 @@ contents: inspect them with `ahub tail`, then use `ahub permit <id> <option>` to
95
113
  allow. They can be denied on the page. PII task details remain available only via
96
114
  `ahub task show <id>` in the terminal. The page also starts a peer in its start
97
115
  mode (a TUI opens in a terminal when the hub has a terminal provider) and shows
98
- the settings; raising one needs `ahub ui --settings` or `ahub settings` in a
99
- terminal. See the operations guide, "Settings from the dashboard and the
116
+ the settings with a Reload configuration button; raising one needs `ahub ui --settings`
117
+ or `ahub settings` in a terminal, and guarded values from an edited file need
118
+ `ahub settings reload` there. See the operations guide, "Settings from the dashboard and the
100
119
  terminal" and "Start modes".
101
120
 
102
121
  `ahub ui --no-open` prints a one-time link instead of launching a browser. Open it