@staix/agent-hub 0.12.30 → 0.12.32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/README.md +29 -9
  3. package/docs/agent-notes/adapters.md +9 -5
  4. package/docs/agent-notes/budget.md +1 -1
  5. package/docs/agent-notes/bus.md +5 -0
  6. package/docs/agent-notes/daemon.md +14 -8
  7. package/docs/agent-notes/local-worker.md +3 -1
  8. package/docs/agent-notes/tasks.md +7 -1
  9. package/docs/agent-notes/tests.md +6 -2
  10. package/docs/cooperbench.md +1 -1
  11. package/docs/gsd-collaboration-analysis.md +1 -1
  12. package/docs/memory.md +2 -2
  13. package/docs/operations.md +236 -37
  14. package/docs/quickstart.md +24 -5
  15. package/docs/security.md +42 -10
  16. package/docs/smoke.md +34 -0
  17. package/docs/specs/2026-09-19-agent-hub-design.md +241 -3
  18. package/docs/specs/2026-09-20-upgrade-recovery-design.md +275 -10
  19. package/docs/verification/2026-10-17-0.12.31.md +71 -0
  20. package/docs/verification/2026-10-17-418-probes.md +21 -0
  21. package/docs/verification/2026-10-18-0.12.32.md +54 -0
  22. package/docs/verified.json +20 -15
  23. package/package.json +2 -2
  24. package/plugins/agent-hub/.claude-plugin/plugin.json +1 -1
  25. package/plugins/agent-hub/server.js +1361 -44
  26. package/src/adapters/acp.ts +5 -6
  27. package/src/adapters/claude-channel.ts +29 -11
  28. package/src/adapters/definitions/builtin-metadata.ts +121 -0
  29. package/src/adapters/definitions/kimi-native.ts +4 -0
  30. package/src/adapters/definitions/qwen-native.ts +24 -0
  31. package/src/adapters/definitions/qwen.ts +71 -0
  32. package/src/adapters/local-worker.ts +2 -2
  33. package/src/adapters/pi.ts +11 -2
  34. package/src/adapters/registry-types.ts +174 -0
  35. package/src/adapters/registry.ts +36 -0
  36. package/src/cli/attention.ts +5 -1
  37. package/src/cli/console-state.ts +130 -17
  38. package/src/cli/console.ts +54 -8
  39. package/src/cli/help.ts +3 -1
  40. package/src/cli/identity.ts +16 -5
  41. package/src/cli/jcode-mcp.ts +1 -1
  42. package/src/cli/launch.ts +1 -6
  43. package/src/cli/main.ts +208 -40
  44. package/src/cli/output.ts +15 -2
  45. package/src/cli/preview.ts +8 -5
  46. package/src/cli/recovery-guidance.ts +137 -0
  47. package/src/cli/recovery-presentation-options.ts +8 -0
  48. package/src/cli/recovery-session-file.ts +18 -0
  49. package/src/cli/terminal-recovery.ts +48 -0
  50. package/src/cli/upgrade-interactive.ts +129 -74
  51. package/src/cli/upgrade-labels.ts +30 -0
  52. package/src/cli/upgrade-presentation-data.ts +41 -0
  53. package/src/cli/upgrade-presentation-flags.ts +31 -0
  54. package/src/cli/upgrade-presentation.ts +217 -0
  55. package/src/cli/upgrade-restore-state.ts +137 -0
  56. package/src/cli/upgrade-runtime.ts +430 -175
  57. package/src/cli/upgrade.ts +325 -49
  58. package/src/hub/board.ts +82 -24
  59. package/src/hub/bus.ts +89 -29
  60. package/src/hub/check-runner.ts +514 -0
  61. package/src/hub/child-process.ts +1 -0
  62. package/src/hub/cohorts.ts +2 -2
  63. package/src/hub/config-apply.ts +242 -0
  64. package/src/hub/config-reload.ts +120 -0
  65. package/src/hub/config-trust.ts +11 -2
  66. package/src/hub/control-client.ts +5 -1
  67. package/src/hub/crash.ts +8 -6
  68. package/src/hub/daemon.ts +931 -209
  69. package/src/hub/delivery-hints.ts +30 -0
  70. package/src/hub/delivery-journal.ts +185 -12
  71. package/src/hub/delivery-superseded.ts +52 -0
  72. package/src/hub/envelope.ts +1 -1
  73. package/src/hub/events.ts +2 -2
  74. package/src/hub/host-executable.ts +11 -0
  75. package/src/hub/hub-tools.ts +9 -1
  76. package/src/hub/manager.ts +1 -1
  77. package/src/hub/peer-catalog.ts +13 -13
  78. package/src/hub/peers.ts +12 -2
  79. package/src/hub/permission-mode.ts +5 -3
  80. package/src/hub/recovery-continuity.ts +152 -0
  81. package/src/hub/recovery-store.ts +10 -4
  82. package/src/hub/routing.ts +35 -16
  83. package/src/hub/sdlc.ts +5 -1
  84. package/src/hub/settings.ts +52 -37
  85. package/src/hub/settled-roles.ts +35 -0
  86. package/src/hub/spec-read.ts +120 -0
  87. package/src/hub/supervision.ts +24 -8
  88. package/src/hub/task-sweep.ts +7 -6
  89. package/src/hub/tasks.ts +199 -40
  90. package/src/hub/ui.ts +1 -1
  91. package/src/memory/brief.ts +6 -5
  92. package/src/memory/capture.ts +2 -1
  93. package/src/pi/session.ts +23 -4
  94. package/src/ui/index.html +35 -16
  95. package/src/ui/needs.ts +7 -5
  96. package/src/ui/office-model.ts +4 -1
  97. package/src/ui/task-board.ts +1 -1
  98. package/src/ui/task-progress.ts +6 -2
  99. package/templates/AGENTS.block.md +1 -1
  100. package/templates/profiles/general.json +1 -1
  101. package/templates/profiles/research.json +1 -1
  102. package/templates/profiles/writing.json +1 -1
@@ -249,11 +249,36 @@ itself is not distinguished from a slow one, and whether Orca reports the bare
249
249
  login shell as TUI-idle is not verified: if it does, the create stops at once as
250
250
  not mappable to the session; if not, after the 10-minute readiness bound. Either
251
251
  way it blocks as needing manual verification with the receipt `pending`, and the
