@staix/agent-hub 0.14.0 → 0.16.0
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 +42 -0
- package/README.md +23 -9
- package/docs/agent-notes/README.md +8 -0
- package/docs/agent-notes/adapters.md +21 -4
- package/docs/agent-notes/budget.md +6 -4
- package/docs/agent-notes/bus.md +1 -0
- package/docs/agent-notes/daemon.md +20 -9
- package/docs/agent-notes/local-worker.md +2 -2
- package/docs/agent-notes/tasks.md +21 -4
- package/docs/agent-notes/tests.md +6 -3
- package/docs/dogfood.md +19 -5
- package/docs/events.md +21 -7
- package/docs/memory.md +78 -10
- package/docs/operations.md +197 -39
- package/docs/profiles.md +1 -0
- package/docs/quickstart.md +16 -6
- package/docs/sdlc.md +17 -0
- package/docs/security.md +110 -21
- package/docs/smoke.md +7 -3
- package/docs/specs/2026-09-19-agent-hub-design.md +156 -16
- package/docs/verification/2026-10-23-0.15.0.md +80 -0
- package/docs/verification/2026-10-23-daemon-responsiveness.md +44 -0
- package/docs/verification/2026-10-23-headless-claude-permissions.md +47 -0
- package/docs/verification/2026-10-23-terminal-claude-execution-root.md +41 -0
- package/docs/verification/2026-10-24-always-ask-adapters.md +52 -0
- package/docs/verification/2026-10-24-amem-runtime.md +69 -0
- package/docs/verification/2026-10-24-codex-0164-reviewer-isolation.md +55 -0
- package/docs/verification/2026-10-24-delivery-holds-ac8.md +264 -0
- package/docs/verification/2026-10-24-hardcoded-values.md +2108 -0
- package/docs/verification/2026-10-25-0.16.0.md +82 -0
- package/docs/verified.json +40 -19
- package/package.json +2 -2
- package/plugins/agent-hub/.claude-plugin/plugin.json +1 -1
- package/plugins/agent-hub/server.js +3109 -2046
- package/src/adapters/acp.ts +46 -7
- package/src/adapters/claude-channel.ts +26 -4
- package/src/adapters/claude-implementer.ts +243 -0
- package/src/adapters/claude-print-child.ts +90 -0
- package/src/adapters/claude-task-sessions.ts +80 -0
- package/src/adapters/codex-appserver.ts +69 -1
- package/src/adapters/compat.ts +6 -2
- package/src/adapters/conformance/enrollment.ts +2 -1
- package/src/adapters/conformance/fakes/acp-server.ts +3 -1
- package/src/adapters/definitions/builtin-metadata.ts +17 -5
- package/src/adapters/definitions/native-channel-state.ts +1 -1
- package/src/adapters/definitions/native-cli-entry-claude.ts +13 -8
- package/src/adapters/definitions/native-cli-entry-types.ts +2 -0
- package/src/adapters/definitions/native-factories.ts +8 -0
- package/src/adapters/kimi-wire-usage.ts +303 -0
- package/src/adapters/local-worker.ts +5 -4
- package/src/adapters/registry-types.ts +8 -4
- package/src/adapters/registry.ts +14 -2
- package/src/adapters/reviewer-print.ts +30 -53
- package/src/cli/console-config.ts +123 -0
- package/src/cli/console-state.ts +48 -3
- package/src/cli/console-symbols.ts +3 -2
- package/src/cli/console-usage.ts +5 -2
- package/src/cli/console.ts +30 -2
- package/src/cli/facts-hook.ts +9 -5
- package/src/cli/help.ts +10 -7
- package/src/cli/identity.ts +3 -1
- package/src/cli/launch.ts +10 -4
- package/src/cli/main.ts +91 -19
- package/src/cli/memory.ts +119 -7
- package/src/cli/output.ts +40 -4
- package/src/cli/reset.ts +1 -1
- package/src/cli/settings-edit.ts +89 -0
- package/src/cli/terminal-recovery.ts +1 -6
- package/src/hub/action-class.ts +211 -17
- package/src/hub/action-enforce.ts +90 -0
- package/src/hub/action-policy.ts +40 -17
- package/src/hub/ask.ts +16 -4
- package/src/hub/board.ts +110 -31
- package/src/hub/budget-notes.ts +65 -0
- package/src/hub/budget.ts +44 -7
- package/src/hub/bus.ts +6 -6
- package/src/hub/claude-launch-proof.ts +33 -0
- package/src/hub/code-facts.ts +56 -16
- package/src/hub/conductor.ts +5 -2
- package/src/hub/config-apply.ts +12 -0
- package/src/hub/config-edit-host.ts +173 -0
- package/src/hub/config-edit.ts +282 -0
- package/src/hub/config-tier.ts +89 -0
- package/src/hub/control-client.ts +24 -3
- package/src/hub/daemon.ts +614 -104
- package/src/hub/deliverable-files.ts +131 -0
- package/src/hub/deliverables.ts +125 -0
- package/src/hub/delivery-journal.ts +18 -2
- package/src/hub/envelope.ts +1 -1
- package/src/hub/events.ts +5 -3
- package/src/hub/hub-tools.ts +22 -6
- package/src/hub/instances.ts +7 -4
- package/src/hub/kimi-usage.ts +156 -0
- package/src/hub/lifecycle.ts +10 -5
- package/src/hub/manager.ts +1 -1
- package/src/hub/memory-code-head.ts +44 -0
- package/src/hub/memory-code-overlay.ts +119 -0
- package/src/hub/memory-plan-guard.ts +10 -1
- package/src/hub/memory-stale-anchors.ts +159 -0
- package/src/hub/memory-symbols.ts +74 -0
- package/src/hub/peers.ts +7 -0
- package/src/hub/permission-payload.ts +15 -0
- package/src/hub/planning.ts +10 -4
- package/src/hub/read-tools.ts +21 -3
- package/src/hub/routing.ts +118 -3
- package/src/hub/sdlc.ts +34 -0
- package/src/hub/settings.ts +18 -3
- package/src/hub/settled-roles.ts +15 -3
- package/src/hub/task-sweep.ts +25 -3
- package/src/hub/tasks.ts +551 -75
- package/src/hub/token-window.ts +46 -0
- package/src/hub/usage-rollup.ts +16 -6
- package/src/hub/window-kind.ts +13 -0
- package/src/hub/workflow.ts +16 -0
- package/src/local/tools.ts +5 -5
- package/src/memory/brief.ts +22 -12
- package/src/memory/capture.ts +26 -40
- package/src/memory/client.ts +137 -65
- package/src/memory/recall.ts +13 -22
- package/src/ui/index.html +215 -19
package/docs/operations.md
CHANGED
|
@@ -730,7 +730,7 @@ stay first. Stream: one aligned row per event (time, kind, sender, body in monos
|
|
|
730
730
|
the section head, above the scrolling list. Memory: result rows show title, kind and age, the selected row is marked with an accent
|
|
731
731
|
edge, and the graph and the detail pane use the colour tokens. Settings: each group is a section with a short header, a key that waits
|
|
732
732
|
for a restart carries a "restart pending" badge, and "Pending restart" shows a count; the text lines, Preview, Save and Undo are as
|
|
733
|
-
they were. Message uses the shared form styles.
|
|
733
|
+
they were. A Structure group edits structural configuration in a settings session (#689, see Structural configuration below). Message uses the shared form styles.
|
|
734
734
|
|
|
735
735
|
Icons replace the symbol glyphs: the star mark, the stream arrow and the Office "checking" mark are sprite icons (twelve Tabler icons
|
|
736
736
|
in all), and the Office draws each condition (idle, busy, offline, paused, waiting on approval) as a shape (ring, disc, cross, bars, raised hand)
|
|
@@ -1087,7 +1087,7 @@ approved; caught (changes were requested and the owner's redo was approved);
|
|
|
1087
1087
|
contradicted (within a week, work on the same file or symbol failed its check
|
|
1088
1088
|
or review); escalated (after the reviewer asked for changes). A record counts
|
|
1089
1089
|
tasks, not verdicts. `ahub task show <id>` lists a task's outcomes and `ahub
|
|
1090
|
-
route explain` shows each reviewer's record with the implementer. With
|
|
1090
|
+
route explain` shows each reviewer's record with the implementer. `ahub route explain <id>` also prints the planner walk (`planner candidate X: ...` lines, then `planner: X (rotation | named | kept)`): the rotation among the rostered planner holders by task id (#525-3), shown for information, since nothing records or enforces a per-task planner yet. A peer that accepted or finished a task never reviews it; when every eligible reviewer did, the person reviews and the trace says so. With
|
|
1091
1091
|
`"review": { "adaptive": true }` in `.agenthub/config.json`, reviewers with at
|
|
1092
1092
|
least `min_reviews` (5) reviews of that implementer in the class are ordered by
|
|
1093
1093
|
how their reviews held up, ahead of quota but after idle before busy; off by
|
|
@@ -1244,16 +1244,16 @@ ahub usage limits [--peer <id>] [--limit <n>] [--json] # current quota windows
|
|
|
1244
1244
|
ahub usage total [--json] # lifetime development tokens since the first event, per peer and overall
|
|
1245
1245
|
```
|
|
1246
1246
|
|
|
1247
|
-
The daemon folds `events.jsonl` into `usage_rollup`, `token_rollup` and `limit_events` from a stored byte offset, at most 8 MiB per pass
|
|
1247
|
+
The daemon folds `events.jsonl` into `usage_rollup`, `token_rollup` and `limit_events` from a stored byte offset, at most 8 MiB per pass, with a 20 ms scheduling slice checked between whole records (one record is indivisible),
|
|
1248
1248
|
only whole lines, and each pass commits its rows and the new offset together, so a crash repeats a pass and never half-applies one. A rebuild
|
|
1249
|
-
from byte 0 gives the same rows (tested). A log that was replaced by a shorter one is folded again from the start.
|
|
1249
|
+
from byte 0 gives the same rows (tested). A log that was replaced by a shorter one is folded again from the start. Before time slicing, on this project's 47 MB,
|
|
1250
1250
|
238k-line log the first fold took about 170 ms and a `usage` command about 95 ms, against about 150 ms for `ahub report --by task`, which
|
|
1251
1251
|
rescans the whole file on each call.
|
|
1252
1252
|
`issue`, `pr` and `release` are the board's current links of each task, read when you ask, so a task linked later is counted under its issue
|
|
1253
1253
|
for the history it already spent. A task with no link, and a record with no task, are `unattributed`.
|
|
1254
1254
|
|
|
1255
1255
|
Every number names its source: `native` (the provider's own counter), `hub count` (the hub's own `tokens` increments, which cover peers that
|
|
1256
|
-
report no usage record, such as Jcode
|
|
1256
|
+
report no usage record, such as Jcode), or `unknown`. Kimi's rows are `native`: the hub reads Kimi's own per-request counters from its session wire log and records them as `kimi_wire` usage records (#285 phase 2). Unknown is never shown as 0. `TOTAL` includes cache reads and `WITHOUT CACHE`
|
|
1257
1257
|
removes them; Claude's total is the sum of its four reported counters because its transcript carries none (`ahub report` still shows it as unknown), and a source whose input already
|
|
1258
1258
|
contains the cached part (Codex, the gateway) gets no derived total. A lifetime total that mixes a native and a hub-counted peer is labelled
|
|
1259
1259
|
`hub count`. When a peer is unknown the overall figure is `partial, at least`: a lower bound that leaves the named peers out, never a sum that counts them
|
|
@@ -1285,7 +1285,7 @@ ahub task label 12 reverted # a later verdict (ok, regressed, reverted, i
|
|
|
1285
1285
|
|
|
1286
1286
|
## Hub memory
|
|
1287
1287
|
|
|
1288
|
-
The hub opens the selected memory profile under `memoryHome()` (default `~/.agenthub/memory/`)
|
|
1288
|
+
The hub opens the selected amem memory profile under `memoryHome()` (default `~/.agenthub/memory/`), with no claude-mem worker dependency ([how it works](memory.md)): notes saved
|
|
1289
1289
|
against an open task are short-term; when the task is approved its decisions, contracts and fails become long-term.
|
|
1290
1290
|
Task briefs, session-start recall and `ahub ask` read it first, and the dashboard has a Memory section.
|
|
1291
1291
|
|
|
@@ -1298,9 +1298,9 @@ ahub memory forget 1a2b3c4d # a person's; also promote, demote, sup
|
|
|
1298
1298
|
|
|
1299
1299
|
`"memory": { "native": false }` in `.agenthub/config.json` turns it off for a project.
|
|
1300
1300
|
|
|
1301
|
-
The exact-pinned `@staix/agent-mem` 0.
|
|
1301
|
+
The exact-pinned `@staix/agent-mem` 0.7.0 resolves `AMEM_HOME`, then `$AGENTHUB_HOME/memory`, then `~/.agenthub/memory`. An absent `M/profile.json` selects shared v1; an explicit generation selects `M/generations/G` with the package's readonly legacy bridge. All daemon memory consumers and the hub memory/goal CLI use that selected profile. Invalid metadata or a missing selected generation makes native memory unavailable while the bus and board continue; there is no fallback to legacy writes. Inspect the daemon's memory binding/availability before interpreting missing memory as an empty store.
|
|
1302
1302
|
|
|
1303
|
-
The daemon checks its selector at hub operation entry and before candidate/counter writes. It does not hot-switch handles or provide an atomic fence against selection changes during an in-flight core call. Quiesce consumers and close their handles before migration or selection changes; reopen through the supported session-preserving lifecycle afterward. Candidate/counter storage remains `M/candidates.db`, independent of `G`; `amem review` on a generation
|
|
1303
|
+
The daemon checks its selector at hub operation entry and before candidate/counter writes. It does not hot-switch handles or provide an atomic fence against selection changes during an in-flight core call. Quiesce consumers and close their handles before migration or selection changes; reopen through the supported session-preserving lifecycle afterward. Candidate/counter storage remains `M/candidates.db`, independent of `G`; since agent-mem 0.7.0 `amem review` also lists and accepts candidates on a selected generation. Every running hub using this home needs an authenticated receipt: a matching ready binding, or a generation-capable unbound receipt (`disabled` when native memory is off, `unavailable` when opening failed) proving it holds no memory handle. An unbound daemon and zero running hubs are quiesced for memory; a stale bound handle, unreadable registry or unknown runtime is not ready. Existing JSON memory/goal results remain unchanged; the additive binding receipt belongs to daemon status, profile-check and the decay object. This source integration does not authorize installing a new runtime, migrating real memory, restarting sessions or claiming real-machine sync/capture receipts. Migration/deactivation and their limits belong to [agent-mem](https://github.com/STAIxBWLB/agent-mem); see [the hub profile contract](memory.md#selected-memory-profile).
|
|
1304
1304
|
|
|
1305
1305
|
Run `ahub memory profile-check [--json]` from the person's terminal for the read-only preflight. It identifies live registry owners by signed process identity and authenticated daemon replies, then reports their loaded memory package and bound home/profile. The receipt names the current `AGENTHUB_HOME` registry scope; zero results establish no live daemon in that inventory, not system-wide process absence. Inventory and check separate custom registries too when they share `AMEM_HOME`. A missing or unreadable runtime receipt never counts as a different home or permission to migrate.
|
|
1306
1306
|
|
|
@@ -1310,7 +1310,7 @@ A curated split (`amem migrate --shards`) writes `M/shards.json`; from 0.12.37 t
|
|
|
1310
1310
|
|
|
1311
1311
|
Managed agents read through `hub_memory_search`, `hub_memory_show` and `hub_memory_graph`, with the server's project identity, the `memory_read` capability and current privacy screening. They cannot supply another project; private turns are refused. The tools bound UTF-8 input/output, screen before counts and truncation, and exclude their arguments/results from hub-managed capture. `hub_memory_correct` has its own `memory_correct` capability and records a screened correction candidate, not a note change. See [the complete memory contract](memory.md) for caps and refusal semantics.
|
|
1312
1312
|
|
|
1313
|
-
Review candidates and rendered/delivered/cited counters stay in machine-local `M/candidates.db`, outside sync, import, recall, briefs, ask and graph evidence. Public changes-requested reviews with unmet items may propose a fail candidate; missing cause/retry details stay unknown.
|
|
1313
|
+
Review candidates and rendered/delivered/cited counters stay in machine-local `M/candidates.db`, outside sync, import, recall, briefs, ask and graph evidence. Public changes-requested reviews with unmet items may propose a fail candidate; missing cause/retry details stay unknown. Acceptance is a person's `amem review` action with its TTY/policy checks, on shared v1 and, since agent-mem 0.7.0, on a selected generation. Read-time `(stale?)` hints and plan-fail advice never change stored rows or task authority. Structured fail notes are validated against 4000 UTF-8 bytes before screening or writes, with no silent truncation.
|
|
1314
1314
|
|
|
1315
1315
|
Recall presentation omits generated task-approval outcome notes and shows only nonempty reasons from generated changes-requested notes; an ordinary decision that merely resembles a header stays visible. Contracts and fails remain eligible. Capped recall lines preserve memory headers and end at word boundaries, and one delivery deduplicates ids across restored/current prefaces and shared note lines. Stored notes and brief evidence are unchanged; platform recall retains its budget split.
|
|
1316
1316
|
|
|
@@ -1606,11 +1606,24 @@ stays the default until an evaluation says otherwise (`docs/cooperbench.md`).
|
|
|
1606
1606
|
|
|
1607
1607
|
## Always-ask action policy foundation (#636)
|
|
1608
1608
|
|
|
1609
|
-
The classifier, local configuration and session budget counter
|
|
1609
|
+
The classifier, local configuration and session budget counter decide. The managed Claude PreToolUse hook (including the headless Claude implementer, #525-4), ACP permission requests with a host gate, received Codex command approval requests, and the hub-owned local/Pi tool boundary consume the same policy. Jcode still has no hub pre-tool approval path and remains listed as not enforceable. A default-on policy adds a pre-tool check only where the hub sees the call before it runs, and each peer's status row says whether it does.
|
|
1610
1610
|
|
|
1611
|
-
|
|
1611
|
+
What is enforced, and where it is not:
|
|
1612
1612
|
|
|
1613
|
-
|
|
1613
|
+
| Peer | Enforced | Not enforceable (the status row says why) |
|
|
1614
|
+
| --- | --- | --- |
|
|
1615
|
+
| Claude (`ahub claude`) | the managed PreToolUse hook returns `ask` for a classed call in `ask`, `ask-when-needed` and `never-ask` alike, and `ask` beats every allow the hook would add | a session with no hub permission hook, or one whose attached session has not yet run it (the launch record outlives the process, so it proves nothing alone: the status row says `no live Claude session has run the hub permission hook yet`); an `--unattended` launch (`--dangerously-skip-permissions` skips every permission check, hooks included); a hub that cannot answer the hook leaves Claude's own policy |
|
|
1616
|
+
| Kimi and other hub-owned ACP peers with a host approval gate (headless) | `session/request_permission` for a classed call is never auto-approved (not even for a hub-owned tool title), carries `Action approval (<classes>): <command>`, withholds `allow_always`, and under `ahub --unattended` still waits for a person and expires as a denial | a peer in its native `ask-when-needed` (`yolo`) or `never-ask` (`auto`) mode: Kimi sends no request for a call that mode allows, so the hub cannot see it; the status row says `its native mode never-ask sends no request for a call it allows`. Switch the peer to `ask` to enforce. A request whose payload the agent did not report is not classed (unknown follows the mode) |
|
|
1617
|
+
| Claude headless implementer | the managed hook asks for classed calls, and the current-child-bound prompt tool accepts only a person's allow-once or denial; ask and ask-when-needed retain their native requirements | an idle/offline implementer without a current child; never-ask and unattended are refused at startup |
|
|
1618
|
+
| Codex app-server | received command approval RPCs (v2 command execution or legacy exec) are classed before reaching the TUI; a classed request offers only allow-once/deny and an explicit bounded class-budget choice | status conservatively says not enforceable: native policy can execute without emitting an approval request; never-ask sends approvalPolicy never. writeStdin, absent/unknown payloads, file-change and permission-profile requests retain native handling |
|
|
1619
|
+
| Local worker and Pi | every model tool call is classed at the host permit boundary before never-ask, ask-when-needed or Pi's tool-wide grant; unattended never answers a classed request. Pi replayed call ids return the stored result without spending again | an offline local worker or Pi without a verified live bridge; Pi's verified person-authored idle shell remains the person's command, not a model tool call |
|
|
1620
|
+
| Jcode | no hub pre-tool approval path | always-ask not enforceable; its unmanaged native policy remains authoritative |
|
|
1621
|
+
|
|
1622
|
+
Class budgets: the approval of a classed ACP, received Codex command, local or Pi call offers one extra choice, `Allow <class> xN for this session`, when the class budget is above one. Only that choice (never an ordinary allow) spends the ledger: it allows this call and the next N-1 of the same classes in the same native session, then asks again; several requests open at once share it, so a budget of N never lets more than N approved calls through. A new native session, a changed policy or a stopped, crashed or restarted peer starts from zero, even when it resumes the same session id. A budget of one is the single call the ordinary allow already covers. Claude's own permission dialog cannot carry that choice, so every classed Claude call asks. Local/Pi show the complete tool title plus its class on the person's console, including private turns. Other surfaces retain the screened public view. Any view that remains cut (`[cut, N chars]`) or withheld offers denial only, with no allow-once or class-budget choice.
|
|
1623
|
+
|
|
1624
|
+
Only ignored, untracked `.agenthub/config.local.json` can hold `action_policy`. Its optional keys are `enabled` (default true), `always_ask` (a distinct subset of publish, external-write, destroy, install; default all), and `budgets` (per-class integers 0..1000; defaults 1, 5, 3, 2 respectively). Shared `config.json` cannot set this policy and gets no confirmation offer. A tracked or unknown-trust local file is ignored. Use `ahub settings set action_policy.enabled <true|false>` or `ahub settings set action_policy.budgets.<class> <n>` for registered settings; change `always_ask` in the local file and use the existing confirmed terminal reload. Policy publication invalidates cached grants and pending approval challenges. Startup reads the untracked local policy without a retained confirmation. A policy that disables enforcement, omits a class or increases a class budget appends an attention notice to every status policy row. `ponytail:` this makes weakened startup policy visible, but the startup confirmation ceiling remains open; the upgrade is retained person-bound startup confirmation.
|
|
1625
|
+
|
|
1626
|
+
The ledger asks first and after the approved class budget is spent. Adapter integrations must request that class allowance explicitly; an ordinary one-time answer does not seed the cache, and a cached budget never suppresses a prompt required by the native mode. One approval includes its own invocation; budget zero asks for every invocation. A fresh native session resets counters, and status polls do not bind sessions. A command with no classed literal prefix retains native permission handling; around a shell expansion the literal words are classed, and where the opaque part could change the class the strictest reachable class applies (#756, #762; [security](security.md)). This foundation never changes a sandbox or bypasses a denied permission; per-adapter enforcement tests land with their integrations.
|
|
1614
1627
|
|
|
1615
1628
|
## Permission modes for running peers
|
|
1616
1629
|
|
|
@@ -1797,7 +1810,9 @@ if another write replaces that record, preview again. For busy roster removal,
|
|
|
1797
1810
|
the panel names `ahub roster remove <peer> --now`, which explicitly stops an owned
|
|
1798
1811
|
runtime or detaches a native session during its active turn; the panel does not force it.
|
|
1799
1812
|
Esc cancels, and pasted confirmation text cannot
|
|
1800
|
-
write. This panel uses the current authenticated daemon connection.
|
|
1813
|
+
write. This panel uses the current authenticated daemon connection. `c` edits
|
|
1814
|
+
structural configuration and `R` prefills `restart` while a restart is pending
|
|
1815
|
+
(see [Structural configuration](#structural-configuration-from-the-console-and-the-dashboard-issue-689)).
|
|
1801
1816
|
|
|
1802
1817
|
The dashboard's Settings section and `ahub settings` show and change the same
|
|
1803
1818
|
closed list of settings (issue #269). Run them from a plain terminal:
|
|
@@ -1828,7 +1843,7 @@ A guarded file edit that the daemon keeps at its accepted value remains visible
|
|
|
1828
1843
|
| Switches | `task_sweep.enabled`, `.auto_reassign`, `.interval_s`, `.unaccepted_min`, `.idle_min`, `.review_min`, `.ready_min`, `.ladder_min`, `.no_writes_turns` | `config.local.json` | live; `.no_writes_turns` sets the turn threshold independently; other keys reschedule the sweep timer |
|
|
1829
1844
|
| Routing | `tasks.wip_limits.<peer>` | `config.local.json` | live |
|
|
1830
1845
|
| Routing | `tasks.escalate_after` (1-10, default 3: consecutive `changes_requested` before a task moves to the next `escalate_to` peer) | `config.local.json` | live; the next verdict uses it |
|
|
1831
|
-
| Roles | `planner` (
|
|
1846
|
+
| Roles | `planner` (one or up to eight planner holders) | `config.local.json` | at once |
|
|
1832
1847
|
|
|
1833
1848
|
- Writes go only to `.agenthub/config.local.json` and `.agenthub/routing.local.toml`,
|
|
1834
1849
|
the machine-local files (`ahub init` ignores both in git). The shared
|
|
@@ -1885,12 +1900,46 @@ Pi relay model aliases (`pi.dgx_coding`, `pi.dgx_fast`) and `routing.pi` retain
|
|
|
1885
1900
|
waits for `y` in `ahub console` at each hub start. Tool approvals stay
|
|
1886
1901
|
deny-only for Pi and local in every session.
|
|
1887
1902
|
- Commands and binaries, credential files, gateway URLs and the local worker's
|
|
1888
|
-
reach are never editable here:
|
|
1903
|
+
reach are never editable here: change them with `ahub settings edit` in a
|
|
1904
|
+
terminal, each confirmed by typing its name (tier 3 below), or edit
|
|
1905
|
+
`.agenthub/config.local.json` yourself.
|
|
1889
1906
|
- Every change is announced in `hub.log` and open consoles with its source and
|
|
1890
1907
|
recorded as a `settings` event. `ahub settings` needs a running hub; an older
|
|
1891
1908
|
hub answers the request as unknown and the CLI advises upgrading. The unified
|
|
1892
1909
|
dashboard (`ahub ui --all`) acts as an ordinary session.
|
|
1893
1910
|
|
|
1911
|
+
### Structural configuration from the console and the dashboard (issue #689)
|
|
1912
|
+
|
|
1913
|
+
Instances, the review and approval blocks and the lifecycle can be edited without an editor. The hub reads the candidate with the loaders it starts with (`readInstanceConfig` and `validateInstances`, `loadConfig` with its effective-config bounds, `checkJcodeInstanceHomes`, `sdlcConfig`), shows a diff and writes only after a person confirms. Three tiers:
|
|
1914
|
+
|
|
1915
|
+
1. **Registry settings** (everything above) are unchanged.
|
|
1916
|
+
2. **Structural keys**, editable in the console and in a dashboard settings session:
|
|
1917
|
+
- `instances.<id>` with `kind`, `roles`, `start_mode`, `review_mode`, `readOnly`, `worktree` and `permission_mode`, in `config.local.json`;
|
|
1918
|
+
- `review.adaptive`, `review.min_reviews`, `review.pool`, `review.rerotate`, `snapshots.keep`, `approvals.timeout_s` and `context.gate`, in `config.local.json`;
|
|
1919
|
+
- `mode` and `required_checks` in `.agenthub/sdlc.toml`. Only those two lines change: comments and every other table stay as written, and a layout the editor cannot change faithfully (a key repeated, or one inside a multi-line string) is refused with its own reason.
|
|
1920
|
+
|
|
1921
|
+
`roster.*`, `tasks.wip_limits.*`, `permission_modes`, `peers` and the rest of the registry keep their own `ahub settings set` path.
|
|
1922
|
+
3. **Executable and secret-locating keys** are console only: the rest of `NEVER_EDITABLE` (`kimi_cmd`, `jcode_cmd`, `codex_bin`, `pi.cmd`, `checks`, `mlx`, `omniroute`, `terminal`, `adapters`, `adapter_modules` and the like) and the Jcode instance fields `jcode_home`, `provider`, `model` and `provider_profile`. The console shows "this runs code with the daemon's rights, or chooses where secrets are read from" and writes only when the key's exact name is typed, one key at a time; `--yes` never confirms one. The dashboard lists each of them with the console command that changes it and nothing else: no value, no path, no input. A forged dashboard request for one is refused by the hub.
|
|
1923
|
+
|
|
1924
|
+
In the console (`ahub console`, Settings tab `6`): `c` asks what to edit (`1` an instance, `2` the lifecycle, `3` another key), asks each field, shows the hub's diff or its loader reason, asks for a reason, then `y`. Esc cancels at any step, and pasted text never confirms. `R` appears while a restart is pending and prefills `restart`; the command still asks its own `y`. In the dashboard, open `ahub ui --settings`: the Structure group has the same forms; outside a settings session it is read only.
|
|
1925
|
+
|
|
1926
|
+
```bash
|
|
1927
|
+
ahub settings edit config.local.json set instances.codex-review '{"kind":"codex","roles":["reviewer"],"start_mode":"headless","review_mode":"fresh"}' --reason "add the fresh reviewer"
|
|
1928
|
+
ahub settings edit sdlc.toml set mode '"enforce"' --preview
|
|
1929
|
+
ahub settings edit config.local.json remove review.pool --yes
|
|
1930
|
+
ahub settings backups # the newest backups of each file
|
|
1931
|
+
```
|
|
1932
|
+
|
|
1933
|
+
Rules:
|
|
1934
|
+
- A missing `start_mode` on the fresh `codex-review` reviewer shows the loader's reason (`fresh requires reviewer-only roles, headless mode ...`), names the field and writes nothing.
|
|
1935
|
+
- The edit carries the revision (a sha256, or `absent`) of the file it was read from. The hub checks it when it plans the edit and again immediately before it writes, so a file changed on disk since is refused with a hint to reload and review again.
|
|
1936
|
+
- The previous file is kept in `<state dir>/config-backups/` (the newest five of each file; `ahub settings backups` lists them) and the new one replaces it atomically. A `config.local.json` that git tracks is never written. Unknown fields and unknown keys are refused by name, never dropped.
|
|
1937
|
+
- A whole instance that holds a native home, account or model (`jcode_home`, `provider`, `model`, `provider_profile`) is tier 3 to remove or replace, so a dashboard can neither see nor delete those values; an existing instance changes leaf by leaf (`instances.<id>.<field>`), and `clear` removes one field. A preview or write shows a tier 3 value only as `(set)`, and a write changes exactly one tier 3 key, counting the keys the file adds (removing two Jcode instances is two writes, each confirmed by its own typed name). The audit record gives a tier 3 key no value hash at all, because a model or provider name is easy to recover from an unsalted hash; the file revisions bind the change instead. An instance already in `config.local.json` is changed leaf by leaf even before a restart has started it. If `.agenthub` or `config.local.json` is a symlink, the Settings view reports its revision as `unavailable` and no edit is planned. An edit of `sdlc.toml` keeps the file's own line endings.
|
|
1938
|
+
- Every write records a `config_edit` event: the file, each key path with a short hash of its value before and after (never a value), the file revisions before and after, the tier, the source (`dashboard` or `terminal`) and `by: person`. The notice and `hub.log` name key paths only.
|
|
1939
|
+
- A changed instance declaration is restart-bound: it is listed as `pending restart` (`instances`) and takes effect at the next hub start. A changed `sdlc.toml` is read once at start and is listed as `sdlc.mode` or `sdlc.required_checks` until the running hub holds the same value. `review`, `snapshots`, `approvals` and `context.gate` publish through the one reload path, one key at a time.
|
|
1940
|
+
- Person only: an agent shell or a hub tool is refused (`ahub settings` is a console command in the identity gate, and the three control requests answer only the console role). Recovery or shutdown holds every edit.
|
|
1941
|
+
- The hub must run this release: an older hub answers `unknown message` and the command says to upgrade and restart it.
|
|
1942
|
+
|
|
1894
1943
|
## Start modes: TUI by default, headless as opt-in
|
|
1895
1944
|
|
|
1896
1945
|
A peer that has a TUI the hub attaches to starts in it by default (issue #269).
|
|
@@ -2056,6 +2105,24 @@ A budget pause remains authoritative until the budget command explicitly
|
|
|
2056
2105
|
overrides it or the window resets. Check `ahub status` and `ahub board` after
|
|
2057
2106
|
a pause or handoff.
|
|
2058
2107
|
|
|
2108
|
+
`ahub budget` (#285 phase 4) prints one row per window and a line for every attached peer that has no number. The KIND column says what the
|
|
2109
|
+
number is, and SOURCE where it came from; MEASURED is its age.
|
|
2110
|
+
|
|
2111
|
+
| Kind | Meaning | Source examples |
|
|
2112
|
+
| --- | --- | --- |
|
|
2113
|
+
| `native` | the provider's own ratio and reset | `claude status line`, `codex rateLimits`, `kimi ACP usage-limit refusal` |
|
|
2114
|
+
| `count` | tokens the hub counted, against a ceiling a person set | `hub count, kimi wire log, of kimi_tokens_5h 800000` (window `tokens`) |
|
|
2115
|
+
| `manual` | a person fed it with `ahub budget set <peer> <0..1> [--window 5h\|week] [--resets-in 2h]` | `ahub budget set` |
|
|
2116
|
+
|
|
2117
|
+
A count never claims to be the provider's quota. For one window and peer a manual value replaces the provider's at the gate, and while any native
|
|
2118
|
+
or manual reading is fresh the count is shown as `info only` and does not gate or feed routing headroom; when those go stale, or reset, the
|
|
2119
|
+
count gates again. A provider's hard refusal clears the person's number for that window, so a pause is never outvoted. A peer without a number says
|
|
2120
|
+
why instead: Pi and local print `no quota: on-prem ... has no provider quota` with the hub's own 5 h token count (information, never a meter);
|
|
2121
|
+
Kimi without `budget.kimi_tokens_5h` says it reports context occupancy only; an unreadable Kimi wire log says so with a reason code; a peer whose
|
|
2122
|
+
source has not reported yet says which. `--json` carries `kind`, `source`, `superseded` and a `peers` list of those notes; an older hub answers
|
|
2123
|
+
without them and the CLI classifies a window by its source. `ahub doctor` adds the row `kimi usage source` (counting, no ceiling, or unreadable).
|
|
2124
|
+
The console's peer detail (Enter on Peers) and the Usage detail, and the dashboard's Usage budgets row, show the same kind and source per window.
|
|
2125
|
+
|
|
2059
2126
|
Kimi Code CLI 2.1.1's observed 5-hour usage-limit refusal creates a hard budget reading (`kimi ACP usage-limit refusal`). `ahub status` shows a budget pause and `ahub budget` shows its source and reset estimate. The refusal gives no reset timestamp, so the hub estimates the reset at five hours after it was observed and resumes on the next budget tick after the existing one-minute grace. With `budget.wait_max_min` below that estimate, the existing budget relay automatically hands open tasks to an attached eligible peer; routing skips Kimi while paused. No checkpoint is requested from an exhausted agent.
|
|
2060
2127
|
`ahub budget resume kimi` overrides the reading so the provider can be tried early. A new provider refusal ends that override and pauses it again; a pending soft checkpoint cannot postpone this hard pause.
|
|
2061
2128
|
During one hub run, an early override followed by the same window's refusal keeps its earlier future reset bound; a provider's explicit reset remains authoritative. A restored pause without a per-window reading cannot identify that earlier window, so its next refusal starts a new estimate.
|
|
@@ -2214,14 +2281,16 @@ dashboard manager does the same when its home directory vanishes.
|
|
|
2214
2281
|
|
|
2215
2282
|
## The planner (#455)
|
|
2216
2283
|
|
|
2217
|
-
|
|
2218
|
-
backlog and sweep notices. `ahub status`
|
|
2219
|
-
|
|
2284
|
+
Planner holders propose and split tasks and read project-wide grooming. Each
|
|
2285
|
+
task's effective planner gets its backlog and sweep notices. `ahub status`
|
|
2286
|
+
prints the holders with their source, the dashboard's Agents view shows a
|
|
2287
|
+
Planner badge, and the console marks their rows.
|
|
2220
2288
|
|
|
2221
2289
|
- `setting`: `planner` in `.agenthub/config.json` or `config.local.json` (the
|
|
2222
|
-
machine's file wins)
|
|
2223
|
-
the role.
|
|
2224
|
-
|
|
2290
|
+
machine's file wins), either one id or a list of up to eight distinct ids.
|
|
2291
|
+
Only those peers hold the role. Builtins are `claude`, `codex`, `kimi`, `qwen`
|
|
2292
|
+
and `jcode`; a declared planner-capable instance is also eligible. A singleton
|
|
2293
|
+
settings write stores a string for older configuration readers.
|
|
2225
2294
|
- `roles`: with no `planner` key, the `roles` planners stand. That is `claude`
|
|
2226
2295
|
by default.
|
|
2227
2296
|
- `automatic`: when no rostered peer holds the role, the hub gives it to the
|
|
@@ -2230,9 +2299,39 @@ dashboard's Agents view shows a Planner badge, and the console marks its row.
|
|
|
2230
2299
|
|
|
2231
2300
|
Change it with `ahub settings set planner codex`, the dashboard Settings row
|
|
2232
2301
|
(a settings session, `ahub ui --settings`) or `l` in the console. Planning
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2302
|
+
holders and their backlog notices update at once. Use a comma list, for example
|
|
2303
|
+
`ahub settings set planner claude,codex`, to select several holders and follow
|
|
2304
|
+
any displayed holder-change confirmation. Role text updates at the next peer
|
|
2305
|
+
start. `ahub settings undo` restores the previous designation. Agents cannot
|
|
2306
|
+
change it.
|
|
2307
|
+
|
|
2308
|
+
New tasks record their planner through the same pure assignment walk shown by
|
|
2309
|
+
`ahub route explain`. Only that effective planner or the person changes their
|
|
2310
|
+
planning. A bound holder keeps authority while busy, offline or paused. If it
|
|
2311
|
+
is removed or leaves the roster, authority falls back to the current holders;
|
|
2312
|
+
the stored binding remains available for audit. Old tasks and releases with a
|
|
2313
|
+
null planner retain the legacy holder-wide authority. PII tasks keep null.
|
|
2314
|
+
The person names a different holder with
|
|
2315
|
+
`ahub task assign <id> <peer> --role planner`; this leaves the owner, reviewer,
|
|
2316
|
+
state and delivery offer intact. A planner-created release belongs to that
|
|
2317
|
+
planner; a person-created release keeps null.
|
|
2318
|
+
|
|
2319
|
+
A plan review is the exception: another settled holder may review a plan even
|
|
2320
|
+
when it is not that task's planner, without gaining its other planning powers.
|
|
2321
|
+
An agent author cannot self-review while another rostered non-offline planner
|
|
2322
|
+
exists. With no independent holder, the receipt says `selfReview: true`; it
|
|
2323
|
+
also records `planAuthor` (null when unknown). A person's own-plan override is
|
|
2324
|
+
marked self-review too. Independent requests contain ids only. Controlled
|
|
2325
|
+
recovery requires `task_planners` once a list/instance planner is configured or
|
|
2326
|
+
any task/release binding or plan-review authorship marker is stored, even after
|
|
2327
|
+
that configuration is removed.
|
|
2328
|
+
|
|
2329
|
+
With the lifecycle on (an `.agenthub/sdlc.toml` mode other than off), a card's planners get a "The board
|
|
2330
|
+
changed" notice (#758). The planner whose own write changed the board is skipped.
|
|
2331
|
+
A planning revision, a dependency change or a new card is a task notice; state
|
|
2332
|
+
moves, reviews and assignments are recorded at `fyi` weight (no turn), at most
|
|
2333
|
+
once per planner per ten minutes. A newer notice replaces an unsettled copy, and
|
|
2334
|
+
the hub's own bookkeeping tells nobody.
|
|
2236
2335
|
|
|
2237
2336
|
## Resetting a project's hub
|
|
2238
2337
|
|
|
@@ -3291,8 +3390,11 @@ unreadable result runs the main gate again and refuses release. A manual
|
|
|
3291
3390
|
it is never accepted as full-gate evidence. A `timing_runs=20` dispatch runs only the daemon, PII screen and ACP
|
|
3292
3391
|
test files twenty times on macOS, in its own concurrency group; it does not replace the full gate. Each PR has its own CI concurrency group, so PRs run side by side; within a PR a newer pending run replaces the older pending one and an admitted run is never cancelled; main pushes and dispatches keep queueing every run. Two groups admitting the same tree at once may run it twice, never a false green (#609). `scripts/check.sh --changed [<base>]` runs every non-test step but only the affected test files, and the full suite when it cannot tell; the full gate stays CI's (#610).
|
|
3293
3392
|
`scripts/check.sh` stops a suite still running after `AHUB_CHECK_HANG_S` seconds
|
|
3294
|
-
(960 by default); hosted CI sets 1080 on Linux
|
|
3295
|
-
|
|
3393
|
+
(960 by default); hosted CI sets 1080 on Linux inside a 25-minute job limit and 1440
|
|
3394
|
+
on macOS inside a 30-minute one (#378, #593, #752).
|
|
3395
|
+
The `closing-refs` workflow fails a PR whose title, body or commit messages would make
|
|
3396
|
+
GitHub close an issue the text only mentions (`Refs #N`, a negated or qualified keyword);
|
|
3397
|
+
an issue linked only in the sidebar passes (#760).
|
|
3296
3398
|
The gate holds `<git common dir>/ahub-heavy.lock` across every worktree of a
|
|
3297
3399
|
repository. A second gate waits up to `AHUB_CHECK_LOCK_WAIT_S` (1800 seconds by
|
|
3298
3400
|
default; 0 fails immediately) and names the holder. A holder whose PID is gone
|
|
@@ -3328,9 +3430,12 @@ ownership, bind servers or start agents, sidecars or models.
|
|
|
3328
3430
|
`ahub status`, `ahub tail` and the dashboard show native context occupancy,
|
|
3329
3431
|
source and measurement freshness. Claude readings come from the status-line
|
|
3330
3432
|
tee installed by `ahub claude`; Codex readings come from its current thread's
|
|
3331
|
-
native token-usage updates. Kimi
|
|
3332
|
-
(`{used, size}`, source `acp_usage_update`)
|
|
3333
|
-
|
|
3433
|
+
native token-usage updates. Kimi's context occupancy comes from its ACP `usage_update`
|
|
3434
|
+
(`{used, size}`, source `acp_usage_update`), not consumption, so no token total is counted from it. Its consumption is counted from its
|
|
3435
|
+
session wire log (`<kimi home>/sessions/.../agents/*/wire.jsonl`, #285 phase 2) and reported as the `tokens` window of
|
|
3436
|
+
`budget.kimi_tokens_5h` (source `hub count, kimi wire log, of kimi_tokens_5h N`; cache reads are not counted); an unreadable log shows
|
|
3437
|
+
unknown with one notice, never a short count. Until the OAuth probe or `ahub budget set kimi ...` feeds the plan quota, the provider's
|
|
3438
|
+
own 5 h and weekly ratios stay unknown. Not yet verified live against Kimi's `/usage` (#285 AC11); the adapter accepts the
|
|
3334
3439
|
update whenever it names the current session, because 2.1.1's source text
|
|
3335
3440
|
emits it after the turn settles (read from the source, not yet observed live
|
|
3336
3441
|
through the hub; docs/smoke.md), so the peer may already be idle.
|
|
@@ -3642,6 +3747,8 @@ A bundled adapter module is authorized by the person with `adapter_modules` (at
|
|
|
3642
3747
|
# Acceptance-criteria checklist (#481)
|
|
3643
3748
|
|
|
3644
3749
|
- The task reviewer/person records a head-bound `criteria` receipt with criterion ids matching the issue's AC ids, required/result fields and hashed evidence refs. This checklist belongs to the Compliance review pass. Use `ahub sdlc record <id> '<receipt JSON>'`; [schema and example](sdlc.md#acceptance-criteria-checklist).
|
|
3750
|
+
- Deliverables (#509a, docs/sdlc.md, Deliverable records): `hub_task_done` and `hub_sdlc_record` take `deliverables: [{path, format, version?}]`; the hub hashes the files itself (a claimed hash is refused), in a plain folder with no git or PR, under the owner's execution root (its own worktree for a declared worktree instance; an unproven root refuses and reads `unknown`), and a reviewer's approval is refused with `deliverable changed since it was delivered` when a file changed since delivery (the owner calls `hub_task_done` again, or the person approves the current bytes). `ahub task show <id>` shows each file's state (`unchanged`, `changed`, `missing`, `unknown`) and `changedSinceReview`; a PII task or `pii.paths` file shows id, hash and size only. The person lists every task's delivered and approved files with `ahub deliverables [--task <id>] [--approved] [--check] [--json]`: without `--check` it reads the board's records and opens no file; `--check` measures them now and marks a row `changed since review`, `a file is missing` or `could not be measured`. The dashboard card shows a `Deliverables n` chip and the task sheet a Deliverables group from the same records; it shows a change only after a live check. An agent's shell is refused (#317).
|
|
3751
|
+
- The review request lists the recorded criteria with their ids and results, and a `hub_review` unmet item that starts with a recorded id (`AC2: ...`) is recorded on the verdict as `unmetCriteria` (#507b); `ahub task show` lists those ids in the history. A task with no checklist, and a PII task, are unchanged.
|
|
3645
3752
|
- Advise shows incomplete/stale checklist blockers; enforce checks them at approval. The `criteria` gate does not need a workflow selector. Dependencies stay with `ahub task propose --after`; checklist task import is removed.
|
|
3646
3753
|
- `status <id>`, `explain <id>` and `export <id>` use the same current board/config projection. Export keeps sanitized state and source hashes, with no external text, extra authority or verification claim.
|
|
3647
3754
|
- Migration from the retired workflow and its compatibility window (until hub 0.13.0) are described in [Retired workflow compatibility](sdlc.md#retired-workflow-compatibility-252-481-s8). Stored checklist task lists are ignored with a visible note; they never change board dependencies.
|
|
@@ -3747,7 +3854,7 @@ are described below. Native planner-cycle evidence remains unverified.
|
|
|
3747
3854
|
|
|
3748
3855
|
## Planning and phased releases (#263)
|
|
3749
3856
|
|
|
3750
|
-
Use `ahub backlog list` to read public staged work, then `ahub backlog plan <id>
|
|
3857
|
+
Use `ahub backlog list` to read public staged work (a table by rank with the reserved owner, dependencies and cut titles, then a count by reserved owner; `--full` and piped output keep whole titles and `--json` prints the raw listing), then `ahub backlog plan <id>
|
|
3751
3858
|
<revision> <fields-json> <reason>` to set rank, priority (0-3), release id, planned
|
|
3752
3859
|
start/due UTC milliseconds or pin. `pin` accepts true/false; `undo` needs the
|
|
3753
3860
|
current revision and latest eligible edit. The dashboard provides local-time
|
|
@@ -3762,8 +3869,8 @@ only after every member is approved, cancelled or moved out; it runs no tag or p
|
|
|
3762
3869
|
The dashboard shows phase progress, blocking dependencies, dates and remaining
|
|
3763
3870
|
work. Actual task dates come from execution/review/approval history, never input.
|
|
3764
3871
|
|
|
3765
|
-
Configured planners read `hub_backlog_list` and `hub_release_list`, edit
|
|
3766
|
-
`hub_backlog_plan`, and undo their own latest eligible change with
|
|
3872
|
+
Configured planners read `hub_backlog_list` and `hub_release_list`, edit the
|
|
3873
|
+
cards they plan (see "The planner") with `hub_backlog_plan`, and undo their own latest eligible change with
|
|
3767
3874
|
`hub_backlog_undo`. Catalog guidance or a caller-supplied role grants no authority.
|
|
3768
3875
|
PII cards stay stubs, reasons are screened/withheld in public history, and planning
|
|
3769
3876
|
telemetry records ids/changed fields without prose. #247 task records carry
|
|
@@ -4134,8 +4241,19 @@ An extra Claude instance is one you start yourself: declare it with `roles` (for
|
|
|
4134
4241
|
terminal. It keeps its own `claude-*.claude-review.json` state files. A planner or reviewer instance reads the
|
|
4135
4242
|
project checkout and refuses `worktree`. From #525-1 an `implementer` or `verifier` instance is accepted and
|
|
4136
4243
|
requires its own `worktree` (for example `"claude-impl": { "kind": "claude", "roles": ["implementer"],
|
|
4137
|
-
"worktree": ".worktrees/claude-impl" }`).
|
|
4138
|
-
|
|
4244
|
+
"worktree": ".worktrees/claude-impl" }`). `ahub claude --as claude-impl` validates that registered branch worktree and starts Claude there while keeping its canonical hub connection. Its private launch record stores the execution root. The channel reports its own canonical cwd (verified model-free with Claude 2.1.309); the daemon grants owner isolation only when that root, the current launch id, the recorded root and its own worktree validation all agree. Missing, legacy or mismatched evidence still permits a channel attachment, but write-owner routing is refused with `owner admission: declared write owner requires a verified isolated execution root`. Status shows the isolation refusal. A detach, replacement claim or launch-record change invalidates the proof. Facts and permission grants use the verified execution root; an unverified implementer gets no automatic grant. Recovery records retain that execution root, checked against the current declaration, separately from the Orca grouping root. This is same-user launch evidence, not kernel filesystem isolation. A Claude instance holding only planner or reviewer roles still uses the canonical checkout. A headless Claude reviewer retains its reviewer-only declaration. A headless implementer is available with the separate declaration below (#525-4).
|
|
4245
|
+
|
|
4246
|
+
A headless Claude implementer (#525-4) is declared separately:
|
|
4247
|
+
|
|
4248
|
+
```json
|
|
4249
|
+
"claude-impl": { "kind": "claude", "roles": ["implementer"], "start_mode": "headless", "worktree": ".worktrees/claude-impl", "permission_mode": "ask" }
|
|
4250
|
+
```
|
|
4251
|
+
|
|
4252
|
+
Create and register the attached-branch worktree first; the hub never creates it implicitly. `ahub claude --as claude-impl` asks the hub to start the instance and returns. Idle holds no native child. Task deliveries use a persisted UUID per task: first `--session-id`, later `--resume`. Unscoped chat reuses a session only when exactly one task is in progress for the instance; otherwise it is ephemeral. Positive missing-transcript evidence starts fresh with a notice; unknown read evidence retains the id. Reset includes the per-peer session map. A child inbox read refuses a queued batch attributed to another task and leaves it queued for that task's own session.
|
|
4253
|
+
|
|
4254
|
+
Both permission modes use native `default`, managed settings/hooks and the instance's strict tools-mode MCP binding. `ask` routes writes and shell calls to the person's approval. `ask-when-needed` may explicitly allow safe project file tools through the facts hook in the execution root; protected configuration, paths outside that worktree and shell/git writes still ask. There is no `acceptEdits` or `never-ask` bypass. A failed hook decides nothing and may be followed by a valid person allow. Prompt failure, timeout, disconnect and a stale child binding never grant permission. Approvals use the existing console and `approvals.timeout_s`; no answer returns deny. A stop holds uncertain delivery until the owned process group is confirmed gone; a failed cleanup keeps the peer busy.
|
|
4255
|
+
|
|
4256
|
+
The [native permission receipt](verification/2026-10-23-headless-claude-permissions.md) covers Claude Code 2.1.309 with a deterministic loopback fixture and no real account/model call. It is not sandbox proof or a runtime receipt gate. The real account/model/person interaction remains a separate live leg.
|
|
4139
4257
|
|
|
4140
4258
|
A headless Claude reviewer is run by the hub instead (#223): declare
|
|
4141
4259
|
`"claude-review": { "kind": "claude", "roles": ["reviewer"], "start_mode": "headless" }`
|
|
@@ -4169,7 +4287,7 @@ From 0.12.37 reviews can rotate across fresh headless Claude and Codex reviewers
|
|
|
4169
4287
|
|
|
4170
4288
|
Start them with `ahub claude --as claude-review`, `ahub codex --as codex-review` and `ahub kimi --as kimi-review`; stop with `ahub stop <id>`. For the Claude and Codex reviewers the command asks the running hub to start the reviewer and returns: nothing runs in that terminal, it takes no launch arguments, and `--print-command` or `--dry-run` prints a hub-start note instead of a launch (#720). Fresh Claude and Codex variants share the project checkout; the Kimi variant runs in a clean temporary working directory and reviews only the screened brief and host facts. All fresh variants refuse a custom worktree or permission mode. Codex and Kimi require `review_mode: "fresh"`; without it, an existing headless instance with the reviewer role keeps its native app-server/ACP behavior, worktree and permission options and does not join this pool. Claude retains its #223 automatic headless-reviewer declaration. The agy reviewer slot remains automatically unavailable (`agy is an implementer peer (#485)`). A failed or unsupported fresh start never downgrades to a native continuing session. Ordinary implementer instances retain their own adapters. The default logical pool order is Claude, Codex, Kimi. Only configured kinds with at least one declared reviewer count as slots, including declared ones that are offline, paused, quota-limited or failing, so availability never renumbers them; configured kinds with no declaration are listed after the walk as `no declared reviewer`. `review.rerotate` defaults to false. Pool selection starts at PR number modulo the number of declared kind slots, or task id when there is no PR, then skips the implementer's family and unavailable candidates. Delta review prefers the preceding eligible independent family in a fresh child. A preceding same-family fallback does not outrank a newly available independent family. `ahub route explain` shows the same pure walk.
|
|
4171
4289
|
|
|
4172
|
-
Codex requires a verified `codex-cli` (0.146.0 or 0.
|
|
4290
|
+
Codex requires a verified `codex-cli` (0.146.0, 0.163.0 or 0.164.0) or one the person trusts on this machine, and a passing bounded runtime receipt before its model child starts. 0.146.0 and 0.163.0 passed the [2026-10-22 model-free production admission](verification/2026-10-22-codex-reviewer-isolation.md) and 0.164.0 the [2026-10-24 one](verification/2026-10-24-codex-0164-reviewer-isolation.md). A refusal names the installed and verified versions. Either set `codex_bin` to a verified executable, or run `ahub agents trust codex-review <version>`: trust lifts only the version pin, and every proof below still runs before each child (#691). The producer checks native binary/config stability, configured MCP inventory with only the two hub tools, effective Apps/plugins/hooks disablement, an explicit empty legacy `notify` command and a named filesystem profile. Apps needs separate feature readback because configured inventory omits runtime connectors. Web search is requested disabled; its effective turn mode is not read back and managed requirements can select Cached (see the verification ceiling). Each launch proves public-read, exact/glob/symlink private-denial, standard host credential denial and write-denial in temporary fixtures. Standard credential and configured tool-home/XDG subtrees are denied independently of project `local.deny`. Its sandboxed shell is filesystem read-only with private paths denied and network configured disabled; it is not Claude's Read/Grep/Glob-only tool whitelist. No credential home is copied.
|
|
4173
4291
|
|
|
4174
4292
|
Kimi requires a compat-admitted Kimi Code on the hub's PATH (receipt-verified 2.2.0 and 2.3.0), signed in through its managed OAuth provider, and a passing runtime preparation before each child; an unverified/untrusted version or a failed preparation is unavailable with its reason. The [2.3.0 receipt](verification/2026-10-22-kimi-qwen-compat.md) is model-free and does not verify real login/provider readiness. Each review runs a new `kimi -p` child without Seatbelt, in a private `KIMI_CODE_HOME` with managed-provider-only config, a clean temporary working directory and an empty skills directory. Its agent may call only `hub_review` and `hub_task_show`, through a task-bound loopback MCP session that never carries the hub's control token, and has no native read, file or shell tool: it reviews the screened brief and host facts only. Its `credentials/`, `oauth/` and `device_id` link to the person's native Kimi files, so it shares the native login, refresh lock and the Kimi account's budget; no token is copied. A stop revokes its verdict authority first, then waits briefly while an OAuth refresh holds the lock; a forced stop mid-refresh may require a native re-login. The Kimi backend records no measured token counts here, so its usage stays unknown; the 2.3.0 receipt makes no usage claim. This is a native tool-authority boundary, not filesystem or network isolation.
|
|
4175
4293
|
|
|
@@ -4236,8 +4354,48 @@ reattachment or TUI detachment clears it. The notice contains fixed guidance, wi
|
|
|
4236
4354
|
|
|
4237
4355
|
## Roles per SDLC stage (#525)
|
|
4238
4356
|
|
|
4239
|
-
The design for planner, implementer and reviewer instances per stage is in the spec section "Amendment: roles per SDLC stage (#525)". Slice 525-1 is available: role capability per kind and form, Claude channel instances as implementer or verifier in their own worktree, and `planner` refused on kinds that cannot plan (pi, local
|
|
4357
|
+
The design for planner, implementer and reviewer instances per stage is in the spec section "Amendment: roles per SDLC stage (#525)". Slice 525-1 is available: role capability per kind and form, Claude channel instances as implementer or verifier in their own worktree, and `planner` refused on builtin kinds that cannot plan (pi, local and agy): an instance declaring it is refused with `this kind cannot plan`, and a `roles` entry keeps its other roles with the notice `roles.<peer>: ignored roles outside the adapter ceiling`. A configured ACP agent (`adapters`) is different: it may hold `planner` in its `roles` or in a `roles` entry and then plans like any peer, but it can never be pinned with the `planner` setting or chosen as the automatic planner, because it has no host projection (#735). Slices 525-3, 525-4 and 525-5 are available too:
|
|
4358
|
+
|
|
4359
|
+
- 525-3: `assign()` walks the planner holders (rotation by task id over every holder, never renumbered by availability; a named planner exact; a recorded planner kept; none for a PII task) and `ahub route explain <id>` prints that walk. Task planner bindings are recorded by 525-2. A peer that accepted or finished a task never reviews it, a named reviewer and the declared reviewer pool included; when no other candidate is left the person reviews.
|
|
4360
|
+
- 525-4: a headless Claude implementer runs one owned child per turn in its declared worktree, with a separate persisted session per task (`start_mode: "headless"`, permission `ask` or `ask-when-needed`; `never-ask` refused).
|
|
4361
|
+
- 525-5: terminal Claude implementer instances own write-class tasks once the daemon has verified their execution root.
|
|
4362
|
+
|
|
4363
|
+
The operator steps for 525-1, 525-4 and 525-5 are in "Additional headless peer instances" above. Slice 525-2 adds the planner settings, task/release bindings, independent plan review and recovery floor described in "The planner" above. Slice 525-6 (Codex planner-only visibility) remains separate.
|
|
4364
|
+
|
|
4365
|
+
## Daemon responsiveness and launch connects (#719)
|
|
4366
|
+
|
|
4367
|
+
Periodic peer-roster and delivery-supervision reads select pending journal metadata/rows, excluding completed payload history. Queue revision reads do not construct a recovery snapshot. Explicit queue/history commands retain terminal history. The pending-state index supports these reads without sorting historical payloads.
|
|
4368
|
+
|
|
4369
|
+
Native launcher connections retry transport timeouts/unclean closes with bounded backoff for at most 15 seconds, printing `hub busy, retrying` once. The ordinary control-connect timeout remains 3 seconds. An immediately unreachable listener, authentication refusals, wire mismatch and project/instance mismatch are terminal. Every retry rereads the descriptor and preserves the invocation's delegated-audit instance pin. Usage queries retain their existing catch-up budgets and report `behind` until complete; time slicing never advances beyond the last atomically folded record.
|
|
4370
|
+
|
|
4371
|
+
## amem runtime (agent-mem#13 P4)
|
|
4372
|
+
|
|
4373
|
+
The hub exact-pins @staix/agent-mem 0.7.0 for recall, curated evidence and local deterministic capture. No runtime call reaches a claude-mem worker; `memory.worker_url` is ignored. The person's `ahub memory import claude-mem` remains explicit and off by default. Existing profile, alias, PII and private-turn fences still apply. `ask --remember` and context checkpoints propose machine-local candidates, never automatic curated evidence. See [memory integration](memory.md#in-process-recall-and-capture-agent-mem13-p4) for changed behavior and bounded-view ceilings.
|
|
4374
|
+
|
|
4375
|
+
## Backlog issue identity and notes
|
|
4376
|
+
|
|
4377
|
+
The card's effective planner or the person can relink an unstarted backlog card through `hub_backlog_plan`, using `fields: {sdlc: {repo: "owner/repo", issue: 525}}`. The change is one planning revision and clears the old spec acceptance. Stage, reviewed heads, checklists and other lifecycle evidence cannot be supplied through this path; `hub_sdlc_record` still refuses backlog work.
|
|
4378
|
+
|
|
4379
|
+
Omit tool `fields`, or use `{}`, to record only the bounded reason as a new revision. The person CLI retains its JSON argument: `ahub backlog plan <id> <revision> '{}' '<reason>'`. Existing planner scope, pins, frozen releases and stale-revision checks still apply. Undo restores identity members without restoring old consent; null members represent an absent previous repo or issue.
|
|
4380
|
+
|
|
4381
|
+
The grooming digest no longer calls ordered dependency phases duplicate merely because they share a design issue. It still reports path/symbol overlap, unrelated same-issue cards and references requiring attention. It uses dependency edges only, including bounded public context for approved intermediate phases.
|
|
4382
|
+
|
|
4383
|
+
## Inspecting memory symbol anchors
|
|
4384
|
+
|
|
4385
|
+
`ahub doctor --stale-anchors [--json]` (#684 phase 3) checks a bounded set of this project's screened symbol anchors through the optional code-facts boundary. Stale means positively absent at the reported head; unavailable or ambiguous evidence stays unknown. Read the coverage/truncation fields before treating the report as complete. This command performs no note mutation or automatic repair.
|
|
4386
|
+
|
|
4387
|
+
A task completion note stores actually observed, existing symbol nodes instead of plan guesses. Earlier notes remain connected through the same reset-safe task node. Related-memory retrieval reaches those earlier notes at memory hop two; the graph's literal two-edge view shows the completion note and task node. Unknown observations are labelled and never substituted with the plan. See [canonical symbol anchors](memory.md#canonical-symbol-anchors-684-phase-3) for bounds.
|
|
4388
|
+
|
|
4389
|
+
## Code-facts inspection cleanup and lookup coverage
|
|
4390
|
+
|
|
4391
|
+
`doctor --stale-anchors` may create transient detached Git worktrees for exact-head analysis. A Ctrl-C or interrupted cleanup can leave a prunable registration. Inspect `git worktree list --porcelain`; remove or prune only an entry confirmed abandoned, through the person's normal Git maintenance. The report performs no automatic prune. Repeated optional cleanup failure is reported as unknown rather than escaping as a second error.
|
|
4392
|
+
|
|
4393
|
+
An absence row says "absent from indexed definitions". Imported package APIs/types and unsupported host qualification are not proof of removed source. Names containing `#`, `->` or `:` remain unknown. Existing raw-signature and normalized note associations are queried together without changing stored entries. See [symbol preparation and query compatibility](memory.md#symbol-preparation-and-historical-query-compatibility-684-follow-ups).
|
|
4394
|
+
|
|
4395
|
+
## Inspecting memory code neighbours
|
|
4396
|
+
|
|
4397
|
+
In the dashboard Memory view (#684 phase 4), select a symbol and enable Code neighbours. Dashed calls are read-time caller/callee evidence at the displayed commit SHA; solid note associations still come from authored metadata. Unknown, lower-bound and truncated coverage are advisory, never a proof of no callers. The accessible edge list carries the same SHA and direction. Toggle off to view the stored graph alone.
|
|
4398
|
+
|
|
4399
|
+
`hub_memory_graph` includes the same bounded derived context for symbol starts within its existing 6 KB output budget. Task briefs prioritize attached fails and decisions within `brief_items`; the console related-note count refers to that bounded selection. Code facts remain optional: no index is copied into memory, no graph edges are persisted and no PII task/turn starts a query.
|
|
4240
4400
|
|
|
4241
|
-
|
|
4242
|
-
- The `planner` setting accepts a list of peers or instance ids; each task records its own planner, and only that planner or the person runs planner tools on it.
|
|
4243
|
-
- A reviewer is never a peer that implemented the task, and a plan's author does not record its own plan review while another planner is available.
|
|
4401
|
+
Optional code work runs only while Memory is open and visible. A cold console count reports unknown immediately; it does not prepare code facts. Direct task memory remains available when optional code facts are ineligible, interrupted or unavailable. Review/completion queries pre-empt optional native work after its owned process/tree cleanup. Unknown lookups have a five-second retry floor; topology caches are commit-bound and note bodies are refreshed under current policy. These are advisory coverage bounds, not empty-result proofs.
|
package/docs/profiles.md
CHANGED
|
@@ -49,6 +49,7 @@
|
|
|
49
49
|
|
|
50
50
|
# Project profile overrides
|
|
51
51
|
|
|
52
|
+
- Acceptance criteria are profile-independent (#507b): a task's recorded criteria checklist (docs/sdlc.md, Acceptance-criteria checklist) is listed in every profile's review request, ahead of the profile's `review_checklist` lines, and an unmet item that starts with a criterion id names it; a profile only changes the wording of its checklist, never the criteria or their ids.
|
|
52
53
|
- `profile_overrides` in shared/local config selects project data over the chosen shipped profile. `classes`, `role_text` and `catalog_roles` maps merge by key across layers; `plan_keys`, `agents`, `example_checks` and `review_checklist` replace as units. A local `profile` selects the active base for both init and native contracts.
|
|
53
54
|
- Classes may add or remap profile aliases to existing base classes. Existing base names keep their meanings; class maps are bounded to 32 override entries. Task storage and route explanations preserve the alias, including a dev custom alias, while routing/budgets/checks use its base. Other tasks under custom dev data retain the selected profile semantics too, so document sections do not become whole-path overlaps. Unmodified dev rows retain their old shape.
|
|
54
55
|
- `plan_keys` selects distinct existing plan fields, not new board fields. Task proposals and their schemas use the selection. Accept schemas retain legacy fields for already existing tasks/profile changes.
|
package/docs/quickstart.md
CHANGED
|
@@ -17,7 +17,7 @@ ahub setup # installs the Claude Code channel plu
|
|
|
17
17
|
Or use the matching GitHub release:
|
|
18
18
|
|
|
19
19
|
```bash
|
|
20
|
-
bun add -g github:STAIxBWLB/agent-hub#v0.
|
|
20
|
+
bun add -g github:STAIxBWLB/agent-hub#v0.16.0
|
|
21
21
|
ahub setup
|
|
22
22
|
```
|
|
23
23
|
|
|
@@ -30,9 +30,17 @@ and upgrade or crash recovery, see the [operations guide](operations.md). To
|
|
|
30
30
|
move running projects to a newer release later, run `ahub upgrade` in a
|
|
31
31
|
terminal: it reviews the plan with you, applies it and follows it.
|
|
32
32
|
|
|
33
|
+
## Upgrading to 0.16.0
|
|
34
|
+
|
|
35
|
+
Always-ask now covers the local worker, Pi and Codex too (#636 slice 3): a local or Pi model tool call is classed before its permission mode, a `never-ask` grant, Pi's `Always allow` or `--unattended`, and a classed command approval request that Codex sends offers only allow-once, deny and the class budget. Unattended local or Pi work that publishes, installs or deletes now waits for you: answer it in the console, or change `action_policy` as in the 0.15.0 notes below. `ahub status` still lists Codex as not enforceable, because its native policy can run a command without sending a request, and Jcode as having no hub approval path. An approval whose command is cut or withheld (an ACP peer's private turn, for one) can only be denied, and a local `action_policy` that weakens the defaults is flagged on every status policy row. The classifier now reads the literal words around a shell expansion (`git push origin $B` asks) and takes the strictest class where the expansion can change it, while a `gh api graphql` call with one literal query no longer asks (#762, #756; see [security notes](security.md)). The hub no longer calls a claude-mem worker (agent-mem#13 P4): recall, briefs, `ahub ask` and the local worker's capture run in process on the exact-pinned `@staix/agent-mem` 0.7.0, `memory.worker_url` is ignored, `ahub doctor` reports the library, and `ahub ask --remember` and context checkpoints save pending candidates that only a person accepts; `ahub memory import claude-mem` stays the explicit way to copy old notes. The planner setting takes up to eight peers (`ahub settings set planner claude,codex`): each new task records one of them, only that planner or you change its planning, an agent's own plan is reviewed by another holder whenever one is online, and `ahub task assign <id> <peer> --role planner` moves it (#525-2; see [the planner](operations.md#the-planner-455)). Once a planner list is set or any task records a planner, `ahub upgrade` and recovery refuse a target release without `task_planners`, so the project cannot be moved back to 0.15.0 that way. `ahub deliverables [--task <id>] [--approved] [--check]` lists what each task delivered and a reviewer approved, and a dashboard card shows a `Deliverables n` chip (#509b). `ahub budget` prints each window's kind and source and says why a peer has no number (#285). The dashboard Memory view gains a Code neighbours toggle for a selected symbol, and `ahub doctor --stale-anchors` is a read-only report of memory symbol anchors at the current head (#684). The `codex-review` reviewer on Codex 0.164.0 no longer needs `ahub agents trust` (#757). Upgrade running hubs with `ahub upgrade` and restart Claude sessions so they load the 0.16.0 plugin. Coming from 0.14.0 or older, the notes below apply too.
|
|
36
|
+
|
|
37
|
+
## Upgrading to 0.15.0
|
|
38
|
+
|
|
39
|
+
Publish, external-write, destroy and install calls now ask a person (#636 slice 2): the Claude PreToolUse hook returns `ask` for such a call in every permission mode, `never-ask` included, and a hub-owned ACP peer such as Kimi in native `ask` mode never auto-approves one, not under `--unattended` either; it waits in the console and the dashboard as `Action approval (<classes>): <command>` and is denied when `approvals.timeout_s` passes. When a class budget is above one, the approval of a classed ACP call also offers `Allow <class> xN for this session`. Unattended work that publishes, installs or deletes now stops for you: answer it, or set `ahub settings set action_policy.enabled false` or `action_policy.budgets.<class> <n>` (the policy and its budgets live only in untracked `.agenthub/config.local.json`). `ahub status` names each peer where the hub cannot see the call before it runs: a Kimi in `yolo` or `auto`, a Claude session that has not run the hub's permission hook, an `--unattended` Claude launch, and Codex, Pi and the local worker until #313 (see [always-ask action policy](operations.md#always-ask-action-policy-foundation-636)). A terminal Claude instance declared with `implementer` or `verifier` and its own `worktree` now owns write-class tasks once the daemon verifies its launch record and channel cwd; start it again with `ahub claude --as <id>` after the upgrade, because a launch recorded without its execution root attaches without isolation and gets no write task (#525-5). A headless Claude implementer can be declared in `.agenthub/config.local.json` (`"start_mode": "headless"`, roles `["implementer"]`, its own registered `worktree`, `permission_mode` `ask` or `ask-when-needed`; `never-ask` is refused): create and register the worktree first, then `ahub claude --as <id>` asks the hub to start it and returns. It keeps one session per task, and its writes and shell calls reach you as allow-once or deny requests in the console; no answer is a deny (#525-4; see [additional headless peer instances](operations.md#additional-headless-peer-instances)). `hub_task_done` and `hub_sdlc_record` take `deliverables: [{path, format, version?}]`: the hub hashes the files itself, a reviewer's approval is refused when a file changed since delivery, and `ahub task show` reports each file as `unchanged`, `changed`, `missing` or `unknown` (#509; see [deliverable records](sdlc.md#deliverable-records-509a)). A review request lists the task's recorded acceptance criteria by id, and an unmet item that starts with one (`AC2: what is missing`) is recorded on the verdict (#507). A peer that accepted or finished a task no longer reviews it; when no other reviewer is left, you review it, and `ahub route explain <id>` also prints the planner walk (#525-3). Instances, `review`, `snapshots.keep`, `approvals.timeout_s`, `context.gate` and the `sdlc.toml` `mode` and `required_checks` can be edited with `ahub settings edit`, the console Settings key `c` or the Structure group of an `ahub ui --settings` session: the hub validates, shows a diff and keeps a backup; a changed instance or `sdlc.toml` waits for a hub restart (console `R`), and keys that run code or locate secrets stay console only with their name typed (#689; see [structural configuration](operations.md#structural-configuration-from-the-console-and-the-dashboard-issue-689)). Kimi's token use is now counted from its session wire log, so a `budget.kimi_tokens_5h` you set pauses Kimi when it is reached (#285). `ahub backlog list` prints a table by rank; a script that read its output uses `--json` (#399). A launcher that meets a busy hub retries for up to 15 s and prints `hub busy, retrying` once (#719). Upgrade running hubs with `ahub upgrade` before relying on deliverables: an older daemon drops them from a newer plugin's `hub_task_done` without a word. Restart Claude sessions so they load the 0.15.0 plugin, and if `ahub status` shows a fresh reviewer instance such as `codex-review` stopped after the upgrade, start it again with `ahub codex --as codex-review`. Coming from 0.13.0 or older, the notes below apply too.
|
|
40
|
+
|
|
33
41
|
## Upgrading to 0.14.0
|
|
34
42
|
|
|
35
|
-
At a terminal width `ahub board` now prints one line per task: the title is cut with `...`, dependencies move to an AFTER column, STAGE is the meter with a short next-step code (`intent: issue?`, `review: CI?`, `ready`) and a legend line explains them; `ahub board --full`, piped output without `COLUMNS` and `--json` keep the whole title and SDLC advice (#724). The dashboard's Agents view gains a Usage view under Usage budgets: lifetime totals, the last 14 UTC days of tokens per peer, the open pauses and recent limit events, and a task table in which a private task shows only as `#id [pii]` (#683 U4). A task sheet gains a Code group: the changed symbols marked `matching` or `unplanned` against the plan, the plan names nothing changed under as `untouched`, and a symbol opens the Memory tab on its node; a private task has no group (#684). `ahub sdlc metrics [--since <date>]` and the planner tool `hub_sdlc_metrics` (planner or person, read-only) report lead times, first-pass approval, rework rounds, stale-head re-reviews and stalls from board history, with `unknown` where the board cannot tell. An optional `[bands.<metric>]` table in `.agenthub/sdlc.toml` turns a breach into a hub notice, a read-only `triage` backlog task or a `plan` backlog card, once per episode, only while `mode` is `advise` or `enforce`, and never a GitHub issue (#481 S7; see [SDLC metrics and control bands](sdlc.md#sdlc-metrics-and-control-bands-481-s7)). In advise and enforce a task's issue identity is now linked when it is proposed or accepted, with no GitHub read; a title that names another repository (`agent-mem#13`) links only when `refs.repo` names it, and the propose result suggests setting it (#723). A fresh reviewer whose start fails now names a cause class (`version`, `binary`, `mcp_inventory`, `plugins_hooks_apps`, `sandbox_proof`, `credential_root`, `timeout` or `unknown`) on the `reviewer` line of `ahub status` and in `hub.log` (#722). A Claude channel instance in `.agenthub/config.local.json` may declare `implementer` or `verifier` and then needs its own `worktree`, while a planner or reviewer instance refuses one; the hub routes no code tasks to such an instance until #525-5, and a headless Claude instance stays reviewer-only. `planner` is refused on a pi, local or agy instance declaration and dropped, with a notice, from a `roles` entry for those kinds (#525-1; see [Roles per SDLC stage](operations.md#roles-per-sdlc-stage-525
|
|
43
|
+
At a terminal width `ahub board` now prints one line per task: the title is cut with `...`, dependencies move to an AFTER column, STAGE is the meter with a short next-step code (`intent: issue?`, `review: CI?`, `ready`) and a legend line explains them; `ahub board --full`, piped output without `COLUMNS` and `--json` keep the whole title and SDLC advice (#724). The dashboard's Agents view gains a Usage view under Usage budgets: lifetime totals, the last 14 UTC days of tokens per peer, the open pauses and recent limit events, and a task table in which a private task shows only as `#id [pii]` (#683 U4). A task sheet gains a Code group: the changed symbols marked `matching` or `unplanned` against the plan, the plan names nothing changed under as `untouched`, and a symbol opens the Memory tab on its node; a private task has no group (#684). `ahub sdlc metrics [--since <date>]` and the planner tool `hub_sdlc_metrics` (planner or person, read-only) report lead times, first-pass approval, rework rounds, stale-head re-reviews and stalls from board history, with `unknown` where the board cannot tell. An optional `[bands.<metric>]` table in `.agenthub/sdlc.toml` turns a breach into a hub notice, a read-only `triage` backlog task or a `plan` backlog card, once per episode, only while `mode` is `advise` or `enforce`, and never a GitHub issue (#481 S7; see [SDLC metrics and control bands](sdlc.md#sdlc-metrics-and-control-bands-481-s7)). In advise and enforce a task's issue identity is now linked when it is proposed or accepted, with no GitHub read; a title that names another repository (`agent-mem#13`) links only when `refs.repo` names it, and the propose result suggests setting it (#723). A fresh reviewer whose start fails now names a cause class (`version`, `binary`, `mcp_inventory`, `plugins_hooks_apps`, `sandbox_proof`, `credential_root`, `timeout` or `unknown`) on the `reviewer` line of `ahub status` and in `hub.log` (#722). A Claude channel instance in `.agenthub/config.local.json` may declare `implementer` or `verifier` and then needs its own `worktree`, while a planner or reviewer instance refuses one; the hub routes no code tasks to such an instance until #525-5, and a headless Claude instance stays reviewer-only. `planner` is refused on a pi, local or agy instance declaration and dropped, with a notice, from a `roles` entry for those kinds (#525-1; see [Roles per SDLC stage](operations.md#roles-per-sdlc-stage-525)). A planner pull of a reserved backlog task now assigns it to the reserved peer and offers it at once; when that peer is offline, off roster, paused, full or excluded, the pull is refused with the reason and no other peer takes it (#718). `ahub codex --as <id>` for a headless fresh reviewer instance starts it and returns (#720). Restart Claude sessions so they load the 0.14.0 plugin. Coming from 0.12.45 or older, the notes below apply too.
|
|
36
44
|
|
|
37
45
|
## Upgrading to 0.13.0
|
|
38
46
|
|
|
@@ -94,7 +102,7 @@ The restarted Claude planner gets the release-train tools (`hub_release_new`, `h
|
|
|
94
102
|
|
|
95
103
|
Jcode must be 0.98.0 or later, below 1.0.0; 0.94.0 is no longer accepted, so `ahub doctor` fails its Jcode row for an older install and the peer does not start (#529). Every owned jcode process runs with `JCODE_NO_TELEMETRY=1`.
|
|
96
104
|
|
|
97
|
-
Since 0.12.37 the hub
|
|
105
|
+
Since 0.12.37 the hub opens a split memory home through its shards (#534); the current exact `@staix/agent-mem` pin is 0.7.0. Before anyone runs `amem migrate --shards` on a memory home, every hub using that home must run 0.12.37 or later: an older hub does not see the split and keeps writing the old layout. `ahub memory profile-check` is split-aware and compares each hub with its own project's shard (#536). See [memory profiles and rollout](memory.md#selected-memory-profile).
|
|
98
106
|
|
|
99
107
|
From 0.12.30 or earlier, existing Jcode project MCP entries need one refresh before conductor or dashboard starts. Once per project, the person runs:
|
|
100
108
|
|
|
@@ -146,8 +154,9 @@ or set `OMNIROUTE_API_KEY`. The `.agenthub/routing.toml` that `ahub init` writes
|
|
|
146
154
|
| `ahub task propose [--class <c>] <title>` | put work on the board; the hub picks an owner and a reviewer, and the class if you name none |
|
|
147
155
|
| `ahub board` | who has what, one line per task at a terminal width; `--full` for whole titles and SDLC advice, `ahub task show <id>` for one task |
|
|
148
156
|
| `ahub task cancel <id> --reason <text>` | close obsolete work without approving it or stopping a native turn |
|
|
149
|
-
| `ahub settings set planner <peer
|
|
157
|
+
| `ahub settings set planner <peer>[,<peer>...]` | pin up to eight planners; status reports whether they came from settings, roles or the automatic choice |
|
|
150
158
|
| `ahub settings reload` | apply edited config files without a restart; guarded values wait for your `y` in this terminal, and restart-only keys stay pending |
|
|
159
|
+
| `ahub settings edit <file> set <path> <json>` | change an instance, the review block or the `sdlc.toml` lifecycle with a validated diff and a backup; `ahub settings backups` lists the backups |
|
|
151
160
|
| `ahub status` | peers, queues, pauses; `ahub budget` for quota windows |
|
|
152
161
|
| `ahub usage [--by peer\|task\|issue\|pr\|release\|day\|model]` | tokens per group, each number with its source; `ahub usage limits` for pauses and resets |
|
|
153
162
|
| `ahub agents` | which installed agent CLI versions the hub accepts; `ahub agents trust <id> <version>` accepts an untested one on this machine |
|
|
@@ -160,7 +169,7 @@ More: `ahub help`. How it is built and why: [`docs/specs/2026-09-19-agent-hub-de
|
|
|
160
169
|
|
|
161
170
|
## Shared memory
|
|
162
171
|
|
|
163
|
-
The hub exact-pins the first-party `@staix/agent-mem` 0.
|
|
172
|
+
The hub exact-pins the first-party `@staix/agent-mem` 0.7.0 core, including deterministic capture; no claude-mem worker is needed. Existing shared-v1 memory remains the default; upgrading does not migrate it. Managed agents use screened `hub_memory_search`, `hub_memory_show` and `hub_memory_graph` tools, or propose a correction with `hub_memory_correct`; only a person accepts candidates through the supported `amem review` path. Since agent-mem 0.7.0, `amem review` also accepts candidates on a selected generation.
|
|
164
173
|
|
|
165
174
|
Before any real generation migration, upgrade every hub sharing that memory home to 0.12.30 or later and check its authenticated binding with `ahub memory profile-check` in each custom registry. Ready bindings prove compatibility, not an atomic live cutover: quiesce consumers and close their handles before migrating, then reopen through the supported session-preserving lifecycle. Invalid or changed profiles disable native memory without falling back to legacy writes; the bus and board continue. See [memory operations](operations.md#hub-memory) for the remaining rollout gates.
|
|
166
175
|
|
|
@@ -178,7 +187,8 @@ allow. They can be denied on the page. PII task details remain available only vi
|
|
|
178
187
|
`ahub task show <id>` in the terminal. The page also starts a peer in its start
|
|
179
188
|
mode (a TUI opens in a terminal when the hub has a terminal provider) and shows
|
|
180
189
|
the settings with a Reload configuration button; raising one needs `ahub ui --settings`
|
|
181
|
-
or `ahub settings` in a terminal
|
|
190
|
+
or `ahub settings` in a terminal (the Structure group edits instances and the
|
|
191
|
+
lifecycle only in such a session), and guarded values from an edited file need
|
|
182
192
|
`ahub settings reload` there. See the operations guide, "Settings from the dashboard and the
|
|
183
193
|
terminal" and "Start modes".
|
|
184
194
|
|