@staix/agent-hub 0.12.34 → 0.12.36
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.
- package/CHANGELOG.md +27 -0
- package/README.md +8 -6
- package/docs/agent-notes/adapters.md +6 -1
- package/docs/agent-notes/budget.md +4 -2
- package/docs/agent-notes/bus.md +5 -1
- package/docs/agent-notes/daemon.md +11 -3
- package/docs/agent-notes/local-worker.md +1 -1
- package/docs/agent-notes/tasks.md +15 -2
- package/docs/agent-notes/tests.md +5 -1
- package/docs/gsd-collaboration-analysis.md +5 -1
- package/docs/operations.md +97 -19
- package/docs/quickstart.md +8 -4
- package/docs/sdlc.md +100 -34
- package/docs/security.md +7 -3
- package/docs/specs/2026-09-19-agent-hub-design.md +237 -7
- package/docs/verification/2026-10-18-0.12.35.md +49 -0
- package/docs/verification/2026-10-18-493-claude-busy-channel.md +91 -0
- package/docs/verification/2026-10-19-0.12.36.md +63 -0
- package/docs/verified.json +26 -17
- package/package.json +1 -1
- package/plugins/agent-hub/.claude-plugin/plugin.json +1 -1
- package/plugins/agent-hub/server.js +15781 -14850
- package/src/adapters/acp.ts +3 -1
- package/src/adapters/claude-channel.ts +59 -29
- package/src/adapters/claude-print.ts +230 -0
- package/src/adapters/codex-appserver.ts +1 -1
- package/src/adapters/definitions/builtin-metadata.ts +17 -1
- package/src/adapters/definitions/native-cli-entry-claude.ts +17 -3
- package/src/adapters/definitions/native-cli-entry-codex.ts +13 -5
- package/src/adapters/definitions/native-cli-entry-jcode.ts +6 -2
- package/src/adapters/definitions/native-cli-entry-kimi.ts +18 -12
- package/src/adapters/definitions/native-cli-entry-local.ts +3 -2
- package/src/adapters/definitions/native-cli-entry-pi.ts +8 -6
- package/src/adapters/definitions/native-cli-entry-qwen.ts +3 -2
- package/src/adapters/definitions/native-cli-entry-types.ts +3 -0
- package/src/adapters/definitions/native-factories.ts +7 -0
- package/src/adapters/definitions/native-recovery.ts +2 -2
- package/src/adapters/definitions/qwen-native.ts +2 -2
- package/src/adapters/local-worker.ts +3 -2
- package/src/adapters/pi.ts +3 -1
- package/src/adapters/registry-types.ts +11 -2
- package/src/adapters/registry.ts +36 -8
- package/src/cli/help.ts +5 -0
- package/src/cli/identity.ts +5 -4
- package/src/cli/launch.ts +45 -7
- package/src/cli/main.ts +136 -29
- package/src/cli/preview.ts +16 -5
- package/src/cli/recovery-guidance.ts +39 -22
- package/src/cli/reset.ts +4 -2
- package/src/cli/statusline-tee.ts +5 -2
- package/src/cli/terminal-recovery.ts +73 -16
- package/src/cli/upgrade-restore-state.ts +16 -7
- package/src/cli/upgrade-runtime.ts +83 -52
- package/src/cli/upgrade.ts +43 -27
- package/src/hub/board.ts +29 -7
- package/src/hub/budget.ts +55 -3
- package/src/hub/bus.ts +12 -6
- package/src/hub/claude-state.ts +37 -0
- package/src/hub/conductor.ts +16 -10
- package/src/hub/config-apply.ts +13 -2
- package/src/hub/config-reload.ts +11 -1
- package/src/hub/config-trust.ts +1 -1
- package/src/hub/control-client.ts +1 -1
- package/src/hub/cost-governance.ts +76 -0
- package/src/hub/crash.ts +14 -5
- package/src/hub/daemon.ts +473 -194
- package/src/hub/execution-budget.ts +3 -3
- package/src/hub/hub-tools.ts +36 -6
- package/src/hub/instance-budget.ts +73 -0
- package/src/hub/instance-config.ts +47 -0
- package/src/hub/instance-execution.ts +50 -0
- package/src/hub/instances.ts +114 -0
- package/src/hub/lifecycle-schema.ts +7 -3
- package/src/hub/permission-mode.ts +7 -7
- package/src/hub/review-brief.ts +175 -0
- package/src/hub/roster.ts +7 -6
- package/src/hub/routing.ts +97 -18
- package/src/hub/sdlc-queue.ts +2 -2
- package/src/hub/sdlc.ts +286 -39
- package/src/hub/settings.ts +34 -6
- package/src/hub/snapshots.ts +40 -9
- package/src/hub/start-mode.ts +7 -4
- package/src/hub/status-roster.ts +18 -0
- package/src/hub/task-sweep.ts +143 -0
- package/src/hub/tasks.ts +595 -47
- package/src/hub/text-projection.ts +7 -3
- package/src/hub/usage.ts +57 -20
- package/src/hub/workflow.ts +30 -52
- package/src/pi/launch.ts +4 -3
- package/src/ui/index.html +1 -1
- package/templates/AGENTS.block.md +2 -1
|
@@ -1696,7 +1696,11 @@ distinct from the completed-message baseline recorded at that start. Later tool
|
|
|
1696
1696
|
activity does not move this turn-start boundary. Missing start evidence or a
|
|
1697
1697
|
start from another session, launch or channel claim leaves completion unknown.
|
|
1698
1698
|
Accepted completion consumes that start before the peer becomes idle, so another
|
|
1699
|
-
message cannot reuse it.
|
|
1699
|
+
message cannot reuse it. The completion and the baseline are read from the last
|
|
1700
|
+
4 MiB of the transcript, whatever its size (#517): the 32 MiB cap applies only to
|
|
1701
|
+
usage accounting, so a long session still ends its turns. A Stop refused because
|
|
1702
|
+
no completion is found tells the console once per turn start that the peer stays
|
|
1703
|
+
busy and its messages wait in its queue. A valid bound Stop request receives one prompt
|
|
1700
1704
|
acknowledgement with pending=true, within the existing two-second hook deadline.
|
|
1701
1705
|
The acknowledgement records observation only, never completion. After the hook
|
|
1702
1706
|
can return, a deferred observer waits up to 1200 monotonic milliseconds for its
|
|
@@ -1837,7 +1841,8 @@ push `accepted` and show none of them.
|
|
|
1837
1841
|
selection excludes pull-only peers; only explicit role-specific naming or an
|
|
1838
1842
|
honored owner reservation permits assignment.
|
|
1839
1843
|
- `hub_inbox` sends `inbox`. The daemon answers "not attached yet; retry"
|
|
1840
|
-
between welcome and attach
|
|
1844
|
+
between welcome and attach. Since #493 the current channel owner may also
|
|
1845
|
+
explicitly pull its queued work, including while its native turn is busy.
|
|
1841
1846
|
`Bus.pull` is held by every hold a drain respects (`Bus.held`: recovery, an
|
|
1842
1847
|
uncertain delivery, a console, budget or conductor pause), though unlike a
|
|
1843
1848
|
drain it does not wait for the peer to be idle; a held pull journals nothing
|
|
@@ -1876,6 +1881,45 @@ push `accepted` and show none of them.
|
|
|
1876
1881
|
- Control protocol 16 adds the hello `channel` field and `inbox`. Recovery
|
|
1877
1882
|
sources add protocol 15 (0.12.17 through 0.12.19); the transition from a real
|
|
1878
1883
|
0.12.19 hub is not yet proven.
|
|
1884
|
+
|
|
1885
|
+
## Amendment: channel queue visibility and explicit pull (issue #493)
|
|
1886
|
+
|
|
1887
|
+
- A channel session's `hub_inbox` reads the daemon queue through the same
|
|
1888
|
+
authenticated `peer` socket as a tools-only Claude session. The daemon checks
|
|
1889
|
+
current socket ownership and the shared roster, pause, recovery, lifecycle and
|
|
1890
|
+
uncertain-delivery holds. It does not require an idle native turn. Tools-role
|
|
1891
|
+
sockets cannot consume another transport's queue.
|
|
1892
|
+
- `Bus.pull` claims one batch synchronously and completes it with its bus
|
|
1893
|
+
checkpoint in the existing journal transaction. A later idle drain or another
|
|
1894
|
+
concurrent inbox call cannot hand those originals out again. Existing accepted
|
|
1895
|
+
pushes remain independent; a pull does not complete them. The hand-out-before-
|
|
1896
|
+
model-read ceiling documented above remains. Framing, `sanitize`, public PII
|
|
1897
|
+
projections and task-offer read evidence retain their existing paths.
|
|
1898
|
+
- The plugin also returns its existing bounded local buffer of failed pushes
|
|
1899
|
+
without journal ids. Journaled failed pushes stay in `needs_review`; the plugin
|
|
1900
|
+
never consumes them from this local buffer. A daemon refusal or an unavailable
|
|
1901
|
+
connection cannot prevent reading that local fallback.
|
|
1902
|
+
- `delivery_holds` adds optional same-peer `queued` and `important` counts, with
|
|
1903
|
+
no bodies or caller-selected target. Every agent-hub tool-call result can show
|
|
1904
|
+
fresh counts when important work waits. Channel and tools-mode sessions remain
|
|
1905
|
+
silent when an older daemon supplies no counts. Plain pull-only sessions keep
|
|
1906
|
+
their old advisory nudge compatibility. A current zero clears old nudges;
|
|
1907
|
+
unavailable metadata never changes a saved result or its effect classification.
|
|
1908
|
+
Inbox replies show counts without suggesting a repeated refused read, and a
|
|
1909
|
+
tools-mode hint does not grant an inbox capability to that transport.
|
|
1910
|
+
- `[FYI]` remains record-only. PR ready, done or submitted, ruling-needed,
|
|
1911
|
+
blocker and changed-contract/path messages require an unmarked or important
|
|
1912
|
+
update. `hub_task_done` and `hub_review` already notify the assigned audience;
|
|
1913
|
+
an extra chat with the same outcome is unnecessary.
|
|
1914
|
+
- Native busy-notification evidence and the decision about channel steering are
|
|
1915
|
+
recorded separately in `docs/verification/2026-10-18-493-claude-busy-channel.md`.
|
|
1916
|
+
Claude Code 2.1.302 / Sonnet 5.5 returned the random notification token before
|
|
1917
|
+
the original interactive turn ended. Push-capable `WsPeer` therefore exposes
|
|
1918
|
+
important-only steer through the existing journal/generation-bound push path;
|
|
1919
|
+
detach and pull-only attach remove that capability. Ordinary messages remain
|
|
1920
|
+
queued while busy. A notification write alone is not proof that the native
|
|
1921
|
+
model saw it; the earlier print-mode probe was inconclusive.
|
|
1922
|
+
|
|
1879
1923
|
## Amendment: owner and reviewer read their task (issue #208)
|
|
1880
1924
|
|
|
1881
1925
|
`hub_task_show` stays a conductor tool, and a task's current owner and current
|
|
@@ -2398,7 +2442,7 @@ the queue.
|
|
|
2398
2442
|
- 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.
|
|
2399
2443
|
- 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.
|
|
2400
2444
|
- 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.
|
|
2401
|
-
-
|
|
2445
|
+
- Later custom definitions and read-only merge/release reports are described below. #481 supersedes the original lifecycle vocabulary and workflow option; a full native advise cycle remains pending. See docs/sdlc.md.
|
|
2402
2446
|
## Amendment: optional Qwen Code 0.25.0 ACP peer (#256)
|
|
2403
2447
|
|
|
2404
2448
|
- `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.
|
|
@@ -2422,9 +2466,9 @@ the queue.
|
|
|
2422
2466
|
- 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.
|
|
2423
2467
|
- 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).
|
|
2424
2468
|
|
|
2425
|
-
#
|
|
2469
|
+
# Historical workflow amendment, 2026-10-11 (#257, superseded by #481)
|
|
2426
2470
|
|
|
2427
|
-
-
|
|
2471
|
+
- The original optional workflow selector used existing SDLC receipts and Tasks authority; its current replacement is the #481 amendment below. A reviewer/person-owned checklist stores bounded criterion ids, hashed evidence refs and verified/failed/unverified claims bound to the reviewed head.
|
|
2428
2472
|
- 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.
|
|
2429
2473
|
- 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.
|
|
2430
2474
|
|
|
@@ -2508,12 +2552,12 @@ pii.paths and data.readonly accept exact paths/subtrees and *, ? and whole-segme
|
|
|
2508
2552
|
|
|
2509
2553
|
## Amendment: custom lifecycle data (#257)
|
|
2510
2554
|
|
|
2511
|
-
Optional ordered stage definitions map at most 32 bounded ids to the
|
|
2555
|
+
Optional ordered stage definitions map at most 32 bounded ids to the semantic bases, existing actor guidance and closed entry/exit gates (updated to nine bases and the criteria gate by #481 below). 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.
|
|
2512
2556
|
|
|
2513
2557
|
|
|
2514
2558
|
### Custom lifecycle review corrections (#257)
|
|
2515
2559
|
|
|
2516
|
-
|
|
2560
|
+
The original phase gate validation is superseded by the criteria gate and compatibility window in #481 below. 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.
|
|
2517
2561
|
|
|
2518
2562
|
|
|
2519
2563
|
## Backlog foundation (#263)
|
|
@@ -3502,3 +3546,189 @@ The guard resolves immutable peer-id constant aliases and supplied-source
|
|
|
3502
3546
|
import/reexport bindings through lexical symbols before classifying comparisons.
|
|
3503
3547
|
Shadowed and unrelated bindings remain independent; named non-peer enum exceptions
|
|
3504
3548
|
keep their exact scope. It performs no filesystem or package lookup.
|
|
3549
|
+
|
|
3550
|
+
## Amendment: playbook lifecycle and criteria checklist, 2026-10-18 (#481 S0/S8)
|
|
3551
|
+
|
|
3552
|
+
- The AI-Native SDLC Playbook supplies the built-in stage model of an enabled lifecycle: intent (Plan), spec (Design), plan and build (Build), test (Test), review, merge and release (Deploy), maintain (Maintain). `mode` advise or enforce without `stages` selects this list. Off (no file, or `mode = "off"`) keeps the seven #257 stages, so its config, receipts, `hub_sdlc_record` schema and status output stay byte for byte. An explicit #257 list still loads: off keeps it as written, and an enabled lifecycle keeps its order under canonical ids (spec, plan, build, review, test, merge, release). Any other list needs definitions.
|
|
3553
|
+
- Valid bases are the nine playbook stages plus the #257 names `implement` and `verify`, which mean build and test. A stored `implement` or `verify` receipt resolves to `build` or `test` in a playbook config; a write with the old id stores the id the config lists. Custom definitions keep loading with their old base names; a playbook-only built-in id (intent, build, test, maintain) cannot take another base. The test base takes the reviewer actor, like verify. Status carries `playbook` (the playbook stage) whenever the mode is not off; the dashboard shows it beside the stage.
|
|
3554
|
+
- The head-bound acceptance-criteria checklist (`criteria` in a receipt) belongs to the Compliance pass. It keeps id, head, 1..32 criteria with required, result and hashed refs, reviewer- or person-only writes and the reviewed-head binding; criterion ids may name issue AC ids (`AC8b`). Once recorded it adds its blockers in any enabled lifecycle; off ignores it unless the retired setting below asks for it. A `criteria` entry or exit gate needs no workflow selector: a missing checklist is a blocker the reviewer can clear.
|
|
3555
|
+
- Checklist task import is removed. A non-empty `tasks` list is refused before any write; dependencies stay with `Tasks.after` (`ahub task propose --after`). A receipt stored under `phase` reads as criteria, and its task list is shown with a note and never gates readiness. Board split-undo still treats such a stored list as a reference.
|
|
3556
|
+
- Deprecation window (constant `RETIRED_WORKFLOW_FROM`, 0.13.0): before it, `workflow = "none"` loads silently, `workflow = "gsd-lite"` loads with a `hub.log` warning and requires a criteria checklist on every task, the `phase` gate loads as an alias of `criteria` with a warning, and the `phase` receipt name is accepted silently. From 0.13.0 each is refused with a field-level reason; the aliases and their tests are then deleted.
|
|
3557
|
+
- Tool schema: when the mode is not off, daemon status carries `lifecycleCriteria: true`, and every managed surface (the channel and tools MCP servers and the local worker) advertises `criteria` instead of `phase` in `hub_sdlc_record`. Custom stage ids and the checklist rename are independent: off and older daemons, custom stage lists included, keep `phase`, because they accept only it. That off schema changes once, when the alias is removed at `RETIRED_WORKFLOW_FROM`.
|
|
3558
|
+
- `ahub sdlc export`: a plain off lifecycle (no retired setting) keeps the #257 export bytes (schema 1, `workflow: "none"`, `phase: null`). An enabled or retired-setting lifecycle emits schema 2: sanitized state (id, state, stage, criteria view or a private stub), `stateHash` and `sourceHash`, without the workflow field. In off, a `phase` receipt write also keeps its #257 bytes (`tasks: []`); task import stays retired in every mode, so a non-empty list is refused.
|
|
3559
|
+
- Contract amendment, seeds (419 before and after: 414 byte-unchanged, 3 modified, 2 removed, 2 added; the registry baseline is unchanged). Modified, each with the same id, test file, test name and mutation intent: `workflow-reviewer-only` (the criteria/phase check), plus `override-local-schema` and `lifecycle-native-schema`. The person approved the last two on 2026-10-18, because the `lifecycleCriteria` plumbing changed their call sites. Removed with the code they mutated: `workflow-exact-after` and `lifecycle-phase-view-required`. Added for the new guards: `criteria-task-import-retired` and `sdlc-workflow-window-closes`. Tests that pinned the retired gsd-lite behaviour (task import, phase naming, the workflow projection, the implement id stored in an enabled config) are amended in the same PR; every other test is unchanged.
|
|
3560
|
+
- S0/S8 implement none of S1-S7 and S9-S11. The issue stays the spec, Tasks owns mutations and GitHub owns PR, check and tag facts.
|
|
3561
|
+
## Reviewer separation amendment (#450, hub task #223)
|
|
3562
|
+
|
|
3563
|
+
Owner decision 2026-10-18 (#450 comment 6248184754), R1-R5. R3's mechanism, chosen by the person: a new headless Claude session per review request.
|
|
3564
|
+
|
|
3565
|
+
- **Declaration.** `"claude-review": { "kind": "claude", "roles": ["reviewer"], "start_mode": "headless" }` declares a headless reviewer. `start_mode: "headless"` on a Claude instance is accepted only when the roles are exactly `["reviewer"]`; `worktree` stays refused. It resolves to a fixed builtin variant of the claude definition (hub-native transport, env MCP identity, a headless factory); the builtin `claude` keeps its terminal-only definition, and external definitions cannot declare a variant. A channel instance (I3, no `start_mode`) may still hold reviewer; it is started from a terminal and its verdicts are recorded as `continuing`.
|
|
3566
|
+
- **Start.** `ahub claude --as <id>` asks the running hub to start the reviewer (the console and dashboard Start do the same); it takes no launch arguments, runs nothing in that terminal, and `ahub stop <id>` stops it. It holds no process while idle.
|
|
3567
|
+
- **R3, one session per verdict.** For each `review` envelope the peer runs one `claude -p` child (own process group, watchdog, `peerChildEnv(<id>)`) with: `--output-format stream-json --verbose --no-session-persistence --session-id <new uuid> --strict-mcp-config --mcp-config <agent-hub tools-mode server for <id>> --setting-sources "" --tools Read,Grep,Glob --allowedTools mcp__agent-hub__hub_review mcp__agent-hub__hub_task_show Read Grep Glob --permission-mode dontAsk`, prompt on stdin. It never passes `--resume` or `--continue`, so no session sees an earlier round. No user or project settings, hooks or plugins load. A delta review also runs fresh (R3 allows continuing; not needed). The child's final text is not published; the verdict is the `hub_review` call.
|
|
3568
|
+
- **R2, review-only delivery.** A declared instance whose effective roles are exactly `["reviewer"]` (headless or channel) receives only hub `review` envelopes, hub `task` envelopes addressed to it and the person's own messages. Every other item (agent chat, digests, presence, budget, `[FYI]`) is discarded and journaled with that reason; an agent that addressed it directly is told why. A headless reviewer starts a session only for a review request; anything else it receives settles without one. The headless reviewer's prompt is built by the hub from facts, not from the envelope text: the task title and detail, the linked spec issue, refs (branch, head commit), check results, the earlier `changes_requested` notes and unmet items, and a diff of the head bounded in size (ponytail: a cap, the reviewer reads files with Read/Grep/Glob for the rest). The implementer's done summary is builder narrative and is left out.
|
|
3569
|
+
- **R4, recorded context.** `hub_review` writes `reviewContext` on its history entry, set by the hub: `fresh` when the verdict comes from a headless reviewer's child started for that task's review, `continuing` from any other peer, absent from the person.
|
|
3570
|
+
- **R1/R5, routing.** `assign()` prefers a dedicated reviewer (holds `reviewer`, not `planner`) among the eligible peers, busy or not; family independence and the PII rule (the person reviews) are unchanged. When a dedicated reviewer is declared but not eligible (offline, not started, paused) the planner reviews as before and the assignment note says `reviewer=planner (fallback)`. With no dedicated reviewer declared nothing changes. The reviewer is chosen at assignment, as before (ponytail: a task assigned during a fallback keeps the planner; re-pick at done if that matters).
|
|
3571
|
+
- **Budget.** The reviewer shares the `claude` account and its pauses; usage from each child's `result` event is added to the peer's tokens. No quota is classified from its text.
|
|
3572
|
+
- **Privacy.** The diff lists changed paths first, with rename and copy detection, and leaves out every change touching a path that `local.deny` or `pii.paths` covers (a move or copy whole, when either side is private), noting only how many were withheld (ponytail: git's 50% similarity decides what counts as a move); a diff that matches a private-data pattern is withheld whole. Those entries are also passed to the child as Claude `Read` deny rules (Claude evaluates them, not the hub's path policy). A private review is never given to it.
|
|
3573
|
+
- **Narrative on the read tool.** `hub_task_show` from a review-only instance returns the task with history notes kept only on `approved` and `changes_requested` entries; the done summary and other notes are dropped.
|
|
3574
|
+
- **Verdict authority.** A headless reviewer's `hub_review` is accepted only while the child that started for that task still runs (a per-child token, so a replacement child for the same task is a new authority). It is captured when the call starts and rechecked before every write, after each await. The leader's exit, a watchdog or a stop revokes it first. A review ends only when the child's whole process group is confirmed gone; survivors hold the delivery as `needs_review` and keep the peer busy with its handle: a stop fails and leaves it busy (never offline), and a start is refused, until they exit.
|
|
3575
|
+
- **Settlement.** A start failure before any review in a delivery ran is `failed_safe`; after one ran, the delivery is held as `needs_review`. A failing facts or verdict-check callback is logged, and the review counts as without a recorded verdict.
|
|
3576
|
+
- **Never an owner.** The reviewer variant carries `routing.reviewOnly`; assignment refuses it as an owner for every task class and when named.
|
|
3577
|
+
|
|
3578
|
+
## Review brief amendment (#520, hub task #228)
|
|
3579
|
+
|
|
3580
|
+
ahub builds the review brief that the workspace gate used to take from `ocr delegate preview` and `rule`, and gives the same brief to every reviewer.
|
|
3581
|
+
|
|
3582
|
+
- **Range.** The task's commit (`refs.commit`, resolved to its full SHA) against its merge base with the remote default branch (`origin/HEAD`, else `origin/main`, else `origin/master`). There is no fallback to the checkout's `HEAD`, which may be the head itself or another session's branch: without a default branch, or when the commit has no changes against it, the brief is unavailable. Any failed git read makes it unavailable too, never partial. git only, bounded (500 files, 8 rule files of at most 32 KB each); the brief never touches the board.
|
|
3583
|
+
- **Files.** Each change comes with its status and line counts; a rename or copy lists both sides. A change touching a `local.deny` or `pii.paths` path, or a path that fails the private-data screen, is withheld whole (both sides of a move) and only counted. Excluded only when every side of a change is (a move keeps its source's obligation), with the reason, status and both sides shown: files marked `linguist-generated` in `.gitattributes`, lockfiles (a fixed list) and binary files. They are listed so a reviewer can still read them. Unlike `ocr delegate preview`, markdown and test files stay reviewable: the workspace gate required reading them anyway, and coverage now records it. Compared on PR #506 (head e305a17e against 3f258a41), OCR excluded 3 markdown and 3 test files and kept the generated bundle; ahub keeps those 6 and excludes the bundle once the `.gitattributes` this PR adds is on the default branch.
|
|
3584
|
+
- **Rules.** `REVIEW.md` applies to every reviewable file. A path whose `.gitattributes` entry sets `ahub-review-rules=<repository path>` also gets that file, and a move gets the rule files of both sides. Files are grouped by the rule files that apply. Attributes and rule files are read at the merge base, not the head, and every diff the brief runs uses `git --attr-source=<merge base>`, so a checkout at the head cannot reclassify files either (for example `* -diff` making them binary): a change cannot lift its own review obligations (marking everything generated, weakening `REVIEW.md`); its own edits apply from the next change after it merges. A rule file's name and whole body pass the private-data screen before any cut; a file that fails is named but not shown. A configured rule file the brief cannot load (missing at the merge base, or beyond the 8-file cap) is listed with the reason; a private or non-nameable rule path is left out unnamed. Deviation from the issue: per-path settings are git attributes, versioned with the change, instead of new `review.exclude` and `review.rules` config keys.
|
|
3585
|
+
- **Cross-check.** The plain `--name-only --no-renames` list of the same range is compared with the brief. A path it shows that the brief does not list is named for a direct read.
|
|
3586
|
+
- **Contract.** The review request already carries the spec issue reference, the task plan and the detail. The brief does not fetch the issue body: the hub reads issue metadata only (S1), so the acceptance checklist stays in the issue.
|
|
3587
|
+
- **Delivery.** `sendReview` appends the rendered brief to the review request (after #215's admission, body only). `hub_task_show` adds a `brief` field while the task is `in_review`. `ahub review brief <id>` prints it for a person. A task without a commit, or a private task, has no brief.
|
|
3588
|
+
- **Coverage gate.** `hub_review` takes `coverage: { reviewed: [paths], skipped: [{ path, reason }] }`. An approval must account for every reviewable path. The gate follows the lifecycle mode (deviation from the issue, which refuses always): `enforce` refuses before any write, naming the paths, and also refuses when the brief is unavailable (an unknown inventory is never an empty one); `advise` records `Coverage gap (N): ...` or `Coverage unknown: ...` in the verdict note; `off` and a person's own verdict skip it. The commit under review is the task's commit, else the head the verdict names, else the head its lifecycle receipt records. Code work (a task with a commit, branch or PR) for which none of these is known, or whose brief cannot be built, has an unavailable brief. Work with no commit, branch or PR is exempt, with nothing to account for. So is a `Tasks` built without a brief provider (library use and tests; the daemon always provides one). One head throughout: the head the verdict names, or the `reviewedHead` it would inherit from an earlier review, must equal the brief's head (with a PR, the lifecycle approval gate already binds the reviewed head to the PR head). The task's commit and its lifecycle receipt (which holds the inherited `reviewedHead`) are pinned when coverage is checked and rechecked before every write after an await, so a commit or receipt that moves during the verdict is refused.
|
|
3589
|
+
|
|
3590
|
+
## Claude peer instances I3 amendment (#450)
|
|
3591
|
+
|
|
3592
|
+
- A declared instance of a channel-plugin kind (Claude) is admitted when its declaration names `roles`, reviewer and/or planner only. `start_mode` and `worktree` are refused: the instance starts only from the person's terminal with `ahub claude --as <id>`, so the hub never starts, watches or owns writes for it, and it is neither startable nor reserved from external admission.
|
|
3593
|
+
- The launcher sets the child's `AGENTHUB_PEER_ID` to the instance id; the channel plugin and the statusline tee already key on it. Launch, session and context state files stay `claude-launch.json`, `claude-session.json` and `claude-context.json` for the builtin and become `<base>.<id>.json` for an instance (`src/hub/claude-state.ts`). Account usage stays shared. The daemon's context and usage readers, the permission-launch check, the facts handler, terminal recovery (project root, no worktree), the upgrade blocker check and `ahub reset` read each instance's own files.
|
|
3594
|
+
- The Claude version probe stays on the builtin peer (ponytail: instances are reviewers started by hand); zero-turn detection reads each peer's own evidence, as below.
|
|
3595
|
+
- Status, which the console and dashboard read, lists each declared instance right after its kind. `ahub <kind> --as <id>` starts only an instance the running daemon bound at startup (status `activeInstances`); otherwise it asks for a restart or an upgrade before any effect.
|
|
3596
|
+
- Each Claude peer reads only its own `terminal-recovery.json` row. Transcript evidence comes from the path that peer's status line reported; an instance without one counts as persisted, because the hub cannot see its `CLAUDE_CONFIG_DIR`. Upgrade runs plugin setup once per distinct Claude profile, under that profile.
|
|
3597
|
+
|
|
3598
|
+
## Headless peer instances I2 amendment (#450)
|
|
3599
|
+
|
|
3600
|
+
`instances` is a person-authored, machine-local object in an untracked
|
|
3601
|
+
`.agenthub/config.local.json`. Each additional `<kind>-<name>` id names its kind
|
|
3602
|
+
explicitly and may set `roles`, `start_mode`, `permission_mode` and `worktree`.
|
|
3603
|
+
The bound catalog belongs to one project/daemon; there is no process-global
|
|
3604
|
+
registration or suffix inference. Declarations are validated before trust
|
|
3605
|
+
filtering, cloned and frozen, and limited to 64 additional ids of at most 32
|
|
3606
|
+
ASCII characters. Settings cannot create or modify declarations. Identity,
|
|
3607
|
+
execution directory and account membership are restart-bound; a live reload
|
|
3608
|
+
cannot publish their derived defaults ahead of that restart.
|
|
3609
|
+
|
|
3610
|
+
I2 accepts definitions with a native headless factory and environment or ACP
|
|
3611
|
+
session MCP identity. Additional Claude/channel peers belong to I3. Jcode's
|
|
3612
|
+
project-file MCP identity is not isolated by this phase and is refused for extra
|
|
3613
|
+
instances. Additional instances start headlessly; the existing Codex native TUI
|
|
3614
|
+
still initializes and attaches to its instance's own app-server proxy. The hub
|
|
3615
|
+
never initializes that app-server on the TUI's behalf. `ahub <kind> --as <id>`
|
|
3616
|
+
selects the declared identity; selection is removed from native passthrough.
|
|
3617
|
+
Missing `peer_instances` evidence on an old daemon/upgrade target is a refusal
|
|
3618
|
+
before instance runtime effects, rather than a guess that the instance is a base
|
|
3619
|
+
peer.
|
|
3620
|
+
|
|
3621
|
+
Each additional implementer requires an explicit registered Git worktree at
|
|
3622
|
+
`<project>/.worktrees/<id>` with an attached branch. I2 creates no worktree or
|
|
3623
|
+
branch; I4 owns automatic worktree orchestration. A supplied reviewer worktree
|
|
3624
|
+
is checked by the same real-path, repository and registration boundary. Without
|
|
3625
|
+
a supplied directory, a reviewer may share the project checkout. The native
|
|
3626
|
+
process executes in that directory while its MCP environment retains the
|
|
3627
|
+
canonical project's hub binding. Launch/restore receipts keep canonical
|
|
3628
|
+
`projectRoot`, optional extra-instance `executionCwd` and observed `terminalRoot`
|
|
3629
|
+
separate. The terminal grouping root may be only that project root or the
|
|
3630
|
+
verified execution directory; exact live launcher, handle, incarnation and
|
|
3631
|
+
worktree evidence is still required. Native kind metadata alone never binds an
|
|
3632
|
+
extra instance. Revoked declarations or changed directories refuse reuse.
|
|
3633
|
+
Effective roles resolve from declaration roles, exact-id policy roles, kind policy
|
|
3634
|
+
roles, then definition defaults; launch validation uses the same order.
|
|
3635
|
+
|
|
3636
|
+
I2 recovery ceiling: a recovering extra Codex launcher records its launch row only
|
|
3637
|
+
after the authenticated start response supplies its execution-root binding. Until
|
|
3638
|
+
then, the coordinator retains durable pending terminal-creation and attachment-wait
|
|
3639
|
+
evidence; it never records an assumed checkout. Base Codex pre-start recording is
|
|
3640
|
+
unchanged. Earlier recording for extras requires independently verified exact-instance
|
|
3641
|
+
execution-root evidence. Past-commit resumes do not repeat pre-commit instance
|
|
3642
|
+
compatibility checks. Abort and stop-and-archive validate historical receipt structure
|
|
3643
|
+
and authenticated runtime ownership independently of mutable declarations; restore,
|
|
3644
|
+
fresh and reattach retain current declaration authority.
|
|
3645
|
+
|
|
3646
|
+
Routing expands a kind preference to its declared members and considers idle
|
|
3647
|
+
state, board WIP and queued load with stable ties. Exact manual candidates,
|
|
3648
|
+
reservations and nominations stay exact ids. Assignment and explain use the same
|
|
3649
|
+
pure decision and name the chosen instance. Reviewer independence compares
|
|
3650
|
+
families (the kind); an eligible other family takes precedence even when busy.
|
|
3651
|
+
Only when no other family is eligible may an assignment use its own family,
|
|
3652
|
+
recording `sameFamilyFallback=true` in assignment history. This independence rule
|
|
3653
|
+
also applies to an explicit same-family reviewer nomination. A declared owner of
|
|
3654
|
+
implement, bulk-edit or test work requires the current implementer role and positive
|
|
3655
|
+
host evidence tied to the actual adapter generation started in a verified noncanonical
|
|
3656
|
+
worktree; a role-only reload cannot promote a canonical reviewer process. External
|
|
3657
|
+
ids, including console recipients, retain their existing admission and explicit
|
|
3658
|
+
nomination behavior without acquiring native metadata or automatic kind expansion.
|
|
3659
|
+
|
|
3660
|
+
Quota readings, pause records and reset windows are shared by the definition's
|
|
3661
|
+
account (one account per kind in I2). Member telemetry retains its exact reporter
|
|
3662
|
+
id, native context remains per instance, and the shared account's quota pause,
|
|
3663
|
+
checkpoint, handoff and reset notice cover all its members. Existing manual
|
|
3664
|
+
pauses remain in force. A startup migration conservatively merges old alias
|
|
3665
|
+
pause rows, retaining their provenance and moves; no pause is discarded.
|
|
3666
|
+
Per-instance ports, native session paths, Pi tool ledgers and model relay
|
|
3667
|
+
callbacks do not borrow another instance's process or conversation.
|
|
3668
|
+
|
|
3669
|
+
Worktree facts and native turn snapshots use the validated execution checkout,
|
|
3670
|
+
while task and turn ids remain in the canonical hub database. An additive
|
|
3671
|
+
`turn_workspaces` receipt stores the exact extra-instance root and its snapshot
|
|
3672
|
+
fields atomically with turn creation. The legacy `turns` snapshot fields remain
|
|
3673
|
+
unknown for those rows, so an older CLI cannot restore their files into the
|
|
3674
|
+
canonical checkout. New readers hydrate the same public turn shape from the
|
|
3675
|
+
receipt. An absent receipt preserves historical external-peer undo behavior;
|
|
3676
|
+
an existing receipt requires the current trusted declaration and the same
|
|
3677
|
+
validated root before context changes or file restoration. Pruning a turn also
|
|
3678
|
+
prunes its workspace receipt. Review projections resolve converter programs, task
|
|
3679
|
+
paths and private-path policy in the execution checkout while their sandbox denies
|
|
3680
|
+
other canonical project file data, including when read_allow encloses that project.
|
|
3681
|
+
Overlap refusal remains conservative across
|
|
3682
|
+
separate worktrees; it may refuse an undo rather than assume independence.
|
|
3683
|
+
|
|
3684
|
+
The I2 seed contract amendment re-anchors only `roster-r-pi-override`,
|
|
3685
|
+
`roster-r-catalog`, `roster-result-stop-text`, `roster-detached-pi-recovery`,
|
|
3686
|
+
`data-pi-factory-wire`, `projection-local-trust`,
|
|
3687
|
+
`planning-reservation-supported` and `planner-reserved-status-row` to the
|
|
3688
|
+
contextual resolver, aggregate Pi ledger, execution directory and declared-id
|
|
3689
|
+
forms. Each keeps its id and named test and removes the same guarantee. The
|
|
3690
|
+
projection mutant still removes only `text_projection`; the status mutant still
|
|
3691
|
+
removes only reservations. The other 411 seeds and registry baseline are
|
|
3692
|
+
unchanged. The PR records every old and new search/replacement and its clean
|
|
3693
|
+
and mutant result, per the reviewer's explicit ruling.
|
|
3694
|
+
|
|
3695
|
+
## Amendment: roster membership in status, 2026-10-18 (#484)
|
|
3696
|
+
|
|
3697
|
+
- The authenticated `status` reply carries `roster: {peer, on}[]` for every supported peer, optional peers included, with the same `on` that `ahub roster list` shows. The field is additive, with no protocol bump; older CLIs ignore it.
|
|
3698
|
+
- Launchers that check membership before starting (`ahub jcode`, `ahub kimi --mode tui`) read it through `rosterInStatus` in `src/hub/status-roster.ts` (no imports, so the registry's native CLI entries add no cycle). A reply without the field (an older hub) is unknown: the launcher stops with an upgrade-or-restart remedy and starts nothing. It never reads unknown as off (the jcode bug) or as on (the dead kimi guard; daemon admission still refused off-roster Kimi, so that one was harmless).
|
|
3699
|
+
- `settings_get` stays console-only.
|
|
3700
|
+
- With declared headless instances, status includes each startup-bound extra id as well as every built-in and optional peer, with its own roster membership. No undeclared suffix acquires a row.
|
|
3701
|
+
|
|
3702
|
+
## Amendment: planner plan review and board governance, 2026-10-18 (#481 S9)
|
|
3703
|
+
|
|
3704
|
+
- The person's mode-boundary ruling separates board governance from lifecycle enforcement. WIP-at-accept and planner/person return of accepted work without work evidence apply in every `sdlc.mode`; only the current plan-review receipt gate uses enforce/refuse, advise/report and off/no gate. Existing lifecycle schema aliases and ordinary off-mode receipts are unchanged.
|
|
3705
|
+
- Tasks owns plan-review receipts, accepted-untouched returns and all offers/acceptances. Review evidence contains the planner, planning revision, recorded time and fixed-query GitHub issue metadata. An issue body or comments are never fetched or stored by this readback. A changed body edit time or planning revision invalidates the receipt; missing evidence remains unknown. The synchronous acceptance API cannot bypass the fresh enforce readback.
|
|
3706
|
+
- S1 person spec acceptance and S9 planner review remain independent. `acceptReviewed` reads both against one task snapshot before the acceptance write. A `done` that implicitly accepts proposed work checks WIP and both readbacks before any cohort or board write; the missing-spec refusal retains precedence over missing-plan admission. Off keeps its synchronous ungated acceptance path apart from the all-mode WIP rule.
|
|
3707
|
+
- The accepted-untouched exception is a distinct, revision-bound return transition with a screened reason. It preserves history and planning fields, withdraws former role requests and enables replanning. Historical acceptance still protects cancellation and undo. Done/check/review/integration evidence or branch/commit/PR/local/review artifacts refuses this exception; it does not grant a general planner unassign permission.
|
|
3708
|
+
- Grooming is an ids/codes-only read projection with repository-scoped comparisons, explicit unknown/truncated evidence and person-only actions rendered as commands. It does not infer a ruling from arbitrary task prose, fetch issue bodies, mutate dependencies or invoke a model. Limits are 500 task rows, 256 findings and eight metadata reads within four seconds; a future paginated repository resolver supplies exhaustive coverage.
|
|
3709
|
+
- Existing seeds and the registry baseline remain byte-identical. Source guards retain the original ordinary backlog and dependency floors outside the explicit untouched-return branch. S10/S11 and the remaining lifecycle slices are not implemented here.
|
|
3710
|
+
|
|
3711
|
+
## Amendment: the daemon's plugin bundle in status, 2026-10-18 (#502)
|
|
3712
|
+
|
|
3713
|
+
- The authenticated `status` reply carries `pluginBundle`, the absolute path of the plugin bundle the running daemon serves and checks against. It is additive, with no protocol bump.
|
|
3714
|
+
- `ahub jcode` and `ahub kimi --mode tui` write that path into their project MCP entries, read through `bundleInStatus` in `src/hub/status-roster.ts`, which accepts only an absolute path ending in `plugins/agent-hub/server.js`. Before this, they wrote the path of the CLI copy on PATH, which can be a different install than the daemon's (for example a global install against a retained release), so the daemon refused Jcode's entry as stale. A hub that reports no bundle gets the CLI's own copy, as before. Kimi's headless start removes the entry, so no path is involved.
|
|
3715
|
+
|
|
3716
|
+
## Amendment: spec acceptance, 2026-10-18 (#481 S1)
|
|
3717
|
+
|
|
3718
|
+
- `ahub sdlc accept <task> --issue <n> [--repo owner/repository]` is person-only (console-role `sdlc` op `accept`; agent shells and live tests are refused). The daemon reads `lastEditedAt` and `updatedAt` with a fixed GraphQL query and `Tasks.acceptSpec` stores `{repo, issue, lastEditedAt, updatedAt, acceptedAt}` as the receipt's `acceptance`; no issue body is fetched or stored. `hub_sdlc_record` refuses the field, and a receipt relinked to another repository or issue drops it.
|
|
3719
|
+
- Build entry (an `implement` or `bulk_edit` task's acceptance, its `hub_task_done` without a separate accept, a self-claim, or a non-person stage change into a build base) in enforce needs a current acceptance. `Tasks.accept` refuses a missing one synchronously; the daemon awaits `Tasks.specGate` first, and `done` and `specStageGate` await the same reread, which refuses a changed body (`lastEditedAt` differs; comments move only `updatedAt`) or an unreadable one. A self-claim without an acceptance stays assigned to the claimant, still proposed, until the person accepts the spec and the claimant accepts the task. A task that changed during a readback (flow, link, acceptance, owner or privacy) is refused before any write. Advise notifies instead, stage changes included; off reads nothing. PII tasks never read the issue, so in enforce their accepted spec reads as unknown, like their PR evidence.
|
|
3720
|
+
- Status shows `spec: {issue, state}` when the lifecycle is enabled and the receipt names an issue. It is not a readiness blocker, so existing approval and merge gates are unchanged.
|
|
3721
|
+
|
|
3722
|
+
### S9 redo admission clarification (#481, hub task #214)
|
|
3723
|
+
|
|
3724
|
+
An acceptance by the current owner since the latest ownership change retains its WIP slot for both in_progress updates and changes_requested redo, including re-accept and implicit done, in every mode. An unaccepted offer does not block that redo. Acceptance from a former ownership span gives no exemption. In enforce, changes_requested re-acceptance and done still re-read spec acceptance and plan-review freshness: an issue body edit requires renewed person acceptance and planner review before resubmission. This WIP exemption does not waive lifecycle review gates.
|
|
3725
|
+
|
|
3726
|
+
S9 privacy and notice ceilings: private build work with an issue ref remains inadmissible in enforce because its issue metadata cannot be read, with no metadata-free person override. Grooming pointers are coalesced per queued board revision but have no minimum delivery interval.
|
|
3727
|
+
|
|
3728
|
+
### S10 cost governance amendment (#481, hub task #215)
|
|
3729
|
+
|
|
3730
|
+
- Task plans carry explicit review scope (none/delta/full, bounded reviewer count) and CI scope (focused/full/reuse); S9 receipts copy the planner-selected values. None uses zero reviewers; other scopes use one to eight. Legacy scope is unspecified, readable and never guessed. Advise reports the gap; new enforce receipts require both scopes, while old scope-less receipts remain valid to their next planning revision. Omitted cost keys on an owner file-list update retain the reviewed scope; explicit prospective drift refuses enforce acceptance. Scope does not change reviewer authority or bypass CI; S2 owns actual conformance comparison.
|
|
3731
|
+
- Review admission is separate from #520 brief/coverage. Before done/cohort writes, enforce requires the task's exact PR head, successful configured checks (native default: both OS checks and seeded guards), and no unanswered pending bot thread. Resolution settles a thread; an unresolved thread needs a user reply after the last bot comment. Only metadata is fetched. Advise reports gaps, including a generic unknown-readiness notice when a private turn finishes its own PII task without remote metadata; ordinary work remains refused during a private turn. Off adds no readback. Identity/privacy/owner and runtime authority are rechecked across awaits and each external read. Background role maintenance may retain a saved role while holding an unadmitted review envelope; a manual reviewer resend performs fresh admission.
|
|
3732
|
+
- Whole-workflow repository serialization closes the admission race, keeping required check names and read-only permissions; queue:max retains up to 100 pending controllers instead of canceling the previous pending one. Identical-tree successful full proof is reused for PR and push. Reuse expands both OS matrix names and reports the required seeded aggregate, using only a `Reuse verified identical-tree full gate` marker step with the original run id. These successful reporting jobs and skipped jobs are not fresh full proof; duplicate active full gates and unknown active coverage refuse admission. Pending controllers do not run gates. CI proof searches are bounded; missed older success can require a new gate, never invent green evidence.
|
|
3733
|
+
- Cost reporting is read-only over bounded current public board links plus merged-PR/check metadata: review handoff rounds and elapsed time, CI run ids and extra attempts, full re-reviews versus deltas, and unknown scope. Private/relinked counterparts are excluded at each read and projection. Pure band-breach proposal data is delivered here; the S7 baseline/configuration/automatic board-card scheduler is deliberately not implemented in S10.
|
|
3734
|
+
- Nonblocking policy ceilings stay unchanged and are recorded in hub task #230: fail-closed metadata errors, repository-wide queue fairness, unknown thread author kinds, and strict advise readback races. Their planner-reviewed alternatives are deferred.
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# 0.12.35 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.35, control protocol 16 (unchanged), from merged main `ac6ff4e382abcec45b5dffcc1fc85f402383dccf`. The person directed the release on 2026-10-18, first so that #493 takes effect, then to ship all open PRs once merged.
|
|
8
|
+
|
|
9
|
+
- #493 (PR #495): a busy `ahub claude` session reads its queue with `hub_inbox`, sees fresh queued and important counts, and receives important messages mid-turn; `[FYI]` is forbidden for actionable messages.
|
|
10
|
+
- #484 (PR #500): `status` carries roster membership, and `ahub jcode` and `ahub kimi --mode tui` read it; an older hub is unknown, not off.
|
|
11
|
+
- #219 task (PR #499): the protected-segment grant test no longer grows with the set (test-only).
|
|
12
|
+
- #450 I2 (PR #497): declared headless peer instances with their own native and MCP identity, worktree execution roots for extra implementers, kind routing across instances, and account-shared quota.
|
|
13
|
+
- #481 S0+S8 (PR #496): the playbook lifecycle as the enabled default, gsd-lite retired into the `criteria` checklist, and a deprecation window until 0.13.0. Off keeps its #257 bytes.
|
|
14
|
+
- Still open (unchanged): live native clients, installed managed-Pi #418 AC8 (#142), #438 AC7, the native console settings leg (#439 AC5), a real upgrade with reattach (#463), a real upgrade with a managed terminal and cancelled rows (#478), and the live advise cycle of #481 AC9.
|
|
15
|
+
- New open legs:
|
|
16
|
+
- After installation, a busy `ahub claude` session reads its queue with `hub_inbox` and sees a steered important message before its turn ends (#493 D3, installed).
|
|
17
|
+
- A live run of two instances of one kind (#450 I4, #138).
|
|
18
|
+
|
|
19
|
+
## Reviews
|
|
20
|
+
|
|
21
|
+
| PR | Final head | Review | CI |
|
|
22
|
+
| --- | --- | --- | --- |
|
|
23
|
+
| #495 (#493) | 3730bf20 | planner plus an independent OCR pass | exact head, success |
|
|
24
|
+
| #500 (#484) | b4a1bd6b | codex, approved | exact head, success |
|
|
25
|
+
| #499 (#219) | a67fd222 | codex, approved | exact head, success |
|
|
26
|
+
| #497 (#450 I2) | 254ba163 | two fresh-context reviews (round 1: changes requested, B1-B5); round-2 fresh review, approved; merge-delta review | exact head, success (macOS watchdog job rerun once) |
|
|
27
|
+
| #496 (#481 S0+S8) | b1120f96 | codex: round 1 five P2s, round 2 one P1 (off-mode PII screen), round 3 approved | exact head, success (macOS #463 attach-timeout job rerun once; passes locally) |
|
|
28
|
+
|
|
29
|
+
## Document review
|
|
30
|
+
|
|
31
|
+
Round 1 checked 10 documents against #495, round 2 against #499 and #500, and round 3 13 stale documents against #497 and #496, read by a fresh-context reviewer and applied by the planner.
|
|
32
|
+
|
|
33
|
+
| Document | Result | Checked claims and correction |
|
|
34
|
+
| --- | --- | --- |
|
|
35
|
+
| `README.md` | corrected (round 1) | Status 0.12.35; the Jcode entry sentence's version; the verification link. Nothing #497 or #496 invalidates. |
|
|
36
|
+
| `docs/quickstart.md` | corrected | `v0.12.35` install. Upgrade paragraphs for #493 (session restart), #484, the #481 deprecation (`workflow`, the `phase` gate, `criteria` receipts) and #450 I2 instances. |
|
|
37
|
+
| `docs/operations.md` | corrected (rounds 1 and 2) | Busy channel sessions; the Jcode roster read. The #497 instance and #496 lifecycle sections match the code. |
|
|
38
|
+
| `docs/security.md` | corrected | `instances` is machine-local (read only from an untracked `config.local.json`) and refused from every surface; extras accept only `headless`. |
|
|
39
|
+
| `docs/sdlc.md` | corrected | The off schema-1 export, and the `phase` tool schema of off or older daemons. |
|
|
40
|
+
| `docs/specs/2026-09-19-agent-hub-design.md` | corrected | The #481 deprecation bullet: only `workflow = "gsd-lite"` and the `phase` gate warn; the `phase` receipt name is accepted silently. |
|
|
41
|
+
| `docs/agent-notes/tasks.md` | corrected | `checklistOf` screening and off compatibility; instance id resolution and family fallback; owner isolation proof. |
|
|
42
|
+
| `docs/agent-notes/budget.md` | corrected | Account-keyed quota, pause, checkpoint and handoff with per-member fanout; scope includes `instance-budget.ts`. |
|
|
43
|
+
| `docs/agent-notes/daemon.md` | corrected | Startup-bound declarations, execution roots, instance recovery and undo; scope includes the instance modules. |
|
|
44
|
+
| `docs/agent-notes/adapters.md` | corrected | Spawn identity per instance; an ACP kind only from the host declaration. |
|
|
45
|
+
| `docs/agent-notes/local-worker.md` | corrected | Scope includes the sandbox root in `instance-execution.ts`; no rule changed. |
|
|
46
|
+
| `docs/agent-notes/bus.md` | corrected (round 1) | Channel pull while busy; `WsPeer.steer` scope. No #497/#496 rule. |
|
|
47
|
+
| `docs/agent-notes/tests.md`, `benchmarks.md`, `README.md` | unchanged | #497/#496 touched only shared paths; no rule is wrong. |
|
|
48
|
+
|
|
49
|
+
`AGENTS.md` area notes and their `docs/verified.json` paths now list `instances.ts`, `instance-config.ts`, `instance-execution.ts` and `instance-budget.ts`. A separate manifest commit restamps the reviewed documents. The release PR must be merged with a merge commit so the stamps stay ancestors of the tag.
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# Busy Claude channel notification receipt (#493)
|
|
2
|
+
|
|
3
|
+
## Result
|
|
4
|
+
|
|
5
|
+
Positive native interactive receipt: Claude Code 2.1.302, Sonnet 5.5 (the native
|
|
6
|
+
`sonnet` alias), consumed a channel notification during the original busy turn.
|
|
7
|
+
The model called the observation tool with the exact random token before its
|
|
8
|
+
first `end_turn`. This supports important-only channel steering in the tested
|
|
9
|
+
interactive mode. It does not prove an arbitrary notification was read merely
|
|
10
|
+
because its stdout write succeeded, nor does it prove delivery in print mode.
|
|
11
|
+
|
|
12
|
+
## Native experiment
|
|
13
|
+
|
|
14
|
+
- A new scratch project outside the repository used one explicitly selected
|
|
15
|
+
development MCP channel, `busy-probe`. The harness preserved the executing
|
|
16
|
+
agent marker, removed live hub binding variables, loaded no project/user
|
|
17
|
+
settings or hooks, and exposed only three fixed fixture tools. It connected
|
|
18
|
+
neither to the person's hub nor to another peer.
|
|
19
|
+
- The original instruction called `probe_hold`, then `probe_after_hold`, then
|
|
20
|
+
finished with `DONE`. It also asked the model to report any actually observed
|
|
21
|
+
channel token, without inventing one. The token was generated only after
|
|
22
|
+
`probe_hold` started; neither the prompt nor the hold result contained it.
|
|
23
|
+
- While that tool was pending, the MCP server wrote
|
|
24
|
+
`notifications/claude/channel` with `priority: important` and the random token.
|
|
25
|
+
The fixed hold result contained only `ready: true`.
|
|
26
|
+
- The interactive run used a real PTY. The operator confirmed that this was a
|
|
27
|
+
locally written development channel. No trust or tool-approval prompt was
|
|
28
|
+
answered automatically, and no second model prompt was sent. After the
|
|
29
|
+
original response completed, the operator exited with Ctrl-D.
|
|
30
|
+
|
|
31
|
+
| Evidence | UTC on 2026-10-18 |
|
|
32
|
+
| --- | --- |
|
|
33
|
+
| Native tool barrier entered | 07:25:36.997 |
|
|
34
|
+
| Notification written while tool pending | 07:25:37.298 |
|
|
35
|
+
| Fixed hold result released | 07:25:38.801 |
|
|
36
|
+
| Correct token received by observation tool | 07:25:41.948 |
|
|
37
|
+
| First original assistant `end_turn`, `DONE` | 07:25:43.016 |
|
|
38
|
+
|
|
39
|
+
The native transcript's zero-based record positions were 29 for the hold call,
|
|
40
|
+
49 for the matching observation call, and 52 for the first original `end_turn`.
|
|
41
|
+
The observation was after the tool barrier released but before that original
|
|
42
|
+
turn ended. The TUI also displayed the channel notification during its busy
|
|
43
|
+
indicator. Native exit was 0; process-table verification found no remaining
|
|
44
|
+
probe-owned native, helper or MCP server processes. The 90-second deadline did
|
|
45
|
+
not fire.
|
|
46
|
+
|
|
47
|
+
The automatic resource controller initially deferred on ordinary Teams/Jump
|
|
48
|
+
Desktop processes with no repository attribution. Manual inspection identified
|
|
49
|
+
their application origins and confirmed normal memory/thermal state, CPU idle
|
|
50
|
+
above 50%, no competing repository job and one probe worker. No existing app
|
|
51
|
+
was stopped. Native account/session metadata writes were not suppressed or
|
|
52
|
+
audited; this receipt does not claim the native client made no home-directory
|
|
53
|
+
writes.
|
|
54
|
+
|
|
55
|
+
## Preserved evidence
|
|
56
|
+
|
|
57
|
+
Private run artifacts are retained under workspace-relative
|
|
58
|
+
`scratchpad/temp/ahub-493-probe/interactive-zaTWkS/`; the invocation receipt points
|
|
59
|
+
to the native client's own transcript. Raw account/profile paths and the random
|
|
60
|
+
token are not copied into this document.
|
|
61
|
+
|
|
62
|
+
| Artifact | SHA-256 |
|
|
63
|
+
| --- | --- |
|
|
64
|
+
| `receipt.json` | `5108a491e3469baf9de67860d7d3fff37b5eb89b980fa9f1835ff28510f524b7` |
|
|
65
|
+
| `server-events.jsonl` | `43b079866ec2c8ac0437d51d2fd50549fec035b1a76feaa8c20142a58cdb1258` |
|
|
66
|
+
| `native-tui.log` | `2fc9182a355038c0b26d662054ee7abee9fda78569ea6b07893afeb44fd6da51` |
|
|
67
|
+
| `pty-events.jsonl` | `5ab8c672ea56512a6bdce111fe6960fc85ceb47ff88d7a1b17d528b1fdb10229` |
|
|
68
|
+
| Native transcript | `0acfd6f66ec20f0cb5ad4fe020d044e326c240289019785c15f3af64ca188ede` |
|
|
69
|
+
|
|
70
|
+
Token SHA-256:
|
|
71
|
+
`ea4326fdc248ddc69ba250005a472f5393c2250b1876fbe039cbef0561125d08`.
|
|
72
|
+
|
|
73
|
+
An earlier isolated print/stream-json run (`run-YwEcfC`) initialized the same
|
|
74
|
+
channel and wrote a notification while the hold tool was pending, then finished
|
|
75
|
+
without an observation call. That result remains inconclusive for interactive
|
|
76
|
+
delivery. It was not treated as a negative, and steering was added only after
|
|
77
|
+
the positive interactive receipt above.
|
|
78
|
+
|
|
79
|
+
## Implementation boundary
|
|
80
|
+
|
|
81
|
+
- A channel-capable attached `WsPeer` exposes steer only while it owns a push
|
|
82
|
+
socket; detach and pull-only attachment remove that capability. The bus admits
|
|
83
|
+
important work only, retains its existing pause/recovery/uncertainty holds and
|
|
84
|
+
removes the queued item before transport hand-off.
|
|
85
|
+
- A steered notification uses the ordinary delivery id, connection generation,
|
|
86
|
+
accepted receipt and explicit completion/correlated-reply contract. A transport
|
|
87
|
+
failure stays uncertain. An idle transition must not deliver it again.
|
|
88
|
+
- Queued ordinary work can be read through `hub_inbox` during a busy turn using
|
|
89
|
+
the existing atomic pull completion path. This does not settle a previously
|
|
90
|
+
accepted push. Fake-transport regressions cover these contracts separately
|
|
91
|
+
from this native observation.
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# 0.12.36 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.36, control protocol 16 (unchanged), from merged main `6e39b616`. The person directed the release once every open PR had merged (2026-10-18/19).
|
|
8
|
+
|
|
9
|
+
- #502 (PR #504): the Jcode and Kimi TUI launchers write the running daemon's plugin bundle into their MCP entries; `status` reports the bundle.
|
|
10
|
+
- #481 S1 (PR #503): person-only spec acceptance bound to the issue edit time; in enforce, build work starts only from a current acceptance.
|
|
11
|
+
- #450 I3 (PR #505): declared Claude reviewer and planner channel instances with per-instance launch, session, context and recovery records.
|
|
12
|
+
- #481 S9 (PR #518): planner grooming, plan-review receipts, WIP admission in every lifecycle mode, untouched-work return.
|
|
13
|
+
- #450 / hub task #223 (PR #506): a headless Claude reviewer that runs a fresh `claude -p` session per review, with review-only delivery, verdict authority fenced to the running child, and process-group cleanup.
|
|
14
|
+
- #517 (PR #521): Claude turn completion read from the transcript's last 4 MiB; a console notice when no completed turn is found in that tail.
|
|
15
|
+
- #520 (PR #522): the hub-built review brief in every review request, `hub_review` coverage with a mode-following gate, and `ahub review brief`.
|
|
16
|
+
- #481 S10 (PR #523): plan review and CI scopes, the premature-review gate, identical-tree CI reuse with reporter jobs for the required check names, and the cost report.
|
|
17
|
+
- #450 / hub task #223 (PR #524, found by this release's document review): `ahub claude --as <id>` asks the hub to start a headless reviewer (`ahub start`, named by #506, never existed), `ahub stop` stops it, and stop replies name `ahub <kind> --as <id>` for every instance.
|
|
18
|
+
- Still open (unchanged): live native clients, installed managed-Pi #418 AC8 (#142), #438 AC7, the native console settings leg (#439 AC5), a real upgrade with reattach (#463), a real upgrade with a managed terminal and cancelled rows (#478), the live advise cycle of #481 AC9, the installed #493 D3 leg, and the live two-instance run (#450 I4, #138).
|
|
19
|
+
- New open legs:
|
|
20
|
+
- A live headless review with a real Claude account: fresh session, read-only tools, the `Read` deny rules for private paths, and the verdict recorded as `fresh` (#223).
|
|
21
|
+
- A live long session over 32 MiB going idle after a Stop (#517).
|
|
22
|
+
- Deferred to backlog: #230 (S10 P3s: fail-closed reuse decision, one repository-wide queue, ghost thread authors, advise races).
|
|
23
|
+
|
|
24
|
+
## Reviews
|
|
25
|
+
|
|
26
|
+
| PR | Final head | Review | CI |
|
|
27
|
+
| --- | --- | --- | --- |
|
|
28
|
+
| #504 (#502) | b26ca1ea | codex, approved | exact head, success |
|
|
29
|
+
| #503 (#481 S1) | 5b22c841 | codex, approved | exact head, success |
|
|
30
|
+
| #505 (#450 I3) | 091689ac | codex: three rounds, then a merge-delta approval | exact head, success |
|
|
31
|
+
| #518 (#481 S9) | 1d2a9ac8 | planner via OCR delegation (Kimi out of quota, read-only Claude subagent): round 1 one P2 (redo blocked by WIP), round 2 approved | exact head, success |
|
|
32
|
+
| #506 (#223) | e305a17e | codex: four rounds (privacy, authority, lifecycle and process-group findings), then rebase-delta approval | exact head, success |
|
|
33
|
+
| #521 (#517) | 7ae00959 | codex: round 1 one P2 (newline-less cut tail), round 2 approved; bot P1/P2 fixed, delta approved | exact head, success |
|
|
34
|
+
| #522 (#520) | c35222f6 | codex: three rounds of findings (task escalated once by the hub's rejection rule; the person directed the planner to finish it), then approvals of the rebase and CI-fix deltas | exact head, success |
|
|
35
|
+
| #524 (#223 start/stop) | 9408ebde | codex: approved, plus a delta approval after the bot's P2 (offline reply command); codex also ran a real CLI/daemon fixture for start, refusal and stop | exact head, success |
|
|
36
|
+
| #523 (#481 S10) | 65ae2705 | planner via OCR delegation (read-only Claude subagent): round 1 P1 (advise PII done) and P2 (reuse missing required names), round 2 approved | exact head, success; a real identical-tree reuse run (39168948253) reported the required names and the PR merged on them |
|
|
37
|
+
|
|
38
|
+
## Document review
|
|
39
|
+
|
|
40
|
+
Ten documents were stale against 03209040, and the agent-notes README became stale through `daemon.md`. Two fresh-context reviewers read them against the eight PRs above; the planner applied the corrections.
|
|
41
|
+
|
|
42
|
+
| Document | Result | Checked claims and correction |
|
|
43
|
+
| --- | --- | --- |
|
|
44
|
+
| `README.md` | corrected | Status 0.12.36; the Jcode entry sentence now says the command writes the running hub's plugin bundle (#502); the verification link and the open live legs (#223, #517, #523 added). |
|
|
45
|
+
| `docs/quickstart.md` | corrected | `v0.12.36` install. "Upgrading to 0.12.36": restart Claude sessions, the review brief and `coverage` (#520), WIP admission in every mode with `tasks.wip_limits` (#481 S9), the enforce-only gates (S1 acceptance, plan review, coverage, premature review), the #502 entry refresh, instances and #517. |
|
|
46
|
+
| `docs/operations.md` | corrected | Version and upgrade commands 0.12.36; the review brief and coverage in the two-agent review section; #517 in the busy-session section; WIP in every mode; the S1, S9 and S10 commands in the SDLC section; the #502 bundle path in the Jcode section. The headless reviewer's start and stop came with #524. `tasks.wip_limits` corrected to apply live (settings.ts, config-apply.ts and the per-admission read in daemon.ts), after the release review. |
|
|
47
|
+
| `docs/security.md` | corrected | Instance start-mode limits per kind (#505, #506); a new paragraph on review-only delivery and the headless reviewer's flags, read-only tools, `Read` deny rules and verdict fence (#223); the brief's privacy and merge-base rules, metadata-only GitHub reads, and the unchanged CI permissions (#520, #523). |
|
|
48
|
+
| `docs/agent-notes/adapters.md` | corrected | `reviewerVariant` joined the restricted-field list; rules for TUI launchers writing the hub's bundle (#502) and for `ClaudePrintPeer`'s authority and cleanup (#223). |
|
|
49
|
+
| `docs/agent-notes/budget.md` | corrected | Per-peer Claude context and session files through `claudeStateFile`; usage stays one shared file (#505). |
|
|
50
|
+
| `docs/agent-notes/bus.md` | corrected | `relevant` may return a discard reason; review-only delivery kept at send and at delivery (#223). |
|
|
51
|
+
| `docs/agent-notes/daemon.md` | corrected | Per-instance launch file name; instance transcript evidence; `claudeStateFile` and `ownTerminalRow`; channel extras never hub-started and `requireActiveInstance`; Stop verification only through the tail reader (#517). |
|
|
52
|
+
| `docs/agent-notes/tasks.md` | corrected | Scope adds `src/hub/review-brief.ts`; rules for `reviewAuthority` in `valid()`, the coverage gate's pins and merge-base reads, owner refusal of `routing.reviewOnly`, and the untouched-return exception. |
|
|
53
|
+
| `docs/agent-notes/tests.md` | corrected | The `seeded guards` job also passes on a verified identical-tree reuse (#523); headless-reviewer tests never run the real `claude`. |
|
|
54
|
+
|
|
55
|
+
| `docs/agent-notes/README.md` | no change | Stale only because `daemon.md`, a tracked path, changed; its console exact-row background still matches `daemon.md`. |
|
|
56
|
+
|
|
57
|
+
`AGENTS.md` lists `src/hub/review-brief.ts` under tasks and `src/hub/usage.ts` under daemon.
|
|
58
|
+
|
|
59
|
+
## Checks
|
|
60
|
+
|
|
61
|
+
- Each merged PR's exact-head CI passed (table above). The release branch merges main `6e39b616` cleanly; the bundle is rebuilt with the pinned Bun 1.4.2 and is fresh; `tsc` is clean.
|
|
62
|
+
- `node scripts/check-docs.mjs --require-fresh` runs after the restamp and before the tag.
|
|
63
|
+
|