252
- next resume, finding no live launcher and no attached session, records `failed`. Resume settles a `pending` or `failed` receipt by what is live
253
- (the table below): an attached planned (or accepted) session is the
254
- restoration, a launcher that may run is waited for, and only nothing live makes
255
- it `failed` or, for `failed`, launches again. No terminal is created while a
256
- recorded launcher for the peer may run on the target or its session is attached.
252
+ next resume, finding no live launcher and no attached session, records `failed`.
253
+ After a new terminal becomes ready, or a `pending` or `failed` receipt finds a
254
+ verified live launcher of the current target, the coordinator saves that exact
255
+ handle, incarnation and worktree before waiting up to 600 seconds for the
256
+ planned (or accepted) session to attach. The restore receipt is an explicit
257
+ tagged union: `pending`, `waiting` with `origin` (`pending` for a new launch, or
258
+ `failed`) and `binding`, `done` with `binding`, or `failed`. A missing receipt
259
+ means no launch has been attempted. Only the compatibility decoder reads released older
260
+ string/bare-binding receipts; new writes use the tagged states. The never-released
261
+ development attachmentReceipt marker is refused rather than inferred as a state. Interruption and
262
+ timeout retain the waiting receipt, and resume waits on that binding without
263
+ adopting a replacement.
264
+ An idle terminal alone is not attachment proof. Each poll checks the selected
265
+ launcher's signed identity. Only that exact launcher being gone and the target
266
+ reporting no attached session or other live launcher exits the wait: a
267
+ pending-origin wait records `failed` and exposes the failed-restoration choices;
268
+ a failed-origin wait returns to `failed` and retries the launch. A launcher
269
+ record not written yet keeps polling within the same bound. A signed ended row
270
+ for a different handle is not a current record for the chosen terminal. An
271
+ attached session with no id keeps that same wait after all older-launcher
272
+ checks; an offline saved id does not count as attachment or bypass those
273
+ checks. A current record arriving between observations continues polling only
274
+ when its handle, incarnation and worktree match the saved binding. Unknown
275
+ records and live replacements still block. An unreadable launcher identity, changed
276
+ terminal binding or unreadable target blocks without recording failure.
277
+ Successful attachment records `done` after exact terminal/session revalidation.
278
+ A `done` receipt only revalidates its saved binding; an exited launcher cannot
279
+ turn it into `failed` or offer a fresh session. No terminal is
280
+ created while a recorded launcher for the peer may run on the target or its
281
+ session is attached.
257
282
  A launch that failed, or a thread found not resumable before the launch, is
258
283
  receipted `restored:<peer>` = `failed` and never counts as restored. A Codex
259
284
  store that cannot be read (other than missing) is unknown and blocks the plan,
@@ -268,7 +293,7 @@ Status. `ahub recovery status <id>` reports the receipt (phase, step, update
268
293
  time, error); whether a runner process holds the operation now (`runner.state`
269
294
  `running` with its pid, or `none`); `stale` when the receipt says `running` but
270
295
  no runner holds it; each project's phase and effect receipts (`closed:<peer>`,
271
- `restored:<peer>` as `done`, `pending` or `failed`); whether the shared plugin
296
+ `restored:<peer>` as `done`, `pending`, `waiting:pending`, `waiting:failed` or `failed`); whether the shared plugin
272
297
  and the global CLI were installed; any lost continuity and disposition; and
273
298
  `next`, the commands that apply now. It never contains task or message text.
274
299
  `resume` does not start a second runner while one is alive.
@@ -439,9 +464,9 @@ An attached session is the target's report of that peer online with a thread
439
464
  | project `prepared`, no `commitSent`, operation of a #215 coordinator | source stopped (crashed before any commit request) | blocks; the phase stays `prepared` (nothing was committed, so there is nothing to start from); not offered | abort if no effects, dispose | `<c> recovery abort <id>` without effects, else stop-and-archive (the lock refuses starting that hub by hand) |
440
465
  | project `prepared` | source unavailable, starting, stopping or not inspected | as above when it reads again | none: abort (its hold may still stand) and stop-and-archive are refused until it reads | `<c> recovery status <id>` once it answers |
441
466
  | project `prepared`, operation of an older coordinator (no `commitSent` written) | source not running, or not inspected | as its own runner does | dispose once it reads running, stopped or missing; abort neither offered nor accepted (it may have committed) | `<c> recovery status <id>` |
442
- | project `started` or `peers-restored` | target stopped (a crash or reboot after it started), this operation's snapshot kept | records the restart (dead instance, time), retires the dead instance's done `restored:<peer>` receipts, moves the project back to `stopped` and starts the target from the snapshot; once per resume | dispose | `the target stopped after it started; resume restarts it from this operation's snapshot` (`stopped again after restart <n> in this resume` when it stops again) |
467
+ | project `started` or `peers-restored` | target stopped (a crash or reboot after it started), this operation's snapshot kept | records the restart (dead instance, time), retires the dead instance's done and waiting `restored:<peer>` bindings, moves the project back to `stopped` and starts the target from the snapshot; once per resume | dispose | `the target stopped after it started; resume restarts it from this operation's snapshot` (`stopped again after restart <n> in this resume` when it stops again) |
443
468
  | project `started` or `peers-restored` | target stopped, snapshot gone | blocks; not offered | dispose | `this operation's restart snapshot is gone, so nothing can start it` |
444
- | `retired:<peer>` (a done restoration of a dead target instance) | Orca lists its terminal, or cannot be read | closed under the close receipt rules (`closedRetired:<peer>` `pending` until Orca no longer lists it); an unreadable inventory changes nothing | dispose | `close Orca terminal <handle> by hand` or `check it in Orca`, `then <c> recovery resume <id>` |
469
+ | `retired:<peer>` (a done or waiting restoration of a dead target instance) | Orca lists its terminal, or cannot be read | closed under the close receipt rules (`closedRetired:<peer>` `pending` until Orca no longer lists it); an unreadable inventory changes nothing | dispose | `close Orca terminal <handle> by hand` or `check it in Orca`, `then <c> recovery resume <id>` |
445
470
  | project `stopped` | target stopped without this operation's snapshot (never committed) | blocks; not offered | dispose | `the target is stopped and this operation's restart snapshot is gone` |
446
471
  | project `stopped`, `started` or `peers-restored` | target running unfenced, as another instance or another version | blocks; not offered | dispose | `daemon is not owned by this recovery operation` (or `daemon instance changed`, `target daemon version mismatch`) |
447
472
  | any, at staging | preserved source or staged target changed, or (first staging of these bytes only) target protocol or recovery waivers refused | blocks; recorded as `final`, so resume is never offered again | abort if no effects, dispose | the refusal |
@@ -451,7 +476,14 @@ An attached session is the target's report of that peer online with a thread
451
476
  | `closed:<peer>` done | peer attached again | blocks | dispose | `end that <peer> session, then <c> recovery resume <id>` |
452
477
  | `restored:<peer>` `pending` or `failed` | session attached with the planned id (or an accepted new one: fresh choice, planned fresh start, zero-turn Claude) | recorded as restored | none: `--fresh-session` is neither offered nor accepted while the inspection shows the planned session attached; when it cannot tell (not inspected, target unreadable), the `failed` receipt alone decides, and a chosen fresh session whose original then attaches is cleared on resume while its audit entry stays | none |
453
478
  | `restored:<peer>` `pending` or `failed` | another session attached | blocks | dispose | `end that <peer> session and close its terminal, then <c> recovery resume <id>` |
454
- | `restored:<peer>` `pending` or `failed` | no session, recorded launcher live or unknown | blocks | dispose | `wait until it attaches, or end it and close terminal <handle>, then <c> recovery resume <id>` |
479
+ | `restored:<peer>` `pending` or `failed` | no session, verified live launcher of the current target | records `waiting {origin, binding}` with the exact binding, waits up to 600 s for authenticated attachment; timeout retains both for resume | dispose | `attachment not verified within 600 s; terminal <handle> retained; resume after it attaches` |
480
+ | `restored:<peer>` `pending` or `failed` | no session, a live launcher belongs to an older target instance | blocks, retains the original receipt; no terminal created | dispose | end that launcher and close its terminal, then `<c> recovery resume <id>` |
481
+ | `waiting {origin, binding}` | the planned or accepted session attaches | runs the ordinary settlement rules, writes a waiver for an accepted replacement or clears `fresh` when the planned session returns, exactly revalidates the selected terminal and clears the waiting origin | none while the planned session is attached | none |
482
+ | `waiting {origin, binding}` | selected launcher gone, but an older target instance's launcher remains live or unknown | blocks and retains the selected binding and waiting origin; no failure or retry is inferred | dispose | end or verify the older launcher, then `<c> recovery resume <id>` |
483
+ | `waiting {origin, binding}` | selected exact signed launcher gone, target confirms no session or other live launcher | pending origin (including a new launch): records `failed` and blocks; failed origin: records `failed` and retries the launch | fresh session (Codex, Claude), dispose | the failed-restoration choices below |
484
+ | `waiting {origin, binding}` | selected identity unreadable, replacement terminal, or target unreadable | blocks, retains exact binding and waiting origin; never adopts a replacement or treats unknown as gone | dispose | verify the saved launch or target, then `<c> recovery resume <id>` |
485
+ | `waiting {origin, binding}` | no current launcher record (including a confirmed-ended other-handle row), with no session or an id-less attachment and no older live/unknown launcher | polls within the same 600 s bound; timeout retains waiting | fresh-session only for waiting:failed (subject to ordinary choices), dispose | `waiting:<origin>`; resume uses the same exact binding |
486
+ | `done {binding}` | launcher gone or no session attached | blocks exact restoration verification, retains done and its resumable conversation; never launches again or records failed | dispose; no fresh-session | resume the recorded conversation; `done` |
455
487
  | `restored:<peer>` `pending` | no session, launcher gone or never recorded | receipted `failed`, blocks | fresh session (Codex, Claude), dispose | the failed-restoration choices below |
456
488
  | `restored:<peer>` `failed` | no session, launcher gone or never recorded | launches again (fresh if chosen) | fresh session (Codex, Claude), dispose | the failed-restoration choices below |
457
489
  | `restored:codex` absent | rollout missing | receipted `failed`, blocks, no terminal created | fresh session, dispose | the failed-restoration choices below |
@@ -463,6 +495,49 @@ An attached session is the target's report of that peer online with a thread
463
495
  | disposition recorded, not finished | any | refused | stop-and-archive only | `rerun <c> recovery dispose <id> --stop-and-archive --reason <text>` where `disposeRefusal` allows it, else `wait until <project>'s hub settles, then <c> recovery status <id>` |
