@staix/agent-hub 0.12.22 → 0.12.24

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 (183) hide show
  1. package/CHANGELOG.md +117 -0
  2. package/README.md +22 -9
  3. package/docs/addons/claude-mem.md +24 -0
  4. package/docs/addons/codex-plugin.md +8 -0
  5. package/docs/addons/dot-admit.md +8 -0
  6. package/docs/addons/open-code-review.md +8 -0
  7. package/docs/addons/ponytail.md +23 -0
  8. package/docs/addons/ripwire.md +22 -0
  9. package/docs/agent-notes/README.md +5 -0
  10. package/docs/agent-notes/adapters.md +18 -6
  11. package/docs/agent-notes/benchmarks.md +3 -0
  12. package/docs/agent-notes/budget.md +4 -0
  13. package/docs/agent-notes/bus.md +3 -1
  14. package/docs/agent-notes/daemon.md +14 -1
  15. package/docs/agent-notes/local-worker.md +6 -3
  16. package/docs/agent-notes/tasks.md +6 -1
  17. package/docs/agent-notes/tests.md +4 -1
  18. package/docs/bench.md +28 -3
  19. package/docs/cooperbench.md +4 -0
  20. package/docs/data-policy.md +36 -0
  21. package/docs/events.md +10 -3
  22. package/docs/gsd-collaboration-analysis.md +48 -0
  23. package/docs/memory.md +231 -0
  24. package/docs/operations.md +873 -30
  25. package/docs/plans/2026-10-11-issues-109-sequential.md +81 -0
  26. package/docs/plans/2026-10-11-routing-evaluation-proposal.md +30 -0
  27. package/docs/profiles.md +57 -0
  28. package/docs/quickstart.md +9 -4
  29. package/docs/research.md +31 -1
  30. package/docs/roles.md +85 -0
  31. package/docs/sdlc.md +170 -0
  32. package/docs/security.md +124 -8
  33. package/docs/smoke.md +354 -5
  34. package/docs/specs/2026-09-19-agent-hub-design.md +676 -15
  35. package/docs/specs/2026-10-12-backlog-implementation-plan.md +186 -0
  36. package/docs/specs/2026-10-12-office-view-design.md +212 -0
  37. package/docs/text-projection.md +19 -0
  38. package/docs/verification/2026-10-10-cli-output-phase1.md +309 -0
  39. package/docs/verification/2026-10-10-cli-output-phase2.md +672 -0
  40. package/docs/verification/2026-10-11-0.12.23.md +90 -0
  41. package/docs/verification/2026-10-11-acp-watch-t0.md +33 -0
  42. package/docs/verification/2026-10-11-agent-config-inventory.md +20 -0
  43. package/docs/verification/2026-10-11-jcode-peer-contract.md +27 -0
  44. package/docs/verification/2026-10-13-0.12.24.md +94 -0
  45. package/docs/verification/2026-10-13-board-phone.md +31 -0
  46. package/docs/verification/2026-10-13-fsmonitor-fixture-attribution.md +19 -0
  47. package/docs/verified.json +34 -16
  48. package/package.json +2 -1
  49. package/plugins/agent-hub/.claude-plugin/plugin.json +1 -1
  50. package/plugins/agent-hub/ROLE-NOTICE.md +26 -0
  51. package/plugins/agent-hub/server.js +1108 -261
  52. package/scripts/check-docs.mjs +129 -0
  53. package/src/adapters/acp-quota.ts +13 -0
  54. package/src/adapters/acp.ts +201 -20
  55. package/src/adapters/claude-channel.ts +48 -11
  56. package/src/adapters/codex-appserver.ts +54 -13
  57. package/src/adapters/jcode.ts +110 -0
  58. package/src/adapters/local-worker.ts +10 -7
  59. package/src/adapters/pi.ts +94 -20
  60. package/src/cli/attention.ts +60 -0
  61. package/src/cli/bench.ts +26 -6
  62. package/src/cli/board-read.ts +12 -0
  63. package/src/cli/console-state.ts +131 -39
  64. package/src/cli/console.ts +73 -17
  65. package/src/cli/facts-hook.ts +12 -4
  66. package/src/cli/help.ts +52 -21
  67. package/src/cli/identity.ts +19 -8
  68. package/src/cli/init.ts +48 -10
  69. package/src/cli/jcode-mcp.ts +58 -0
  70. package/src/cli/kimi-mcp.ts +53 -0
  71. package/src/cli/launch.ts +16 -1
  72. package/src/cli/main.ts +641 -193
  73. package/src/cli/memory.ts +193 -0
  74. package/src/cli/output.ts +404 -0
  75. package/src/cli/pet-config.ts +1 -0
  76. package/src/cli/pet.ts +83 -0
  77. package/src/cli/preview.ts +40 -6
  78. package/src/cli/reset.ts +3 -0
  79. package/src/cli/status-lines.ts +1 -29
  80. package/src/cli/tail-render.ts +1 -0
  81. package/src/cli/terminal-recovery.ts +27 -1
  82. package/src/cli/upgrade-runtime.ts +56 -10
  83. package/src/cli/upgrade.ts +23 -5
  84. package/src/cli/watch.ts +31 -0
  85. package/src/hub/activity.ts +53 -0
  86. package/src/hub/ask.ts +10 -5
  87. package/src/hub/bench.ts +10 -3
  88. package/src/hub/board.ts +224 -16
  89. package/src/hub/budget.ts +39 -7
  90. package/src/hub/bus.ts +58 -20
  91. package/src/hub/child-process.ts +11 -0
  92. package/src/hub/citations.ts +7 -0
  93. package/src/hub/conductor.ts +34 -17
  94. package/src/hub/config-trust.ts +20 -7
  95. package/src/hub/conflicts.ts +2 -0
  96. package/src/hub/context-window.ts +8 -1
  97. package/src/hub/crash.ts +11 -1
  98. package/src/hub/daemon.ts +1218 -113
  99. package/src/hub/db-timeout.ts +3 -0
  100. package/src/hub/delivery-journal.ts +7 -1
  101. package/src/hub/envelope.ts +1 -1
  102. package/src/hub/events.ts +14 -2
  103. package/src/hub/execution-budget.ts +2 -0
  104. package/src/hub/facts.ts +28 -8
  105. package/src/hub/git.ts +38 -0
  106. package/src/hub/github-import.ts +28 -0
  107. package/src/hub/hub-tools.ts +49 -10
  108. package/src/hub/inference.ts +1 -1
  109. package/src/hub/lifecycle-schema.ts +17 -0
  110. package/src/hub/lifecycle.ts +10 -4
  111. package/src/hub/listen.ts +15 -0
  112. package/src/hub/manager.ts +26 -6
  113. package/src/hub/path-policy.ts +96 -0
  114. package/src/hub/peer-catalog.ts +28 -0
  115. package/src/hub/peers.ts +5 -3
  116. package/src/hub/permission-mode.ts +33 -5
  117. package/src/hub/planning.ts +70 -0
  118. package/src/hub/profiles.ts +74 -0
  119. package/src/hub/project.ts +2 -1
  120. package/src/hub/projected-diff.ts +73 -0
  121. package/src/hub/projection-exec.ts +24 -0
  122. package/src/hub/recovery-error.ts +31 -0
  123. package/src/hub/recovery-store.ts +6 -5
  124. package/src/hub/registry.ts +2 -1
  125. package/src/hub/research.ts +144 -21
  126. package/src/hub/roles.ts +123 -0
  127. package/src/hub/roster.ts +23 -0
  128. package/src/hub/routing.ts +132 -18
  129. package/src/hub/sdlc-queue.ts +112 -0
  130. package/src/hub/sdlc-release.ts +125 -0
  131. package/src/hub/sdlc.ts +250 -0
  132. package/src/hub/settings.ts +411 -0
  133. package/src/hub/shipped-roles.ts +25 -0
  134. package/src/hub/snapshots.ts +92 -16
  135. package/src/hub/start-mode.ts +50 -0
  136. package/src/hub/supervision.ts +1 -0
  137. package/src/hub/task-sweep.ts +1 -1
  138. package/src/hub/tasks.ts +1014 -111
  139. package/src/hub/terminal-open.ts +64 -0
  140. package/src/hub/text-projection.ts +126 -0
  141. package/src/hub/tooling.ts +159 -0
  142. package/src/hub/ui.ts +40 -14
  143. package/src/hub/workflow.ts +71 -0
  144. package/src/local/deny.ts +29 -7
  145. package/src/local/sandbox.ts +50 -10
  146. package/src/local/tools.ts +11 -6
  147. package/src/memory/brief.ts +28 -14
  148. package/src/memory/import.ts +55 -0
  149. package/src/memory/recall.ts +86 -2
  150. package/src/memory/store.ts +750 -0
  151. package/src/memory/sync.ts +145 -0
  152. package/src/models/mlx.ts +2 -1
  153. package/src/pet/NOTICE.md +10 -0
  154. package/src/pet/characters.ts +1438 -0
  155. package/src/pet/config.ts +31 -0
  156. package/src/pet/frame.ts +17 -0
  157. package/src/pet/pixels.ts +28 -0
  158. package/src/pi/tool-receipts.ts +2 -1
  159. package/src/role-text.d.ts +1 -0
  160. package/src/ui/index.html +983 -40
  161. package/src/ui/needs.ts +58 -0
  162. package/src/ui/office-model.ts +440 -0
  163. package/src/ui/peer-palette.ts +16 -0
  164. package/src/ui/task-board.ts +49 -0
  165. package/src/ui/task-progress.ts +5 -1
  166. package/templates/AGENTS.block.md +3 -2
  167. package/templates/config.json +5 -1
  168. package/templates/profiles/dev.json +22 -0
  169. package/templates/profiles/general.json +26 -0
  170. package/templates/profiles/research.json +57 -0
  171. package/templates/profiles/writing.json +28 -0
  172. package/templates/roles/NOTICE.md +26 -0
  173. package/templates/roles/dev/backend-engineer.md +26 -0
  174. package/templates/roles/dev/code-reviewer.md +26 -0
  175. package/templates/roles/dev/frontend-engineer.md +26 -0
  176. package/templates/roles/dev/security-reviewer.md +26 -0
  177. package/templates/roles/dev/software-architect.md +26 -0
  178. package/templates/roles/dev/test-engineer.md +26 -0
  179. package/templates/roles/research/analyst.md +26 -0
  180. package/templates/roles/research/fact-checker.md +26 -0
  181. package/templates/roles/research/research-lead.md +26 -0
  182. package/templates/roles/research/researcher.md +26 -0
  183. package/templates/roles/research/statistician.md +26 -0
@@ -1,8 +1,25 @@
1
1
  # Operations guide
2
2
 
3
- This guide describes ahub 0.12.22 and control protocol 16. Live verification
3
+ This guide describes ahub 0.12.24 and control protocol 16. Live verification
4
4
  results and remaining prerequisites are recorded separately in [the smoke ledger](smoke.md).
5
5
 
