@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
@@ -95,8 +95,11 @@ Facts below are tagged **verified** (measured on 2026-09-19 on the owner's Mac)
95
95
  WebSocket to 127.0.0.1), so the control WS requires a per-run token and both hub
96
96
  servers refuse requests that carry an `Origin` header (amended in M1).
97
97
  9. Single machine, one hub daemon per project directory. Cross-machine broker is out.
98
+ (Amended in #258: hub memory is replicated between a person's machines through a git
99
+ remote; that is memory replication, not a broker, and the bus stays single-machine.)
98
100
  10. Shared memory reuses claude-mem as the single store; the hub never runs its own
99
- memory database. Native capture stays where it exists (Claude hooks, Codex plugin,
101
+ memory database. (Amended in #258: the hub owns a long-term store and its graph,
102
+ `docs/memory.md`; claude-mem stays the optional capture and session-recall source.) Native capture stays where it exists (Claude hooks, Codex plugin,
100
103
  Kimi transcript bridge); the hub captures only the local worker and adds
101
104
  cross-platform recall, task-scoped briefs and explicit shared notes. Hub tool calls
102
105
  are not captured; Tasks alone decides what screened tool text reaches memory.
@@ -151,7 +154,9 @@ hub CLI / console ── control WS 127.0.0.1:<ctl> ─────────
151
154
  when it has one, otherwise what the `tool_call` update announced for the same `toolCallId`.
152
155
  A payload that cannot be resolved either way is titled as unresolved and its `allow_always`
153
156
  option is withheld, so a blind click cannot grant every later call of the session. The
154
- watchdog sends `session/cancel` before forcing idle. `--model` maps to `kimi --model <alias> acp`
157
+ watchdog sends `session/cancel`. A durable delivery goes offline with `needs_review`;
158
+ without a journal, the peer stays busy until its cancelled prompt reports, bounded by
159
+ 30 s, then goes offline with queued work retained if no report arrives. `--model` maps to `kimi --model <alias> acp`
155
160
  (verified flag). Reusable for `opencode acp`.
156
161
  - Local worker (amended in M3): a hub-native tool-calling loop over non-streaming
157
162
  `POST /chat/completions` with plain `fetch`, no SDK (the repo keeps zero runtime
@@ -243,9 +248,13 @@ interface Envelope {
243
248
  Every queue is bounded (`queue_cap`, default 200): on overflow the oldest non-`important`
244
249
  envelope is dropped and reported on the console.
245
250
 
246
- Inactivity watchdog per busy turn (default 300 s) forces `idle` after cancelling the silent
247
- turn (`session/cancel` for ACP, `turn/interrupt` for Codex); a late result of the cancelled
248
- turn is discarded. Queues are drained in order on `idle`. Delivery is at-least-once with
251
+ The inactivity watchdog per busy turn defaults to 300 s. ACP sends `session/cancel`: a
252
+ durable delivery goes offline with `needs_review`; on a bus without a journal, the peer
253
+ stays busy until the cancelled prompt reports, then drains on idle. After the 30 s bound
254
+ without a report it goes offline with queued work retained, never idle. Cancelled results
255
+ and errors are discarded; an error during that wait leaves one log line. Other adapters
256
+ keep their cancellation rules (`turn/interrupt` for Codex). Queues drain in order only
257
+ when the adapter is idle. Delivery is at-least-once with
249
258
  idempotency by `id`: a failed delivery returns to the queue head and is retried after 1 s, and
250
259
  after 3 failures it is reported as undeliverable on the console so one envelope cannot block a
251
260
  peer. Peer ids claimed over the control WS must not be `user` or a hub-managed adapter id.
@@ -382,12 +391,23 @@ inside a peer.
382
391
  and runs the original command unchanged. `~/.claude/settings.json` is never edited; a
383
392
  user-supplied `--settings` wins and turns the tee off. The `--settings` injection is
384
393
  verified live (2026-09-19: `claude-usage.json` appears within seconds, the wrapped HUD
385
- renders unchanged, `ahub budget` shows both windows). Kimi: `usage_update` tokens over a
386
- rolling 5 h against `budget.kimi_tokens_5h` (off by default). Verified live on kimi
394
+ renders unchanged, `ahub budget` shows both windows). Kimi has an optional soft
395
+ rolling 5 h ceiling for validated consumed-token readings, `budget.kimi_tokens_5h`
396
+ (off by default), and the observed Kimi Code CLI 2.1.1 five-hour provider refusal
397
+ is a hard source (#306). Only the pinned rejected-prompt text is recognised,
398
+ bound to verified native identity and the current turn. It reports `5h`, used 1,
399
+ source `kimi ACP usage-limit refusal`, and a conservative 300-minute reset
400
+ estimate; weekly/monthly limits and other ACP providers remain unverified. Verified live on kimi
387
401
  2.0.1: one update per turn, payload `{"sessionUpdate":"usage_update","used":<tokens>,
388
402
  "size":<context window>}`; `used` is the session's context occupancy against `size`
389
403
  (1M), not billed quota. ACP records this shape as context occupancy diagnostics,
390
- never as cumulative consumed tokens. Only validated cumulative totals or input/output
404
+ never as cumulative consumed tokens. Since #285 phase 1 it is also the peer's
405
+ native context reading (source `acp_usage_update`), shown in `ahub status`, the
406
+ console and the dashboard like Claude's and Codex's; the adapter accepts the
407
+ update whenever it names the current session, since 2.1.1's source text emits it
408
+ after the prompt resolves (an order read from the source, not yet observed live
409
+ through the hub; docs/smoke.md). A gate crossing records the
410
+ event and notice for an ACP peer but sends it no checkpoint request yet. Only validated cumulative totals or input/output
391
411
  pairs feed native token readings; unsupported shapes remain unknown. `ahub budget set`
392
412
  feeds a reading by hand. `local` has no quota and is never paused.
393
413
  - Gate at `budget.gate` (default 0.9) on any fresh window; readings older than
@@ -405,7 +425,17 @@ inside a peer.
405
425
  released, so it leads the first delivery. Moved tasks stay with their new owners. A manual
406
426
  `ahub pause` is never lifted by the coordinator; `ahub resume` does not override a budget
407
427
  pause, `ahub budget resume <peer>` does, and the coordinator then leaves that peer alone
408
- until the window that paused it has reset. A handoff waits until another peer is attached
428
+ until the window that paused it has reset, unless a provider refuses another turn:
429
+ that hard refusal ends the override and supersedes a pending soft checkpoint. An
430
+ untouched ACP refusal is requeued only after the hub confirms its budget pause;
431
+ otherwise it stays held for review. After activity, the delivery remains held
432
+ even though open tasks are relayed, and the queue stays held after the budget
433
+ reset until a person inspects and resolves it. Keep one pending resume notice carrying
434
+ every public move since the previous notice was delivered; retain an older unstructured
435
+ notice as public text. Within one hub run, retain a still-future reset bound for the same
436
+ window across an override, while an explicit provider reset remains authoritative. A
437
+ restored pause without per-window reading identity starts a fresh estimate at the next refusal.
438
+ A handoff waits until another peer is attached
409
439
  (right after a restart nobody is), readings keep their own timestamp, and a window whose
410
440
  reset time has passed no longer counts. A peer whose window reset while the hub was down is
411
441
  not paused again, and still gets the resume envelope once it attaches. With no status line
@@ -667,7 +697,7 @@ M6 internal inference, packaging
667
697
  | Anthropic-to-chat translation drops `tool_use` | Claude never runs on local models in this design |
668
698
  | Local worker executes untrusted room text | Untrusted framing, cwd scope, denylist, no `--unattended` by default |
669
699
  | Steering a Codex turn changes its plan mid-flight | Only `important` steers; default tier is `status` |
670
- | Kimi ACP has no quota API | Token-based soft limit only; documented |
700
+ | Kimi ACP has no quota API | Optional token soft ceiling plus the observed five-hour provider refusal as a hard source; conservative reset, other limits unverified |
671
701
  | claude-mem worker API is internal and unversioned for third-party clients | Client isolated in `src/memory/`, pinned to a plugin version range, fail-open everywhere, contract test against a fake worker plus one live smoke |
672
702
 
673
703
 
@@ -824,7 +854,7 @@ session modes (`default`, `plan`, `auto`, `yolo`) but nothing per server or tool
824
854
  the refusal to change a bypassed session.
825
855
  - Claude ask-when-needed allows only Read/Edit/Write/MultiEdit/NotebookEdit/LS
826
856
  and bounded Glob/Grep targets resolved with realPath beneath project root,
827
- outside .agenthub/.git/.claude/.codex/.qwen/.kimi/.pi/.mcp.json. Missing/nonresolving or escaping targets,
857
+ outside .agenthub/.git/.claude/.codex/.qwen/.kimi/.kimi-code/.pi/.mcp.json. Missing/nonresolving or escaping targets,
828
858
  protected case aliases, symlinks and uncertain wildcard/filter targets yield
829
859
  no decision. Never-ask answers allow; ask and transport errors decide nothing.
830
860
  Merged/generated settings are 0600 state files passed by path, never inline
@@ -845,7 +875,7 @@ session modes (`default`, `plan`, `auto`, `yolo`) but nothing per server or tool
845
875
  observation purposes retain native turn bookkeeping. Hook identity/purpose
846
876
  are launch/session bound; unverified hook status reads unverified.
847
877
  - Pi/local read never asks. Ask-when-needed grants write/edit inside the project, outside the shared native
848
- configuration segments (.claude/.codex/.qwen/.kimi/.pi/.mcp.json, compared folded and by the path within the
878
+ configuration segments (.claude/.codex/.qwen/.kimi/.kimi-code/.pi/.mcp.json, compared folded and by the path within the
849
879
  project) and never through a hard link; bash and mutating
850
880
  git retain console approval. Never-ask grants once, retaining sandbox and
851
881
  path guards; no mode gives allow-always. ACP tools have no hub sandbox and
@@ -1333,6 +1363,8 @@ qualification. Primary and fallback dispatches have independent outcomes.
1333
1363
 
1334
1364
  ## Task idle sweep (#186, 2026-10-09)
1335
1365
 
1366
+ Body-free memory-reference markers do not count as owner or reviewer activity: they preserve the inactivity threshold and the current sweep ladder activity index.
1367
+
1336
1368
  `Tasks.sweep(now)` owns a deterministic, default-off between-turn sweep. It
1337
1369
  classifies proposed tasks with an owner as unaccepted assignments, in-progress
1338
1370
  tasks with an idle owner as idle-owner findings, and in-review tasks with a
@@ -1402,12 +1434,19 @@ Codex reports `tokenUsage.last.totalTokens / tokenUsage.modelContextWindow` in
1402
1434
  and [native TUI](https://github.com/openai/codex/blob/main/codex-rs/tui/src/token_usage.rs)
1403
1435
  distinguish the last active context from the accumulated `total`; the displayed
1404
1436
  raw occupancy does not apply the TUI's baseline-adjusted remaining percentage.
1437
+ The Kimi peer reports `used / size` in `usage_update` (source
1438
+ `acp_usage_update`, #285 phase 1; only Kimi is wired): the session's context
1439
+ occupancy, accepted whenever it names the adapter's current session, including
1440
+ outside a turn; 2.1.1's source text emits it after the prompt resolves (read
1441
+ from the source, not observed live), when the peer may already be idle.
1405
1442
  Pi's RPC state exposes no measured native counter. Its extension context API
1406
1443
  returns an estimate, so Pi and unsupported peers remain unknown here.
1407
1444
 
1408
1445
  Each reading records source and measurement time. Claude's status-line file is
1409
1446
  bound to the daemon instance, managed launcher and native session; Codex's
1410
- notification is fenced by its owning link and native thread. Stale, invalid,
1447
+ notification is fenced by its owning link and native thread; an ACP reading is
1448
+ bound to the adapter's own session id and dropped when that is not the daemon's
1449
+ current session. Stale, invalid,
1411
1450
  disconnected or replaced-session readings expose unknown occupancy, never zero.
1412
1451
  `context.gate` defaults to 0 (off); `context.stale_min` defaults to 30.
1413
1452
  A valid above-gate reading emits one metadata-only `context_pressure` event
@@ -1446,6 +1485,15 @@ approval. Deny is direct. Pending requests include expiry and are withdrawn by
1446
1485
  `permission_closed` on any answer or cancellation. Answer audits have no title.
1447
1486
  Panels expose Peers, Approvals, Tasks, Queue and Events with bounded polling and
1448
1487
  Unicode cell widths, fall back below 80x24, and restore terminal state on exit.
1488
+ Tabs change with the digits 1 to 5 or with Left and Right, wrapping at both
1489
+ ends, with the digit's guards and resets (an arrow under a confirmation dismisses
1490
+ it like any key but y, without moving a tab); a read holding nothing but arrow
1491
+ sequences is that many key presses, never a paste. An Events row's header is
1492
+ tokenized by the stream's own tokenizer on the same tab-flattened text, with the
1493
+ event's tone and kind; body lines stay plain, and selection changes only the
1494
+ `>` marker. The tail prints a peer's context reading once and repeats it only
1495
+ when the printed line changes apart from its time (the printed percentage, the
1496
+ freshness, the source, or known against unknown).
1449
1497
 
1450
1498
  Whole-board progress (#246) uses one pure `taskProgress` function shared by the
1451
1499
  console and hashed dashboard script. It reads only public id/state/deps fields;
@@ -1769,8 +1817,9 @@ push `accepted` and show none of them.
1769
1817
  push drain needs the peer deliverable (`Bus.deliverable`: not held, idle, not
1770
1818
  pull-only), checked at each loop and again after condensation, so a plain
1771
1819
  session that takes the peer while a push is condensed gets nothing. Its
1772
- messages stay queued and count as `queued`. Board routing still treats the
1773
- peer as attached.
1820
+ messages stay queued and count as `queued`. Board routing still sees it as attached, but automatic owner/reviewer
1821
+ selection excludes pull-only peers; only explicit role-specific naming or an
1822
+ honored owner reservation permits assignment.
1774
1823
  - `hub_inbox` sends `inbox`. The daemon answers "not attached yet; retry"
1775
1824
  between welcome and attach, and refuses it for a session with pushes.
1776
1825
  `Bus.pull` is held by every hold a drain respects (`Bus.held`: recovery, an
@@ -2137,3 +2186,615 @@ acts on the stopped state directory.
2137
2186
  - `ahub stop <peer>` is human-only in `classifyPeerCommand`, prints the returned state, and reports an older hub's unknown request as requiring an upgrade, with a nonzero exit. The upgrade plan's headless `endPlannedPeer` uses the same console request; the daemon does not close a native terminal.
2138
2187
 
2139
2188
  - Requested stop admission also holds per-peer drain, pull and steering before any teardown await, without changing operator/budget pauses. Arriving work remains queued for explicit restart. Idle Pi captures live empty-session proof before stopping; a first accepted prompt with unpersisted history is not silently recreated as empty.
2189
+
2190
+ ## Amendment: settings from the dashboard and the terminal (issue #269, part 1)
2191
+
2192
+ - The dashboard stops being read-mostly for one closed list: a settings registry in `src/hub/settings.ts`, one entry per editable setting (key, type and allowed values, the store, when it applies, and whether it can raise authority). The dashboard's Settings section and `ahub settings list|get|set|undo` render from it and write through it; a key outside it cannot be written from either. Keys that choose what the hub runs or where secrets and task text go (`kimi_cmd`, `codex_bin`, `pi.cmd`, `checks`, `mlx`, `omniroute`, `memory.worker_url`, `local.read_allow`, `local.bash_network`, `local.network_allow`, `bench.enabled`, `terminal`) are refused by name from every surface.
2193
+ - First list: `permission.<peer>` (the running mode, the console's `permission` request), `permission_modes.<peer>` (the default at hub start), `pi.auto_start`, `routing.stay_switch`, per class `routing.classes.<class>.peers`, `.escalate_to`, `.route` and `.pi_backend`, and the switches `research.enabled`, `approvals.notify`, `snapshots.enabled` and `coordination`. Start modes (`peers.<id>.start_mode`, the terminal provider, Pi's TUI default) are part 2 of the issue.
2194
+ - Stores: config values go to `.agenthub/config.local.json`; routing values go to a new machine-local overlay, `.agenthub/routing.local.toml`, which may hold only those routing keys and is merged over `routing.toml` key by key by the one loader (`parseRouting`). `assign()` stays pure; its trace, and so `ahub route explain`, names the keys the overlay set. The tracked `config.json` and the hand-written `routing.toml` are never written, a machine-local file that git tracks is refused, and `ahub init` adds the overlay to `.gitignore`. A write is validated by the real loader first (a scratch copy for the config, the parser for the overlay), replaces the file through a temp file and rename, and keeps one previous version: undo restores it, refuses when the file changed since, and validates what it restores. The undo record is written after the file, so a write that failed leaves the earlier undo in place. A write that would change nothing (the same value again, or removing a value that is not set) writes no file, keeps the undo record and records no event. A config setting is refused in a project that has no config file at all (neither `config.json` nor `config.local.json`): its first config file would switch the project defaults on (snapshots, limits, the budget relay), and that is `ahub init`'s to do. In a repository where git cannot say whether the file is tracked, nothing is written; a project outside git has nothing tracked. Removing a machine-local value (`inherit`) is a write like any other. When config trust (#17) drops the written field at load (`permission_modes` in a file git cannot vouch for), the reply and the setting's row say that the hub does not read the value.
2195
+ - Authority. An ordinary dashboard session reads settings, lowers a mode to `ask`, turns `pi.auto_start` off and changes the safe switches. A settings session, opened by `ahub ui --settings` (a console command behind the identity gate, a console-role `ui` request with `settings: true`), may also raise: a non-ask mode or default, routing, `pi.auto_start`, removing a machine-local value, and undo. Its ticket marks the session for 15 minutes; afterwards the session continues as an ordinary one until its hour ends. `never-ask`, running or stored, needs the peer id as the confirmation (typed in the dashboard, `--yes` in the terminal); a stored never-ask default still waits for the console's `y` at each hub start (#242). No other path puts never-ask on disk: an undo that would restore it is refused (set it again with its confirmation), and `inherit` that would uncover a never-ask from the shared file needs the same confirmation. Tool approvals stay deny-only for Pi and local in every session. The unified dashboard forwards settings actions with ordinary authority.
2196
+ - A mode set from the dashboard or `ahub settings` is `changePermission` inside `permissionChange`, the console's path, with its refusals (not attached, unverified Claude hook, unattended Codex or Claude, a stop in progress) and its `permission_mode` event.
2197
+ - Preview before save: a routing change returns `route explain` for up to 20 open tasks under the policy in force and under the candidate (PII tasks are counted, not shown); a mode change returns the peer's bounds and what the mode grants.
2198
+ - Every change is announced in `hub.log` and open consoles with its source and recorded as a `settings` event: key, value before and after, source (`dashboard` or `terminal`), `undo`. Values are closed words, booleans, peer ids or route ids, never free text.
2199
+ - Control protocol: `settings_get`, `settings_set`, `settings_undo` and `settings_preview` are new console-role requests, and `ui` takes an optional `settings` flag and echoes it; an older hub answers the requests as unknown, and the CLI refuses a `ui` reply without the echo, so `PROTOCOL` stays 16. The `ui_snapshot` reply gains an optional `settings` object. Events schema stays 1.
2200
+ - `ahub settings` talks to the running hub (ponytail: a file-only path if setting a start-time value on a stopped hub is ever wanted).
2201
+
2202
+ ## Amendment: TUI by default, headless as opt-in (issue #269, part 2)
2203
+
2204
+ - `peers.<id>.start_mode` (`tui` or `headless`, for pi, codex and kimi; `tui` when unset) is the mode a start takes when nothing more specific was asked. Claude has only a TUI; Kimi defaults to its own pull-only TUI, with ACP selectable; local stays headless. The loader refuses a malformed `peers` block.
2205
+ - A person typing `ahub pi` gets that mode: the TUI in their terminal by default. `--mode headless` or `--headless` asks for headless. Without a terminal (the console's command line, a script) and with the default asking for the TUI, the CLI sends the console-role `peer_start` request and the hub opens a terminal, or refuses with the command; an option given then is refused, because the fixed command carries none. An explicit `--mode tui` is taken at its word. `ahub codex` and `ahub claude` typed by a person are unchanged.
2206
+ - A start the hub makes itself is `hubStart(peer)`: the dashboard's `start_peer` action, `peer_start`, the conductor's `hub_peer_start` and `pi.auto_start` at hub start. With `headless` it starts the peer as before (for Codex: the app-server only). With `tui` it opens a terminal running `<runtime> <CLI entry> --project <root> <peer>` (`--mode tui` for Pi), assembled from the hub's own words and quoted word by word; no caller text is part of it. The peer is reserved before the provider is asked, so starts that arrive together open one terminal, and a second start within 30 seconds of an opened terminal is refused instead of opening another (a failed open frees it at once). A start mode of headless never takes over a Pi that runs in a terminal.
2207
+ - Terminal providers, in order: `terminal.open`, a machine-local argv template (`{command}` in exactly one element, plus `{title}` and `{cwd}`; a `MACHINE_LOCAL` field under config trust and on the never-editable list), then Orca (`orca terminal create --worktree id:<id> --command ...`) when the hub runs in an Orca worktree or a recorded launch of the project names one. Each template placeholder is substituted once; only `{command}` is shell-quoted. The opened terminal's environment carries no agent marker and no Orca terminal identity of the hub's own. A provider's error text is logged, not returned. With no provider the start is refused with the manual command; it never falls back to headless. Only the running product wires the real providers; a daemon constructed without them opens nothing.
2208
+ - The conductor's `hub_peer_start` no longer takes a mode: it takes the peer's start mode, and a `mode` argument that differs is refused. It may now start claude and codex through the provider, and codex headless when a person set that.
2209
+ - Recovery restores each peer in the mode its recorded session had. After an unplanned stop, `pi.auto_start` no longer starts a fresh headless Pi in place of one that ran in a terminal (with or without a recorded session file), unless headless is Pi's start mode. `peers.<id>.start_mode` may be set in the shared config file too: it is not a machine-local field.
2210
+ - Settings: `peers.pi.start_mode`, `peers.codex.start_mode` and `peers.kimi.start_mode` join the registry (group Start, stored in `config.local.json`, raising except to `tui`). They are the one stored setting a running hub takes up: after a settings write the hub re-reads the block, so the mode applies at that peer's next start. The dashboard gains a Start control per peer that is not attached, saying the mode and the provider (or why there is none); it offers no button when the start would be refused. An ordinary session may press it: it runs only the fixed start. The page blocks repeat starts while the request is in flight and unlocks after a confirmed answer, leaving the hub's terminal reopen guard authoritative. The manager waits 35 seconds (the terminal provider cap plus its margin); a slower headless start can end unconfirmed. After an unconfirmed manager result the page holds that project/instance/peer control for `PEER_START_RETRY_MS` (the same 30-second bound as the hub's reopen guard), or until the `starts` snapshot confirms attachment, and names the retry bound. A confirmed project-local dashboard start behaves as before; no manager or settings authority changes.
2211
+ - Control protocol stays 16: `peer_start` is a new console-role request an older hub answers as unknown, and `ui_snapshot` gains the optional `starts` list.
2212
+ - Migration: Pi's default changes from headless to its TUI. `ahub settings set peers.pi.start_mode headless` (or the same key in `config.local.json`) keeps a headless auto-started Pi; scripts add `--headless`.
2213
+
2214
+ ## Live peer roster (#315)
2215
+
2216
+ The native catalog comes from `KNOWN_PEERS`. A boolean `roster.<peer>` setting
2217
+ controls participation through the existing settings registry, store, preview,
2218
+ write, undo and authority. Without a roster entry, the existing defaults apply;
2219
+ Pi uses pi.enabled only as that fallback. A future catalog member defaults off.
2220
+ External ids retain their existing admission rules.
2221
+
2222
+ Only a person changes the roster. Removal is available to an ordinary dashboard
2223
+ session, while adding requires a settings session or terminal. The active
2224
+ conductor cannot be removed. Removal is previewed and confirmed; an active turn
2225
+ requires --now. Owned runtimes stop and personal native terminal sessions detach
2226
+ without closing their native process. Removed peers receive no new messages or
2227
+ assignments and cannot start or attach. Queued and uncertain work is retained,
2228
+ with off-roster rows visible while work remains. Runtime permission overrides
2229
+ are cleared; configured defaults govern return, with existing pauses preserved.
2230
+
2231
+ The roster view shows the whole catalog; status remains lazy. Owner and reviewer
2232
+ work uses the existing reassignment. No eligible replacement means the previous
2233
+ assignment remains with a public-title notice. Membership enters the pure
2234
+ assignment function as data, so route explain states the same off-roster reason.
2235
+ A live write or undo changes only its authorized key, not other config edits.
2236
+ Tracked defaults and machine-local overrides are read normally on the next hub
2237
+ start. The CLI and dashboard use the settings API and no roster hub tool exists.
2238
+
2239
+ Removal orders its steps as membership fence, detach or stop, then handoff. Its
2240
+ preview and result name the peer whose retained terminal work the person must
2241
+ stop, and the result lists the saved task moves with public titles. Detached
2242
+ sessions receive no forced stop notice or journal bypass. Codex 0.146.0 exits
2243
+ its TUI on close 4000 rather than retrying. Its app-server/proxy and terminal
2244
+ window remain; preview/removal/return print ahub codex resume with the full
2245
+ thread id when known, or the native resume picker. After adding it back the
2246
+ person runs that command. Automatic return is guaranteed for the Claude
2247
+ channel, not this observed Codex version. The preview names
2248
+ roles offered and those without a replacement; the result names every saved
2249
+ move and every assignment that stays. An unconfirmed stop reports the skipped
2250
+ permission reset and handoff after the roster write.
2251
+
2252
+ Removal includes in-review ownership (keeping its review state) and reviewer
2253
+ roles. Later task messages follow the current owner/reviewer. An explicit
2254
+ off-roster recipient is retained, including one recipient of a mixed audience,
2255
+ with one public notice to the person; native senders get a decision note and
2256
+ console/channel senders get the existing notice field. A removed personal Pi TUI
2257
+ whose verified native owner is alive still blocks controlled recovery under the
2258
+ existing settlement fence; the person ends that retained TUI before restart. Broadcasts omit removed
2259
+ peers, and a person or agent addressing only removed peers is refused before
2260
+ publication. The dashboard roster undo carries peer confirmation.
2261
+
2262
+ Pi detached/unowned native activity preserves only monotonic generation from
2263
+ the authenticated bridge and verified owner (the legacy unnamed event uses
2264
+ that current-session binding; an explicit session mismatch is refused). Personal
2265
+ output, tokens and managed turn state remain unclaimed. That activity revokes
2266
+ an earlier empty-session resume proof; stale unowned completion cannot release
2267
+ the queue.
2268
+
2269
+
2270
+ ## Amendment: Kimi TUI as the default pull-only peer (#316)
2271
+
2272
+ - One id, kimi, owns either an attached pull-only WsPeer or headless ACP. The unset
2273
+ start mode is tui for existing and new projects; upgrade announces the change
2274
+ once with `ahub settings set peers.kimi.start_mode headless`. A person's one-start
2275
+ mode override also controls that launch's admission, without changing the setting.
2276
+ - Only a person's launcher atomically merges or removes the agent-hub entry in
2277
+ `.kimi-code/mcp.json`. It preserves foreign meanings, warns if tracked, and a
2278
+ preview writes nothing. Init ignores the untracked machine-path file. A daemon
2279
+ headless start refuses a stale entry with the human cleanup command. TUI argv
2280
+ derives only from a single executable or an exact trailing acp word.
2281
+ - In TUI mode only a peer hello with channel false is admitted. It reads queued
2282
+ chat/task/review via hub_inbox, journaled completed once, and answers via hub_send.
2283
+ It has no push, steer, busy state, watchdog, console approval, hub permission
2284
+ mode, automatic quota pause/handoff, context reading, shared final answer or
2285
+ session resume. Status surfaces pull-only, waiting and last read. Stop belongs
2286
+ to the person in the native terminal. A live TUI blocks headless replacement;
2287
+ after detach the same queue and open tasks reach ACP, without continuing its
2288
+ session in the TUI.
2289
+ - Pure routing excludes every automatic Kimi pull-only candidate, including automatic
2290
+ singleton escalation/handoff. Explicit proposer owner/own claim, validated owner
2291
+ assign and honored persisted reservation are named. Reviewer assign is person or
2292
+ conductor only, preserves task state and uses the existing guarded review request;
2293
+ dependencies must be approved first. No roster/PII/pause/capability guard is bypassed.
2294
+ - Kimi Code 2.1.1 source preflight confirms trusted ACP workspace MCP file discovery
2295
+ and a separately connected same-name session overlay. The engine does not carry
2296
+ MCP initialize instructions into its model request: tool descriptions and the
2297
+ managed AGENTS block carry the pull rules. Live trust/discovery and model tool
2298
+ use remain unverified in smoke.md.
2299
+ - Recovery for #316: an attached Kimi TUI carries `launch.mode: tui` and blocks controlled upgrade/restart planning before effects, with the human end-and-replan instruction. It is never restored as an ACP worker. Headless restoration explicitly selects headless when the staged target catalog includes Kimi modes; legacy targets retain their old no-mode command. The target catalog read is a stated source-capability shortcut.
2300
+ - A person/conductor changing the reviewer of an in-review task withdraws unread prior requests and sends the former reviewer a withdrawal notice. Already-delivered requests cannot be recalled; current reviewer authority rejects a late verdict. Publication failure remains guarded after the saved board change.
2301
+
2302
+ - Compatibility: Tasks supplies Kimi TUI ids to the generic pure pull-only filter. Legacy Claude pull-only sessions retain existing automatic owner/reviewer selection and queued inbox requests. Init adds the Kimi ignore for an existing untracked MCP file, preserving previous ignore bytes when the file is absent.
2303
+ ## Amendment: offline ACP approval fencing and lexical scoped-path checks (#311, #322)
2304
+
2305
+ - ACP cancels new permission requests while offline or waiting for watchdog cancellation, before consulting either approver. Pending permissions carry abort signals to the daemon approval registry and are withdrawn on watchdog cancellation, offline transitions and stop. Late answers cannot grant them; a restarted session may request approval normally.
2306
+ - An acknowledged ACP permission-mode change waits for watchdog cancellation cleanup only when that prompt response has already been observed. A mode acknowledgement while the prompt is still unreported returns without declaring it idle or delaying cancellation diagnostics. Native prompt cleanup releases the gate; its existing bounded deadline, stop and transport loss also release it, preserving offline and stale-turn fences.
2307
+ - Pi and local write/edit approval passes the original path separately from the `guardPath` real target, through every wrapper. Scoped automatic grants require both project-relative forms to avoid protected names. A protected directory symlinked into an ordinary project directory and an ordinary alias into a protected directory both require a person. `realPath` and the post-approval target check remain the authority for effects. Explicit approval and never-ask keep their meaning.
2308
+
2309
+ ## Amendment: further scoped-grant exclusions and instruction option (#323)
2310
+
2311
+ - `.agents` and `.claude.json` join the folded protected configuration names. The dated source inventory records the supported project locations and discovery limits; `.claude.json` is excluded conservatively without a project-loading claim.
2312
+ - `protect_instruction_files` is machine-local, boolean, false by default. Only the settings registry exposes it, as `scoped_grants.protect_instructions`, in Permissions, applied live after a write or undo. A person may change it; no agent surface gains a setter. Lowering protection from an ordinary dashboard session is refused.
2313
+ - Enabled protection withholds scoped automatic writes/edits to `AGENTS.md`, `CLAUDE.md`, `QWEN.md`, folded like configuration names in both lexical and resolved paths. Reads and explicit approval/never-ask retain their meaning. Default grants remain unchanged. The daemon downgrades a Claude scoped grant reply for a protected write as well as supplying the optional flag to the current hook, so an older hook cannot silently ignore protection.
2314
+
2315
+ ## Amendment: initial head-bound SDLC gates (#257)
2316
+
2317
+ - Optional .agenthub/sdlc.toml selects off/advise/enforce, off by default, with a fixed built-in stage order and bounded explicit required check names. The initial delivery has no custom stage/gate language.
2318
+ - Tasks owns optional board artifact receipts and every mutation. Repository, issue/PR ids, claimed local result/head and a reviewed full SHA are distinct from fresh external evidence. Only the owner/reviewer/person records; only the reviewer/person binds a review head. Invalid identities, unsupported externally supplied facts and private-turn cloud records are refused before effects.
2319
+ - Enforce rechecks the current PR head, successful required checks, local receipt on that head, GitHub review and complete unresolved-thread readback before approval. Missing/unknown data blocks, a new head invalidates derived readiness, and changes requested needs no green CI. Advise exposes gates without additional blocks; off retains existing transitions. Historical board approval is not approval of a new head.
2320
+ - CLI sdlc status/explain reads bounded structured metadata, not remote bodies. Shared console/dashboard views expose unknown external evidence and the next actor/action; they cannot certify freshness. No merge/release authority is granted.
2321
+ - Custom definitions, full merge/release presentation, gsd-lite and a native advise cycle remain pending; see docs/sdlc.md.
2322
+ ## Amendment: optional Qwen Code 0.25.0 ACP peer (#256)
2323
+
2324
+ - `qwen` joins the known catalog with default participation off. Only the project's roster selects it; no second enabled switch or default routing preference is added. Its flow roles default to implementer/verifier, which is guidance, not a claim of native reliability.
2325
+ - `qwen_cmd` is machine-local, default `["qwen", "--acp"]`. The CLI, conductor and dashboard share the normal start/stop/permission fences. `ahub qwen --print-command` previews without execution; only headless is offered before #286 native TUI verification.
2326
+ - Production Qwen explicitly requires the ACP native identity `qwen-code`, version `0.25.0`. The mode table is ask/default, ask-when-needed/auto-edit, never-ask/yolo; auto and plan are unmapped. Available mode ids and successful set-mode acknowledgement precede every first prompt. Fresh/resumed sessions start at the operator's selected mode, including ask. Wrong identity/version is refused without a model turn. Existing benchmark ACP instances do not opt into this production table and retain their native policy.
2327
+ - Qwen runs its own tools and has no hub sandbox. Never-ask text and confirmation say yolo approves every tool. Exact canonical hub-tool approval remains bound to the announced call id and this session's server names.
2328
+ - Context occupancy carries the native session and acp_usage_update source. No unobserved quota is inferred or automatically paused/handed off; manual pause stays available. Native startup errors and stderr diagnostics withhold host/payload details. A source using Qwen cannot stage a target without Qwen support and then strand its restore after shutdown.
2329
+ - CLI/source version drift was observed locally: the installed CLI prints 0.25.0, its package and ACP source say 0.24.1. That installation is not native readiness evidence. Real 0.25.0 provider/turn/quota verification remains owed; fake tests and strict runtime verification are separate proof.
2330
+
2331
+ ## Amendment: optional owned Jcode peer (#332)
2332
+
2333
+ - jcode is optional on the roster, default off, with implementer/verifier guidance and no default routing replacement. Its source-pinned native identity is jcode 0.94.0.
2334
+ - A private foreground daemon/socket and ACP client belong to this peer. The global daemon is never adopted or stopped. No automatic update, self-dev or credential copy. The native MCP store must already exist to avoid implicit Codex import.
2335
+ - ACP session MCP arrays are ignored natively, so the person launcher manages only agent-hub-jcode, shared:false, in project .jcode/mcp.json. Later override layers, foreign names and links refuse. Daemon starts verify read-only. .jcode is outside scoped grants.
2336
+ - Native policy is unmanaged and has no hub sandbox. Hub permission mappings refuse; native quota/consumption are not inferred. Every task mutation stays in Tasks and PII remains at existing redaction/routing boundaries.
2337
+ - Native 0.94.0 load lacks identity proof. Controlled recovery refuses before effects, crash recovery is manual and a load without an exact echoed id refuses before a prompt or restored claim. Real provider/tool/teardown evidence and comparative measurement remain unverified.
2338
+
2339
+ # ACP watch amendment, 2026-10-11 (#286)
2340
+
2341
+ - Headless Kimi/Qwen expose `watch` to console-role clients: bounded memory replay followed by activity pushes, no protocol bump, no peer input or approvals from the view. The CLI displays safe wrapped text; private/PII turns display a stub.
2342
+ - Activity contains delivery ids/senders, message/thought chunks, bounded tool summaries, plans, permission request/outcome ids and turn end. It never enters persistent events/logs, UI, tools or cloud memory. Existing final answers still travel through the answer bus.
2343
+ - Kimi TUI defaults remain pull-only. Qwen TUI and native visualizer support remain gated by unverified T0 checks. See [verification](../verification/2026-10-11-acp-watch-t0.md).
2344
+
2345
+ # gsd-lite amendment, 2026-10-11 (#257)
2346
+
2347
+ - Optional workflow none|gsd-lite, none by default, uses existing SDLC receipts and Tasks authority. A reviewer/person-owned checklist stores bounded criterion ids, hashed evidence refs and verified/failed/unverified claims bound to the reviewed head.
2348
+ - Existing task/predecessor ids must match current Tasks.after edges; missing/cyclic/private cross-links are refused before effects. Imports do not change task ownership, reservations or dependencies.
2349
+ - Required unknown/failed criteria and stale heads keep readiness false. Advise remains nonblocking; enforce adds these only to existing approval gates. Route explain, console/dashboard lifecycle views and read-only hashed exports derive the same board/config state. No second writable workflow store, automatic advance, permissions, merge/release or study execution.
2350
+
2351
+ # Role catalog amendment, 2026-10-11 (#295)
2352
+
2353
+ - Separate optional catalog guidance from unchanged flow roles/authority. Eleven shipped dev/research definitions and bounded project overrides carry flat headers, six fixed sections, content hashes and source notices.
2354
+ - Session selections contain up to two ids and must match an existing flow base. Default absence preserves legacy contracts. Native preambles and Claude instructions publish guidance through existing paths; tools-mode instructions omit catalog text to avoid duplicate headless publication.
2355
+ - Metadata-only prepared events and read-only list/show/doctor diagnostics do not attest native ingestion or execution. Project text is sanitized at rendering; invalid definitions disclose no contents. No new permission, routing, sandbox or tool authority follows from a catalog role.
2356
+ - Task roles, person/settings assignment, pending/session attribution surfaces, later groups and measurement remain follow-up slices. See docs/roles.md for the current contract.
2357
+
2358
+ # Project profile amendment, 2026-10-11 (#259)
2359
+
2360
+ - Four shipped data profiles map optional named classes onto the unchanged seven base classes. Non-dev proposals persist profile/alias metadata beside the base; routing, reviewers, budgets and outcomes keep consuming the base. Default dev template/contracts/schema and legacy rows retain their prior shape.
2361
+ - Profile-aware init preserves existing config and refuses conflicting explicit selections before writes. Peer contracts and task schemas derive from profile data; guidance grants no authority. Non-dev plans carry bounded paths/sections/sources/claims through Tasks and the existing privacy screen, with declared anchor/source overlap.
2362
+ - Explicit machine-local alias check commands precede base check commands; profile selection installs no automatic command. Profile/base/alias metadata is shown in board/route/UI and #247 records without task text. Document projections, shadow repositories, path policy and custom data overrides remain subsequent slices. See docs/profiles.md.
2363
+
2364
+ - Accept schemas expose all supported plan fields because an open task keeps its stored profile across a project profile change. Tasks still normalizes by that stored profile; no new plan field changes authority.
2365
+
2366
+ # Data path policy amendment, 2026-10-11 (#259)
2367
+
2368
+ - Optional bounded project-relative pii.paths and data.readonly lists preserve defaults when absent. Declared private paths receive a hard local-only signal before triage/board/notice/memory; a new private plan cannot enter an ordinary task without re-proposal.
2369
+ - Managed local/Pi write/edit check lexical/real paths before and after approval and refuse hardlinked targets under an active read-only policy. Managed command profiles/runner remove broad filesystem write grants, including owned temporary writes, when data.readonly is active. Reads/stdout and /dev/null remain available; unprotected outputs use managed write/edit. The stricter command boundary closes the reproduced hardlink-alias bypass of path-only denies.
2370
+ - These controls do not contain the owner or other native same-user processes. Config policies apply at daemon start; no permission mode overrides managed data policy. Native-account/research legs remain unverified. See docs/data-policy.md.
2371
+
2372
+ - Parent directory task scopes containing a configured private path are private too. Automatic facts omit configured private files before reading/showing them, including outside an open private task.
2373
+
2374
+ # Text projection amendment, 2026-10-11 (#259)
2375
+
2376
+ - Optional machine-local extension/argv mappings use immutable bounded input snapshots, no-network/read-only converters, process-group deadlines and bounded output. Shared/tracked config cannot choose execution. Default absence preserves raw facts.
2377
+ - State cache keys bind raw content and argv/program/script metadata. Conversion failure/absence falls back once per extension without leaking stderr. Private paths are excluded before conversion.
2378
+ - Facts retains raw hashes/blob identities and renders projected text as presentation only; projected reads/patches never establish raw-file attribution. Review/undo and shadow-repository surfaces remain follow-ups. See docs/text-projection.md.
2379
+
2380
+ # Task catalog role amendment, 2026-10-12 (#295)
2381
+
2382
+ - An optional proposal role names a validated catalog id compatible with the stored base class. Tasks validates before the board write; the board persists only the id. Role guidance never affects routing, authority, checks or policy.
2383
+ - Owner assignments and reassignments carry sanitized bounded role guidance; a native session whose role contract was prepared by this daemon gets the id without a repeated body. Review requests always carry the role id and its Review duties only. Unknown prior definitions yield an id-only notice.
2384
+ - Public PII stubs may expose the role id, never task text. Role/task events and research records carry id/layer/hash only. Default absent roles preserve old notices and row shapes.
2385
+ - This slice does not add person role mutation commands/settings or infer that an externally started Claude/plugin session consumed its roles. Those assignment surfaces and native ingestion/measurement remain follow-ups.
2386
+
2387
+ - Complete task role guidance, header included, is capped at 2000 characters. An oversized definition is refused before proposal storage; a saved task whose definition later exceeds the cap keeps an id-only notice. Definitions are never truncated.
2388
+
2389
+ # Person role control amendment, 2026-10-12 (#295)
2390
+
2391
+ - Catalog-role settings are person-only registry entries, stored only in config.local.json and applied at the next peer start. At most two compatible ids per supported peer; explicit empty disables and inherit restores shared/profile defaults. Flow authority, routing and permission policies remain independent.
2392
+ - Existing task roles change only through Tasks for a console person, before approval. The saved change keeps ownership/class and sends bounded sanitized guidance to current holders. It never rewrites the original proposal identity in research evidence.
2393
+ - Status/UI role preparation and pending fields are advisory transport/configuration metadata, not proof of model consumption. External plugin/TUI sessions without a receipt remain unconfirmed. Session research attribution and #263 board-card work remain follow-ups.
2394
+
2395
+ # Session role research amendment, 2026-10-12 (#295)
2396
+
2397
+ - Turn start freezes the native preamble role identities; attributed completion events carry that snapshot to the shared live/backfill research builder. Records contain peer/turn/id/layer/hash only, never role or task text. Pending configuration edits cannot rewrite an open turn.
2398
+ - Empty preparation is distinct from an unknown external session or an older event without metadata. The additional fields preserve the existing event/research schemas and CSV summary. Preparation is not evidence of native model consumption; #263 cards and role effectiveness measurement remain pending.
2399
+
2400
+ # Rich-document review and undo amendment, 2026-10-12 (#259)
2401
+
2402
+ - Machine-local bounded converters may project regular historical git blobs for review notices and reverse undo previews. Raw snapshots remain the attribution and restore identities; converted text is presentation only.
2403
+ - A task's exact proposal baseline is persisted by id/proposal time outside task history. Replacements and restart reuse it, never a guessed current or later baseline. Private windows do not capture it; missing/pruned/disabled evidence is explicitly unavailable.
2404
+ - Review remains within declared task refs/plan/section files. Denylisted and declared private paths are not converted, private-data patterns are withheld and inserted headers are sanitized. No projected document body is added to task history or memory.
2405
+ - Previews share an 8-second monotonic deadline, at most 8 files and 12000 UTF-8 presentation bytes. Individual converters remain limited to 5 seconds, no network or writes, with owned-group cleanup on timeout or termination. Format participates in the content/command cache key; changing converter identity invalidates a pair.
2406
+ - Raw undo planning, overlap/later-edit refusal and the final pre-restore readback stay authoritative. Linux conversion and native/account/measurement legs remain unavailable or unverified as documented; shadow repositories and override/glob work follow separately.
2407
+
2408
+ # Non-git shadow repository amendment, 2026-10-12 (#259)
2409
+
2410
+ - Explicit init `--shadow` creates a validated bare `.agenthub/shadow.git` with the project as its explicit work tree; previews contain action metadata only. Real Git projects retain their selection and are refused for shadow creation. No `.git` entry is added.
2411
+ - Repo-aware hardened git calls supply snapshot/facts/projected-diff/undo operations. Shadow calls ignore global/system git config and honor the owner-managed `.agenthub/ignore`. Own shadow/runtime/local metadata never enters snapshots or facts, and remains unwritable to managed workers.
2412
+ - Snapshots and restore leave HEAD/index unchanged. Metadata links at any depth, shared alternate object stores and invalid directories are refused. Each shadow Git call revalidates the metadata walk (20000 entries and 32 levels maximum), even for a previously discovered handle. Missing evidence and later/concurrent raw edits retain existing conservative refusals.
2413
+ - Non-dev profiles without a repository disable these features with one notice. Dev named-file facts retain the existing #108 behavior and tests; Git directory facts and snapshots/undo remain unavailable without a repository. This reconciles the profile proposal with its explicit unchanged-dev contract.
2414
+ - Native research/account/measurement and custom profile/glob work remain follow-ups, not claims of this source delivery.
2415
+
2416
+ # Per-project profile data amendment, 2026-10-12 (#259)
2417
+
2418
+ - Pure `profile_overrides` resolution supplies per-project class maps, supported plan-key selection, flow-role guidance, catalog defaults, managed AGENTS content and advisory example checks. Shipped defaults are not mutated. Map fields merge across shared/local layers; lists/text replace.
2419
+ - Base flow meanings, routing, budgets and permission checks stay unchanged; aliases persist beside their bases even for custom dev data. Ordinary tasks under custom dev data also retain profile semantics for document overlap; unmodified dev data keeps the legacy row shape. Unknown fields/base meanings, duplicate/unknown plan fields and oversized guidance fail before task effects.
2420
+ - Schemas, CLI classification, Tasks, daemon/native contracts, plugin instructions, both local-worker tool-building paths, check-name allowlists and init use the same resolved data. No-override dev contracts/schemas/instructions remain byte-identical. Old accept schemas support existing task fields.
2421
+ - Flow authority remains the separately validated `roles` map; executable checks remain trusted `checks`. Example checks are display data and do not execute. Managed instruction content keeps surrounding text and quotes forged headers.
2422
+ - Override maps are bounded to 32 class entries and existing base classes; plan selections use existing fields. Role text is 2000 characters, agents 16000, examples 16 strings of 2000 characters. Native ingestion/retention/measurement remains unverified; configuration changes apply after daemon/MCP restart.
2423
+
2424
+
2425
+ ## Amendment: bounded data policy globs (#259)
2426
+
2427
+ pii.paths and data.readonly accept exact paths/subtrees and *, ? and whole-segment ** patterns. Validation keeps 64 entries, 200 characters each and at most 16 wildcard characters. Unsupported bracket/brace/negation/escape syntax, absolute paths and parent traversal refuse. Matching folds case, protects matched subtrees and treats parent task scopes as private when a future matching descendant is possible. Resolve both declared and real paths; wildcard alias discovery is uncached and bounded to 4096 directory entries and 32 levels. Resolution/discovery failure conservatively matches an active policy. Managed local/Pi tools retain hardlink and read-only command protections. Only an authenticated pre-tool ask-when-needed write grant evaluates the daemon-side read-only matcher; other phases/modes perform no grant-policy discovery. Protected grants are withheld without exposing policy paths; explicit approval/never-ask remain native authority, with no new sandbox claim. No account/research pilot is implied.
2428
+
2429
+ ## Amendment: custom lifecycle data (#257)
2430
+
2431
+ Optional ordered stage definitions map at most 32 bounded ids to the existing seven semantic bases, existing actor guidance and closed issue/pr/local/review/checks/phase entry/exit gates. Explicit after edges name at most eight earlier configured ids; missing/self/forward/cyclic references refuse. Review and merge base destinations are required by existing Tasks completion transitions. Built-in names cannot change base. Existing holder/person authority and the full approval floor remain; enforce additionally checks an explicit custom stage-change actor without granting a new caller authority. Off/advise preserve claim behavior. Config-aware receipts, projections and every managed native/local task schema use the same stage ids. Historical removed definitions remain unknown, not silently remapped. No new state, executable gate, auto-advance, merge, release, import authority or native success is introduced.
2432
+
2433
+
2434
+ ### Custom lifecycle review corrections (#257)
2435
+
2436
+ Phase gates require gsd-lite phase views at configuration validation. Authenticated daemon status gains optional lifecycleStages metadata, with no protocol bump. Separate MCP tools lists use that active snapshot; a live legacy daemon without the field keeps seven stages, while unknown/unavailable metadata withholds the lifecycle-record tool. Editing project data during a live daemon no longer changes its advertised stage ids.
2437
+
2438
+
2439
+ ## Backlog foundation (#263)
2440
+
2441
+ `backlog` is a durable task state for known, unoffered work. Its only flow edge is
2442
+ `backlog -> proposed`; `proposed -> backlog` requires no current owner. Backlog
2443
+ rows have no owner or reviewer. Existing rows and proposal history are unchanged.
2444
+
2445
+ `hub_task_propose(backlog: true)` still validates class, plan, role, dependencies,
2446
+ roster reservation and PII before persistence. A named owner is a reservation,
2447
+ never a claim. No routing, offer, overlap announcement, sweep or conductor feed
2448
+ occurs. The person alone uses `Tasks.moveBacklog` through console task operations
2449
+ and `ahub backlog pull|return`; peers cannot invoke these transitions. Pull uses
2450
+ existing dependency and assignment delivery rules, recording a durable ready or
2451
+ blocked marker for restart recovery. Return clears transient ready-offer state.
2452
+
2453
+ Public progress counts Backlog separately at stage zero only when present.
2454
+ Ordinary agent list/show/explain and conductor task tools exclude staged work;
2455
+ future explicit planner tools provide its agent read path. This foundation does
2456
+ not implement ranks, undoable planner grooming, release states, planned dates or
2457
+ dashboard drag/columns. Those remain required by #263. The live planner grooming
2458
+ cycle into two releases remains unverified.
2459
+
2460
+
2461
+ ### Backlog execution boundary (#263)
2462
+
2463
+ First `backlog pulled` is equivalent to the first offered proposal for snapshot
2464
+ initialization, projected-review baseline lookup, role provenance and research
2465
+ creation identity. Backlog itself has no execution baseline. Repeat unstarted
2466
+ staging preserves that first identity; reset-generation `backlogged` events
2467
+ separate old research records, and an unpulled current generation takes no label.
2468
+
2469
+ Structured accepted/done/check/review/integration history is execution evidence.
2470
+ Tasks refuses an ownerless proposed row's return when that evidence exists; the
2471
+ Board shares the same floor before its write. Free-text history is never read
2472
+ to infer execution. Native projected-converter validation remains separate from
2473
+ the portable stored-tree regression.
2474
+
2475
+
2476
+ ## Project board presentation (#263)
2477
+
2478
+ Five fixed state-derived columns share a structural public model with tests;
2479
+ unknown states stay explicit. To Do waits derive from authoritative dependency
2480
+ states and peer availability/holds. Priority P0/P1 has a star plus a text label;
2481
+ legacy urgent maps to P0 and ordinary work to P2 until planning data exists.
2482
+
2483
+ One identity palette supplies terminal board/status tones and dashboard CSS.
2484
+ Owner markers are filled, reviewer markers outlined, with text names. Legend
2485
+ state, WIP and active task ids derive from the same snapshot and permission
2486
+ display used by status. Filter/lane actions are read-only. Recent Done records
2487
+ precede collapsible older work. Responsive columns stack at phone width.
2488
+
2489
+ Only assignment and eligible Backlog/To Do staging have drag controls, each with
2490
+ labelled buttons/selects. Origin/project/instance/generation fences prevent
2491
+ stale gestures, including standalone dashboards on different loopback ports.
2492
+ Server authority and all task writes remain in existing console/session gates
2493
+ and Tasks. A capability bit prevents an older hub silently ignoring Backlog
2494
+ intent. CSP hashes include the injected model/palette, with no outside assets.
2495
+
2496
+ Planner grooming, releases, editable planning data, dates and one-way import
2497
+ remain required source slices. Browser visual and the native planner/two-release
2498
+ cycle remain unverified until their independent checks run.
2499
+
2500
+
2501
+ ## Planning and release persistence (#263, in progress)
2502
+
2503
+ Tasks owns planning and release mutations. Optional rank, P0-P3 priority, release
2504
+ id, UTC planned start/due and pin metadata migrate without inventing a legacy
2505
+ plan. Planning revisions fence stale edits; history records screened reasons,
2506
+ changed fields and previous values. The configured planner role changes only
2507
+ unpinned backlog work outside frozen releases and preserves a person's rank.
2508
+ Undo refuses an intervening change or another planner's edit.
2509
+
2510
+ Planner backlog notices carry at most 64 ids per recipient. Recovery coalesces
2511
+ ids already present in that recipient's restored queue or unresolved journal
2512
+ originals. Configured planners retain staged ids while off roster; roster and
2513
+ attachment gate publication only. An overflow retains
2514
+ only that recipient's pending ids and waits for its queue to change before
2515
+ retrying, using the existing scheduler without another timer.
2516
+
2517
+ Releases persist planning, active, frozen, shipped and dropped states and planned
2518
+ start/cut/ship. Only a person freezes, drops, ships or changes a frozen release.
2519
+ Shipping requires every scoped task approved or moved out, records its first
2520
+ ship time and runs no external release process. Public name/goal must pass the
2521
+ existing PII boundary. Actual task dates derive structured execution, review and
2522
+ approval history, including reviewerless completion; no input supplies actual
2523
+ start/review/done. Old absent evidence remains unknown.
2524
+
2525
+ CLI/dashboard/tools, batched planner notices, dependency edits/splitting, WIP
2526
+ pull, bounded undo surfaces, research metadata and optional GitHub import remain
2527
+ in progress. Source/fixture/platform/seed/visual/native proof is not yet complete.
2528
+
2529
+
2530
+ ## Planner dependency and reservation grooming (#263, in progress)
2531
+
2532
+ Planning may replace at most 64 unique existing positive dependency ids and a
2533
+ rostered peer reservation (or clear it). Tasks checks transitive cycles, current
2534
+ unstarted backlog state, ownership and existing revision/pin/frozen/person-order
2535
+ floors before screening the reason and again afterwards. Board saves metadata,
2536
+ dependencies, reservation, revision and prior values in one compare-and-swap.
2537
+ Undo restores the same fields only when the latest eligible edit still applies.
2538
+ Public planning history excludes previous values. Suggested owners remain
2539
+ reservations; editing never offers or starts work. Native grooming remains
2540
+ unverified; split, WIP pull, batched notices and import are still required.
2541
+
2542
+
2543
+ Incoming backlog ids accumulate through Tasks and are flushed on the existing
2544
+ one-second daemon tick as one task-kind notice to attached rostered configured
2545
+ planners, at most 64 ids per notice. No task prose enters the notice. Pulled or
2546
+ removed ids are omitted, no planner means pending work is retained, and a new
2547
+ hub run regroups its currently staged backlog. This is advisory grooming; no
2548
+ ownership or execution state changes. Planned reservation edits participate in
2549
+ the conductor's latest ownership-decision check, preserving a person's decision
2550
+ when the hub later carries it out. Full proof remains pending.
2551
+
2552
+
2553
+ ## Planner pull admission and undo (#263, in progress)
2554
+
2555
+ Planner pull reserves a bounded per-peer WIP slot and moves ready backlog work
2556
+ into To Do through Tasks. A proposed planner-pull reservation counts as WIP
2557
+ before assignment; its own slot is excluded while the normal routing path offers
2558
+ it to that reserved peer. Capacity and recovery/review holds are checked again
2559
+ at offer time. Default capacity is one per peer; machine-local integer limits
2560
+ 0..32 use the existing settings registry and loader.
2561
+
2562
+ Pull requires current revision and a screened reason, unstarted/unowned/unpinned
2563
+ backlog, approved dependencies and unfrozen scope. Person P0 order and explicit
2564
+ reservations remain protected. Board saves the pull provenance and previous
2565
+ reservation in one CAS. The latest eligible pull can return to backlog only
2566
+ while unowned and unstarted, restoring its previous reservation; it never claims
2567
+ to cancel a dispatched native turn. Native/visual proof remains unverified.
2568
+
2569
+
2570
+ ## Backlog split contract (#263, in progress)
2571
+
2572
+ The manager split deadline includes the shared 8-second screening bound, the
2573
+ hub SQLite busy wait and a five-second margin. A missing answer is unconfirmed
2574
+ and requires task readback before retry. Stored parent role IDs remain guidance
2575
+ metadata when the current catalog entry is unavailable; they confer no authority.
2576
+
2577
+ Task-scoped memory note/link attempts record one body-free board-history marker
2578
+ before external persistence. Split undo preserves that fence even when memory
2579
+ is disabled or unavailable; failed attempts conservatively retain the child.
2580
+
2581
+ Splitting keeps the original card as integration/acceptance responsibility and
2582
+ adds two to eight unoffered child cards as prerequisites. Existing prerequisites
2583
+ and conservative privacy/phase planning are retained. Per-part dependencies may
2584
+ name existing tasks or earlier parts; no child may transitively depend on its
2585
+ parent. Tasks screens and revalidates the entire bounded request before writing.
2586
+ Board commits all children, parent edges and undo provenance in one transaction;
2587
+ change callbacks run only after commit.
2588
+
2589
+ Latest eligible owned split undo restores original edges and deletes only unused
2590
+ unchanged unstarted backlog children, refusing later edits, owners, execution or
2591
+ external references. Role, revision, pin/person and frozen scope floors remain.
2592
+ Public projections expose child ids without private prior values. Source/native
2593
+ verification remains pending; no live operation or release process is implied.
2594
+
2595
+ ## One-way GitHub backlog intake (#263, in progress)
2596
+
2597
+ A person may import open issues selected by a required label and optional
2598
+ milestone/repository, using fixed read-only gh argv. The existing reader bounds
2599
+ stdout and execution; intake uses a 2 MiB output ceiling for the 33-row sentinel
2600
+ page, including worst-case escaped title/body JSON. Other SDLC reads retain
2601
+ their 256 KiB default. One page stages at most 32 issues and reports truncation.
2602
+ Comma-containing and double-quote-containing labels are refused because gh --label uses CSV-style parsing;
2603
+ selection must never silently broaden. The entire returned page must validate before any staging. Repository/issue
2604
+ identity is stored persistently and deduplicated across restart and concurrent
2605
+ screening. Tasks screens imported content and stages unoffered backlog; links
2606
+ are shown only through the central public projection, with no source identity
2607
+ exposed for PII cards. No GitHub comment, label, assignment or close is written.
2608
+ Current source/native proof remains pending.
2609
+
2610
+
2611
+ ## Remaining board projections (#263, in progress)
2612
+
2613
+ Terminal `board --columns` uses the same state/ready/waiting model as the
2614
+ dashboard, retaining public rows and unknown states. `board --release <name> | --release-id <id>`
2615
+ filters read-only through the existing task-list authority; it never exposes
2616
+ backlog to an unprivileged peer. Frozen/phase views flag ids of approved tasks
2617
+ outside the release whose structured approval time is after its planned cut.
2618
+ Missing cut or approval evidence stays unknown, not inferred from notes.
2619
+ Source/native/phone proof remains pending.
2620
+ ## Console attention foundation (#280, in progress)
2621
+
2622
+ The self-contained needs(input,now) model receives structural console-owned
2623
+ approval/default/delivery/storage/message/budget/recovery facts. It copies only
2624
+ bounded ids, peers and known timestamps into sorted act/watch items. Approval
2625
+ expiry is checked against now; watch items never override state.
2626
+ Delivery action counts require positive `needsReview` evidence. A `heldBy` id
2627
+ alone also names dispatching/accepted holds, which cannot be resolved by the
2628
+ person, and does not create an action item. No title,
2629
+ message/error/option text, path, network call or timer enters the model. Phase1
2630
+ console line/keys/configuration now uses a read-only console-local config reader,
2631
+ the existing redraw/poll requests and body-free unread metadata. The line is
2632
+ ASCII only, with STAI/off session choices; alternate artwork remains gated.
2633
+ Review/offline/act-level recovery and
2634
+ artwork variants remain later explicit phases. Native/visual proof is unknown.
2635
+
2636
+ ## Global attention status and CLI (#280, phase 3 in progress)
2637
+
2638
+ Global needs summaries contain only act/watch counts, the known state and the
2639
+ first structural item. Console-local unread messages are excluded at the
2640
+ allowlisted summary boundary. Person review is one act item per in_review task
2641
+ whose reviewer is user; offline ownership is one watch item per offline peer
2642
+ with proposed/in_progress/changes_requested work, using its lowest task id.
2643
+ Only an observed absent runner makes an open recovery operation an act item;
2644
+ an unreadable/unknown runner remains watch. This phase is independent of the
2645
+ owner-held larger artwork/variant selection. Daemon/status.json, existing
2646
+ console input and CLI pet/status wiring and full verification remain pending.
2647
+ No protocol/event schema, authority, mutation, timer or account scope is added.
2648
+
2649
+ The authenticated console-role reply to the existing status request also carries
2650
+ attentionItems, the complete structural global item list, so stream-mode next
2651
+ navigation can reach review/offline ids without a new task-list request. This
2652
+ optional read-only projection contains only the NeedItem allowlist; it is not
2653
+ written to status.json, returned to peer/tools status callers, or sent to memory.
2654
+ The persisted needs field remains counts/state/first, excluding console messages.
2655
+
2656
+ Status task facts are selected once from the board as id/state/owner/reviewer
2657
+ columns, excluding approved rows, and reused for retained off-roster peer ids and
2658
+ attention. No task JSON payload is decoded for this projection. Reserved
2659
+ pseudo-peers user and hub never produce offline-agent attention; a task reviewed
2660
+ by user still produces its normal review action.
2661
+
2662
+ ## Approved terminal characters and sizes (#280, phase 2)
2663
+
2664
+ The owner approved the STAIx reductions and public distribution on 2026-10-13,
2665
+ and selected gyul, lantern, cursor-cat and boxbot. All five built-in characters
2666
+ have complete line/mini/full ASCII and block data; no image is loaded at build
2667
+ or run time. The ASCII STAI line remains byte-compatible. Actual consoles
2668
+ advertise the five choices and P cycles through them and off; older embedding
2669
+ states without advertised choices retain the former STAI/off toggle.
2670
+
2671
+ Mini fits at100 columns, full at100 columns/40 rows, otherwise the next smaller
2672
+ size is used. Full reserves the catalog maximum of eight sprite rows plus the
2673
+ unchanged full-width prompt, independent of state and session character. Mini
2674
+ shares the existing four footer rows. Stream scroll bounds and panels body
2675
+ height use the same footer geometry. Notice/source prose is excluded beside
2676
+ expanded frames. Only a live approval deadline permits the waiting blink;
2677
+ C/dumb/linux/unknown locale surfaces use ASCII even when blocks were requested.
2678
+ Body foreground is uncoloured; only the Gyul leaf uses an existing accent tone.
2679
+ Native terminal/font/tmux proof remains a separate verification leg.
2680
+
2681
+ ## Shared dashboard attention (#280, phase 4)
2682
+
2683
+ The existing authenticated UI snapshot receives an optional allowlisted attention
2684
+ input and enabled/character/blink presentation fields. Status wire/file callers
2685
+ retain their phase3 summary/items projection and never receive this input. The
2686
+ page invokes the same injected needs function on this body-free input, renders
2687
+ the selected built-in full block frame as SVG pixels and exposes state/counts
2688
+ through an accessible button. Its click only reaches an exact visible list row
2689
+ or the relevant heading with fixed structural guidance; no action request occurs.
2690
+
2691
+ DOM writes and title counts follow the derived signature, not every poll. A
2692
+ waiting pulse uses CSS transform/opacity only, with a static reduced-motion and
2693
+ blink-off escape. There is no extra timer, request, route or authority; legacy
2694
+ or invalid snapshots make attention unavailable. Project changes clear stale
2695
+ attention and restore the title. The existing CSP/header policy is unchanged.
2696
+
2697
+ ## Amendment: hub memory, tiers and graph (#258, phase 1)
2698
+
2699
+ Decision 10 is amended: the hub owns a store of its own in `~/.agenthub/memory/`, machine-wide, and claude-mem stays
2700
+ where it is installed as the capture and session-recall source (notes still go to both). Append-only JSONL segments are
2701
+ the truth (`log/<machine>.jsonl` long-term, `local/<machine>.jsonl` short-term and never synced); `index.db` is derived,
2702
+ content-addressed rows inserted idempotently, so an incremental index equals a rebuild in any order. Notes on an open
2703
+ task are short-term; approval copies decision, contract and fail notes to long-term and starts the short-term clock
2704
+ (`memory.short_ttl_days`, 14); `hub_remember` takes `horizon` and `scope`. Deterministic edges (refs, plan paths and
2705
+ symbols, existing paths in the text, `#N`, `task #N`) are fixed at write time. Task briefs, session-start recall and
2706
+ `ahub ask` read the graph first; superseded entries are dropped and a linked fail leads. PII task text never enters the
2707
+ store, and secret-looking text is refused. `ahub memory` reads and, for a person, promotes, demotes, forgets, supersedes
2708
+ and rebuilds; the dashboard's Memory section is read-only inside the existing CSP. On with any project config
2709
+ (`memory.native`). Proposed defaults 1 to 5 of #258 are taken as confirmed by the request to implement it. Machine sync,
2710
+ long-term tasks with leases (decision 9's amendment), claude-mem import and model-suggested edges follow in later phases.
2711
+
2712
+
2713
+ ## Dashboard attention projection (#280, phase 4 in progress)
2714
+
2715
+ The existing dashboard snapshot supplies optional allowlisted needs input and
2716
+ known presentation choices; normal status/file payloads do not gain that input.
2717
+ The header independently projects the shared pure needs function into literal
2718
+ built-in SVG pixels and an accessible state/count label. Unchanged state and
2719
+ choices do not rewrite pet DOM. Clicks navigate only to exact visible rows or
2720
+ related headings, never issue actions or alter filters. Missing/invalid legacy
2721
+ input hides the widget. Project resets clear retained navigation and title.
2722
+
2723
+ The two approved waiting frames alternate in CSS once per second only while
2724
+ a live approval exists. Reduced motion and blink-off remain static. Every other
2725
+ state stays still. No timer/request or new asset dependency is introduced;
2726
+ existing header policy and computed CSP hashes apply.
2727
+ ## Amendment: hub memory between machines and long-term tasks (#258, phase 2)
2728
+
2729
+ Decision 9 is amended for memory only: the memory directory is a git repository that tracks `log/*.jsonl` and syncs
2730
+ through a private remote a person sets (`ahub memory sync --remote`); each machine commits only its own segment and
2731
+ merges others' unrelated histories, so a merge never conflicts. A GitHub remote that `gh` reports public is refused;
2732
+ an unknown one warns. Sync is fail-open (one log line), runs at hub start and every `memory.sync_interval_min`, one at a
2733
+ time per machine. Git calls keep the hub's safe configuration except the person's credential helper, for this
2734
+ repository only. Long-term tasks (`goal`, `goal_state`, `goal_link`, `lease`, `lease_force` entries) carry state,
2735
+ milestones, dependencies and linked board tasks (project, id and proposal time). A hub working on a linked board task
2736
+ holds the lease (4 h, renewed past half) unless another machine holds it; a person's `ahub goal take --force` voids
2737
+ earlier claims. The lease is advisory: claims inside one sync window both stand and show as a conflict, the earlier
2738
+ holding (`ponytail:` no consensus; a broker if concurrent cross-machine work needs one). A peer links its own board task
2739
+ through `hub_task_propose(goal)` to this project's long-term tasks only; a person links across projects. Status, the
2740
+ console at hub start, recall and the dashboard's Long-term tasks tab show state and lease.
2741
+
2742
+
2743
+ Queued planner batches retain bounded ids-only backlog references and recheck
2744
+ the board at actual delivery. A batch containing pulled/removed work is discarded
2745
+ before reaching the planner; its remaining backlog ids join the next batch. This
2746
+ floor also applies during the legacy stale-notice delivery experiment. No task
2747
+ text is copied and no routing/ownership state changes.
2748
+ ## Amendment: claude-mem import, suggested edges and the memory measurement (#258, phase 3)
2749
+
2750
+ `ahub memory import claude-mem` (a person's) copies claude-mem observations whose metadata names a `peer` into
2751
+ long-term hub memory as `source: claude-mem`, opening claude-mem's database read-only and skipping model answers,
2752
+ PII-pattern and secret-looking text; ids are deterministic, so a re-import adds nothing. `memory.suggest_edges` (off by
2753
+ default) lets the hub's model suggest `contradicts` / `same_topic` between a new entry and up to six near ones, checked
2754
+ against that closed list and stored as `hub-model` suggestions; they are drawn dashed and excluded from briefs, recall
2755
+ and `ahub ask` until a person confirms them. Measurement: `memory_brief` events (counts), research records' `briefs`
2756
+ and the report's by-memory-brief split, and `ahub bench run --memory off|claude-mem|native|both` arms checked against
2757
+ the project's settings. Whether hub memory helps stays a research result, not an acceptance claim.
2758
+
2759
+
2760
+ Planner notice retries are per recipient. A stale copy requeues current backlog
2761
+ ids only for the planner whose copy was discarded; a planner that already read
2762
+ its original copy is not sent the retry. Queue overflow returns that recipient's
2763
+ ids to pending state on the existing bus event, including immediate eviction
2764
+ during publication. Pending ids are removed before publication so overflow can
2765
+ restore them; no extra timer, route, ownership change or task text is introduced.
2766
+
2767
+ ## Automatic control port exclusion (#375)
2768
+
2769
+ When controlPort is zero, the daemon excludes requested positive Codex app and
2770
+ proxy ports from its automatic listener selection. A rejected owned listener
2771
+ stays bound until a distinct replacement is selected; only these temporary
2772
+ listeners are closed, including on binding failure. Selection is bounded by
2773
+ the number of excluded ports plus one. Explicit control-port behavior and
2774
+ existing Origin/token/native ownership refusals remain unchanged.
2775
+
2776
+ Split child external-use checks include persisted SDLC phase checklist task ids and predecessor ids, as well as Tasks dependency edges. An undo preserves referenced children and the original board when it refuses.
2777
+
2778
+ Declining rework in changes_requested returns it to proposed before rerouting, just as declining in_progress work does. The Board permits that transition; the Tasks owner/person authority remains required. Planner-pulled work without destination WIP is retried from To Do once capacity becomes available.
2779
+
2780
+ Split undo preserves children referenced by persisted task-scoped execution budgets. The person may disable the budget through the existing budget action before undoing otherwise-unused children; a run-scoped budget alone is not a child reference.
2781
+
2782
+ Split screening retains the initial deterministic child and inherited parent privacy signals across asynchronous screening and final policy revalidation. Removing a routing pattern while a screen is pending cannot publish an unscreened private child or invent a new screening verdict.
2783
+
2784
+ Final deterministic split signals also determine classification provenance. A pattern added during a pending model screen records regex-private history/telemetry instead of retaining an obsolete clear model verdict; inherited parent privacy remains distinct.
2785
+
2786
+ The outer dashboard HTTP request for backlog_split receives a per-request idle bound above the manager forwarding deadline, derived from the shared screen and hub database bounds plus margin. Other actions retain their existing HTTP policy. The boundary regression observes actual native timeout allocation; Bun 1.4.2 pending-handler idle expiry is not assumed.
2787
+
2788
+ Split reasons retain deterministic privacy from both initial validation and final revalidation, including inherited parent privacy. Later routing policy removal cannot expose an already-withheld reason in public history.
2789
+
2790
+ Ask evidence ignores body-free memory-reference bookkeeping when selecting the latest task event and note. The selected meaningful note retains its PII and withheld provenance under the existing on-campus boundary.
2791
+
2792
+ GitHub intake rechecks its total staging deadline after every awaited proposal, including the final issue. A late confirmed write returns its ID with partial=true and complete=false; it is not represented as an unconfirmed write or rolled back.
2793
+
2794
+ After a confirmed GitHub task insertion, failure in later bookkeeping triggers canonical source-identity readback. A recovered row is returned among imported IDs with partial=true/complete=false; unavailable readback remains unconfirmed. A recovered backlog row is queued for the planner notice even when earlier bookkeeping prevented the normal enqueue.
2795
+
2796
+ The per-issue intake failure boundary includes existing-row lookup and profile preparation as well as proposal staging, so a later lookup failure retains prior confirmed IDs in the partial response.
2797
+
2798
+ Release snapshots group scope rows once and read approval dates once per task. Cross-release audit previews contain at most 32 IDs per category plus exact counts, with truncation disclosed in the UI. Sorted date indexes preserve strict after-cut semantics without rescanning every task history for every release. Full audit pagination remains a future extension.
2799
+
2800
+ Release-card invalidation includes the task-state snapshot, so approval of a prerequisite outside the release refreshes blocked counts even when the release row and audit preview are unchanged.