464
496
  | `completed` or `cancelled` | any | nothing to do | none | none |
465
497
 
498
+ The restore transition function is `restoreTransition` in
499
+ `src/cli/upgrade-restore-state.ts`. Its generated table below is checked byte for
500
+ byte by `test/upgrade-restore-state.test.ts`; the Cartesian test separately
501
+ checks all 540 receipt/evidence/choice cells. `settle` and `revalidate` propose a
502
+ state only: the runtime commits it after authenticated session and exact
503
+ terminal validation. Fresh-session eligibility is shared by status, interactive
504
+ operation lines and refusal messages: only `failed` and `waiting:failed` expose
505
+ it, further narrowed by Pi, an existing choice, a planned fresh start, target
506
+ waiver support and the planned session already being attached.
507
+
508
+ Restore transition table (generated).
509
+
510
+ Cells show action -> next receipt status. Fresh-session eligibility is marked fresh; peer/operation-specific restrictions still apply. Exact terminal revalidation and settlement must succeed before persisting a proposed done receipt.
511
+
512
+ | Priority condition | Decision |
513
+ |---|---|
514
+ | Target stopped or changed | block -> unchanged |
515
+ | Running target, other session not allowed | block -> unchanged |
516
+ | Absent receipt | unstarted; initial launch is handled by the runtime outside this receipt table |
517
+ | Done, running target, no attached session, gone launchers and positively gone saved terminal (#463 supplemental evidence) | reattach -> failed; one recorded-session repair, no fresh-session choice |
518
+
519
+ Running target, no attached session (either allowOther value):
520
+
521
+ | Receipt | live | gone | unknown | no-record-yet | replaced | older-instance |
522
+ |---|---|---|---|---|---|---|
523
+ | pending | poll -> waiting:pending | fail -> failed; fresh | block -> pending | fail -> failed; fresh | block -> pending | block -> pending |
524
+ | waiting:pending | poll -> waiting:pending | fail -> failed; fresh | block -> waiting:pending | poll -> waiting:pending | block -> waiting:pending | block -> waiting:pending |
525
+ | waiting:failed | poll -> waiting:failed; fresh | create -> failed; fresh | block -> waiting:failed; fresh | poll -> waiting:failed; fresh | block -> waiting:failed; fresh | block -> waiting:failed; fresh |
526
+ | done | block -> done | block -> done | block -> done | block -> done | block -> done | block -> done |
527
+ | failed | poll -> waiting:failed; fresh | create -> failed; fresh | block -> failed; fresh | create -> failed; fresh | block -> failed; fresh | block -> failed; fresh |
528
+
529
+ Running target, planned session or explicitly allowed other session (different decisions are labeled):
530
+
531
+ | Receipt | live | gone | unknown | no-record-yet | replaced | older-instance |
532
+ |---|---|---|---|---|---|---|
533
+ | pending | settle -> done | settle -> done | settle -> done | settle -> done | settle -> done | settle -> done |
534
+ | waiting:pending | settle -> done | settle -> done | block -> waiting:pending | settle -> done | block -> waiting:pending | block -> waiting:pending |
535
+ | waiting:failed | settle -> done | settle -> done | block -> waiting:failed; fresh | settle -> done | block -> waiting:failed; fresh | block -> waiting:failed; fresh |
536
+ | done | planned: revalidate -> done; other: block -> done | planned: revalidate -> done; other: block -> done | planned: revalidate -> done; other: block -> done | planned: revalidate -> done; other: block -> done | planned: revalidate -> done; other: block -> done | planned: revalidate -> done; other: block -> done |
537
+ | failed | settle -> done | settle -> done | settle -> done | settle -> done | settle -> done | settle -> done |
538
+
539
+ End of generated restore transition table.
540
+
466
541
  The failed-restoration choices are `<c> recovery dispose <id> --fresh-session
467
542
  <peer> --reason <text>` (Codex or Claude; records the lost session and resumes;
468
543
  if the original session attaches after all, the recorded loss is cleared) and
@@ -490,7 +565,7 @@ replaces the record of a Codex already running.
490
565
  #225: a target that stopped after it started is restarted only while its state
491
566
  directory holds this operation's unreleased snapshot. The runner records the restart
492
567
  in the project's receipt (`restarts`: the dead instance and the time) before acting,
493
- moves each done `restored:<peer>` binding to `retired:<peer>`, clears the instance
568
+ moves each done or waiting `restored:<peer>` binding to `retired:<peer>`, clears the instance
494
569
  and moves the project back to `stopped`, whose path starts the target from the
495
570
  snapshot; the journal imports the snapshot only at revision 0, so the second start
496
571
  continues from what the first wrote. `closed:<peer>`, `commitSent`, `fresh`, waivers
@@ -584,3 +659,193 @@ front end to the commands above, never a second coordinator.
584
659
  - Out of scope: a hub-side interrupt of a running turn (the running source may
585
660
  be older and would not know the request), and answering approvals from the
586
661
  screens.
662
+
663
+
664
+ ### Post-restore detachment and recorded-session reattachment (#463)
665
+
666
+ A done restore receipt remains done for an offline peer unless both independent
667
+ proofs hold on the same running target instance: every relevant launcher is gone,
668
+ including older target instances, and the exact saved terminal is positively
669
+ orphaned or missing. Disconnection alone, an unreadable or truncated inventory,
670
+ unknown launch records, changed terminal identity and a different attached session
671
+ never authorize a replacement.
672
+
673
+ The pure restore table has one additional rule: done + running target + no attached
674
+ session + gone launchers + positively gone saved terminal proposes reattach ->
675
+ failed. The original 540 cells with no new evidence remain unchanged. Before
676
+ returning the block, the runtime saves a per-project, per-peer reattachment marker
677
+ with the accepted done binding, detection time, fixed cause `detached after restore`
678
+ and state `ready`, plus the failed restore receipt and `started` project phase.
679
+ The blocked operation identifies that project and peer structurally, never by
680
+ parsing error text.
681
+
682
+ Resume reuses the ordinary restore path with that accepted conversation, session
683
+ file, backend and model. Before any new terminal effect the marker becomes
684
+ `attempted`. Chosen waiting bindings remain durable and reuse the existing 600 s
685
+ attachment bound; an interruption cannot grant another create. A second detach or
686
+ an exhausted attempt blocks with its recorded cause. These repairs default to
687
+ recorded-session-only continuity: no automatic fresh/zero-turn replacement is
688
+ introduced. Only the explicit missing-history exception below permits a person
689
+ to select a replacement. Strict session/file checks remain for repairs;
690
+ ordinary verified-empty Pi attachments retain their pre-existing id-only rules.
691
+ When `recordRestart` retires a known done or waiting binding from a dead target,
692
+ it clears that binding's repair fence. The normal #225 relaunch preserves its
693
+ accepted conversation and a new target gets its own repair allowance. The additive
694
+ per-peer `repairedSessions: true` provenance survives this fence reset and repeated
695
+ restarts. It authorizes no creation: accepted done/retired bindings remain the
696
+ session source, and fresh-session choices and zero-turn substitutions remain
697
+ excluded automatically for that repaired conversation. A person may explicitly
698
+ choose `dispose --fresh-session` for a failed repaired Codex or Claude conversation only after
699
+ the coordinator records a typed positive missing-transcript/rollout observation
700
+ bound to the accepted session, and disposal rechecks that same recorded store as
701
+ missing before writing the loss and audit. Found, unreadable, malformed or absent
702
+ evidence never permits this choice. The choice records the accepted conversation
703
+ as lost; it does not run a terminal. The receipt also records
704
+ `freshOverride {peer, evidence, checked, at}`, exposed in person status and the
705
+ archive summary. New missing observations and overrides include `checkedPath`: the
706
+ exact Claude transcript file or recursively searched Codex sessions directory.
707
+ The lookup and display share the same captured-environment/default-home path
708
+ resolver; this is evidence of that checked location, not proof of every native
709
+ store layout. Refusals name the checked location as well. Resume retains the existing launcher fences,
710
+ close-before-create and waiver rules. An uncertain
711
+ creation with no durable selected binding does not gain a second creation by
712
+ merely losing the target. Database contention retains its typed retryable outcome.
713
+
714
+ Repaired missing-history disposal is never delegated under `--live-test`.
715
+ Because ordinary #408 fresh disposal uses the same argv and remains delegable,
716
+ the CLI first classifies the already-loaded receipt read-only. An unreadable,
717
+ unparseable or unclassifiable receipt, including a peer absent from its projects,
718
+ refuses delegation. A repaired override is refused before runner/lock acquisition
719
+ or coordinator mutation. Core repeats the trusted per-invocation delegation
720
+ check before the lock and after its under-claim read. No model/request field
721
+ can grant person authority, and no new public waiver flag is introduced.
722
+
723
+ Pi remains excluded from fresh-session under #215. For a positively missing
724
+ accepted Pi session file, blocked guidance prints the operation's
725
+ `recovery dispose <id> --stop-and-archive --reason <text>` command and then
726
+ `ahub --project <root> pi`. The normal Pi start retires a proven-unresumable
727
+ archived bookmark without falling back fresh in that same start; its notice
728
+ guides a subsequent normal start. The Pi fresh-session refusal itself prints
729
+ the same stop-and-archive and project-scoped start commands. Unreadable or invalid
730
+ evidence stays held.
731
+
732
+ The person-only `ahub recovery reattach <operation> <peer>` is admitted only for
733
+ that operation's current structured reattachment block. It claims the existing
734
+ runner fence, rechecks the held target and restores only the selected peer. It
735
+ accepts no session override, performs no release or installation, and leaves the
736
+ remaining operation for resume. Agent shells and live-test delegation cannot
737
+ invoke this person decision. Person status and block guidance list the recorded
738
+ Codex thread, Pi session file and Claude session with quoted commands from the
739
+ operation's coordinator.
740
+
741
+ Status guidance, the archive summary and the Pi continuity bookmark share one
742
+ accepted-binding resolver: restored done/waiting, then a validated reattachment
743
+ marker, then a decoded retired binding for this peer and project, then the plan.
744
+ A malformed retained binding is unavailable, never permission to fall back to an
745
+ older conversation. This includes the accepted Pi file, backend and model after
746
+ a #225 target restart.
747
+
748
+ Stop and archive retains the operation's accepted session identities. After a
749
+ confirmed owned target stop and snapshot archive, it may write one private,
750
+ project-bound Pi continuity bookmark. The next normal `pi.auto_start` passes that
751
+ recorded identity through the existing start-mode and lifecycle path; it never
752
+ falls back fresh because a bookmark is invalid or unreadable. The bookmark is
753
+ consumed only after authenticated attachment proves the same session and file,
754
+ not merely after opening a terminal. Atomic compare/consume cannot remove a newer
755
+ operation's bookmark. No global operation-directory scan or native probe is used
756
+ to discover sessions. The person summary distinguishes historical target startup,
757
+ plugin installation and the remaining global CLI installation, and continues to
758
+ say abandoned, not completed or rolled back.
759
+
760
+ A missing, expired, unreadable or foreign snapshot prevents a continuity bookmark,
761
+ not stop-and-archive itself. Disposal records a per-project continuity warning and
762
+ still releases its machine lock. An actual rename failure of this operation's own
763
+ snapshot retains the existing failure and retry path. Optional bookmark storage
764
+ failure is recorded as unavailable rather than blocking this last-resort exit.
765
+
766
+ A valid bookmark is archived with a structured reason under its exact CAS when a
767
+ different authenticated Pi session becomes the saved crash record, its recorded
768
+ session is proven unresumable, or a later recovery successfully releases the
769
+ project. Unknown I/O or provider failures do not prove an unresumable session.
770
+ Malformed or unverifiable bookmark evidence remains fail-closed. The TUI resume
771
+ argv carries `--session-file` when available, otherwise `--session-id`, never both.
772
+
773
+ ### Continuity retirement follow-up (#463)
774
+
775
+ An externally retired or replaced bookmark invalidates the daemon's cached copy.
776
+ A failed compare-and-swap re-reads the private bookmark; absence drops the old
777
+ in-memory selection, while newer or unreadable evidence remains distinct from
778
+ absence. Session recording writes `sessions.json` only when its serialized peers
779
+ change. Settlement may use an already durable unchanged crash record but may not
780
+ retire continuity before that record was successfully written. No offline-Pi event
781
+ forces a redundant write. A header whose session id disagrees with the selected
782
+ bookmark is `bookmark_mismatch` (bookmark inconsistent), not evidence that the
783
+ session itself cannot resume. Archival remains non-destructive and never starts
784
+ a fresh session.
785
+
786
+ Repeated Pi continuity settlement storage failures back off for 30 seconds for
787
+ the same bookmark digest and authenticated peer generation/metadata. A new
788
+ digest or authenticated identity can retry immediately; successful settlement
789
+ clears the failure. An unchanged failure logs once, without session-file churn.
790
+
791
+ ## Recovery presentation (#466)
792
+
793
+ Interactive upgrade and recovery screens reuse the console's Span tones, paint,
794
+ measured wrapping and resolveColor precedence. Auto uses TTY and environment
795
+ rules; explicit always has exactly the console's behaviour, including on a pipe.
796
+ Default and never retain existing piped, dry-run, status and dispose JSON bytes.
797
+ Raw JSON, including [j] and --json, bypasses paint and width handling. Human plan,
798
+ progress, error, menu and summary lines fit the measured terminal width.
799
+ The #272 simulated-TTY golden moves to this #466 presentation contract; its
800
+ restart identity, board and non-TTY byte assertions remain unchanged.
801
+
802
+ Only nextChoices supplies operation actions. Presentation may annotate a choice
803
+ as recommended or disabled, but cannot create an action, bypass a refusal or run
804
+ a driver. Enter defaults only to a read-only action; applying, resuming or
805
+ reattaching requires the explicit action key. Preserve the full human wait
806
+ condition from nextChoices, replacing only its retained status command in normal
807
+ output. Existing commands through io.run remain the only mutation path. A
808
+ destructive choice names its stop/abandon consequence before confirmation. Resume
809
+ really runs stage again, labelled "checking retained release"; the screen reports
810
+ only work observed on that attempt and keeps internal coordinator paths verbose.
811
+
812
+ Operation receipts may add read-only wait timing metadata with ISO waitStartedAt,
813
+ deadlineAt and waitEndedAt values. The coordinator records them at the actual
814
+ prepare and awaitAttachment wait boundaries. They do not set or extend any
815
+ deadline, change controls, alter the 540-cell transition oracle or its supplemental
816
+ matrix, or turn unknown evidence into a decision. Older receipts say "timing
817
+ unknown"; updatedAt is never substituted for the actual wait start.
818
+ Each new runner attempt clears the previous timing projection before observing
819
+ its own waits, so a resumed step cannot display a previous wait as current.
820
+
821
+ Preservation errors carry a typed cause from the exact queue, manual-pause,
822
+ task-board and budget integrity comparisons. What/Why/What-to-do is rendered from
823
+ that cause and recorded recovery guidance, never inferred by parsing a combined
824
+ error string. A read-only end-inspection port may supply current runtime state to
825
+ the human summary; a failed readback is unknown. Summary rendering performs no
826
+ lifecycle action and distinguishes recorded installation effects from current
827
+ runtime observations. Older readers ignore the optional presentation metadata.
828
+
829
+ Current native terminal, session, launcher, target and attachment-timeout guards
830
+ may record a closed presentation cause containing only the actual IDs, states
831
+ and wait window observed at that guard. A repair wrapper retains only a proven
832
+ inner presentation error. Generic errors and lookalike objects remain untyped;
833
+ their messages are never classification input. This metadata changes no guard,
834
+ error message, restoration receipt transition or permission to create a terminal.
835
+
836
+ Presentation timing writes are best-effort observations: retain their in-memory
837
+ values, log a fixed warning on a metadata write failure and continue. Ordinary
838
+ receipt/effect writes remain authoritative and fail normally. A newly observed
839
+ blocked or completed step with no measured start has unknown elapsed time, never
840
+ an invented zero. Waiting prints on a changed condition plus at most one elapsed
841
+ tick per minute. Screen-owned recovery children keep stdout quiet on capable
842
+ coordinators so the parent alone renders progress and outcome. All external
843
+ renderer values containing line breaks or controls are visibly quoted before
844
+ wrapping; they cannot become new column-zero guidance. Colour flags follow the
845
+ console grammar exactly: a single `--color=<mode>`, never a bare or repeated flag.
846
+
847
+ Recovery authorization and the presentation parser share the pure
848
+ `recoveryPresentationFlag` classifier. Authorization identifies the action after
849
+ skipping the accepted one-shot presentation flags (`--json`, `--verbose`, `--color=<mode>`). Such flags never hide
850
+ person-only reattachment from agent or live-test refusal checks; normalization
851
+ confers no authority and unknown flags still fail the command parser.
@@ -0,0 +1,71 @@
1
+ # 0.12.31 release verification
2
+
3
+ This record covers release preparation and source review. It does not claim publication, installation, a running-hub restart or native/live acceptance.
4
+
5
+ ## Candidate
6
+
7
+ Version 0.12.31, control protocol 16 (`src/hub/control-client.ts`), from merged main `09bfd51b5c00b9e8e584693cef135cc2f21ad3a7`. The candidate includes all 14 PRs merged since `v0.12.30`: #435, #436, #440, #442, #443, #444, #448, #453, #454, #456, #458, #459, #460 and #461. Every body and final head was read back; intermediate PR evidence is historical where the final head differs. The exact first-party memory pin remains `@staix/agent-mem` 0.3.0.
8
+
9
+ - After upgrade, run `ahub jcode --mode headless` once per Jcode project before conductor or dashboard starts of Jcode to update the owned MCP entry. It requires a running daemon with Jcode on the roster and starts Jcode; it is a person operation, not a readiness check or an action performed during preparation.
10
+ - Cancellation requires a daemon advertising `task_cancel`; current clients and controlled downgrade paths refuse incompatible versions while cancelled rows exist. An older binary started by hand remains outside that guarantee. Cancelled work is closed history, never approval and never a released dependency.
11
+ - `seeded guards` is now required alongside both OS checks. The live branch-protection readback during preparation listed exactly `check (ubuntu-latest)`, `check (macos-latest)` and `seeded guards`; the latter succeeds only after all four shards.
12
+ - Local/Pi non-PII implement/test/bulk_edit owners need an enabled, available isolated runner; issue-backed owners need authenticated bounded spec access. PII and designated-reviewer exemptions remain. Source and CI evidence does not close installed managed-Pi #418 AC8.
13
+ - Planner designation, task stalls/offers, recipient retry and recovery changes retain their task/privacy/transport fences. #439 live settings reload is not included and remains frozen for this release.
14
+
15
+ ## Document review
16
+
17
+ The initial `node scripts/check-docs.mjs --require-fresh` reproduced 13 stale documents. Each was compared against its covered source changes from `79a113dfc4395a0e00890ba8b8d2d90bb289ee9f` through main `09bfd51b`, then against the release metadata and generated assets. Current symbols and numeric limits were checked, not inferred from commit counts. No document review is deferred. The already-fresh models note retains its stamp.
18
+
19
+ | Document | Prior source stamp | Review result | Checked claims and correction |
20
+ | --- | --- | --- | --- |
21
+ | `README.md` | `79a113dfc4395a0e00890ba8b8d2d90bb289ee9f` | corrected | Version/protocol, planner and closed cancellation, isolated owner admission, Jcode refresh and explicitly open live legs; routing, board, hub tools and Jcode entry checked. |
22
+ | `docs/agent-notes/README.md` | `79a113dfc4395a0e00890ba8b8d2d90bb289ee9f` | unchanged | Console attention exact-row identity and human background remain accurate after the console navigation/event changes. |
23
+ | `docs/agent-notes/adapters.md` | `79a113dfc4395a0e00890ba8b8d2d90bb289ee9f` | corrected | Pre-effect classification after durable receipt/output changes; task/session/privacy fences, actual-adapter retry authority and failed_safe fallback. |
24
+ | `docs/agent-notes/benchmarks.md` | `79a113dfc4395a0e00890ba8b8d2d90bb289ee9f` | unchanged | Covered source commits have no net benchmark-runner/sandbox contract change; retained benchmark ceilings and teardown rules still match. |
25
+ | `docs/agent-notes/budget.md` | `79a113dfc4395a0e00890ba8b8d2d90bb289ee9f` | corrected | Context PII association uses the shared closed-state predicate, excluding cancelled tasks while preserving a private turn fence. |
26
+ | `docs/agent-notes/bus.md` | `79a113dfc4395a0e00890ba8b8d2d90bb289ee9f` | corrected | Exact positive offer-read evidence and cancellation revision-bound stop notices; existing presence-excluded retry and delivery-only refusal rules verified. |
27
+ | `docs/agent-notes/daemon.md` | `79a113dfc4395a0e00890ba8b8d2d90bb289ee9f` | corrected | Immutable target-feature evidence, prepared commitSent bounded polling and tagged restore receipt origin/binding rules. |
28
+ | `docs/agent-notes/local-worker.md` | `79a113dfc4395a0e00890ba8b8d2d90bb289ee9f` | unchanged | Retry tool filtering and bounded-tool capture exclusions match the existing central instructions; sandbox/path/permission contracts are unchanged. |
29
+ | `docs/agent-notes/tasks.md` | `79a113dfc4395a0e00890ba8b8d2d90bb289ee9f` | corrected | Cancelled is closed but never approval, persisted pull-only offers, planner authority, ready-sweep admission and owner-only capability exemptions. |
30
+ | `docs/agent-notes/tests.md` | `79a113dfc4395a0e00890ba8b8d2d90bb289ee9f` | corrected | Delivery-only fixture marker stripping, .bun-version, dual-OS/aggregate seeded release checks and separated publish/release credential authority. |
31
+ | `docs/operations.md` | `79a113dfc4395a0e00890ba8b8d2d90bb289ee9f` | corrected | Presence-excluded retry, bounded Pi access and inactive/unknown receipt retention, durable offer attention, guarded ready sweep, cancellation and cached-feature/resume behavior; current 0.12.31 guide/header/upgrade examples and protocol range, existing planner and console keys verified. |
32
+ | `docs/quickstart.md` | `79a113dfc4395a0e00890ba8b8d2d90bb289ee9f` | corrected | 0.12.31 example, one-time person-run Jcode refresh, opt-in check/spec requirements and planner/cancel commands; memory migration prerequisite remains 0.12.30 or later. |
33
+ | `docs/security.md` | `79a113dfc4395a0e00890ba8b8d2d90bb289ee9f` | corrected | Planner/cancel/version refusal, exact offer and retry evidence, marker names, explicit non-GitHub references, Unicode staging collision screen and active/unknown retention exceptions. |
34
+
35
+ Reviewed baseline source `fce7777f208f4885cf6524c4403fd5048cfe8f8b` contains the generated assets. A subsequent source review corrected the operations guide header, explicit upgrade targets and protocol-16 release range to 0.12.31, and clarified the unchanged minimum memory-profile migration prerequisite as 0.12.30 or later. The historical warning about the 0.12.30 CLI mislabelling waiting receipts is intentionally preserved. The original stamp follow-up advanced the 13 reviewed entries to corrected source `56ae16dfd69d3c72bcc1f4efdabbda1905f75b9c`. A later wording pass clarifies that Jcode refresh requires an already-running daemon and precedes conductor or dashboard starts of Jcode, attributes required seeded guards to the repository setting after #458, and restores tag-on-main refusal and Dependabot actions coverage. The unstamped `docs/memory.md` also now says 0.12.30 or later. The README stamp names the reviewed wording commit `6637a383c3f46ae173b14268d29c8b0d306eac95`; the other 12 reviewed entries and the already-fresh models entry remain unchanged.
36
+
37
+ Source review is distinct from native/runtime verification. The release PR must use a merge commit so every source stamp remains an ancestor; before tagging, rerun committed freshness. A separate manifest commit follows the reviewed source and generated assets, without stamping itself.
38
+
39
+ ## Recorded checks
40
+
41
+ GitHub readback verified each run below is completed successfully and its `headSha` exactly matches the PR's final head. Both OS check jobs and `seeded guards` succeeded for every row. Earlier runs used the sequential seeded job; rows with sharded CI also had all four shards and the aggregate green. These prior PR gates do not replace the release candidate's own exact-head CI.
42
+
43
+ | PR | Final head | CI run | Recorded result |
44
+ | --- | --- | --- | --- |
45
+ | [#435](https://github.com/STAIxBWLB/agent-hub/pull/435) | `c135f8827aa76d482fa7938edd80a63677c52718` | [38997048821](https://github.com/STAIxBWLB/agent-hub/actions/runs/38997048821) | Both OS checks and sequential seeded guards SUCCESS |
46
+ | [#436](https://github.com/STAIxBWLB/agent-hub/pull/436) | `d336b895eb556e6c674e8c4ae9dc7838fda581d4` | [38987274924](https://github.com/STAIxBWLB/agent-hub/actions/runs/38987274924) | Both OS checks and sequential seeded guards SUCCESS |
47
+ | [#440](https://github.com/STAIxBWLB/agent-hub/pull/440) | `df55c6b45bea7fd219d28d6f634410d5f5c3c36f` | [38993748843](https://github.com/STAIxBWLB/agent-hub/actions/runs/38993748843) | Both OS checks and sequential seeded guards SUCCESS |
48
+ | [#442](https://github.com/STAIxBWLB/agent-hub/pull/442) | `45420bed8b70e99d7d3865a66530c76a7bba9e6e` | [38987497318](https://github.com/STAIxBWLB/agent-hub/actions/runs/38987497318) | Both OS checks and sequential seeded guards SUCCESS |
49
+ | [#443](https://github.com/STAIxBWLB/agent-hub/pull/443) | `3094d3f2ffdb73a4086b6215e5807208557df245` | [39010001473](https://github.com/STAIxBWLB/agent-hub/actions/runs/39010001473) | Both OS checks; four seeded shards and aggregate SUCCESS |
50
+ | [#444](https://github.com/STAIxBWLB/agent-hub/pull/444) | `8eee1da65712109df3d25f361e209c207ce3c25f` | [38990131100](https://github.com/STAIxBWLB/agent-hub/actions/runs/38990131100) | Both OS checks and sequential seeded guards SUCCESS |
51
+ | [#448](https://github.com/STAIxBWLB/agent-hub/pull/448) | `37bf6b863eacdea273d5957ca67c9b871cee4ad9` | [39011678855](https://github.com/STAIxBWLB/agent-hub/actions/runs/39011678855) | Both OS checks; four seeded shards and aggregate SUCCESS |
52
+ | [#453](https://github.com/STAIxBWLB/agent-hub/pull/453) | `876824867a254bcfa99726b61999a46ed2bfd939` | [38997592343](https://github.com/STAIxBWLB/agent-hub/actions/runs/38997592343) | Both OS checks and sequential seeded guards SUCCESS |
53
+ | [#454](https://github.com/STAIxBWLB/agent-hub/pull/454) | `ee338b3459ab809d13dbdc3de22fc306d0a9bd15` | [39004948075](https://github.com/STAIxBWLB/agent-hub/actions/runs/39004948075) | Both OS checks; four seeded shards and aggregate SUCCESS |
54
+ | [#456](https://github.com/STAIxBWLB/agent-hub/pull/456) | `5541bcf1c01ef21008d4ab7fd60b7127ac8a808b` | [39004850799](https://github.com/STAIxBWLB/agent-hub/actions/runs/39004850799) | Both OS checks; four seeded shards and aggregate SUCCESS |
55
+ | [#458](https://github.com/STAIxBWLB/agent-hub/pull/458) | `9104e00b5b0b742656b24f2d40e731bf0a054748` | [39002544473](https://github.com/STAIxBWLB/agent-hub/actions/runs/39002544473) | Both OS checks; four seeded shards and aggregate SUCCESS |
56
+ | [#459](https://github.com/STAIxBWLB/agent-hub/pull/459) | `757c47e613d289dee9edac388276f87e0e72317a` | [39012529459](https://github.com/STAIxBWLB/agent-hub/actions/runs/39012529459) | Both OS checks; four seeded shards and aggregate SUCCESS |
57
+ | [#460](https://github.com/STAIxBWLB/agent-hub/pull/460) | `0625808d12eccfc21c15bb902b9901ae5b4f0db8` | [39016099853](https://github.com/STAIxBWLB/agent-hub/actions/runs/39016099853) | Both OS checks; four seeded shards and aggregate SUCCESS |
58
+ | [#461](https://github.com/STAIxBWLB/agent-hub/pull/461) | `4789b436aeb75d337141a14b800486b40fa93f82` | [39018722513](https://github.com/STAIxBWLB/agent-hub/actions/runs/39018722513) | Both OS checks; four seeded shards and aggregate SUCCESS |
59
+
60
+ - Hosted preparation [39020520475](https://github.com/STAIxBWLB/agent-hub/actions/runs/39020520475) ran `bun install --frozen-lockfile` and `bun run build` at metadata source `e59c5551c7e31fe93767185575f404f5ab64da9f`. Only actual generated plugin assets were copied back; no dependency tree was copied. Later edits are documentation only and do not change bundle inputs.
61
+ - Generated `server.js`: 618526 bytes, SHA-256 `1bc69dee0b1fbdf7b6f08904212fd2a869ac6401157076a26a6784f83f7540cf`. Plugin manifest: 379 bytes, SHA-256 `d7c1ba72407bae6c658ac0ddfc0a3f9b8e4ac9239931aafb9efdd41fd8ce5c74`, version 0.12.31.
62
+ - The final committed candidate requires `node scripts/check-docs.mjs --require-fresh --committed` and its own exact-head CI with both `scripts/check.sh` gates, all four seeded shards and aggregate before merge. The tag workflow independently checks main ancestry, fresh documentation and successful identical-tree CI.
63
+
64
+ ## Not verified by this record
65
+
66
+ - Installed managed-Pi #418 AC8 / task #142 remains open. This preparation does not run managed tools against the person's active session, enable the container runner, install code or restart frozen-schema sessions.
67
+ - #438 AC7 remains open: no live task cancellation or sweep enablement was performed. Fixture/CI cancellation, attention and sweep tests are not native operational receipts.
68
+ - Native/live legs in #273 and #1 remain open according to their ledgers; no source-only or historical evidence is promoted to native success.
69
+ - Previously unrun #412 P5 legs L03 (real claude-mem import), L04 (real model suggestions/person confirmation) and L05 (visual Memory/Long-term checks) are not completed by this release.
70
+ - The person's package/plugin installation, running-hub upgrade/restart, recovery/session continuity, real-home migration and remote memory synchronization require separate authorized operational readbacks.
71
+ - npm publication/provenance and the GitHub Release are later workflow outcomes, not actions or results of release preparation.
@@ -0,0 +1,21 @@
1
+ # #418 isolated runner feasibility
2
+
3
+ - Observed: 2026-10-17 KST, Apple container CLI 1.5.0, Bun 1.4.2, Linux/arm64 VM.
4
+ - Exact source: `7d470afe86b0dc0d9ff4f80701731aa869c922e4`.
5
+ - Image: `oven/bun@sha256:9114c058aeae42162ee16dd5084b95fe9473970bb6bcb5b232ab1630f0546895`.
6
+ - Network: `agenthub-check`, verified configuration `mode: hostOnly`, verified internal gateway, no DNS.
7
+ - Source: Git blobs from the named commit; no source symlinks/gitlinks. Dependency lockfile equal to the source; regular dependency tree with internal relative links copied, no host mount.
8
+ - Admission: ran after the admitted #433 native gate completed. Earlier admission deferrals were honored; no memory worker or other session was stopped.
9
+
10
+ ## Results
11
+
12
+ - `container create` succeeded; copying into its stopped VM failed explicitly with `container ... is not running`. The created container was removed. This alternative is not used.
13
+ - `container run --detach --rm` with the pinned image, internal network, no DNS, two CPUs, 4 GiB and bounded idle process succeeded.
14
+ - Source/dependency copy into the running VM succeeded.
15
+ - `container exec --workdir /work <name> bun test test/control-client.test.ts`: 12 pass, 0 fail, 36 assertions, exit 0. These unchanged repository tests bind their own loopback servers.
16
+ - Separate fixed isolation probe: VM loopback server returned `pong`; `/root/.config/gh` absent; HTTP connection attempts to both observed host gateways on the hub control port and Internet `1.1.1.1` failed within bounded waits; exit 0.
17
+ - Kill succeeded and `--rm` removed the VM. Subsequent container inventory contained no probe container. Unrelated containers were preserved.
18
+
19
+ ## Limits
20
+
21
+ This proves the selected transfer and Linux runtime mechanism on this Mac. It does not certify a managed Pi calling the new tools, a deployed daemon, macOS Seatbelt behavior, another Mac, failing-check receipt handling or every lifecycle negative. Those require the implementation fixtures and issue #418 live rows. No fallback removal, daemon restart or security-policy change was performed.
@@ -0,0 +1,54 @@
1
+ # 0.12.32 release verification
2
+
3
+ This record covers release preparation and source review. It does not claim publication, installation, a running-hub restart or native/live acceptance.
4
+
5
+ ## Candidate
6
+
7
+ Version 0.12.32, control protocol 16 (`src/hub/control-client.ts`), from merged main `2b2d6d2d67d3ed54a94fab19b5745e20a779b7d5`. The candidate includes all 9 PRs merged since `v0.12.31`: #465, #467, #468, #470, #471, #472, #473, #474 and #475. The exact first-party memory pin remains `@staix/agent-mem` 0.3.1.
8
+
9
+ - The upgrade runs with the target release's own coordinator (`bunx --package @staix/agent-hub@0.12.32 ahub upgrade`), so an upgrade into 0.12.32 already uses the #463 reattach and continuity changes and the #466 screens.
10
+ - #439 live settings reload ships with per-key trust: a write or undo publishes only its own key, guarded or machine-local file edits are adopted only by a confirmed terminal `ahub settings reload`, and a change of the settled planner or conductor holders is guarded. The native real-terminal console leg (#439 AC5) is not verified here.
11
+ - #451 A1 (adapter registry) is a refactor with no intended behaviour change; the registry guard baseline is 415 sites in 171 groups at the candidate.
12
+ - agent-mem main contains the curated shard migration (agent-mem#15 T2), which is not released. agent-hub still opens memory through `new MemoryStore()` (`src/hub/memory-profile.ts`); task #175 must land before any agent-mem release that ships T2, and the person must not run `amem migrate --shards` before then.
13
+ - Still open: a real Orca upgrade exercising `ahub recovery reattach` (#463), installed managed-Pi #418 AC8 (#142) and #438 AC7.
14
+
15
+ ## Document review
16
+
17
+ The initial `node scripts/check-docs.mjs --require-fresh` reported 13 stale documents. Each was compared against its covered source changes from its prior stamp through the candidate, then against the release metadata. Symbols and limits were checked in the source, not inferred from commit messages. No document review is deferred. The models note was already fresh and keeps its stamp.
18
+
19
+ | Document | Prior source stamp | Review result | Checked claims and correction |
20
+ | --- | --- | --- | --- |
21
+ | `README.md` | `6637a383c3f46ae173b14268d29c8b0d306eac95` | corrected | Status 0.12.32 and protocol 16; the Jcode MCP refresh is scoped to upgrades from 0.12.30 or earlier (`src/cli/jcode-mcp.ts` last changed in 0.12.31); live settings reload; the unreleased shard migration warning; the verification link and open legs. |
22
+ | `docs/quickstart.md` | `56ae16dfd69d3c72bcc1f4efdabbda1905f75b9c` | corrected | `v0.12.32` examples, the target coordinator and `ahub recovery reattach`, `ahub settings reload` in the working-day table, and the dashboard reload button. |
23
+ | `docs/security.md` | `56ae16dfd69d3c72bcc1f4efdabbda1905f75b9c` | corrected | Memory pin 0.3.1; the Pi continuity bookmark record; dashboard reload and ordinary-session floors; reload trust (watched files, per-key provenance, automatic privacy tightening, confirmed terminal reload only); live-test refusals for reattach and the repaired fresh-session dispose. |
24
+ | `docs/operations.md` | `56ae16dfd69d3c72bcc1f4efdabbda1905f75b9c` | corrected | 0.12.32 header and upgrade examples, protocol 16 covering 0.12.20 through 0.12.32, the console Settings panel, the ordinary dashboard settings authority, the repaired-session fresh dispose and the Pi bookmark. |
25
+ | `docs/agent-notes/README.md` | `56ae16dfd69d3c72bcc1f4efdabbda1905f75b9c` | unchanged | Console tab 6 and the settings editor do not affect the exact-row navigation rule; the cited tests and verification file exist. |
26
+ | `docs/agent-notes/adapters.md` | `56ae16dfd69d3c72bcc1f4efdabbda1905f75b9c` | corrected | `KIMI_MODE_IDS` location; a reloaded permission default only through `applyPendingPermissionDefault`; adding a native peer through an `AdapterDefinition`; the registry guard baseline only shrinks; watchdog reload; typed Pi session failures. |
27
+ | `docs/agent-notes/benchmarks.md` | `56ae16dfd69d3c72bcc1f4efdabbda1905f75b9c` | unchanged | The covered changes only move Qwen identity and mode ids into definitions and add Pi session error classes; the benchmark rules still match. |
28
+ | `docs/agent-notes/budget.md` | `56ae16dfd69d3c72bcc1f4efdabbda1905f75b9c` | unchanged | The budget, statusline, journal, restart and context-window sources are unchanged; the bus and daemon changes do not touch budget rules. |
29
+ | `docs/agent-notes/bus.md` | `56ae16dfd69d3c72bcc1f4efdabbda1905f75b9c` | corrected | Reloaded batching and queue limits only through `Bus.configureScheduling`, affecting later batching and admission only. |
30
+ | `docs/agent-notes/daemon.md` | `56ae16dfd69d3c72bcc1f4efdabbda1905f75b9c` | corrected | `reloadConfig` as the only publication path with scoped writes, per-key trust, guarded holder changes, the reload token and undo identity; the Pi bookmark exception scoped to `pi.auto_start`; `reattachRecovery`; the #466 presentation rules. Four new source files added to its scope. |
31
+ | `docs/agent-notes/local-worker.md` | `56ae16dfd69d3c72bcc1f4efdabbda1905f75b9c` | corrected (ASCII only) | One existing em-dash replaced; the sandbox, path and permission rules are unchanged. |
32
+ | `docs/agent-notes/tasks.md` | `56ae16dfd69d3c72bcc1f4efdabbda1905f75b9c` | corrected | `resolveSettledRoles`; the coordination mode captured per task at creation, cohorts within one mode, and the restart re-pin; `src/hub/settled-roles.ts` added to its scope. |
33
+ | `docs/agent-notes/tests.md` | `56ae16dfd69d3c72bcc1f4efdabbda1905f75b9c` | corrected | The registry guard scans `src/` against the committed baseline, and no test writes or regenerates it. |
34
+
35
+ `AGENTS.md` area notes and `docs/verified.json` paths now include `src/hub/config-reload.ts`, `src/hub/config-apply.ts`, `src/hub/recovery-continuity.ts` and `src/cli/recovery-presentation-options.ts` (daemon) and `src/hub/settled-roles.ts` (tasks). A separate manifest commit restamps the reviewed documents against the reviewed source; it does not stamp itself. The release PR must use a merge commit, and committed freshness is rerun on main before tagging.
36
+
37
+ ## Recorded checks
38
+
39
+ GitHub readback found a successful `check.yml` run at each PR's final head. Both OS check jobs, all four seeded shards and the `seeded guards` aggregate succeeded for every row. These prior PR gates do not replace the release candidate's own exact-head CI.
40
+
41
+ | PR | Final head | CI run |
42
+ | --- | --- | --- |
43
+ | [#465](https://github.com/STAIxBWLB/agent-hub/pull/465) | `fcb27ca4af74bef6b264af9bf9f3e0490a824971` | [39025787130](https://github.com/STAIxBWLB/agent-hub/actions/runs/39025787130) |
44
+ | [#467](https://github.com/STAIxBWLB/agent-hub/pull/467) | `94a52afb4638e687049c13ef0c27dc4a66483355` | [39027067759](https://github.com/STAIxBWLB/agent-hub/actions/runs/39027067759) |
45
+ | [#468](https://github.com/STAIxBWLB/agent-hub/pull/468) | `de30d9e3518da40546a900d3e0940dc882179e6d` | [39028179223](https://github.com/STAIxBWLB/agent-hub/actions/runs/39028179223) |
46
+ | [#470](https://github.com/STAIxBWLB/agent-hub/pull/470) | `17c593b7e04ee82f789525552b8b6e0f922d8c8f` | [39039356493](https://github.com/STAIxBWLB/agent-hub/actions/runs/39039356493) |
47
+ | [#471](https://github.com/STAIxBWLB/agent-hub/pull/471) | `04f55cd942533e7b49c00f5e2d941e42e448fbd5` | [39046673325](https://github.com/STAIxBWLB/agent-hub/actions/runs/39046673325) |
48
+ | [#472](https://github.com/STAIxBWLB/agent-hub/pull/472) | `e214fc9ec7306e88b9906ff3847fdda4f3227785` | [39049995436](https://github.com/STAIxBWLB/agent-hub/actions/runs/39049995436) |
49
+ | [#473](https://github.com/STAIxBWLB/agent-hub/pull/473) | `11fe040e500bf65d3e9c38792a2e05f5fd338bae` | [39056391496](https://github.com/STAIxBWLB/agent-hub/actions/runs/39056391496) |
50
+ | [#474](https://github.com/STAIxBWLB/agent-hub/pull/474) | `cfcd087452e8afe7215039168cbd535ef8088765` | [39063863001](https://github.com/STAIxBWLB/agent-hub/actions/runs/39063863001) |
51
+ | [#475](https://github.com/STAIxBWLB/agent-hub/pull/475) | `1abbaebe235ccfd4ea30ee2c6961ad55f51aec3a` | [39066256392](https://github.com/STAIxBWLB/agent-hub/actions/runs/39066256392) |
52
+
53
+ - Generated assets: `bun install --frozen-lockfile` and `bun run build` ran locally at `6883f4d8`. The only change to `plugins/agent-hub/server.js` and the plugin manifest is the version string 0.12.31 -> 0.12.32; the release PR's CI checks bundle freshness.
54
+ - The release PR's own exact-head CI and the release workflow's tag checks are recorded on the PR and the tag, not here.