6
+ ## Command output
7
+
8
+ `ahub status`, `board`, `budget`, `doctor`, `projects`, `queue list`, `turns` and `report` print shared console tables and labelled details.
9
+ `status --all` uses the projects table. `queue show`, `models status` and `budget execution status` show labelled fields; add `--json` for the raw fetched document.
10
+ `report --by task` keeps the attribution and coverage sentences with section headings and aligned counters.
11
+ Use `--json` for scripts; it returns the fetched data without color, and `status --json` keeps its existing document.
12
+ 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.
13
+ 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:
14
+ turn ids, queue ids, project ids, execution budget ids and ids in labelled views. Only status's informational settlement and hold ids are shortened;
15
+ `status --full` keeps those whole too. Identifiers in suggested commands are always whole.
16
+
17
+ `--color=auto|always|never` uses the console palette. Auto colors only a TTY with `TERM` other than `dumb`
18
+ and empty `NO_COLOR`; pipes and redirects stay plain. Color never replaces a state or level word.
19
+ TTY width is its columns (at least 80). A pipe uses a positive integer `COLUMNS` when supplied, otherwise rows
20
+ are complete and unwrapped. Long fields wrap within their column; when whole metadata words and the readable flexible-column minimum do not fit, table bands retain every field. Each band carries the row id; when it cannot share a line with the metadata, a per-row id banner links them. Labelled two-column views keep each label beside its value, wrapping the value instead of separating labels and values into bands. In `turns`, the time and state cells wrap at word boundaries only when the file list needs the room and the listing gets shorter for it. When `projects` bands, the task list stays with the state columns in the first band and the second band is always PROJECT and ROOT. Console children receive the console's width
21
+ minus its four-column indent and remain uncolored.
22
+
6
23
  ## Command help
7
24
 
8
25
  `ahub help`, `ahub --help` and `ahub -h` print the commands grouped by section;
@@ -47,6 +64,34 @@ its footer. The active tab is bracketed, as in `[2 Approvals]`, so it reads
47
64
  without color. The Approvals tab counts pending requests and the Queue tab
48
65
  counts `needs_review` deliveries, in the attention and failure tones.
49
66
 
67
+ The console attention companion (#280) shows waiting, blocked, review, working,
68
+ idle or asleep with separate action/watch counts. `n` selects the exact approval,
69
+ held queue or review row, or prints applicable guidance; it never answers a
70
+ request or runs a command. Editing, choices and confirmation retain their controls.
71
+ `P` cycles the five built-in characters and off for the current console.
72
+
73
+ Configure `pet` in `.agenthub/config.json` or `config.local.json`; local options
74
+ override shared ones. Defaults are `character: "stai"`, `size: "line"`,
75
+ `glyphs: "auto"`, `blink: true`, `bell: false`. Line preserves the three footer
76
+ rows and prompt position. Mini/full reserve a bounded character rectangle and
77
+ fall back when the terminal is too small. Supported glyphs and character choices
78
+ are described below. `pet: false` or `ahub console --no-pet` disables presentation.
79
+ Unknown options produce one bounded notice and fall back. Only an open approval
80
+ blinks through the existing redraw; `blink: false` disables it. The optional bell
81
+ sounds on an action-count transition from zero, at most once per minute, never
82
+ for a message alone. Plain mode prints the line only when the action count changes.
83
+ Messages addressed to `user` remain attention items until the next key. Drawing
84
+ adds no timer, network request or writable settings path.
85
+ Tabs change with the digits 1 to 5 or with Left and Right (wrapping at both
86
+ ends), never while a command is being edited or a choice is open; under a
87
+ confirmation an arrow dismisses it like any key but y, without moving a tab. A pasted
88
+ chunk can only edit the command line, but a read that holds nothing but arrow
89
+ sequences is that many key presses, so a held key repeats its tab move. In the Events
90
+ tab a row's header line is tokenized and coloured exactly as the same event in
91
+ the stream; only the header is tab-flattened before tokenizing. Body lines retain
92
+ the previous rendering and stay plain, as does command output; colour never changes
93
+ what the panel's text says.
94
+
50
95
  Peers, Approvals, Tasks and Queue are tables with a header row. A column is as
51
96
  wide as its widest cell, up to a third of the terminal; the last column takes
52
97
  the rest and is cut with `...`. In Tasks, TITLE takes the rest and the STAGE
@@ -78,7 +123,7 @@ prompts, are quoted unless they are a single word starting with a letter, so
78
123
  punctuation, a newline or a bare number in them cannot imitate the console's own
79
124
  structure. Under the `?` key table only `?`, Escape and `q` act.
80
125
 
81
- Arrow keys or j/k move, Enter opens a detail of labeled fields (relative times,
126
+ Up/Down arrows or j/k move, Enter opens a detail of labeled fields (relative times,
82
127
  never JSON), Escape returns, and `?` shows the keys grouped by panel; in the
83
128
  stream, `?` prints that table and `v` prints the selected request as its push
84
129
  showed it. The footer's last line lists only the keys that act in the current
@@ -122,6 +167,60 @@ OS color preference through CSS. Both inline scripts and the style retain CSP
122
167
  hashes; there are no external chart/theme assets. Live theme/readability inspection
123
168
  is tracked in `docs/smoke.md` and remains unverified until performed.
124
169
 
170
+ The dashboard Office section (#264, phase 1 of 4) draws the same snapshot as a
171
+ static flat office: one desk per peer in a stable slot (claude, codex, kimi, pi,
172
+ local, then others by id; a peer going offline dims its desk and never moves
173
+ another), rooms for the board columns in a fixed order (To Do, Work floor,
174
+ Review, Done shelf as a count only), at most 8 cards per room with "+N more"
175
+ filtering the task list to that state, and at most 12 desks with "+N peers".
176
+ Work-floor cards sit at the owner's desk, marked for rework; a busy peer's task
177
+ bubble names its task only when it has exactly one in progress. Every peer
178
+ condition (idle, busy, offline, paused, waiting on approval) has a glyph and a
179
+ text label, and the scene carries ids, classes, states, kinds, counts and public
180
+ titles only: message bodies, task details and approval titles never enter it.
181
+ The scene adds no timer, frame loop or request and re-renders only when its
182
+ signature changes. A View control offers Off (the default), Flat and
183
+ Isometric; the choice is stored in a second host-scoped loopback cookie `agent-hub-office` with the
184
+ same attributes as the theme cookie, and blocked cookie access defaults to Off
185
+ without preventing operation. Desks and cards are focusable buttons; activating
186
+ one scrolls to and highlights the matching list row, and a list row highlights
187
+ its desk or card on focus and hover. The scene performs no action: every control
188
+ stays in the lists. The View control's third option, Isometric (phase 4),
189
+ renders the same model through the same code path with the grid coordinates
190
+ projected (x' = (x - y) cos 30, y' = (x + y) sin 30): tiles become
191
+ parallelograms, cards and labels stay upright, and the DOM order and
192
+ accessible names are identical to Flat. Switching the view jumps to the new
193
+ projection without animating; the settle rule and reduced motion apply
194
+ unchanged. The live browser look is tracked in `docs/smoke.md` and
195
+ remains unverified until performed.
196
+
197
+ Motion (phase 2): card moves between rooms and desks, message arcs between
198
+ desks (from the hub or the console they start at an anchor point), delivery
199
+ warning marks and the busy latch all follow the snapshot. Motion is CSS only:
200
+ transitions on transform and opacity (at most one second), keyframe fades for
201
+ the transient marks. Arcs and marks hold, then fade out ten seconds after the
202
+ event, timed at render from the model's timestamps; expired nodes purge on the
203
+ next changed render or their own animationend, never on a timer. Arcs expire on
204
+ the snapshot's own envelope clock, so an unchanged snapshot re-renders
205
+ identically and writes nothing to the DOM. The scene goes straight to final
206
+ positions on the first snapshot, after a project switch, after a snapshot gap
207
+ over three seconds, or when one snapshot brings more than six transitions.
208
+ `prefers-reduced-motion: reduce` removes all scene transitions and animations.
209
+ Event reasons and bodies never enter the scene; arcs carry from, to, kind,
210
+ priority, the task ref and the dropped flag only.
211
+
212
+ Snapshot fields (phase 3): three additive optional fields, so older pages and
213
+ older daemons mix freely and `PROTOCOL`/`EVENTS_SCHEMA` stay unchanged. A peer's
214
+ open turn (`since`, `task`, `attribution`) names the busy bubble's task exactly
215
+ instead of the single-in-progress-task heuristic, and a turn still open while
216
+ the peer is paused adds a "finishing a turn" line under the Break sign. A task's
217
+ `checking` flag draws a check-running mark on its card, which stays at its
218
+ owner's desk (rooms follow states only). Warning `links` (overlap from the
219
+ board's overlap test, cohorts, and recent turn-end conflicts the daemon keeps in
220
+ a bounded in-memory list) draw dashed lines between the desks they name, labeled
221
+ with kind and task ids; all three carry task and peer ids only, and a PII task
222
+ never joins a link.
223
+
125
224
  Console color policy is `--color=auto|always|never`, with `auto` as the default.
126
225
  Auto enables color only when both input and output are TTYs, `TERM` is not
127
226
  `dumb`, and `NO_COLOR` is empty or absent. Explicit `always` overrides these
@@ -199,10 +298,12 @@ Launch that peer with `ahub claude` for channel pushes, or select `codex` in
199
298
  `roles` and launch `ahub codex`. The conductor splits work into owned tasks,
200
299
  observes `hub_status`, moves stalled work and obtains review before reporting
201
300
  results and open decisions. It does not implement the tasks it handed out.
202
- `hub_peer_start` starts local, Kimi or headless Pi; requests for native TUIs
203
- return the `ahub` command for the person to run, after validating it through
204
- the shared launcher planner. The wrapper plans again at launch when native
205
- endpoints are available. `hub_peer_hold` and `hub_peer_release`
301
+ `hub_peer_start` starts a peer in the start mode a person set for it (see
302
+ "Start modes"): local and headless Kimi, Pi or Codex start at once; for a
303
+ TUI peer the hub opens a terminal running the fixed `ahub <peer>` command,
304
+ after validating it through the shared launcher planner, and when it cannot
305
+ open one the call fails with that command for the person to run. The
306
+ conductor cannot choose the mode. `hub_peer_hold` and `hub_peer_release`
206
307
  manage only holds placed by that conductor. Assignment also requires `assign`
207
308
  when the conductor has an explicit capabilities list.
208
309
 
@@ -351,7 +452,7 @@ Managed launchers attach native peers to the project daemon:
351
452
  ahub claude
352
453
  ahub codex
353
454
  ahub kimi
354
- ahub pi --mode headless --backend auto
455
+ ahub pi # its TUI; --headless for the background peer
355
456
  ahub local
356
457
  ahub local --model <served-model-id>
357
458
  ```
@@ -380,7 +481,19 @@ A delivery in `needs_review` holds later deliveries to that peer. The console an
380
481
  the hold once, and status, task assignment and route explanations name its delivery id.
381
482
  Inspect it with `ahub queue show <id>` and explicitly choose `completed`, `retry` or
382
483
  `discard` through `ahub queue resolve`. Reassignment or approval of its task never
383
- resolves an uncertain delivery automatically.
484
+ resolves an uncertain delivery automatically. The same rule holds on every path that
485
+ assigns a task (#297): once the move is saved on the board, a failed delivery prints
486
+ exactly one console notice ("the move is saved... delivery is not confirmed"), printed
487
+ where the error is thrown, and the caller (a peer in its turn, or the CLI) still gets
488
+ its error. Two exceptions, by construction: a move superseded while the assignment was being prepared, meaning a later history entry that moves or settles the task (another assignment, an unassign, the owner's accept, done, approval, close; the hub's quiet bookkeeping such as a late check result or a reviewer change does not supersede), is
489
+ the caller's error as before, with no notice naming either owner; and a claim is its own hand-over, so its
490
+ accepted write and line stay outside the delivery rule (its overlap and routing announcements to earlier
491
+ owners are deliveries and share it). The repair is always
492
+ to look for a queued or needs_review delivery with
493
+ `ahub queue list --peer <owner>` (then `ahub queue show <id>`, or the accepted entry in
494
+ `ahub task show <id>` if the journal itself is down) and then send the assignment again
495
+ with `ahub task assign <id> <owner>`. Nothing resends automatically: a blind resend can
496
+ duplicate a delivery that actually left.
384
497
 
385
498
  Reviewer candidates follow `[classes.review].peers`, then attached peers with a
386
499
  `reviewer` role in `roles`. The owner cannot review its own task. If none is available,
@@ -582,6 +695,30 @@ ahub research backfill # build this project's records once from even
582
695
  ahub task label 12 reverted # a later verdict (ok, regressed, reverted, incomplete, wrong, abandoned)
583
696
  ```
584
697
 
698
+ ## Hub memory
699
+
700
+ The hub keeps its own memory in `~/.agenthub/memory/` beside claude-mem ([how it works](memory.md)): notes saved
701
+ against an open task are short-term; when the task is approved its decisions, contracts and fails become long-term.
702
+ Task briefs, session-start recall and `ahub ask` read it first, and the dashboard has a Memory section.
703
+
704
+ ```bash
705
+ ahub memory # this project's entries, newest first
706
+ ahub memory search parser # every word must match
707
+ ahub memory show 1a2b3c4d # one entry, its provenance and edges
708
+ ahub memory forget 1a2b3c4d # a person's; also promote, demote, supersede, rebuild
709
+ ```
710
+
711
+ `"memory": { "native": false }` in `.agenthub/config.json` turns it off for a project.
712
+
713
+ Between your machines, through a private git remote, with long-term tasks that span them:
714
+
715
+ ```bash
716
+ ahub memory sync --remote git@github.com:you/agent-hub-memory.git # once per machine; then every 10 minutes
717
+ ahub goal new "native memory" # a long-term task
718
+ ahub goal # open ones, who holds each and until when
719
+ ahub goal take 1a2b3c4d --force # take one over from another machine
720
+ ```
721
+
585
722
  ## Benchmarks
586
723
 
587
724
  In a git repository kept for benchmarks (`"bench": { "enabled": true }` in its `.agenthub/config.json`, a clean tree),
@@ -644,7 +781,7 @@ ahub undo <turn> --yes --context # Codex's latest turn: also drop it from Codex
644
781
  has not removed yet included, and a PII file left in the project is
645
782
  snapshotted by later turns like any other file. Keep PII files in an ignored
646
783
  directory.
647
- - A turn the hub stopped in the middle of shows as `(no end snapshot)` and
784
+ - A turn the hub stopped in the middle of shows the state `no end snapshot` and
648
785
  cannot be undone.
649
786
  - Claude's turns are not recorded: its channel shows the hub no turn boundary.
650
787
  Claude Code's own checkpoints cover its edits, though not its shell commands.
@@ -875,7 +1012,7 @@ denylist (Pi and local), or native vendor boundaries (Claude and Codex).
875
1012
  | --- | --- | --- | --- |
876
1013
  | Kimi Code CLI | ACP yolo | ACP auto | ACP default |
877
1014
  | Codex | on-request for every outgoing turn/start | never for every outgoing turn/start | Restore the known native policy once, then stop overriding |
878
- | Claude | Allow resolving project file tools outside .agenthub/.git/.claude/.codex/.qwen/.kimi/.pi/.mcp.json | Hook allow for every tool | No hook decision |
1015
+ | Claude | Allow resolving project file tools outside .agenthub/.git/.claude/.codex/.qwen/.kimi/.kimi-code/.pi/.mcp.json | Hook allow for every tool | No hook decision |
879
1016
  | 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 |
880
1017
 
881
1018
  Kimi's map applies only to the actual Kimi Code CLI identity, not another ACP
@@ -956,6 +1093,246 @@ permission_mode (peer/from/to) with no tool arguments under events schema 1.
956
1093
  The optional control requests preserve PROTOCOL; an older hub answers unknown
957
1094
  and the CLI advises upgrading.
958
1095
 
1096
+ ## Change the participating peers while the hub runs
1097
+
1098
+ `ahub roster` lists every known peer, whether it participates, its start mode,
1099
+ current state, queued messages and open tasks. `ahub roster --json` is the same
1100
+ ordered catalog view for scripts. Status and the console keep their existing lazy
1101
+ rows; an off-roster peer is shown only while it has retained messages, an uncertain
1102
+ delivery or open work, with the words `off roster`.
1103
+
1104
+ ```bash
1105
+ ahub roster
1106
+ ahub roster remove kimi --yes # print the preview, confirm and remove
1107
+ ahub roster remove kimi --yes --now # stop a busy owned runtime before handing work over
1108
+ ahub roster add kimi
1109
+ ahub settings set roster.kimi false --preview
1110
+ ahub settings set roster.kimi false --yes
1111
+ ```
1112
+
1113
+ These are person's commands and use the same settings preview, write and undo as
1114
+ the dashboard's Roster settings. An ordinary dashboard session may remove a peer;
1115
+ adding requires `ahub ui --settings` or a person's terminal. Removal requires the
1116
+ peer id as confirmation. Without `--now`, a busy peer is refused. A conductor
1117
+ holder cannot be removed until its role is moved.
1118
+
1119
+ Removal fences membership, stops hub-owned runtimes or detaches sessions in a
1120
+ person's terminal, and then hands work over. The removal preview and result name
1121
+ the peer whose existing work the person must stop in that retained terminal;
1122
+ the preview names the roles offered and those with no eligible replacement; the
1123
+ result lists the saved owner/reviewer moves and every assignment that stays. No stop notice is forced into
1124
+ a detached session and nothing bypasses the journal. Codex 0.146.0
1125
+ exits its TUI on the close-4000 disconnect and does not reconnect automatically.
1126
+ Its app-server and proxy remain available; after `ahub roster add codex`, run
1127
+ `ahub codex resume <thread-id>` (the full id is printed in the preview, removal
1128
+ result and return) or `ahub codex resume` to select its previous native session. Removal never closes
1129
+ the terminal window itself. The Claude channel retries and reconnects on return.
1130
+ Pi return retains the verified owner's monotonic generation even after refused
1131
+ native activity while detached; it shares no personal output and invalidates any
1132
+ cached empty-session resume proof after that activity.
1133
+ It leaves queued and held deliveries, and existing manual or budget pauses,
1134
+ untouched. The queue listing names `off roster` as the membership hold. Returning
1135
+ and starting the peer makes retained queued messages available again; held
1136
+ uncertain work still needs the existing queue resolution command. A detached
1137
+ personal Pi TUI with a live owner still blocks controlled recovery as `pi is not
1138
+ settled`; end that retained TUI before restart/upgrade. The hub does not declare
1139
+ a live native owner settled or close it implicitly during preparation. Open owner and
1140
+ reviewer work, including ownership of `in_review` tasks, is offered through the
1141
+ existing reassignment path; a transferred review keeps its review state. If nobody can
1142
+ take it, its assignment stays and a notice names the person's next action. Task
1143
+ text in a notice uses its public title, so a private task remains a stub. A stop
1144
+ that is unconfirmed leaves the roster saved and reports that permission reset and
1145
+ handoff were not attempted; reapply the removal after checking the runtime.
1146
+
1147
+ A hub task, verdict, review or budget message addressed to an off-roster peer
1148
+ stays in its retained queue, with one public notice to the person. Task operations
1149
+ use the current owner and reviewer after reassignment. A mixed addressed audience
1150
+ receives the on-roster copies now and retains the off-roster copies; the sender
1151
+ sees the existing notice field (or a decision note for native answers). Broadcasts
1152
+ exclude off-roster peers; a person or agent addressing only removed peers is
1153
+ refused before publishing. The dashboard roster undo has its own peer-id
1154
+ confirmation and optional active-turn stop checkbox.
1155
+
1156
+ Without a roster setting, participation keeps the previous defaults. An explicit
1157
+ `roster.pi` overrides `pi.enabled`; otherwise that legacy switch continues to
1158
+ control Pi starts. External peer ids remain governed by their existing admission
1159
+ rules. A runtime permission override is cleared on removal and the configured
1160
+ default governs the next attachment. Config file edits outside the authorized
1161
+ roster setting do not change running participation: they take effect at the next
1162
+ hub start. The tracked config can provide defaults and config.local.json can
1163
+ override them.
1164
+
1165
+ ## Settings from the dashboard and the terminal
1166
+
1167
+ The dashboard's Settings section and `ahub settings` show and change the same
1168
+ closed list of settings (issue #269). Run them from a plain terminal:
1169
+
1170
+ ```bash
1171
+ ahub settings # every setting: value, source file, when it applies
1172
+ ahub settings get permission.kimi
1173
+ ahub settings set routing.classes.implement.peers codex,kimi,pi --preview
1174
+ ahub settings set routing.classes.implement.peers codex,kimi,pi
1175
+ ahub settings set permission_modes.kimi ask-when-needed
1176
+ ahub settings set research.enabled inherit # remove the machine-local value
1177
+ ahub settings undo # put back the file the last write changed
1178
+ ahub ui --settings # dashboard with a 15-minute settings session
1179
+ ```
1180
+
1181
+ | Group | Keys | Stored in | Applies |
1182
+ | --- | --- | --- | --- |
1183
+ | Permissions | `permission.<peer>` (the mode now) | the running hub only | at once |
1184
+ | Permissions | `permission_modes.<peer>` (the mode at hub start) | `config.local.json` | next hub start |
1185
+ | Start | `peers.pi.start_mode`, `peers.codex.start_mode`, `peers.kimi.start_mode` (`tui` or `headless`) | `config.local.json` | that peer's next start |
1186
+ | Start | `pi.auto_start` | `config.local.json` | next hub start |
1187
+ | Routing | `routing.stay_switch`, `routing.classes.<class>.peers`, `.escalate_to`, `.route`, `.pi_backend` | `routing.local.toml` | at once |
1188
+ | Switches | `research.enabled`, `approvals.notify`, `snapshots.enabled`, `coordination` | `config.local.json` | next hub start |
1189
+
1190
+ - Writes go only to `.agenthub/config.local.json` and `.agenthub/routing.local.toml`,
1191
+ the machine-local files (`ahub init` ignores both in git). The shared
1192
+ `config.json` and the hand-written `routing.toml` are never rewritten, and a
1193
+ machine-local file that is committed to git is refused. Each write is read by
1194
+ the hub's own loader first and replaces the file atomically.
1195
+ - `routing.local.toml` overrides `routing.toml` key by key and may hold only the
1196
+ routing keys in the table. `ahub route explain` and the Settings rows name the
1197
+ file each value comes from. `--preview`, and the dashboard's Preview button,
1198
+ show `ahub route explain` for the open tasks before and after, or what a
1199
+ permission mode grants, and save nothing.
1200
+ - A row shows the value in force, its source file, when it applies, and for a
1201
+ value read at hub start what the next start will read (`Pending restart`).
1202
+ - `ahub settings undo` (the dashboard's "Undo last write") puts back the one
1203
+ previous version of the file the last write changed. It refuses when that
1204
+ file was edited since, and when it would put a stored never-ask back (set it
1205
+ again with its confirmation instead). A mode changed for the running hub is
1206
+ not a file: set it again instead. Setting a value it already has, or
1207
+ removing one that is not set, writes nothing. A project with no
1208
+ `.agenthub/config.json` gets no first config file from a settings write
1209
+ (any config file turns the project defaults on): run `ahub init` first.
1210
+ - A project initialised before 0.12.23 has no `.gitignore` line for
1211
+ `.agenthub/routing.local.toml`: run `ahub init` again, or add it. A
1212
+ `permission_modes` value is read only from a file git confirms nobody
1213
+ committed (config trust); where the hub will not read what was written, the
1214
+ reply and the Settings row say so.
1215
+ - Authority: a dashboard opened with `ahub ui` reads settings, lowers a mode to
1216
+ `ask`, turns `pi.auto_start` off, sets a start mode back to `tui` and changes
1217
+ the Switches group. Everything
1218
+ else needs `ahub ui --settings`, whose session may raise for 15 minutes, or
1219
+ `ahub settings` in a terminal. `never-ask` needs the peer id typed in the
1220
+ dashboard, or `--yes` in the terminal, and a stored never-ask default still
1221
+ waits for `y` in `ahub console` at each hub start. Tool approvals stay
1222
+ deny-only for Pi and local in every session.
1223
+ - Commands and binaries, credential files, gateway URLs and the local worker's
1224
+ reach are never editable here: edit `.agenthub/config.local.json` yourself.
1225
+ - Every change is announced in `hub.log` and open consoles with its source and
1226
+ recorded as a `settings` event. `ahub settings` needs a running hub; an older
1227
+ hub answers the request as unknown and the CLI advises upgrading. The unified
1228
+ dashboard (`ahub ui --all`) acts as an ordinary session.
1229
+
1230
+ ## Start modes: TUI by default, headless as opt-in
1231
+
1232
+ A peer that has a TUI the hub attaches to starts in it by default (issue #269).
1233
+
1234
+ | Peer | Default | Headless |
1235
+ | --- | --- | --- |
1236
+ | pi | `tui` | `ahub pi --headless` (or `--mode headless`), or `peers.pi.start_mode: headless` |
1237
+ | codex | `tui` (`ahub codex`) | `peers.codex.start_mode: headless`: a hub-made start runs the app-server only |
1238
+ | claude | `tui` (`ahub claude`) | none |
1239
+ | kimi | `tui`, pull-only (`ahub kimi`) | `ahub kimi --mode headless`, or `peers.kimi.start_mode: headless` |
1240
+ | local | headless (hub-native) | not applicable |
1241
+
1242
+ - **You type the command:** `ahub pi` opens Pi's TUI in that terminal.
1243
+ `--headless` and the start mode setting are the two ways to ask for the
1244
+ background peer. `ahub settings set peers.pi.start_mode headless` writes the
1245
+ setting; it applies at Pi's next start.
1246
+ - **The hub starts the peer** (the dashboard's Start control, `pi` typed in
1247
+ `ahub console`, the conductor's `hub_peer_start`, `pi.auto_start`): it
1248
+ follows the peer's start mode. For `tui` it opens a terminal running the
1249
+ fixed command `ahub <peer>`, through a terminal provider:
1250
+ 1. `terminal.open` in `.agenthub/config.local.json`, an argv in which one
1251
+ element holds `{command}` (the quoted command line to run); `{title}` and
1252
+ `{cwd}` are replaced too. Examples:
1253
+ `["tmux", "new-window", "-n", "{title}", "{command}"]`,
1254
+ `["wezterm", "start", "--cwd", "{cwd}", "--", "sh", "-c", "{command}"]`.
1255
+ Only a config file nobody committed may set it, and it is not a setting
1256
+ the dashboard or `ahub settings` can write. It is read at hub start.
1257
+ `{command}` is quoted for a POSIX shell; `{title}` and `{cwd}` are raw,
1258
+ so give each an argv element of its own.
1259
+ 2. Orca, when the hub runs in an Orca worktree or an earlier `ahub <peer>`
1260
+ launch of this project recorded one (the path recovery uses).
1261
+ - **No provider:** the start is refused with the command to run by hand. It is
1262
+ never downgraded to headless. `ahub settings` lists each start mode, and the
1263
+ dashboard's Start control says which mode a start will use and where its
1264
+ terminal comes from.
1265
+ - **Dashboard Start:** the control is locked while its request is in flight. A confirmed answer unlocks it immediately, so a retry reaches the hub's own 30-second terminal reopen guard and shows any known refusal. The unified dashboard waits 35 seconds, covering a terminal provider's 30-second cap plus a 5-second response margin; a slower headless start can still end unconfirmed while the hub continues. Check the Peers panel before retrying. An unconfirmed unified-dashboard start holds that peer's control for the shared 30-second reopen bound, or until its `starts` snapshot confirms attachment, across redraws and project switches within the same hub instance; the row states the retry bound. The project-local dashboard keeps its usual confirmed-answer behavior. Other forwarded actions keep their 10-second wait; the manager opens no settings session.
1266
+ - The conductor cannot choose the mode: `hub_peer_start` takes the peer's own.
1267
+ - Recovery restores each peer in the mode its recorded session had. After an
1268
+ unplanned stop, a Pi that ran in a terminal is reported with its command and
1269
+ is not replaced by a headless one unless headless is its start mode.
1270
+
1271
+ ### Kimi in its own TUI
1272
+
1273
+ `ahub kimi` runs Kimi in the person's terminal by default. The launcher atomically
1274
+ merges only `mcpServers["agent-hub"]` in `.kimi-code/mcp.json`, keeping foreign
1275
+ entries and fields. It contains machine paths and the peer identity, not a token.
1276
+ `ahub init` ignores that file when it is untracked; a tracked file is still written
1277
+ with a warning. `--print-command` shows the change and command without writing.
1278
+ The configured `kimi_cmd` must be a single executable or end in exactly `acp`;
1279
+ the TUI uses the executable or drops that final word. Other wrappers are refused
1280
+ with the headless command rather than guessed.
1281
+
1282
+ The TUI is pull-only. Its model reads `hub_inbox` at the start of work and before
1283
+ reporting, and shares results explicitly with `hub_send`. Status, the console and
1284
+ the dashboard show `pull-only`, the waiting count and the last inbox read. Messages
1285
+ and important markers do not push or interrupt it. There is no hub busy state,
1286
+ watchdog, console approval, hub permission mode, context reading, automatic quota
1287
+ pause/handoff, shared final answer or session resume. Read quota and approve tools
1288
+ in Kimi's own TUI; a person can pause the hub queue by hand. End the native terminal
1289
+ session there, not with `ahub stop kimi`.
1290
+
1291
+ Automatic routing never picks a pull-only owner or reviewer, even as the only
1292
+ candidate. A proposer can name the owner or claim its own task; a person or the
1293
+ conductor can name an owner or reviewer with
1294
+ `ahub task assign <id> kimi --role owner|reviewer`. A waiting task reserves its
1295
+ named owner; naming its reviewer is refused until dependencies are approved.
1296
+ A named review waits in the same inbox. Queue holds and pauses refuse a pull with
1297
+ the reason; an unaccepted assignment still follows the existing release deadline.
1298
+
1299
+ To switch to ACP, end the attached TUI and run `ahub kimi --mode headless`: the
1300
+ person's command removes only the hub's project MCP entry before starting ACP.
1301
+ A daemon-made headless start refuses a stale entry with that command and never
1302
+ edits the project file. To switch back, stop the headless peer with `ahub stop kimi`
1303
+ then run `ahub kimi --mode tui`. The peer id, queued messages and open tasks remain;
1304
+ the ACP session is not resumed in the TUI. Agents cannot switch modes.
1305
+
1306
+ Projects with no explicit Kimi start mode also move to this default on upgrade.
1307
+ The coordinating upgrade command announces it once; to keep ACP, run
1308
+ `ahub settings set peers.kimi.start_mode headless`.
1309
+
1310
+ Source preflight checked Kimi Code 2.1.1 at
1311
+ [f67e6398](https://github.com/MoonshotAI/kimi-code/tree/f67e6398fb3210ad8ace970e2dfd5bcc984ed61f):
1312
+ trusted ACP workspaces read the user, repository-root and project MCP files, and a
1313
+ passed session entry connects beside the project entry. Its model request path
1314
+ uses tool definitions and managed AGENTS instructions, not MCP initialize
1315
+ instructions. Folder trust, real TUI tool discovery and the model round trip are
1316
+ still unverified live; see `docs/smoke.md`.
1317
+
1318
+ ### Migration from 0.12.22 and earlier
1319
+
1320
+ Pi's default changes from headless to its TUI.
1321
+
1322
+ - `ahub pi` in a terminal now opens the TUI. For the background peer run
1323
+ `ahub pi --headless`.
1324
+ - A project with `"pi": { "auto_start": true }` used to get a headless Pi at
1325
+ every hub start. To keep that, set the start mode once:
1326
+ `ahub settings set peers.pi.start_mode headless` (or add
1327
+ `"peers": { "pi": { "start_mode": "headless" } }` to
1328
+ `.agenthub/config.local.json`). Without it the hub opens Pi's TUI in a
1329
+ terminal at start, or, with no terminal provider, says
1330
+ `pi.auto_start did not start Pi` with the command to run.
1331
+ - Scripts and the console's `pi` command: without a terminal, `ahub pi` asks
1332
+ the hub to open one. Add `--headless` where a headless Pi is meant.
1333
+ - A conductor's `hub_peer_start` no longer takes a mode. A call that passes one
1334
+ is refused unless it repeats the peer's start mode.
1335
+
959
1336
  ## Approvals and pauses
960
1337
 
961
1338
  Inspect permission requests in the terminal:
@@ -995,6 +1372,13 @@ A budget pause remains authoritative until the budget command explicitly
995
1372
  overrides it or the window resets. Check `ahub status` and `ahub board` after
996
1373
  a pause or handoff.
997
1374
 
1375
+ Kimi Code CLI 2.1.1's observed 5-hour usage-limit refusal creates a hard budget reading (`kimi ACP usage-limit refusal`). `ahub status` shows a budget pause and `ahub budget` shows its source and reset estimate. The refusal gives no reset timestamp, so the hub estimates the reset at five hours after it was observed and resumes on the next budget tick after the existing one-minute grace. With `budget.wait_max_min` below that estimate, the existing budget relay automatically hands open tasks to an attached eligible peer; routing skips Kimi while paused. No checkpoint is requested from an exhausted agent.
1376
+ `ahub budget resume kimi` overrides the reading so the provider can be tried early. A new provider refusal ends that override and pauses it again; a pending soft checkpoint cannot postpone this hard pause.
1377
+ During one hub run, an early override followed by the same window's refusal keeps its earlier future reset bound; a provider's explicit reset remains authoritative. A restored pause without a per-window reading cannot identify that earlier window, so its next refusal starts a new estimate.
1378
+ Unread quota resume notices are coalesced without losing their public task moves; the next notice lists moves accumulated across those pauses. An older notice without structured move metadata is kept as public text inside that notice.
1379
+
1380
+ A refused prompt with no acceptance or activity is requeued without a review hold. At the estimated reset it is tried again; another quota refusal pauses it again without consuming the poison-envelope retry count. Work that already started remains held for review even while its open tasks move to other peers. After the quota reset its queue stays held: inspect `ahub queue show <delivery-id>` and the associated task, then choose `ahub queue resolve <delivery-id> --action completed|retry|discard --reason "<text>"`. Do not retry work that another owner already took over without inspecting it. If the hub cannot confirm the pause, the refusal is also held instead of spending retries. Other errors keep their ordinary review behavior. Only the observed Kimi 5-hour text is recognised; weekly/monthly limits and other ACP vendors, including Qwen, remain unverified. The recognised text and its provenance live in `src/adapters/acp-quota.ts`.
1381
+
998
1382
  Quota also shapes routing and handoffs:
999
1383
 
1000
1384
  - Among peers a task could go to, those with quota readings are ordered by
@@ -1052,8 +1436,8 @@ Only `ahub claude` starts Claude Code with the development-channel flag. A
1052
1436
  Claude session started another way (plain `claude`, an IDE) keeps the hub tools
1053
1437
  but cannot show pushes, so it attaches tools-only (protocol 16, issue #205):
1054
1438
 
1055
- - Its messages stay queued. `ahub status` shows `queued N` and `tools-only:
1056
- messages wait for hub_inbox; for pushes restart Claude with ahub claude`; the
1439
+ - Its messages stay queued. `ahub status` shows the queue count in `Q` and a `tools-only` detail:
1440
+ `messages wait for hub_inbox; for pushes restart Claude with ahub claude`; the
1057
1441
  console footer shows `tools-only: ahub claude` and the dashboard shows the
1058
1442
  status line.
1059
1443
  - The session reads them with `hub_inbox`, at most ten messages at a time plus
@@ -1183,8 +1567,8 @@ can run again), unless the error says the state cannot be read (a damaged
1183
1567
  `hub.db` or journal fails the same way every time): `ahub reset --all --yes`
1184
1568
  archives such a state directory as it is. A full reset names the archive once
1185
1569
  the state directory has moved.
1186
- It never touches claude-mem: notes saved with `hub_remember` are shared memory,
1187
- not hub state. Claude Code sessions attached to the hub lose their hub session;
1570
+ It never touches claude-mem or hub memory (`~/.agenthub/memory/`): notes saved with
1571
+ `hub_remember` are shared memory, not hub state. Claude Code sessions attached to the hub lose their hub session;
1188
1572
  relaunch them with `ahub claude`.
1189
1573
 
1190
1574
  ## Orphaned daemons
@@ -1230,21 +1614,21 @@ section is what they run.
1230
1614
 
1231
1615
  Upgrade running projects with the target release's own coordinator. It accepts
1232
1616
  a running source on control protocol 9 (0.6.x), 10 (0.7.0 through 0.12.0),
1233
- 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.22), and only
1617
+ 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.24), and only
1234
1618
  a target on its own protocol, so the target's coordinator fits every supported
1235
1619
  source and carries every recovery fix released up to it. Protocol 8 and older
1236
1620
  (0.5.x and earlier) are refused as `manual-bootstrap-required`. Run from the
1237
1621
  project directory, without replacing the global CLI first:
1238
1622
 
1239
1623
  ```bash
1240
- bunx --package @staix/agent-hub@0.12.22 ahub upgrade --to 0.12.22 --dry-run
1241
- bunx --package @staix/agent-hub@0.12.22 ahub upgrade --to 0.12.22 --yes
1624
+ bunx --package @staix/agent-hub@0.12.24 ahub upgrade --to 0.12.24 --dry-run
1625
+ bunx --package @staix/agent-hub@0.12.24 ahub upgrade --to 0.12.24 --yes
1242
1626
  ```
1243
1627
 
1244
1628
  | Running now | Coordinator to use |
1245
1629
  | --- | --- |
1246
1630
  | 0.6.x (protocol 9) | the target's, through `bunx` as above |
1247
- | 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.22 (protocol 16) | the target's, through `bunx` as above |
1631
+ | 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.24 (protocol 16) | the target's, through `bunx` as above |
1248
1632
  | any supported source, with the installed CLI already at the target | `ahub upgrade` below, which is the same coordinator |
1249
1633
  | 0.5.x or earlier (protocol 8 and older) | not supported: bootstrap by hand with the matching CLI |
1250
1634
 
@@ -1276,14 +1660,14 @@ projects first:
1276
1660
 
1277
1661
  ```bash
1278
1662
  ahub restart --dry-run
1279
- ahub upgrade --to 0.12.22 --dry-run
1663
+ ahub upgrade --to 0.12.24 --dry-run
1280
1664
  ```
1281
1665
 
1282
1666
  Apply only after reviewing the plan:
1283
1667
 
1284
1668
  ```bash
1285
1669
  ahub restart --yes
1286
- ahub upgrade --to 0.12.22 --yes
1670
+ ahub upgrade --to 0.12.24 --yes
1287
1671
  ahub recovery status [<operation-id>]
1288
1672
  ahub recovery resume [<operation-id>]
1289
1673
  ahub recovery abort [<operation-id>]
@@ -1510,6 +1894,28 @@ next actions").
1510
1894
  restart snapshot.
1511
1895
  A second `resume` while its own hold still stands checks the peers again
1512
1896
  before it closes anything.
1897
+ - If a restart stops with `database_busy`, the receipt stays `blocked` and
1898
+ carries `failure: { code: "database_busy", retryable: true, site: [...] }`.
1899
+ Let the other connection settle, inspect `ahub recovery status <id>` and
1900
+ use its offered `ahub recovery resume <id>`. Resume rechecks the source and
1901
+ reconciles a commit that may already have been requested. A busy read while
1902
+ that committed source is stopping stays inside the existing shutdown wait.
1903
+ A stop-and-archive that meets contention instead says to retry that
1904
+ disposition; resume remains refused while abandonment is partway. Successful
1905
+ abort, fresh-session choice and disposal clear the earlier failure annotation.
1906
+ Do not delete database files or start a second operation to bypass the lock.
1907
+ A failed installed-layout CI restart retains bounded, redacted fixture logs,
1908
+ receipt fields (including `commitSent` and failure frames) and file-mode
1909
+ metadata as a per-OS artifact.
1910
+
1911
+ The historical CI receipt (38061057253, attempt 1) kept no throw site or
1912
+ hub log. At its main, status/inspect RPC failures were swallowed and the
1913
+ synchronous catch sent a fixed sentence, so its raw SQLite text could only
1914
+ have come from the commit rejection or the runner's own `registry.db` read.
1915
+ "Resume | wait until the hub settles", without stop-and-archive, means its
1916
+ next inspection saw neither running nor stopped/missing. Which of the two
1917
+ paths, which statement and which holder remain unknown. The controlled
1918
+ rollback-copy reproduction is separate evidence, not that historical cause.
1513
1919
  - When a target hub dies after it started (a crash or a reboot), `resume`
1514
1920
  starts it again from the operation's snapshot while the project's state
1515
1921
  directory still holds it: it records the restart (status shows `restarts`),
@@ -1648,8 +2054,9 @@ crash of one is not reported this way.
1648
2054
  spends no cloud quota), and on a fresh session if that fails, keeping the
1649
2055
  recorded backend and model; the report says which. Malformed records in
1650
2056
  `sessions.json` are skipped. A Pi that ran in a terminal (`--mode tui`) is never started on its
1651
- recorded session by the hub; the report gives the command, and with
1652
- `pi.auto_start` a fresh headless Pi starts instead.
2057
+ recorded session by the hub; the report gives the command. With
2058
+ `pi.auto_start` a fresh headless Pi starts instead only when Pi's start mode
2059
+ is headless; with the default (tui) nothing is started in its place.
1653
2060
  - Codex's app-server died with the hub; run `ahub codex` again. Claude Code's
1654
2061
  plugin reconnects by itself while that session is open.
1655
2062
 
@@ -1776,7 +2183,7 @@ whose MLX slot is still busy after that wait goes to `dgx/fast` first (`source:
1776
2183
  so does an enforced tool loop pinned to it (`source: "pin"`); without it nothing moves for load. `dgx/fast`
1777
2184
  never goes first while it is cooling down, or while its own last dispatch failed in any way,
1778
2185
  an error status or a failed stream included, until it succeeds or 30 s pass (`ahub status`:
1779
- `last dispatch failed, no load moves until ...`). No load move or pin happens while the request
2186
+ a `dispatch held` detail with a relative time and `no load moves until then`). No load move or pin happens while the request
1780
2187
  runs under an execution budget, and enforced, a load move happens only at a user turn. A moved
1781
2188
  attempt gets 15 s to its response headers after the gateway lookup (OmniRoute's own probe,
1782
2189
  up to two 4 s rounds when no gateway is cached) and is then abandoned for MLX, which serves
@@ -1790,7 +2197,7 @@ consecutive transport or startup failures outside a cooldown (a failure more tha
1790
2197
  the last counted one starts the count over), a relay alias cools down for 30 s, doubling up to
1791
2198
  5 min. A busy MLX slot and timeouts cut short by an execution budget never count; any HTTP
1792
2199
  answer, a success or an error status, proves the transport works and ends the streak and the
1793
- cooldown. `ahub status` shows `cooling down until ...` on the backend line and `events.jsonl`
2200
+ cooldown. `ahub status` shows a `cooling` detail with a relative time and failure count and `events.jsonl`
1794
2201
  records `cooldown` events.
1795
2202
  Progress judgements suggest reassignment; they never change task ownership.
1796
2203
 
@@ -1898,7 +2305,12 @@ include the stamped ancestors (CI checks out full history).
1898
2305
  During release preparation, source review precedes restamping. Review each stale
1899
2306
  page against its covered source, correct drift, and use the full SHA of the
1900
2307
  reviewed source commit as `verifiedAgainst`. Record any deferred page and its
1901
- specific unverified claims in the release verification report before tagging.
2308
+ specific unverified claims in the release verification report before tagging. Deferred
2309
+ pages must still be source-reviewed and current; a deferral is not a stale-stamp waiver.
2310
+ The tag gate runs `node scripts/check-docs.mjs --require-fresh` with full history
2311
+ before publishing. Stale or nonancestor stamps refuse publication, with the
2312
+ release merge-commit instruction; an identical tree and green CI cannot waive this.
2313
+
1902
2314
  Do not advance a stamp solely to clear a notice. Source stamps can name an
1903
2315
  ancestor: the manifest-only follow-up commit need not hash or stamp itself.
1904
2316
 
@@ -1930,7 +2342,8 @@ sequential seeded-guard job. Main and release jobs reuse only a successful full
1930
2342
  PR or push check with the identical Git tree and all three successful jobs. An absent or
1931
2343
  unreadable result runs the main gate again and refuses release. A manual
1932
2344
  `prepare_bundle` dispatch builds reviewable plugin assets without publishing;
1933
- it is never accepted as full-gate evidence.
2345
+ it is never accepted as full-gate evidence. A `timing_runs=20` dispatch runs only the daemon, PII screen and ACP
2346
+ test files twenty times on macOS, in its own concurrency group; it does not replace the full gate.
1934
2347
 
1935
2348
  ## Preview initialization and native launch
1936
2349
 
@@ -1959,9 +2372,19 @@ ownership, bind servers or start agents, sidecars or models.
1959
2372
  `ahub status`, `ahub tail` and the dashboard show native context occupancy,
1960
2373
  source and measurement freshness. Claude readings come from the status-line
1961
2374
  tee installed by `ahub claude`; Codex readings come from its current thread's
1962
- native token-usage updates. Pi and other unsupported surfaces show unknown.
2375
+ native token-usage updates. Kimi readings come from its ACP `usage_update`
2376
+ (`{used, size}`, source `acp_usage_update`): context occupancy, not
2377
+ consumption, so no token total is counted from it; the adapter accepts the
2378
+ update whenever it names the current session, because 2.1.1's source text
2379
+ emits it after the turn settles (read from the source, not yet observed live
2380
+ through the hub; docs/smoke.md), so the peer may already be idle.
2381
+ Pi and other unsupported surfaces show unknown.
1963
2382
  A stale or disconnected reading is unknown, not 0%. Codex's accumulated session
1964
- usage is never used as context occupancy.
2383
+ usage is never used as context occupancy. In the tail (`ahub tail` and the
2384
+ console's stream) a reading prints once and repeats only when the line changes
2385
+ apart from its time: the printed percentage, the freshness, the source, or known
2386
+ against unknown. Status, the Peers panel and the dashboard always read the
2387
+ latest reading with its time.
1965
2388
 
1966
2389
  Context-triggered checkpoints are disabled by default. To enable them, add
1967
2390
  this to `.agenthub/config.json` and restart the daemon deliberately:
@@ -1973,8 +2396,9 @@ this to `.agenthub/config.json` and restart the daemon deliberately:
1973
2396
  `gate` is a fraction between 0 and 1; 0 disables checkpoint requests.
1974
2397
  `stale_min` must be positive. A reading at or above the threshold records a metadata-only
1975
2398
  event and console notice, then asks an attached Claude/Codex with active work
1976
- for a checkpoint when no checkpoint request is already outstanding. The request
1977
- supplies a `request_id`; include that id with
2399
+ for a checkpoint when no checkpoint request is already outstanding (an ACP peer
2400
+ such as Kimi gets the event and notice only; no checkpoint request is sent to it
2401
+ yet). The request supplies a `request_id`; include that id with
1978
2402
  `hub_checkpoint {summary, request_id}`. Repeated high readings do not repeat
1979
2403
  it until a fresh below-threshold reading or new session rearms the crossing.
1980
2404
 
@@ -2090,3 +2514,422 @@ prompt was accepted but before history was persisted is not treated as empty:
2090
2514
  its delivery is held, and another start refuses until resume history is verified.
2091
2515
  Inspect and settle the held delivery before deliberately replacing that unpersisted
2092
2516
  session by restarting the hub; the stop never silently chooses a fresh session.
2517
+
2518
+ A pull-only Kimi TUI has no controlled restore or resume. While it is attached,
2519
+ upgrade/restart planning stops before effects and asks the person to end Kimi in
2520
+ that terminal and make a new plan. Headless Kimi restoration stays headless even
2521
+ though the unset launch mode now means TUI; older targets keep their legacy
2522
+ command without a mode flag. Native recovery remains unverified.
2523
+
2524
+ Changing a reviewer on a task in review withdraws unread requests and tells the
2525
+ former reviewer its request is withdrawn. A delivered request cannot be recalled,
2526
+ but a later verdict from that former reviewer is refused by current authority.
2527
+
2528
+ Legacy Claude pull-only sessions retain their existing automatic owner/reviewer
2529
+ selection; the watched-Kimi exclusion does not disable that review path. After
2530
+ first creating the Kimi MCP file, run `ahub init` to ignore the untracked file.
2531
+ Init leaves existing ignore bytes alone when no Kimi MCP file exists.
2532
+ ## Scoped grants for instruction files
2533
+
2534
+ `ahub settings set scoped_grants.protect_instructions true` asks a person before
2535
+ Pi/local scoped writes and edits to `AGENTS.md`, `CLAUDE.md` and `QWEN.md`, and
2536
+ withholds automatic permission from the managed Claude hook. Case, compatibility
2537
+ forms and both symlink spellings are checked. The default is false: these project
2538
+ documents remain editable under scoped grants. Reads, explicit approval and
2539
+ never-ask keep their existing behavior.
2540
+
2541
+ Use `ahub settings preview scoped_grants.protect_instructions true` before a
2542
+ change and `ahub settings undo` to restore it. It is in the Permissions registry,
2543
+ writes only machine-local `protect_instruction_files`, and applies immediately
2544
+ in the running hub. A dashboard settings session may change it; an ordinary
2545
+ session may turn protection on but cannot weaken it. No agent surface changes it.
2546
+ Like other machine-local security defaults, loading it requires git to establish
2547
+ that the file is untracked; a dropped value is reported by the settings result.
2548
+
2549
+ ## SDLC artifact receipts and gates
2550
+
2551
+ The initial #257 lifecycle is off without .agenthub/sdlc.toml. Advise shows blockers; enforce checks head-bound review and approval transitions. See [the SDLC contract](sdlc.md) for the fixed stage order, required check names, claimed local receipts, console-only readbacks and pending custom/release/live parts. Owners/reviewers record bounded identities through hub_sdlc_record; these grant no additional authority.
2552
+ ## Optional Qwen Code peer
2553
+
2554
+ Select Qwen per project with `ahub roster add qwen`; it defaults off and is absent
2555
+ from default class preferences. `ahub qwen [--mode headless] [--model <alias>]`
2556
+ starts its ACP peer. `--print-command` previews; TUI is refused until #286's
2557
+ verification. `ahub stop qwen` stops the owned process group. A conductor may start
2558
+ it only through the selected roster and existing capabilities.
2559
+
2560
+ The supported native ACP identity is qwen-code 0.25.0. A CLI version label alone
2561
+ is insufficient: startup verifies its native identity/version and advertised mode
2562
+ ids before any prompt. The observed local installation reports CLI 0.25.0 while
2563
+ its package/ACP source says 0.24.1; do not call that installation ready. Configure
2564
+ `qwen_cmd` only in untracked config.local.json with a verified 0.25.0 executable.
2565
+ The provider's tunnel/relay, if needed, must already be available. Startup cannot
2566
+ prove network readiness from a version command.
2567
+
2568
+ Modes: ask maps to default, scoped frequency maps to auto-edit, never-ask maps to
2569
+ yolo. Qwen yolo approves every tool outside any hub sandbox; its own vendor bounds
2570
+ apply. Auto and plan are not hub mode mappings. Unknown quota refusals are not
2571
+ classified as authoritative quota; until a real pinned refusal is recorded, pause
2572
+ by hand. Occupancy is context with a source, never a consumption estimate. Roles
2573
+ do not establish that Qwen can reliably replace Kimi before the live leg.
2574
+
2575
+ Qwen controlled recovery and automatic crash resume load the recorded conversation with ACP session/load. The emitted launcher passes --session-id; a controlled plan with a missing or unsafe identity refuses before effects. Preview redacts the id. A custom executable argv keeps its wrapper arguments before appended model flags. Native recovery remains unverified.
2576
+
2577
+ ## Optional Jcode peer
2578
+
2579
+ 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.
2580
+
2581
+ 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.
2582
+
2583
+ # Headless ACP watch (#286)
2584
+
2585
+ - 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`.
2586
+ - 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.
2587
+ - 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 verified ACP 0.25.0. `ahub qwen --mode tui` remains refused.
2588
+ - Protocol stays 16; a same-protocol older daemon answers the new request as unknown, which the CLI reports. No automatic pane opening is included in this slice.
2589
+ - Native T0 limits: [ACP watch verification](verification/2026-10-11-acp-watch-t0.md).
2590
+
2591
+ # gsd-lite lifecycle guidance (#257)
2592
+
2593
+ - Set `workflow = "gsd-lite"` in `.agenthub/sdlc.toml` for the next daemon start; default none preserves the existing flow. Mode advise displays checklist blockers without blocking, while enforce checks them at approval.
2594
+ - The task reviewer/person records phase criteria via `ahub sdlc record <id> '<receipt JSON>'`. Existing tasks and predecessor ids must match the board; import does not move owners or edit dependencies. Use the existing task propose `--after` command to create edges.
2595
+ - `ahub sdlc status <id>`, `explain <id>` and `export <id>` read the same current board/config projection. Export hashes are projection/config hashes, with no external text, extra authority or verification claim. Schema and example: [SDLC](sdlc.md#gsd-lite-checklist-guidance).
2596
+
2597
+ # Catalog session guidance (#295)
2598
+
2599
+ - Read available guidance with `ahub role list [--group dev|research]` and `ahub role show <id>`. Each definition identifies its layer and content hash. Doctor reports invalid files/selections without printing their contents.
2600
+ - Select up to two ids per peer in `catalog_roles` in the shared/local config, with at least one flow base already held by that peer. Empty local lists clear shared selections. This initial slice applies selections at a new daemon/MCP/adapter start; live assignment/settings and task roles follow separately.
2601
+ - Defaults preserve the existing flow. Catalog guidance adds no authority or routing preference. Native ingestion/retention and measured benefit remain unverified. Schema, bounds and source notice: [roles](roles.md).
2602
+
2603
+ # Project profiles (#259)
2604
+
2605
+ - Initialize new projects with `ahub init --profile research|writing|general`; default dev retains its existing templates and contracts. Profile aliases map to the existing base flow and are displayed beside it.
2606
+ - Non-dev plans declare paths, section anchors, source ids and claims. Configure completion checks explicitly in machine-local config; selecting a profile never starts a check or study. Schema, examples and pending converter/policy slices: [profiles](profiles.md).
2607
+
2608
+ # Private and read-only data paths (#259)
2609
+
2610
+ - Optional pii.paths forces matching declared refs/plans/section files to the on-prem flow before triage and memory, including when ordinary pattern routing is off. Optional data.readonly protects managed local/Pi writes and makes managed commands filesystem read-only.
2611
+ - Both lists are empty by default and apply at daemon start. Reads/stdout remain available; command-created files/caches are blocked in read-only mode. Exact path rules, alias handling and evidence: [data policy](data-policy.md).
2612
+
2613
+ # Rich-document text projections (#259)
2614
+
2615
+ - Configure text_projection only in an untracked machine-local file, with a separate {input} argv argument. Facts uses bounded read-only/no-network conversion and a content/config cache; failure keeps the prior file view and logs a bounded notice.
2616
+ - Raw change identity and projected presentation stay separate; private paths never enter conversion. Schema, limits and current surface scope: [text projections](text-projection.md).
2617
+
2618
+ # Task catalog guidance (#295)
2619
+
2620
+ - A proposal may name `role` from `ahub role list`. The allowed class list is checked in Tasks, and assignment/review notices carry bounded guidance. The role grants no authority and changes no routing decision. Scope and pending person-assignment surfaces: [roles](roles.md).
2621
+
2622
+ # Person catalog-role assignment (#295)
2623
+
2624
+ - Use `ahub role assign <peer> <id>` or `ahub role clear <peer> [<id>]`, or the dashboard Roles settings group. The selection is bounded to two compatible catalog ids, writes only machine-local settings and applies at the next peer start. Inherit and explicit no roles are distinct.
2625
+ - Change an open task's guidance with `ahub task role <id> <role|none>`. Agent shells and peer/tools control clients cannot use these mutation commands. Details and unconfirmed native consumption: [roles](roles.md).
2626
+
2627
+ # Document projection review and undo
2628
+
2629
+ - Machine-local text_projection also supplies bounded review and reverse undo previews from stored raw snapshots. Task-proposal baselines survive restart and reviewer changes; missing/private/pruned evidence is unavailable. See [text projections](text-projection.md) for caps and converter requirements.
2630
+ - Undo remains a raw-file operation: projected text cannot bypass later-edit, concurrency or unknown-turn refusals. Native model/account ingestion remains unverified.
2631
+
2632
+ # Opt-in shadow repository
2633
+
2634
+ - `ahub init --profile research|writing|general --shadow [--dry-run --json]` supplies hub-owned snapshot/facts/undo storage for a non-git folder. It creates no `.git` entry and never switches an existing Git project.
2635
+ - Maintain `.agenthub/ignore` for large/raw data. Snapshot and facts operations leave the shadow index/HEAD alone; raw undo refusal rules remain authoritative. Shadow metadata stays protected from managed worker writes. See [profiles](profiles.md).
2636
+
2637
+ # Per-project profile data
2638
+
2639
+ - Use `profile_overrides` for class aliases, supported plan selection, role guidance, catalog defaults, managed AGENTS content and advisory example checks. Shared/local maps merge by key; selections/text replace. See [profiles](profiles.md).
2640
+ - Refresh instructions with init and restart the daemon/MCP clients to apply their resolved contracts. Existing flow-role and executable-check authority remains in `roles`/trusted `checks`. Native model/account evidence remains unverified.
2641
+
2642
+
2643
+ ## Staging work in Backlog (#263)
2644
+
2645
+ Use `ahub task propose implement "Later work" --backlog --owner codex` to stage
2646
+ work without routing it. The owner is a reservation, including when an agent
2647
+ names itself. Normal proposal behavior is unchanged without `--backlog`.
2648
+
2649
+ The person inspects `ahub board backlog` and `ahub task show <id>`, then runs
2650
+ `ahub backlog pull <id>` to put it in To Do. Dependencies still block assignment.
2651
+ Ready work uses the existing assignment and delivery-recovery contract; if no
2652
+ peer can take it, a later attachment or restart can offer it. Return ownerless
2653
+ To Do work with `ahub backlog return <id>`. Owned or started work cannot return.
2654
+
2655
+ Ordinary agent task lists and conductor task reads exclude Backlog. Staged work
2656
+ is never claimed, accepted, completed, swept, escalated or relayed. PII cards and
2657
+ notices use the existing public stub. Planner grooming, five-column views, releases and dates are described below.
2658
+ The native planner/two-release smoke remains unverified; board release actions
2659
+ never tag or publish software.
2660
+
2661
+
2662
+ Pulling Backlog establishes its first execution-proposal boundary for projected
2663
+ review snapshots and research records. An initial Backlog row is not an offered
2664
+ proposal. Research uses the first pull time and preserves identity across later
2665
+ unstarted return/pull cycles; a new backlogged id after reset starts a new record
2666
+ generation. Partial work with acceptance/check/review evidence cannot return to
2667
+ Backlog even after decline or reassignment leaves it ownerless.
2668
+
2669
+
2670
+ ## Dashboard project board (#263)
2671
+
2672
+ The board displays Backlog, To Do, In Progress, Review / QA and Done from task
2673
+ states. To Do separates ready work from dependency, reservation, delivery-hold
2674
+ and unavailable-owner waits. Review and Done offer no flow dragging. Owner and
2675
+ reviewer names remain readable beside their filled/outlined color markers.
2676
+ Urgent tasks display P0 and a star; ordinary legacy tasks display P2.
2677
+
2678
+ The legend reads the same live peer status as `ahub status`, with a derived
2679
+ owned-work count, active board ids and explicit permission display. Use the agent
2680
+ filter or By agent lanes to inspect work. Done shows recent rows first, with
2681
+ older rows expandable. At phone width columns stack and controls remain usable.
2682
+
2683
+ Drag eligible work onto a peer to assign it, or use its labelled select and
2684
+ Assign button. Drag Backlog into To Do to pull it; return only ownerless To Do
2685
+ work to Backlog. Each move has a button/keyboard equivalent and reaches `Tasks`
2686
+ through the existing authenticated console/dashboard action path. Cards carry
2687
+ origin, project, instance and view-generation fences; stale or foreign drags
2688
+ are refused. Review/verdict/approval transitions stay with their flow actors.
2689
+
2690
+ A hub advertises Backlog support explicitly. Older or unknown snapshots cannot
2691
+ silently turn Add to Backlog into an immediate offer. PII cards retain their
2692
+ public stub; legend entries contain ids/counts, never task prose. Planning priority/rank, releases, dates, planner grooming/undo and GitHub import
2693
+ are described below. Native planner-cycle evidence remains unverified.
2694
+
2695
+
2696
+ ## Planning and phased releases (#263)
2697
+
2698
+ Use `ahub backlog list` to read public staged work, then `ahub backlog plan <id>
2699
+ <revision> <fields-json> <reason>` to set rank, priority (0-3), release id, planned
2700
+ start/due UTC milliseconds or pin. `pin` accepts true/false; `undo` needs the
2701
+ current revision and latest eligible edit. The dashboard provides local-time
2702
+ date fields, task/release filters and lanes, and Reload current values when an
2703
+ edit is stale. A person's order, pins and frozen scopes protect planner changes.
2704
+
2705
+ Create a phase with `ahub release new <name> <goal> <order>`, inspect `list` or
2706
+ `show`, and set planned start/cut/ship with `plan <name> <revision> <dates-json>`.
2707
+ `activate`, `freeze`, `ship` and `drop` need its current revision. Only a person
2708
+ freezes, ships, drops or edits frozen scope. Ship records the first ship time
2709
+ only after every member is approved or moved out; it runs no tag or publish.
2710
+ The dashboard shows phase progress, blocking dependencies, dates and remaining
2711
+ work. Actual task dates come from execution/review/approval history, never input.
2712
+
2713
+ Configured planners read `hub_backlog_list` and `hub_release_list`, edit with
2714
+ `hub_backlog_plan`, and undo their own latest eligible change with
2715
+ `hub_backlog_undo`. Catalog guidance or a caller-supplied role grants no authority.
2716
+ PII cards stay stubs, reasons are screened/withheld in public history, and planning
2717
+ telemetry records ids/changed fields without prose. #247 task records carry
2718
+ optional release, priority, plannedStart and due, retaining unknown legacy data.
2719
+
2720
+ Dependency/reservation planning, split/pull WIP limits, batched incoming notices
2721
+ and one-way GitHub import are described below. Source checks are recorded in the
2722
+ release verification report. Native planner work across two releases remains
2723
+ unverified; source and fixture checks do not establish installed live behavior.
2724
+
2725
+ Office merge corrections retain the header's view selector when Off hides the
2726
+ scene. Activating a card reveals its task if a state filter excluded it; Work
2727
+ includes rework. Stable desk slots determine bounds after peers disconnect.
2728
+ Reduced motion removes departures immediately and the existing snapshot poll
2729
+ prunes transient deadlines without new timers. Explicit unattributed turns have
2730
+ no guessed task bubble. Warning caps retain conflicts first and parallel warning
2731
+ kinds have separate segments/labels. Physical visual validation remains pending.
2732
+
2733
+
2734
+ Planner backlog plans also accept `deps` (at most 64 unique task ids) and
2735
+ `reserved` (rostered peer id or null). Dependency/reservation edits require
2736
+ unstarted, unowned backlog work even for the person; cycles and missing ids
2737
+ are refused before persistence. Planning undo restores previous dependency and
2738
+ reservation values at the same revision fence. Editing never routes work.
2739
+
2740
+
2741
+ Release date editors invalidate stale revisions and offer Reload current release
2742
+ without overwriting unsaved dates. Project changes clear release creation drafts.
2743
+ Dashboard release actions use public numeric ids even when labels are withheld;
2744
+ `ahub release show <name>` looks up the stored identity on the console and returns
2745
+ the screened public projection. Exact-head source verification is recorded in the release report.
2746
+
2747
+
2748
+ ## Planner WIP pull (#263)
2749
+
2750
+ `hub_backlog_pull` takes id, current planning revision and a bounded reason. A
2751
+ configured planner with assignment capability reserves a ready To Do slot using
2752
+ current routing, roster, class, quota and health constraints. It refuses pins,
2753
+ unapproved dependencies, frozen scope and overriding person P0 order/reservations.
2754
+ The person uses `ahub backlog pull-ready <id> <revision> <reason>` or Pull within
2755
+ WIP on a card. Explicit manual pull/assignment retain their existing authority.
2756
+
2757
+ Capacity defaults to one per peer. `ahub settings set tasks.wip_limits.codex 2`
2758
+ uses the existing machine-local registry path; integers 0..32 apply at hub start,
2759
+ with 0 disabling planner admission for that peer. Stored pending values and
2760
+ effective runtime limits remain distinct. Status and the agent legend count
2761
+ owned unfinished work plus unowned planner-pull reservations.
2762
+
2763
+ Pending unowned, unstarted pull can be undone at its latest owned revision via
2764
+ `hub_backlog_undo` or the existing planning undo control, restoring its earlier
2765
+ reservation. An ordinary return to Backlog also restores the pre-pull reservation unless a later explicit reservation edit superseded it. Normal release routing offers work only while that reserved peer
2766
+ still has capacity; no other peer inherits its slot. Split and one-way import are described below. Native verification remains
2767
+ outstanding; exact-head source checks are recorded separately.
2768
+
2769
+
2770
+ Planned-date editors preserve loaded UTC milliseconds until their displayed
2771
+ value changes, including repeated local wall times during a clock change. Local
2772
+ inputs retain seconds/milliseconds and support HTML date years without truncating
2773
+ fields; see https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#local-dates-and-times.
2774
+ Date-editor source proof is recorded with the exact-head checks.
2775
+
2776
+
2777
+ ## Backlog split (#263)
2778
+
2779
+ Use `hub_backlog_split` with parent id/revision, reason and two to eight part
2780
+ objects, or `ahub backlog split <id> <revision> <parts-json> <reason>`. Each part
2781
+ has a title and optional detail/class/refs/plan; `after` names existing ids and
2782
+ `afterParts` names earlier zero-based parts. The selected task's dashboard Split
2783
+ form accepts one title per line and optional sequential dependencies.
2784
+
2785
+ The original card remains integration/acceptance work and waits for every part.
2786
+ Children retain prerequisite, privacy and phase planning. A person's P0 order
2787
+ permits that goal's required predecessors, preventing dependency deadlock.
2788
+ Unused unchanged backlog children can be removed by latest split undo; later
2789
+ edits, execution, ownership or outside references refuse it. All writes roll
2790
+ back together and observers receive changes only after commit. Exact-head source checks are recorded separately; native verification remains
2791
+ unverified.
2792
+
2793
+
2794
+ The manager allows split screening, the bounded database wait and forwarding margin before declaring a missing reply unconfirmed. Reload the task before retrying an unconfirmed split. Stored role ids survive unavailable catalog guidance. Task memory-reference markers do not supersede assignment or check results, and dependency recovery ignores them.
2795
+
2796
+ ## One-way GitHub intake (#263)
2797
+
2798
+ `ahub board import github --label <label> [--milestone <milestone>]
2799
+ [--repo <owner/repo>]` is person-only. Omitted repo is resolved by gh in the
2800
+ project directory. The command reads open issues with fixed bounded argv and
2801
+ stages up to 32 into unoffered Backlog, retaining canonical repo/issue identity
2802
+ across restarts. Repeating intake does not refresh or overwrite existing cards.
2803
+
2804
+ The response lists confirmed imported/existing task ids and explicit partial,
2805
+ complete and unconfirmed state. A truncated page, time budget or interrupted
2806
+ staging is incomplete; repeat safely to reconcile the persisted identity.
2807
+ Public cards link to their source; PII cards expose no external identity.
2808
+ GitHub comments/labels/assignment/closure are never written. Exact-head source checks are recorded separately. Native verification remains
2809
+ unverified; no live account import was performed.
2810
+
2811
+
2812
+ `ahub board --columns` groups the same state-derived columns and ready/waiting
2813
+ reasons as the dashboard; `--release <name> | --release-id <id>` filters public rows on the hub.
2814
+ `--columns --json` returns filtered tasks and column metadata together. Ordinary
2815
+ peer reads retain the existing backlog prohibition. Phase views flag public ids
2816
+ approved after a known cut outside that release, and separately list unknown
2817
+ approval times without inventing dates. Exact-head source verification is recorded in the release report.
2818
+ ## Global attention and prompt output (#280, phase 3)
2819
+
2820
+ `ahub pet` reads the selected project's status file without a control token or
2821
+ network connection. It accepts only structural counts/state/first metadata from
2822
+ a confirmed daemon owner. Missing, malformed, legacy or unconfirmed data is
2823
+ reported as unavailable; it is not an empty live hub. `ahub pet --short` writes
2824
+ `ahub!N` when a known action count is positive, otherwise no bytes, including no
2825
+ newline. Explicit `pet` reads remain available when the presentation is off;
2826
+ normal `ahub status` appends the line only while the project's pet is enabled.
2827
+
2828
+ An open recovery lock is read without coordinating the operation. Only the
2829
+ shared runner check's observed absence adds an action; unknown remains watch and
2830
+ is labelled unknown. A matching daemon recovery watch is replaced once, without
2831
+ double counting. A missing hub status is labelled unavailable even when a known
2832
+ recovery action can be shown. The output never resumes, aborts or disposes a run.
2833
+
2834
+ Person-reviewed tasks contribute review actions; an offline peer holding
2835
+ unfinished work contributes one watch item with its lowest task id. The console
2836
+ receives those structural facts through its existing authenticated status reply.
2837
+ `n` selects an exact visible review task, or prints the task/review guidance if
2838
+ that row is unavailable. Offline guidance names status/task reads and an explicit
2839
+ assignment command. No command is executed by navigation. There is no extra
2840
+ console poll, timer or task-list request for stream mode.
2841
+
2842
+ Intentionally person-owned work is not an offline agent. Neither user nor hub
2843
+ creates an offline watch item, while person-reviewed tasks remain actionable.
2844
+ Status reads only the board's structural id/state/owner/reviewer projection and
2845
+ reuses it for retained peer ids, avoiding task body/plan/history decoding.
2846
+
2847
+ Planner reservations normalize the same lowercase peer syntax as owner arguments,
2848
+ reject reserved pseudo-peers and unknown unconfigured ids, and still enforce the
2849
+ roster. Returning unstarted ownerless work to Backlog joins the next planner
2850
+ notice batch without waiting for a restart.
2851
+
2852
+ Queued planner batches retain bounded ids-only backlog references and recheck
2853
+ the board at actual delivery. A batch containing pulled/removed work is discarded
2854
+ before reaching the planner; its remaining backlog ids join the next batch. This
2855
+ floor also applies during the legacy stale-notice delivery experiment. No task
2856
+ text is copied and no routing/ownership state changes.
2857
+
2858
+ ## Console character choices (#280)
2859
+
2860
+ `pet.character` selects stai (default), gyul, lantern, cursor-cat or boxbot.
2861
+ `pet.size` selects line (default), mini or full. Mini needs 100 columns; full also
2862
+ needs 40 rows, and smaller terminals fall back automatically. `P` cycles the
2863
+ built-ins and off for the current console only. `?` lists this under Pet, even
2864
+ while drawing is off. The command prompt keeps its original row and width.
2865
+
2866
+ `pet.glyphs` selects auto/ascii/blocks; unsupported locales and dumb/linux
2867
+ terminals retain the ASCII floor. `pet.blink:false` is static. Neither choosing
2868
+ nor drawing a character changes authority, config files, task state or polling.
2869
+ Explicit `ahub pet` and text status use the configured line face; prompt tokens
2870
+ remain character-independent. Native glyph width and tmux are unverified.
2871
+
2872
+ ## Dashboard attention character (#280)
2873
+
2874
+ The dashboard header draws the configured built-in character independently of
2875
+ Office. It uses the same structural needs model as status and the console. The
2876
+ accessible button names the character, state and action/watch counts; the tab
2877
+ title shows the action count. Activating the button scrolls and focuses the exact
2878
+ visible approval/task/peer row, or its related section with fixed id-only guidance
2879
+ when the row is filtered or unavailable. It performs no action and changes no
2880
+ filters. Legacy snapshots without attention keep the widget hidden.
2881
+
2882
+ Only a live approval alternates the two waiting poses once per second through
2883
+ CSS. `pet.blink:false` and reduced motion retain a static pose. No new timer,
2884
+ request, image protocol or character-file load is added. Project reset clears
2885
+ the widget and title. Native/browser visual validation remains unverified.
2886
+ With mini/full characters, active console notices remain visible away from the
2887
+ character: panel body rows show the bounded wrapped notice, and stream mode
2888
+ prints each fresh notice once through the existing local stream. Footer prose
2889
+ exclusion and fixed prompt/footer geometry remain. No new request or timer.
2890
+
2891
+ Automatic reroutes of planner-pulled work retain WIP and delivery-hold admission
2892
+ during offline, budget, roster and idle recovery. Explicit manual assignments
2893
+ retain their existing override authority.
2894
+
2895
+
2896
+ GitHub intake refuses comma-containing labels rather than allowing gh to split
2897
+ one literal label into several filters. WIP capacity excludes owner candidates
2898
+ only; eligible reviewers retain normal review routing. An auto-reassigning
2899
+ planner idle sweep waits without consuming its final step while no owner has
2900
+ capacity. Parent-only memory notes do not prevent unused child undo; child
2901
+ reference markers remain protected. Split-part plan schemas follow the selected
2902
+ project profile. Terminal tables preserve the visible read for stages and use
2903
+ a fresh peer status read on the same authenticated connection.
2904
+
2905
+ Integer WIP editors retain a saved pending value, including zero and inheritance, before hub restart. GitHub intake accepts dot-prefixed repository names within the existing bounded owner/repository identity. Split undo also refuses children referenced by another task's persisted phase checklist.
2906
+
2907
+ Declining rework returns changes_requested to To Do before rerouting. When a planner-pulled task has no eligible destination capacity, it remains ownerless in To Do and is retried after capacity clears, preserving the declined-owner exclusion.
2908
+
2909
+ With no release cut, outside approved tasks are reported under unknown cut evidence, including tasks with a known approval time. A child task execution budget also prevents split undo until the person disables that budget.
2910
+
2911
+ Split children retain their initial deterministic and inherited privacy signals across awaited screening. A routing-pattern reload cannot remove those captured signals from an unscreened child at final validation.
2912
+
2913
+ If a routing pattern adds deterministic privacy during screening, split history and telemetry use regex-private provenance rather than an earlier clear model result. The same captured final signals determine both the child and its provenance.
2914
+
2915
+ Dashboard backlog splits receive a dedicated outer HTTP request bound above manager forwarding, using the shared screening/database bounds and margin. Ordinary action policy remains unchanged. At phone widths, split form grids use one column so native date controls remain inside their panels.
2916
+
2917
+ An acknowledged ACP permission-mode change awaits queued cancellation cleanup only when the cancelled prompt response has already been observed. A still-unreported cancelled prompt stays busy under its existing deadline, while mode acknowledgements remain available. A successful mode acknowledgement alone does not prove the peer is idle.
2918
+
2919
+ Task idle sweeps ignore body-free memory-reference bookkeeping when finding the last real activity. Saving a task note or goal link does not postpone an idle notice or restart its escalation ladder.
2920
+
2921
+ Split reasons preserve deterministic privacy from both initial and final policy checks, including parent privacy. Once withheld, a reason stays withheld in public history even if routing patterns are later removed.
2922
+
2923
+ GitHub import rejects labels containing commas or double quotes before invoking gh, since its CSV-style label parser could otherwise select a different literal label.
2924
+
2925
+ Ask evidence skips body-free memory-reference markers when selecting the latest task transition and note. The selected note retains the existing withheld and on-campus privacy checks.
2926
+
2927
+ GitHub intake checks its staging deadline after every awaited proposal, including the final issue. A confirmed late save returns its task ID with partial=true and complete=false so the operator can read back and resume.
2928
+
2929
+ If GitHub intake saves a row but later bookkeeping fails, canonical identity readback preserves the confirmed ID and queues its Backlog notice. The response remains partial; unreadable or missing readback remains unconfirmed.
2930
+
2931
+ A later issue lookup or profile-preparation failure also returns the IDs confirmed earlier in the import as partial progress.
2932
+
2933
+ Release cut audits return exact counts with at most 32 example IDs per category; the dashboard states how many IDs are shown when truncated. Scope grouping and indexed approval dates avoid scanning each task history for every release. Full audit pagination remains a future extension.
2934
+
2935
+ Release cards include task states in their refresh key, so completion of an outside prerequisite updates blocked counts even when the release and audit preview are unchanged.