@staix/agent-hub 0.12.45 → 0.13.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 +18 -0
- package/README.md +83 -116
- package/docs/agent-notes/README.md +6 -0
- package/docs/agent-notes/adapters.md +10 -7
- package/docs/agent-notes/budget.md +6 -1
- package/docs/agent-notes/bus.md +6 -4
- package/docs/agent-notes/daemon.md +6 -1
- package/docs/agent-notes/local-worker.md +2 -1
- package/docs/agent-notes/tasks.md +10 -0
- package/docs/agent-notes/tests.md +4 -2
- package/docs/dogfood.md +92 -0
- package/docs/events.md +14 -1
- package/docs/operations.md +250 -19
- package/docs/profiles.md +2 -2
- package/docs/quickstart.md +8 -2
- package/docs/sdlc.md +36 -6
- package/docs/security.md +20 -11
- package/docs/smoke.md +9 -4
- package/docs/specs/2026-09-19-agent-hub-design.md +759 -8
- package/docs/verification/2026-10-19-reviewer-isolation.md +2 -0
- package/docs/verification/2026-10-22-code-facts.md +78 -0
- package/docs/verification/2026-10-22-codex-reviewer-isolation.md +47 -0
- package/docs/verification/2026-10-22-kimi-qwen-compat.md +79 -0
- package/docs/verification/2026-10-23-0.13.0.md +89 -0
- package/docs/verification/dogfood/2026-10-22.md +3109 -0
- package/docs/verified.json +14 -14
- package/package.json +1 -1
- package/plugins/agent-hub/.claude-plugin/plugin.json +1 -1
- package/plugins/agent-hub/server.js +613 -329
- package/src/adapters/agy/entry.ts +5 -4
- package/src/adapters/claude-channel.ts +20 -9
- package/src/adapters/codex-appserver.ts +18 -2
- package/src/adapters/codex-review-isolation.ts +12 -5
- package/src/adapters/compat.ts +140 -0
- package/src/adapters/definitions/builtin-metadata.ts +2 -1
- package/src/adapters/definitions/native-cli-doctor.ts +12 -5
- package/src/adapters/definitions/native-cli-entry-jcode.ts +9 -6
- package/src/adapters/definitions/native-cli-jcode-mcp.ts +9 -2
- package/src/adapters/definitions/native-cli-preview-common.ts +2 -0
- package/src/adapters/definitions/native-cli-preview-jcode.ts +8 -2
- package/src/adapters/definitions/native-cli-preview-qwen.ts +2 -1
- package/src/adapters/definitions/qwen-native.ts +7 -3
- package/src/adapters/definitions/qwen.ts +2 -1
- package/src/adapters/jcode.ts +72 -31
- package/src/adapters/kimi-review.ts +6 -3
- package/src/adapters/registry-types.ts +3 -1
- package/src/adapters/registry.ts +1 -0
- package/src/cli/agents.ts +40 -0
- package/src/cli/console-review.ts +54 -0
- package/src/cli/console-state.ts +124 -29
- package/src/cli/console-symbols.ts +74 -0
- package/src/cli/console-usage.ts +89 -0
- package/src/cli/console.ts +26 -1
- package/src/cli/help.ts +16 -6
- package/src/cli/identity.ts +29 -6
- package/src/cli/init.ts +109 -11
- package/src/cli/main.ts +122 -11
- package/src/cli/output.ts +44 -1
- package/src/cli/preview.ts +1 -1
- package/src/cli/sdlc-release-guard.ts +82 -0
- package/src/hub/action-class.ts +362 -0
- package/src/hub/action-policy.ts +106 -0
- package/src/hub/board.ts +43 -8
- package/src/hub/budget.ts +71 -2
- package/src/hub/bus.ts +43 -3
- package/src/hub/checks.ts +80 -31
- package/src/hub/code-facts.ts +223 -0
- package/src/hub/config-apply.ts +10 -1
- package/src/hub/config-trust.ts +7 -4
- package/src/hub/daemon.ts +237 -22
- package/src/hub/dogfood-read.ts +199 -0
- package/src/hub/dogfood.ts +163 -0
- package/src/hub/envelope.ts +1 -1
- package/src/hub/events.ts +11 -2
- package/src/hub/hub-tools.ts +24 -2
- package/src/hub/inbox-polling.ts +25 -0
- package/src/hub/instances.ts +73 -1
- package/src/hub/profiles.ts +7 -2
- package/src/hub/release-worktree.ts +56 -0
- package/src/hub/review-brief.ts +36 -0
- package/src/hub/sdlc-queue.ts +31 -9
- package/src/hub/sdlc-release-authorization.ts +173 -0
- package/src/hub/sdlc.ts +49 -11
- package/src/hub/settings.ts +5 -2
- package/src/hub/snapshots.ts +93 -8
- package/src/hub/symbol-normalizer.ts +26 -0
- package/src/hub/task-code-symbols.ts +90 -0
- package/src/hub/task-sweep.ts +3 -2
- package/src/hub/tasks.ts +292 -54
- package/src/hub/test-integrity.ts +162 -0
- package/src/hub/usage-rollup.ts +361 -0
- package/src/local/sandbox.ts +5 -3
- package/src/ui/index.html +1 -0
- package/templates/AGENTS.block.md +1 -1
- package/templates/profiles/dev.json +6 -1
- package/templates/profiles/general.json +6 -1
- package/templates/profiles/research.json +6 -1
- package/templates/profiles/writing.json +6 -1
- package/templates/release-guard.block.md +6 -0
package/docs/operations.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Operations guide
|
|
2
2
|
|
|
3
|
-
This guide describes ahub 0.
|
|
3
|
+
This guide describes ahub 0.13.0 and control protocol 16. Live verification
|
|
4
4
|
results and remaining prerequisites are recorded separately in [the smoke ledger](smoke.md).
|
|
5
5
|
|
|
6
6
|
## Agent-operated live verification
|
|
@@ -61,7 +61,7 @@ smoke ledger; the presence of this option proves no outstanding #273 live leg.
|
|
|
61
61
|
|
|
62
62
|
## Command output
|
|
63
63
|
|
|
64
|
-
`ahub status`, `board`, `budget`, `doctor`, `projects`, `queue list`, `turns` and `
|
|
64
|
+
`ahub status`, `board`, `budget`, `doctor`, `projects`, `queue list`, `turns`, `report` and `usage` print shared console tables and labelled details.
|
|
65
65
|
`status --all` uses the projects table. `queue show`, `models status` and `budget execution status` show labelled fields; add `--json` for the raw fetched document.
|
|
66
66
|
`report --by task` keeps the attribution and coverage sentences with section headings and aligned counters.
|
|
67
67
|
Use `--json` for scripts; it returns the fetched data without color, and `status --json` keeps its existing document.
|
|
@@ -141,6 +141,30 @@ its footer. The active tab is bracketed, as in `[2 Approvals]`, so it reads
|
|
|
141
141
|
without color. The Approvals tab counts pending requests and the Queue tab
|
|
142
142
|
counts `needs_review` deliveries, in the attention and failure tones.
|
|
143
143
|
|
|
144
|
+
Tab `7 Usage` (#683 U3, key `7`; Left and Right wrap as Settings does, so the `1`..`5` cycle is unchanged) lists each peer with the tokens of today (the UTC day),
|
|
145
|
+
the last seven UTC days and its lifetime, the current budget pause, its quota windows with their reset time, and its last reset. Every number names its
|
|
146
|
+
source (`native`: the provider's own total, `hub`: what the hub counted for a peer that reports none, `at least`: a partial sum); a counter nobody reported
|
|
147
|
+
is `unknown` and a period with no records is `no records`, never 0. Enter opens a peer: today, 7 days and lifetime with input, output, cache read, cache
|
|
148
|
+
write and the hub count each on its own, and the last three resets. The task selected in Tasks when you press `7` is shown below the table with its tokens
|
|
149
|
+
per peer (`#id [pii]` for a private task, never a title). The panel asks the hub's `usage` op only while it is open, and a refusal shows as
|
|
150
|
+
`usage unavailable`. The numbers come from the roll-up of `ahub usage`, so the console and the CLI agree. A request folds the event log first, within 250 ms;
|
|
151
|
+
when a very large log is not folded yet the answer carries `behind: true`, the panel says `still catching up` and `ahub usage` prints a warning on stderr, so a partial number is never shown as the whole.
|
|
152
|
+
|
|
153
|
+
Reviewing from the console (#711): on a task in review in Tasks (a selected row, or the open task detail), `r` asks which verdict first on the prompt line,
|
|
154
|
+
`review #372 "<title>": a approve c request changes Esc cancel` (the title is quoted and cut, a private task shows `[pii]`). `a` puts `review 372 approved ` on
|
|
155
|
+
the input line with a guide line above it (`Enter approves #372. You can type a note first. Esc cancels.`); `c` puts `review 372 changes_requested ` there and
|
|
156
|
+
asks for what to fix (`Say what to fix, then Enter. Esc cancels.`): Enter with no note is refused in the console with `say what to fix before requesting
|
|
157
|
+
changes`, and nothing reaches the hub. The footer says `r approve or request changes`, and `your review: r approve or request changes` when the reviewer is
|
|
158
|
+
`user`, also while the task detail is open. When the command finishes the console shows `#372 approved` or `#372 changes requested`, or the CLI's refusal verbatim
|
|
159
|
+
as a failure notice, in panels mode too. A task that left review while the choice was open says `#372 is no longer in review (<state>)` and nothing is
|
|
160
|
+
prefilled. The console runs `ahub review` as the person; the hub still decides who may review, and nothing about authority changed.
|
|
161
|
+
|
|
162
|
+
An agent shell (a `!` command inside a Claude or Codex session, or any shell with `AGENTHUB_PEER_ID`, `CLAUDECODE` or `CODEX_THREAD_ID` set) runs as that agent, not as
|
|
163
|
+
you. When the hub refuses it something only the person or the task's own reviewer may do, stderr adds one line: `This shell runs as agent "claude" (AGENTHUB_PEER_ID
|
|
164
|
+
and CLAUDECODE are set), not as you. Run the command in your own terminal, or use the ahub console: Tasks, select #372, r.` The refusal and the authority are the
|
|
165
|
+
same as before, and the console identity never gets the line. The hub's notice that a task waits for your review now names the console path as well as
|
|
166
|
+
`ahub review N approved|changes_requested [note]`.
|
|
167
|
+
|
|
144
168
|
The console attention companion (#280) shows waiting, blocked, review, working,
|
|
145
169
|
idle or asleep with separate action/watch counts. Outside the Tasks table, `n` selects the exact approval,
|
|
146
170
|
held queue or review row, or prints applicable guidance; it never answers a
|
|
@@ -175,10 +199,10 @@ the stream; only the header is tab-flattened before tokenizing. Body lines retai
|
|
|
175
199
|
the previous rendering and stay plain, as does command output; colour never changes
|
|
176
200
|
what the panel's text says.
|
|
177
201
|
|
|
178
|
-
Peers, Approvals, Tasks, Queue and
|
|
202
|
+
Peers, Approvals, Tasks, Queue, Settings and Usage are tables with a header row. A column is as
|
|
179
203
|
wide as its widest cell, up to a third of the terminal; the last column takes
|
|
180
204
|
the rest and is cut with `...`. In Tasks, TITLE takes the rest and the STAGE
|
|
181
|
-
meter keeps a fixed column at the right edge.
|
|
205
|
+
meter keeps a fixed column at the right edge. In Usage, LAST RESET is the column that gives way on a narrow terminal.
|
|
182
206
|
|
|
183
207
|
| Panel | Columns |
|
|
184
208
|
|---|---|
|
|
@@ -188,6 +212,7 @@ meter keeps a fixed column at the right edge.
|
|
|
188
212
|
| Tasks, backlog view (`b`) | ID PRI RESERVED DEPS CLASS AGE TITLE |
|
|
189
213
|
| Queue | ID PEER STATE REV AGE |
|
|
190
214
|
| Settings | GROUP KEY VALUE SOURCE APPLIES |
|
|
215
|
+
| Usage | PEER TODAY 7D LIFETIME PAUSE QUOTA LAST RESET |
|
|
191
216
|
|
|
192
217
|
In Tasks, `b` toggles open work and backlog. The backlog heading counts its rows;
|
|
193
218
|
rows sort by rank, then id. PRI shows priority/rank, RESERVED the reserved peer,
|
|
@@ -320,7 +345,21 @@ owner and to stop working.
|
|
|
320
345
|
`ahub task assign <id> <peer> [--role owner|reviewer] [--revision N]` uses a
|
|
321
346
|
checked console operation when a revision is present. Without it, existing CLI
|
|
322
347
|
behavior is unchanged. `ahub queue resolve ... [--revision N]` uses the supplied
|
|
323
|
-
revision instead of a fresh show.
|
|
348
|
+
revision instead of a fresh show. A `queued` delivery was never handed to its peer, so it can be discarded while the peer is busy (a pull-only TUI is busy most of
|
|
349
|
+
the time); `dispatching` and `accepted` deliveries stay refused, and `retry` keeps its rules. A refused resolution names its cause (`active delivery`, `peer busy`,
|
|
350
|
+
`stale revision`, `unknown delivery`, `already resolved`, `queued delivery is already scheduled`, `recipient queue is full`, `delivery journal unavailable`), never one
|
|
351
|
+
generic sentence (#713).
|
|
352
|
+
|
|
353
|
+
`ahub queue discard --peer <id> --reason <text> [--state queued|needs_review] [--yes] [--json]` clears one peer's backlog and is for the person only (an agent identity is
|
|
354
|
+
refused). Without `--yes` it only says how many deliveries it would discard; with `--yes` it discards each queued (default) or `needs_review` delivery of that peer through the
|
|
355
|
+
same resolution as `queue resolve --action discard`, each recorded with the reason, and prints `discarded N of M` with the causes of any it could not discard. Only the
|
|
356
|
+
named peer's queue is read, so other peers are untouched; it is refused while recovery or shutdown holds queue mutations. In the console Queue panel, `D` on a row opens
|
|
357
|
+
the same command for that row's peer, asks for a reason, then a `y` that names the count. No task is cancelled and no native turn is stopped.
|
|
358
|
+
|
|
359
|
+
Completed-change notices (`Task #N (owner X) is done and touches your open ...`, #713) go one per recipient per done, naming all of that recipient's overlapping tasks, and
|
|
360
|
+
only for tasks the recipient has accepted (in progress, in review or changes requested): an offered or proposed task gets none, since its offer or its accept already shows the
|
|
361
|
+
current board. A newer notice for the same done task replaces the queued, undelivered one for that recipient (a `superseded completed-change notice` discard in the journal), so
|
|
362
|
+
a task that is sent back and done again three times leaves one queued notice, the newest. Revision mismatches and superseded post-await
|
|
324
363
|
publications fail without a board or delivery side effect; a reviewer-only change
|
|
325
364
|
keeps a valid owner assignment but refreshes its reviewer content.
|
|
326
365
|
|
|
@@ -967,6 +1006,57 @@ conductor sees it, and only a stub for a PII task. Other peers are refused. Each
|
|
|
967
1006
|
request also carries the hub's review brief for the task's commit: reviewable and
|
|
968
1007
|
excluded files with reasons, the `REVIEW.md` and `ahub-review-rules` rules read at
|
|
969
1008
|
the merge base, and a cross-check list; `ahub review brief <id>` prints it.
|
|
1009
|
+
Optional code facts (#682) add per-file observed symbol names, kinds and spans,
|
|
1010
|
+
plus changed/planned, changed/not-planned and planned/not-seen lists. Install
|
|
1011
|
+
ripwire 0.6.7 on the daemon's host PATH to enable them; missing, unsupported,
|
|
1012
|
+
failed, busy or timed-out reads show `unknown` and never stop the review request.
|
|
1013
|
+
Each native call is capped at 5 s, output is capped, and successful values are
|
|
1014
|
+
cached by repo, commit and query. PII tasks never query it; displayed names use
|
|
1015
|
+
the hub's public metadata screen. It always analyzes a disposable raw-blob
|
|
1016
|
+
snapshot, never main or a dirty/untracked owner tree, and removes that worktree
|
|
1017
|
+
after the owned process stops. No heavy slot is acquired. Trees beyond the
|
|
1018
|
+
regular-file/4096-file/32-MiB bounds remain unknown.
|
|
1019
|
+
|
|
1020
|
+
Ripwire 0.6.7 omits deleted definitions and does not classify change kinds, so
|
|
1021
|
+
all symbol rows say `change: unknown`; planned/not-seen is not proof of no
|
|
1022
|
+
change. Graph name-only matches are hidden as ambiguous, and graph count floors
|
|
1023
|
+
remain explicit. The file-based coverage gate is unchanged. A future both-tree
|
|
1024
|
+
inventory or bounded base/head probes can improve this advice after dogfooding.
|
|
1025
|
+
|
|
1026
|
+
At completion, optional symbol advice also becomes a head-bound task observation
|
|
1027
|
+
(`#684` phase 2a). Console task detail and the UI task snapshot expose the
|
|
1028
|
+
screened IDs, paths, names and kinds, without source/spans or internal repository
|
|
1029
|
+
keys. Public reads re-screen current policy; PII stores nothing. Unknown or
|
|
1030
|
+
stale evidence remains unavailable. Completion prepares this optional data even
|
|
1031
|
+
without a reviewer, without adding a review gate. Foreign-repository tasks stay
|
|
1032
|
+
unknown until the brief can independently bind its analysis repository.
|
|
1033
|
+
|
|
1034
|
+
In the console, Enter on a task in Tasks shows a `symbols` block after its plan (#684 phase 2b): each observed changed symbol is `matching` the plan or
|
|
1035
|
+
`unplanned`, and each planned symbol that nothing changed under is `untouched`, with the counts and the head they were observed at. The match rule is the review
|
|
1036
|
+
brief's own (a pair of qualified names must be equal, otherwise the last segments are). Without code facts it reads `changed symbols: unknown (no code facts)`;
|
|
1037
|
+
an incomplete observation says an untouched symbol may have changed; a private task shows nothing. Names are quoted like every agent-written string, at most 40 are
|
|
1038
|
+
listed and the rest are counted. The block is advice: deleted definitions are not reported, so it never proves a plan was or was not followed.
|
|
1039
|
+
|
|
1040
|
+
Task detail also shows an `overlaps` block (#379), using the hub's read-only
|
|
1041
|
+
`symbolOverlaps` projection of its existing open-task/other-owner overlap selection.
|
|
1042
|
+
Each row names the other task ID and screened shared paths. A row says "same file,
|
|
1043
|
+
different symbols" only when the same current screened predicate used by completion
|
|
1044
|
+
notices establishes observed disjointness; otherwise it remains an ordinary overlap.
|
|
1045
|
+
The block states "observed names only, deleted definitions may be missing". PII tasks
|
|
1046
|
+
are excluded on both sides by their markers, even if the routing locality limit is
|
|
1047
|
+
disabled. No pair result is stored, and the console never infers
|
|
1048
|
+
one from its own plan or receipt. Missing fields on older hubs show no block; an
|
|
1049
|
+
empty list says `none`. At most 40 pairs and 40 paths per pair are listed, with
|
|
1050
|
+
omitted counts. Related-note counts remain a later slice.
|
|
1051
|
+
|
|
1052
|
+
When both tasks have complete public observations and non-empty disjoint sets
|
|
1053
|
+
for every exact shared file, a completed-change notice says "same file, different
|
|
1054
|
+
symbols" with the observed-name/deleted-definition ceiling. It still tells the
|
|
1055
|
+
recipient to check the completed work. Missing or partial evidence keeps the
|
|
1056
|
+
ordinary notice; plan-time overlap and coverage gates are unchanged. The receipt
|
|
1057
|
+
keeps one current head, with at most 500 entries and 64 KiB total. This is the
|
|
1058
|
+
data slice; the formatted Code panel and memory links follow separately.
|
|
1059
|
+
|
|
970
1060
|
`hub_review` takes `coverage {reviewed, skipped}`: in enforce an approval that leaves
|
|
971
1061
|
a reviewable path unaccounted is refused, and advise notes the gap in the verdict
|
|
972
1062
|
(#520). The hub
|
|
@@ -1100,8 +1190,14 @@ ahub report --since 7d # turns, busy time and tokens per peer, messages
|
|
|
1100
1190
|
ahub report --since 7d --json # the same numbers as JSON
|
|
1101
1191
|
ahub report --by task # tokens, turns and wall time per task and class, with the unattributed share
|
|
1102
1192
|
ahub export --since 24h # the raw events as JSON lines, for your own analysis
|
|
1193
|
+
ahub report --dogfood [--since 7d|<iso>] [--json] # read-only scorecard: flow, quality, cost, delivery, performance, adoption
|
|
1103
1194
|
```
|
|
1104
1195
|
|
|
1196
|
+
`ahub report --dogfood` (#687) reads the event log, `hub.log`, the board and the delivery journal in `hub.db`, up to 16 recently merged
|
|
1197
|
+
PRs through `gh`, and the feature table in `docs/dogfood.md`. It covers the last seven days by default, takes no `--by`, and prints the same
|
|
1198
|
+
document as `--json` with `unknown` in place of null; missing or truncated evidence is unknown, never 0. It exports ids, timestamps and counts
|
|
1199
|
+
only and runs no model. Its bounds and the weekly routine are in [dogfood](dogfood.md#weekly-scorecard).
|
|
1200
|
+
|
|
1105
1201
|
Per peer and model route, `ahub report` also counts model changes between consecutive
|
|
1106
1202
|
decisions, how many of them landed inside tool loops and, with `stay_switch` on, sessions
|
|
1107
1203
|
and the planner's switches (#197). With `stay_switch = "off"` session boundaries are not
|
|
@@ -1109,6 +1205,41 @@ recorded; `shadow` routes exactly as `off` does, so it is the baseline to compar
|
|
|
1109
1205
|
A route event records the decision, so a load-moved request that its MLX fallback served counts
|
|
1110
1206
|
as a change to `dgx/fast`; the relay's request journal records which backend served it.
|
|
1111
1207
|
|
|
1208
|
+
The event log also keeps the history of limits (#683). Each Codex update that adds tokens writes a
|
|
1209
|
+
`usage` event with source `codex_appserver` next to the existing `tokens` event, split into input, cached
|
|
1210
|
+
input, output and reasoning, so re-sent cached context is visible. A budget pause writes `budget_pause`
|
|
1211
|
+
and its end `budget_resume`, with the window, the reset time and who ended it (`hub`, or `person` for an
|
|
1212
|
+
`ahub budget resume`). A window's reset writes `quota_reset` when its `resetsAt` moves forward or its `used`
|
|
1213
|
+
falls by 0.5 or more inside one window id, once per peer, window and `resetsAt`. These events hold ids and
|
|
1214
|
+
numbers only, add no protocol version and are ignored by a reader that does not know them. `ahub report`
|
|
1215
|
+
does not show them: `ahub usage` and `ahub usage limits` read them (below), and the console's Usage tab shows each peer's last resets (#683 U3). A dashboard usage view is pending (U4).
|
|
1216
|
+
|
|
1217
|
+
`ahub usage` reads the same events from an incremental roll-up in `hub.db` instead of rescanning the log (#683):
|
|
1218
|
+
|
|
1219
|
+
```bash
|
|
1220
|
+
ahub usage [--since 7d|<iso>] [--by peer|task|issue|pr|release|day|model] [--json]
|
|
1221
|
+
ahub usage limits [--peer <id>] [--limit <n>] [--json] # current quota windows, plus the newest 200 (up to 5000) pauses, resumes and resets
|
|
1222
|
+
ahub usage total [--json] # lifetime development tokens since the first event, per peer and overall
|
|
1223
|
+
```
|
|
1224
|
+
|
|
1225
|
+
The daemon folds `events.jsonl` into `usage_rollup`, `token_rollup` and `limit_events` from a stored byte offset, at most 8 MiB per pass and
|
|
1226
|
+
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
|
|
1227
|
+
from byte 0 gives the same rows (tested). A log that was replaced by a shorter one is folded again from the start. On this project's 47 MB,
|
|
1228
|
+
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
|
|
1229
|
+
rescans the whole file on each call.
|
|
1230
|
+
`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
|
|
1231
|
+
for the history it already spent. A task with no link, and a record with no task, are `unattributed`.
|
|
1232
|
+
|
|
1233
|
+
Every number names its source: `native` (the provider's own counter), `hub count` (the hub's own `tokens` increments, which cover peers that
|
|
1234
|
+
report no usage record, such as Jcode and Kimi), or `unknown`. Unknown is never shown as 0. `TOTAL` includes cache reads and `WITHOUT CACHE`
|
|
1235
|
+
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
|
|
1236
|
+
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
|
|
1237
|
+
`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
|
|
1238
|
+
as 0 (it is `unknown` when no peer is known). The overall `WITHOUT CACHE` is unknown unless every peer's cache split is known.
|
|
1239
|
+
`usage limits` shows the newest 200 events and says `N older events are not shown` when it cuts (`--limit <n>`, up to 5000, shows more). A pause that the events
|
|
1240
|
+
never ended and the hub no longer holds (cleared by `ahub reset`, which keeps the log as it was) shows as `pause ended, end unknown`, not as open. A private task shows its id and `[pii]`, never
|
|
1241
|
+
a title. The person and a configured planner may read usage, in the console, the dashboard control link or the CLI; every other agent is refused.
|
|
1242
|
+
|
|
1112
1243
|
`ahub report` counts the same overlap warnings as `scripts/overlaps.ts`, from the
|
|
1113
1244
|
structured events instead of log lines. `--by task` uses the task each usage and
|
|
1114
1245
|
token record was attributed to when it was written: the delivery that started the
|
|
@@ -1451,6 +1582,14 @@ stays the default until an evaluation says otherwise (`docs/cooperbench.md`).
|
|
|
1451
1582
|
turns the stale-notice drop off, for a controlled comparison only (the #106
|
|
1452
1583
|
ablation in `docs/cooperbench.md`); the hub logs it at start.
|
|
1453
1584
|
|
|
1585
|
+
## Always-ask action policy foundation (#636)
|
|
1586
|
+
|
|
1587
|
+
The classifier, local configuration and session budget counter are available in source. Adapter enforcement is pending: each peer's `ahub status` row says `always-ask not enforceable: adapter integration pending`. A default-on policy does not add a pre-tool check to a native CLI by itself.
|
|
1588
|
+
|
|
1589
|
+
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 currently reads the untracked local policy without a retained confirmation; this ceiling must be addressed before the adapter gates ship (#312/#313).
|
|
1590
|
+
|
|
1591
|
+
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. Unknown command syntax retains native permission handling. This foundation never changes a sandbox or bypasses a denied permission; per-adapter enforcement tests land with their integrations.
|
|
1592
|
+
|
|
1454
1593
|
## Permission modes for running peers
|
|
1455
1594
|
|
|
1456
1595
|
Use a plain terminal to inspect or change a running peer:
|
|
@@ -1794,6 +1933,8 @@ with the headless command rather than guessed. The launcher uses the running
|
|
|
1794
1933
|
hub's `kimi_cmd`; when that value has no TUI form, the refusal says so, since an
|
|
1795
1934
|
edited file value waits for `ahub settings reload`.
|
|
1796
1935
|
|
|
1936
|
+
After three empty inbox reads within ten minutes by a pull-only peer with no assigned task or review, the hub adds polling advice and one console notice per streak (peer id and counts only); a delivery or assignment resets it, and restart clears the in-memory counters.
|
|
1937
|
+
|
|
1797
1938
|
The TUI is pull-only. Its model reads `hub_inbox` at the start of work, between
|
|
1798
1939
|
steps of longer work and before reporting, and shares results, and mid-work
|
|
1799
1940
|
blockers or changed contracts, explicitly with `hub_send` addressed with `to`
|
|
@@ -1803,7 +1944,9 @@ and important markers do not push or interrupt it. There is no hub busy state,
|
|
|
1803
1944
|
watchdog, console approval, hub permission mode, context reading, automatic quota
|
|
1804
1945
|
pause/handoff, shared final answer or session resume. When important messages are
|
|
1805
1946
|
waiting, every other hub tool result ends with a line saying how many, so the model
|
|
1806
|
-
reads `hub_inbox` before starting long local work (#398).
|
|
1947
|
+
reads `hub_inbox` before starting long local work (#398). One `hub_inbox` read drains the queue oldest first up to
|
|
1948
|
+
64 KiB of rendered text and, when more waits, ends with `N more waiting: call hub_inbox again before you start work` (#713).
|
|
1949
|
+
Read quota and approve tools
|
|
1807
1950
|
in Kimi's own TUI; a person can pause the hub queue by hand. End the native terminal
|
|
1808
1951
|
session there, not with `ahub stop kimi`.
|
|
1809
1952
|
|
|
@@ -1973,8 +2116,9 @@ but cannot show pushes, so it attaches tools-only (protocol 16, issue #205):
|
|
|
1973
2116
|
`messages wait for hub_inbox; for pushes restart Claude with ahub claude`; the
|
|
1974
2117
|
console footer shows `tools-only: ahub claude` and the dashboard shows the
|
|
1975
2118
|
status line.
|
|
1976
|
-
- The session reads them with `hub_inbox`,
|
|
1977
|
-
the hub's recall note when one waits (
|
|
2119
|
+
- The session reads them with `hub_inbox`, which drains the queue oldest first (important messages marked, as ever) up to 64 KiB of rendered text plus
|
|
2120
|
+
the hub's recall note when one waits (#713; a push peer's digest is still ten items). When more is waiting the result ends
|
|
2121
|
+
`N more waiting: call hub_inbox again before you start work`. Each read is one `completed` delivery (`read through
|
|
1978
2122
|
hub_inbox` in `ahub queue list`); nothing is ever `accepted`, and the session
|
|
1979
2123
|
has no `hub_delivery_done`. A read the model never saw (the tool call was
|
|
1980
2124
|
cancelled, the plugin died) cannot be retried: `ahub queue show <id>` of the
|
|
@@ -2184,6 +2328,22 @@ killed.
|
|
|
2184
2328
|
Rows without a live process are stale registrations; forget them with
|
|
2185
2329
|
`ahub projects remove <id>`.
|
|
2186
2330
|
|
|
2331
|
+
## Agent CLI versions
|
|
2332
|
+
|
|
2333
|
+
Agent CLIs update themselves often, and a hub release cannot follow every one. One policy decides each gated CLI: the Codex and Kimi fresh reviewers, Jcode, agy and Qwen (#691).
|
|
2334
|
+
|
|
2335
|
+
- `ahub agents [--json]` lists each gated CLI with its version, verdict and verified versions.
|
|
2336
|
+
- **verified:** a receipt exists.
|
|
2337
|
+
- **in-line:** untested, inside the compatible line that a contract gate (Jcode, agy) declares; it starts with a note.
|
|
2338
|
+
- **trusted:** you accepted this exact version on this machine.
|
|
2339
|
+
- **refused:** the reason names the installed and verified versions and the command that admits it.
|
|
2340
|
+
- **unknown:** the CLI is not on PATH, or its version could not be read.
|
|
2341
|
+
- `ahub agents trust <id> <version>` accepts one untested version on this machine (`~/.agenthub/agent-compat.json`); `--revoke` undoes it. Only the person can run it; agent shells are refused.
|
|
2342
|
+
- For the reviewers, trust lifts only the version pin. The MCP inventory, Apps/plugins/hooks readback, sandbox denial fixtures and binary fence still run before every child, and a failed leg still refuses.
|
|
2343
|
+
- What trust cannot prove is printed when you trust.
|
|
2344
|
+
- `ahub doctor` shows one line for each installed CLI that is not on a verified version.
|
|
2345
|
+
- A weekly workflow (`.github/workflows/agent-compat.yml`) compares the latest npm versions of Codex, Kimi Code and Qwen Code with the verified sets, keeps one `agent-compat` issue up to date while one is ahead and closes it when none is. The next step for each listed version is a model-free receipt in `docs/verification/`, then adding it to `verified` in the same PR. Jcode and agy are not watched.
|
|
2346
|
+
|
|
2187
2347
|
## Upgrade and crash recovery
|
|
2188
2348
|
|
|
2189
2349
|
On a terminal, one command reviews, applies and follows an upgrade:
|
|
@@ -3358,11 +3518,12 @@ starts its ACP peer. `--print-command` previews; TUI is refused until #286's
|
|
|
3358
3518
|
verification. `ahub stop qwen` stops the owned process group. A conductor may start
|
|
3359
3519
|
it only through the selected roster and existing capabilities.
|
|
3360
3520
|
|
|
3361
|
-
|
|
3521
|
+
Receipt-verified native ACP identities are qwen-code 0.25.0 and 0.26.0 ([dated receipt](verification/2026-10-22-kimi-qwen-compat.md)). A CLI version label alone
|
|
3362
3522
|
is insufficient: startup verifies its native identity/version and advertised mode
|
|
3363
|
-
ids before any prompt. The
|
|
3364
|
-
its package/ACP source
|
|
3365
|
-
|
|
3523
|
+
ids before any prompt. The earlier local installation reported CLI 0.25.0 while
|
|
3524
|
+
its package/ACP source said 0.24.1; that was not a ready identity. The 0.26.0 receipt
|
|
3525
|
+
used a private prefix and did not upgrade PATH. Configure `qwen_cmd` only in
|
|
3526
|
+
untracked config.local.json with a receipt-verified executable.
|
|
3366
3527
|
The provider's tunnel/relay, if needed, must already be available. Startup cannot
|
|
3367
3528
|
prove network readiness from a version command.
|
|
3368
3529
|
|
|
@@ -3394,11 +3555,11 @@ TUI input may interleave with an ACP turn; there is no single-writer guard. Clos
|
|
|
3394
3555
|
After upgrading to the recipient-retry release, a Jcode project MCP entry written before `AGENTHUB_DELIVERY_ONLY` was added is intentionally stale. Once per project, the person runs `ahub jcode --mode headless` before using conductor/dashboard starts. The launcher rewrites only the owned entry with the delivery-only marker, preserving foreign entries and refusing collisions; recovery relaunches already use this CLI path. Readiness checks never rewrite the file, and an explicit false marker or any other drift remains refused. Until that rewrite, daemon starts keep their actionable stale-entry refusal rather than advertising a retry tool Jcode cannot use.
|
|
3395
3556
|
|
|
3396
3557
|
|
|
3397
|
-
Native policy is unmanaged and has NO hub sandbox; no permission_modes.jcode or runtime mode mapping is invented. Quota and consumption remain unknown. Supported versions run from 0.98.0 up to, not including, 1.0.0 (#529). Every owned jcode process (version probe, daemon, ACP and TUI) runs with `JCODE_NO_TELEMETRY=1`. Native session/load (verified on 0.94.0 and 0.98.1) cannot prove identity, so attached Jcode blocks controlled recovery before effects and crash recovery asks for deliberate native reopening. A requested load without an echoed identity refuses; no fresh session is presented as restored. Provider/tool/native teardown receipts remain unverified in the pinned contract report.
|
|
3558
|
+
Native policy is unmanaged and has NO hub sandbox; no permission_modes.jcode or runtime mode mapping is invented. Quota and consumption remain unknown. Supported versions run from 0.98.0 up to, not including, 1.0.0 (#529); another version is refused before the owned daemon starts, with the version named and the trust command (#691). Every owned jcode process (version probe, daemon, ACP and TUI) runs with `JCODE_NO_TELEMETRY=1`. Native session/load (verified on 0.94.0 and 0.98.1) cannot prove identity, so attached Jcode blocks controlled recovery before effects and crash recovery asks for deliberate native reopening. A requested load without an echoed identity refuses; no fresh session is presented as restored. Provider/tool/native teardown receipts remain unverified in the pinned contract report.
|
|
3398
3559
|
|
|
3399
3560
|
## Optional Antigravity (agy) peer
|
|
3400
3561
|
|
|
3401
|
-
Antigravity is optional and off roster by default. Use `ahub roster add agy`, then run `ahub agy` in a terminal: it runs the Antigravity CLI as a fresh pull-only TUI in that terminal. It accepts the 1.4.x line: 1.4.2 is the verified version, any other 1.4.x launches with a stderr warning (agy updates itself), and other versions are refused (#589). The running hub must advertise `native_hook_launch`; an older hub refuses before any write with an upgrade-or-restart remedy. Only the person's launcher starts it: conductor starts are refused, there is no controlled restore or resume, and a declared agy extra instance is refused when the config loads (#625). Headless/print, resume (`--conversation`, `--continue`, `--new`), `--mode`, `--dangerously-skip-permissions` and `--unattended` are refused until their native mapping is verified; `--print-command` previews without writing.
|
|
3562
|
+
Antigravity is optional and off roster by default. Use `ahub roster add agy`, then run `ahub agy` in a terminal: it runs the Antigravity CLI as a fresh pull-only TUI in that terminal. It accepts the 1.4.x line: 1.4.2 is the verified version, any other 1.4.x launches with a stderr warning (agy updates itself), and other versions are refused (#589) unless the person trusts that exact version with `ahub agents trust agy <version>` (#691). The running hub must advertise `native_hook_launch`; an older hub refuses before any write with an upgrade-or-restart remedy. Only the person's launcher starts it: conductor starts are refused, there is no controlled restore or resume, and a declared agy extra instance is refused when the config loads (#625). Headless/print, resume (`--conversation`, `--continue`, `--new`), `--mode`, `--dangerously-skip-permissions` and `--unattended` are refused until their native mapping is verified; `--print-command` previews without writing.
|
|
3402
3563
|
|
|
3403
3564
|
The launcher writes exactly `plugin.json`, `mcp_config.json` and `hooks.json` in `.agents/plugins/agent-hub/`, refusing linked or foreign entries before any write, and removes only its own matching files when the TUI ends. It never writes project-level `.agents/hooks.json` or the person's `~/.gemini` settings. Run `ahub init` afterwards to ignore the untracked plugin directory; a tracked plugin is written with a warning. The native model sees the hub tools under the server name `agent-hub_agent-hub`.
|
|
3404
3565
|
|
|
@@ -3452,7 +3613,7 @@ A bundled adapter module is authorized by the person with `adapter_modules` (at
|
|
|
3452
3613
|
|
|
3453
3614
|
- A person opens `ahub watch kimi` or `ahub watch qwen` in a second terminal. `--no-thoughts` hides thought items; `--color=auto|always|never` controls colour. `q` or Ctrl+C leaves the view, keeping the peer running. Answer approvals in `ahub console` or with `ahub permit`.
|
|
3454
3615
|
- Watch replays bounded memory history from this daemon, then displays live updates. It is the hub's read-only view, with no prompt input. It does not read native session files.
|
|
3455
|
-
- Kimi's default is its own pull-only TUI (#316). Watch requires `ahub kimi --mode headless`; its own TUI remains visible in its native terminal. Qwen requires roster participation and verified ACP
|
|
3616
|
+
- Kimi's default is its own pull-only TUI (#316). Watch requires `ahub kimi --mode headless`; its own TUI remains visible in its native terminal. Qwen requires roster participation and a receipt-verified ACP identity. `ahub qwen --mode tui` remains refused.
|
|
3456
3617
|
- Protocol stays 16; a same-protocol older daemon answers the new request as unknown, which the CLI reports. Since 0.12.44 a headless start that the hub itself makes for Kimi or Qwen opens this view automatically through the terminal provider (see Start modes; #286).
|
|
3457
3618
|
- Native T0 limits: [ACP watch verification](verification/2026-10-11-acp-watch-t0.md).
|
|
3458
3619
|
|
|
@@ -3883,8 +4044,62 @@ restart the hub. For example, a reviewer can use:
|
|
|
3883
4044
|
|
|
3884
4045
|
Start them with `ahub codex --as codex-review` and
|
|
3885
4046
|
`ahub kimi --as kimi-review`. Codex keeps its native TUI and its own hub-owned
|
|
3886
|
-
app-server proxy; extra Kimi, Qwen, Pi and local instances use headless starts.
|
|
3887
|
-
Extra Jcode instances are
|
|
4047
|
+
app-server proxy; extra Kimi, Qwen, Jcode, Pi and local instances use headless starts.
|
|
4048
|
+
Extra Jcode instances are supported (#685), in `.agenthub/config.local.json` only:
|
|
4049
|
+
|
|
4050
|
+
```json
|
|
4051
|
+
{
|
|
4052
|
+
"instances": {
|
|
4053
|
+
"jcode-claude": { "kind": "jcode", "roles": ["verifier"], "jcode_home": "/Users/you/.agenthub/jcode/claude",
|
|
4054
|
+
"provider": "claude", "model": "claude-sonnet-5-5" },
|
|
4055
|
+
"jcode-local": { "kind": "jcode", "roles": ["verifier"], "jcode_home": "/Users/you/.agenthub/jcode/local",
|
|
4056
|
+
"provider_profile": "onprem" }
|
|
4057
|
+
}
|
|
4058
|
+
}
|
|
4059
|
+
```
|
|
4060
|
+
|
|
4061
|
+
`jcode_home` is required, absolute, and must differ from the base `jcode_home`, from
|
|
4062
|
+
every other instance's and from any directory inside or around them, however it is
|
|
4063
|
+
spelled: a symlink, a system alias such as `/tmp` and `/private/tmp`, or a case-only
|
|
4064
|
+
alias is the same home (the hub refuses the configuration at startup otherwise). At most 8 Jcode instances are accepted per
|
|
4065
|
+
project. `provider`, `model` and `provider_profile` are optional and passed to Jcode
|
|
4066
|
+
as `-p`, `--model` and `--provider-profile` exactly as written; any other field is
|
|
4067
|
+
refused, and these fields are never editable from settings.
|
|
4068
|
+
|
|
4069
|
+
You authenticate inside Jcode, never in the hub. Run Jcode's own setup against each
|
|
4070
|
+
home (provider login, API key, an OpenAI-compatible base URL such as the on-prem
|
|
4071
|
+
gateway, a provider profile), and initialize that home's MCP store with Jcode's own
|
|
4072
|
+
client, as for the base peer. The hub never reads, writes, copies or injects a model
|
|
4073
|
+
credential, a key, a token or a provider URL, and never creates the home. Its only
|
|
4074
|
+
start preflight is read-only: the home must exist as a directory you own, otherwise
|
|
4075
|
+
the start is refused and nothing runs. A Jcode sign-in failure appears as the start
|
|
4076
|
+
or turn error, with bounded text. An instance reports tokens only if Jcode itself
|
|
4077
|
+
does; until then they show `unknown`, never 0.
|
|
4078
|
+
|
|
4079
|
+
Each instance owns its private `jcode serve` and `jcode acp` pair, socket, roster row
|
|
4080
|
+
and launch record, and acts as its own peer id (for example `jcode-local`), never as
|
|
4081
|
+
`jcode`. Start it with `ahub jcode --as jcode-local` (headless; an instance has no
|
|
4082
|
+
TUI) and stop it with `ahub stop jcode-local`: the base Jcode and every other instance
|
|
4083
|
+
keep running. An extra implementer needs the same managed worktree as every extra
|
|
4084
|
+
implementer (`worktree: ".worktrees/jcode-local"`). Every instance is a cloud peer
|
|
4085
|
+
(`trust.onPrem` is false), whatever provider you configured: it never receives PII
|
|
4086
|
+
work. `ahub status` and the dashboard show the provider, model and profile as
|
|
4087
|
+
declared, and `ahub doctor` lists the MCP servers each rostered instance's home would
|
|
4088
|
+
load.
|
|
4089
|
+
|
|
4090
|
+
Upgrade note (#368): the project's `.jcode/mcp.json` entry for Jcode no longer names
|
|
4091
|
+
`AGENTHUB_PEER_ID`, because the file is shared by every Jcode in the project and Jcode
|
|
4092
|
+
gives an entry's own env precedence over the process env. Each hub-started Jcode now
|
|
4093
|
+
supplies its own peer id and a launch id, and the hub admits a hub-tools connection
|
|
4094
|
+
for Jcode only with the launch id of that peer's current owned launch. After
|
|
4095
|
+
upgrading, `ahub status` and `ahub doctor` report the Jcode MCP entry as not ready
|
|
4096
|
+
once (`jcodeMcpReady` is false for the old entry): run `ahub jcode` once and it
|
|
4097
|
+
rewrites its own entry, or follow the remedy text the start refusal shows. A Jcode you
|
|
4098
|
+
run yourself in this project outside the hub has no peer id: its hub tools refuse
|
|
4099
|
+
every call with that reason and never default to `jcode`, and a process that only
|
|
4100
|
+
sets `AGENTHUB_PEER_ID` without an owned launch is refused by the hub.
|
|
4101
|
+
|
|
4102
|
+
An extra Claude instance is a reviewer or
|
|
3888
4103
|
planner you start yourself: declare it with `roles` only (for example
|
|
3889
4104
|
`"claude-review": { "kind": "claude", "roles": ["reviewer"] }`, no `start_mode` or
|
|
3890
4105
|
`worktree`) and run `ahub claude --as claude-review` in a terminal. It keeps its own
|
|
@@ -3922,9 +4137,9 @@ From 0.12.37 reviews can rotate across fresh headless Claude and Codex reviewers
|
|
|
3922
4137
|
|
|
3923
4138
|
Start them with `ahub claude --as claude-review`, `ahub codex --as codex-review` and `ahub kimi --as kimi-review`; stop with `ahub stop <id>`. 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.
|
|
3924
4139
|
|
|
3925
|
-
Codex requires
|
|
4140
|
+
Codex requires a verified `codex-cli` (0.146.0 or 0.163.0) or one the person trusts on this machine, and a passing bounded runtime receipt before its model child starts. Both verified versions passed the [2026-10-22 model-free production admission](verification/2026-10-22-codex-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.
|
|
3926
4141
|
|
|
3927
|
-
Kimi requires Kimi Code
|
|
4142
|
+
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.
|
|
3928
4143
|
|
|
3929
4144
|
A dangling or unreadable standard/configured credential root makes the Codex reviewer unavailable with only its path class in the reason (for example `~/.docker` or `$DOCKER_CONFIG`, never an expanded path or contents); repair the root and start the reviewer again.
|
|
3930
4145
|
|
|
@@ -3965,6 +4180,14 @@ CLI checks the saved workspace against the current declaration again before any
|
|
|
3965
4180
|
context change or file restoration. Removing the declaration intentionally
|
|
3966
4181
|
blocks that undo until the identity and workspace can be reviewed.
|
|
3967
4182
|
|
|
4183
|
+
## Release approval and optional tag guard
|
|
4184
|
+
|
|
4185
|
+
Run `ahub sdlc authorize-release <version>` from the running daemon's release-candidate checkout in a person's terminal after committed documentation is fresh. The receipt binds commit, package version, remote identity and the docs verdict. Agents and delegated live-test calls cannot authorize. The daemon keeps approval only in memory and logs metadata for audit; restart requires a new approval. The read-only `ahub sdlc release <owner/repo>` report shows its receipt, retaining native-verification blockers.
|
|
4186
|
+
|
|
4187
|
+
`ahub init --release-guard` installs a managed Git pre-push guard and release instructions (`--dry-run --json` previews them). It preserves an existing default hook as `pre-push.agent-hub-original` and passes original argv/stdin to it only after approval matches. Unknown or mismatched `v*` tag pushes fail closed, including when the daemon is down. Non-version branch pushes remain independent of the daemon. Custom `core.hooksPath` and linked/hardlinked hook files require manual integration. Re-run init after changing the Bun/package location. The person's `git push --no-verify` remains an explicit bypass; agents are instructed never to use it.
|
|
4188
|
+
|
|
4189
|
+
For `gh release create` and `npm publish`, use the exact literal command after `ahub sdlc release-guard --`. This preflight reads evidence and never executes the command. New GitHub tags require an explicit full commit target; alternate-repository, workspace/archive and bulk target forms refuse. GitHub/npm adapter enforcement is deferred to #312/#313. This consent record does not certify a tarball, native acceptance or live publication. Detailed limits: [S6 authorization](sdlc.md#person-release-authorization-481-s6).
|
|
4190
|
+
|
|
3968
4191
|
## Planner release scheduling
|
|
3969
4192
|
|
|
3970
4193
|
Use `ahub sdlc train report <release-id>` for scope readiness and recorded release metrics. The planner creates future release rows, activates one train, and assigns tasks through the release-only hub tools. A due date requests a cut review; it never clears unfinished work. Move missed tasks to the next row with a reason, then use `ahub sdlc train cut <release-id> <revision>` from the person's terminal or `hub_release_cut` as the planner. The cut retains a short host admission lease through freeze and defers on held gate slots or unknown/quota-limited peer windows with a real quota source. Accounts without a quota reader (Kimi included when `kimi_tokens_5h` is zero) report `no quota source`; manual and budget-record pauses still defer. It does not run release preparation or publish anything. Schedule bundle/check/docs work under separate heavy admission and retain the person's native verification, authorization and upgrade window. A hotfix records its enumerated cause and keeps every gate.
|
|
@@ -3978,3 +4201,11 @@ If Codex is offline with `statusNotice.code = unidentified-cancellation`, the hu
|
|
|
3978
4201
|
could not identify a cancelled native turn. Reattach the native session before
|
|
3979
4202
|
further hub delivery. A late completion keeps this hold; verified native
|
|
3980
4203
|
reattachment or TUI detachment clears it. The notice contains fixed guidance, without native ids.
|
|
4204
|
+
|
|
4205
|
+
## Roles per SDLC stage (#525, planned)
|
|
4206
|
+
|
|
4207
|
+
The design for planner, implementer and reviewer instances per stage is in the spec section "Amendment: roles per SDLC stage (#525)". Nothing in it is available yet. Each implementation slice (525-1 to 525-6) adds its operator steps here when it ships. Until then, the instance rules in "Additional headless peer instances" above are current. The planned changes an operator will see:
|
|
4208
|
+
|
|
4209
|
+
- A Claude instance with `["implementer"]` and a `worktree`, as a terminal instance (started with `ahub claude --as <id>`) or as `start_mode: "headless"` (`permission_mode` `ask` or `ask-when-needed`; `never-ask` refused).
|
|
4210
|
+
- 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.
|
|
4211
|
+
- 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.
|
package/docs/profiles.md
CHANGED
|
@@ -49,9 +49,9 @@
|
|
|
49
49
|
|
|
50
50
|
# Project profile overrides
|
|
51
51
|
|
|
52
|
-
- `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` and `
|
|
52
|
+
- `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
53
|
- 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
54
|
- `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.
|
|
55
55
|
- `role_text` is bounded guidance for existing flow roles (2000 characters each); it grants no authority. `catalog_roles` supplies bounded compatible guidance ids; the existing explicit catalog selections take precedence. Actual flow maps remain in `roles` and retain their existing validation.
|
|
56
|
-
- `agents` replaces only the managed AGENTS block (16000 characters maximum); surrounding instructions remain. Init previews contain paths/actions only. `example_checks` is at most 16 display strings of 2000 characters, shown as advisory examples by init and never selected as executable checks. Existing `checks` trust remains authoritative.
|
|
56
|
+
- `agents` replaces only the managed AGENTS block (16000 characters maximum); surrounding instructions remain. Init previews contain paths/actions only. `example_checks` is at most 16 display strings of 2000 characters, shown as advisory examples by init and never selected as executable checks. `review_checklist` is at most 16 non-empty strings of 500 characters, customizing the checklist items in review requests with `{target}` and `{check}` interpolations. Existing `checks` trust remains authoritative.
|
|
57
57
|
- No override mutates shipped profile data or another project. Unknown fields, base remapping and invalid/oversized data are refused. Headers are quoted. Daemon/MCP restart is required for config changes; no native model consumption or research measurement is claimed.
|
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.13.0
|
|
21
21
|
ahub setup
|
|
22
22
|
```
|
|
23
23
|
|
|
@@ -30,6 +30,10 @@ 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.13.0
|
|
34
|
+
|
|
35
|
+
One version policy now gates the Codex and Kimi fresh reviewers, Jcode, agy and Qwen (#691): `ahub agents` lists each installed CLI with its version and verdict, a version outside the verified ones (or, for Jcode and agy, outside their compatible line) is refused with the trust command, and `ahub agents trust <id> <version>` accepts that exact version on this machine; only the person can run it, and the reviewers' isolation proofs still run. See [agent CLI versions](operations.md#agent-cli-versions). If you use Jcode, run `ahub jcode` once per project: the hub-owned `.jcode/mcp.json` entry no longer names a peer, `ahub status` and `ahub doctor` show the old entry as not ready until it is rewritten, and the hub admits Jcode's hub tools only from an owned launch (#368). Extra Jcode instances, each with its own `jcode_home`, can be declared in `.agenthub/config.local.json` and started with `ahub jcode --as <id>` (#685; see [Jcode operations](operations.md#optional-jcode-peer)). Run `ahub init` once per project to refresh the hub block in `AGENTS.md`: it tells pull-only agents never to poll `hub_inbox` or CI on a timer and to run one heavy job per repository at a time (#681). `ahub usage` (with `limits` and `total`) and the console's Usage panel (`7`) show tokens per peer, task, issue, PR, release, day or model and the quota pause and reset history (#683); `ahub report --dogfood` prints a read-only scorecard (#687). In the console, `r` on a task in review now asks `a` (approve) or `c` (request changes, which needs a note) (#711), and a task's detail shows an overlaps block and, when ripwire 0.6.7 is on the daemon's PATH, its changed symbols, which the review brief lists too (#684). A pull-only peer now drains its queue up to 64 KiB per `hub_inbox` read, a queued delivery can be discarded while its peer is busy, and the person clears one peer's queue with `ahub queue discard --peer <id> --reason <text> --yes` (#713). `ahub sdlc authorize-release <version>` records the person's release approval, and `ahub init --release-guard` installs an optional tag pre-push guard (#481 S6; see [release approval](operations.md#release-approval-and-optional-tag-guard)). As announced since 0.12.x, `sdlc.workflow = "gsd-lite"` no longer loads and the `phase` receipt name is refused (#481): remove the setting and record a `criteria` checklist with `hub_sdlc_record`. Restart Claude sessions so they load the 0.13.0 plugin. Coming from 0.12.44 or older, the notes below apply too.
|
|
36
|
+
|
|
33
37
|
## Upgrading to 0.12.45
|
|
34
38
|
|
|
35
39
|
The dashboard is redesigned (#469): from 1024px a top bar and a left sidebar (a row of tabs below that), keys `1`-`7` switch views, `?` lists the keys and `Esc` closes a sheet; a task opens as a side sheet, and the plan, split, releases, delivery evidence and propose forms sit in a Plan sheet opened from the board toolbar. View names, ids and the view cookie are unchanged. A person can load a bundled ACP adapter module declared under `adapter_modules` (a `path` and its `sha256`) in untracked `.agenthub/config.local.json`: only the daemon imports it, at startup, so a changed declaration needs a restart; Settings and hub tools cannot write it, and a declaration in the shared `.agenthub/config.json` is ignored. A project that declares modules can be upgraded or recovered only between releases that advertise `external_adapter_modules`. See [Adding an AI tool](adding-an-ai-tool.md#5-external-adapter-modules-451-a4) (#451). `hub_review` and `ahub review ... --findings '<json>'` take structured findings, `max_nits` in `.agenthub/sdlc.toml` caps the nits per report (default 5), and in enforce an open Important finding refuses approval (#481 S3). Plans take optional `proof` and `risks`. In enforce, approval also needs every changed PR file covered by a literal `plan.paths` entry; otherwise amend the plan through `hub_task_accept` and call done again, or the person runs `ahub sdlc accept-departure <task> <head> <reason...>`, which lapses when the hub restarts (#481 S2). An unresolved review thread now settles only by resolution or a later reply from a GitHub user; any other author kind counts as a pending bot comment (#481). `ahub roster remove <peer>` also deletes the roster key of an instance no longer declared (#225). When `ahub kimi` refuses a `kimi_cmd` with no TUI form, it now says the value is the running hub's, retained until `ahub settings reload` (#654). A Claude session no longer gets `hub_inbox` advice while a delivery hold refuses its pulls (#221). A same-size rewrite of a large file within one filesystem timestamp tick is now told apart by its bytes (#428). Restart Claude sessions so they load the 0.12.45 plugin. Coming from 0.12.43 or older, the notes below apply too.
|
|
@@ -76,7 +80,7 @@ The 0.12.38 plugin reports a reply stopped by the hop cap as not delivered inste
|
|
|
76
80
|
|
|
77
81
|
Antigravity (`agy`) can join as an optional pull-only implementer (#485). It is off roster by default: install the Antigravity CLI 1.4.x (1.4.2 verified; other 1.4.x patches launch with a warning; on 1.4.3 the hub tools appear from the second TUI turn), run `ahub roster add agy`, then run `ahub agy` in a terminal. Its native permissions are unmanaged and it has no hub sandbox. See [Antigravity operations](operations.md#optional-antigravity-agy-peer).
|
|
78
82
|
|
|
79
|
-
Reviews can rotate across fresh Claude, Codex and Kimi reviewer sessions (#519, #533). Declare headless reviewer-only instances in `.agenthub/config.local.json`; Codex and Kimi join only with `review_mode: "fresh"`. Codex also needs
|
|
83
|
+
Reviews can rotate across fresh Claude, Codex and Kimi reviewer sessions (#519, #533). Declare headless reviewer-only instances in `.agenthub/config.local.json`; Codex and Kimi join only with `review_mode: "fresh"`. Codex also needs a compat-admitted Codex (receipt-verified 0.146.0 and 0.163.0; select it with `codex_bin` when needed), and Kimi needs a compat-admitted Kimi Code on PATH (receipt-verified 2.2.0 and 2.3.0), signed in with its own OAuth login. Run `ahub agents` for the current version policy; every fresh reviewer still needs a passing runtime preparation. The [2.3.0 receipt](verification/2026-10-22-kimi-qwen-compat.md) is model-free and does not establish real login or model readiness. A headless reviewer instance without `review_mode` keeps its native behavior and stays out of the pool. agy is not a reviewer: naming it in `review.pool` shows an unavailable skip in `ahub route explain`, never a review. Once a train is active or frozen, or `review.pool` is set or fresh reviewer instances are declared, `ahub upgrade` refuses a target release without that support, so an older release cannot take the project over. See [fresh reviewer pool](operations.md#fresh-reviewer-pool-519).
|
|
80
84
|
|
|
81
85
|
A guarded config edit that the hub keeps at its running value now shows as `config retained: <keys>; run ahub settings reload` in status, the console and the dashboard's Settings, and starting a peer whose launch keys are retained says it uses the running value (#542). See [settings](operations.md#settings-from-the-dashboard-and-the-terminal).
|
|
82
86
|
|
|
@@ -141,6 +145,8 @@ or set `OMNIROUTE_API_KEY`. The `.agenthub/routing.toml` that `ahub init` writes
|
|
|
141
145
|
| `ahub settings set planner <peer>` | pin the planner; status reports whether it came from settings, roles or the automatic choice |
|
|
142
146
|
| `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 |
|
|
143
147
|
| `ahub status` | peers, queues, pauses; `ahub budget` for quota windows |
|
|
148
|
+
| `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 |
|
|
149
|
+
| `ahub agents` | which installed agent CLI versions the hub accepts; `ahub agents trust <id> <version>` accepts an untested one on this machine |
|
|
144
150
|
| `ahub memory profile-check` | a person's read-only check of running memory bindings in the current registry |
|
|
145
151
|
| `ahub ask <question>` | what the board, shared memory and the log say, with the ids the answer rests on |
|
|
146
152
|
| `ahub stop <peer>` | stop one headless peer (Kimi, headless Pi, `local`); the hub and the other peers keep running |
|
package/docs/sdlc.md
CHANGED
|
@@ -16,10 +16,10 @@ The built-in lifecycle follows the [AI-Native SDLC Playbook](https://claude.com/
|
|
|
16
16
|
| spec | Design | person/planner | issue identity and scope | spec acceptance/body drift checked at build entry |
|
|
17
17
|
| plan | Build | planner/owner | plan, branch, existing predecessor gates | current planner review required at build admission; literal-path conformance gates approval in enforce |
|
|
18
18
|
| build | Build | owner | PR identity/current head and local check on that head | entering review, when enabled |
|
|
19
|
-
| test | Test | verifier/reviewer | required checks and local gate on the reviewed head | approval, when enabled; integrity
|
|
19
|
+
| test | Test | verifier/reviewer | required checks and local gate on the reviewed head | approval, when enabled; bug test integrity below, evals pending S5 |
|
|
20
20
|
| review | Deploy | assigned reviewer | current head-bound verdict, no pending change request/open thread; AC checklist under Compliance | approval, when enabled; open Important findings block in enforce |
|
|
21
21
|
| merge | Deploy | person | current-head readiness, ordered touching PRs | shown; no mutation |
|
|
22
|
-
| release | Deploy | person | merged commit, version/tag, docs freshness/live receipt checklist |
|
|
22
|
+
| release | Deploy | person | merged commit, version/tag, docs freshness/live receipt checklist | person authorization and optional tag hook below |
|
|
23
23
|
| maintain | Maintain | person/planner | follow-up intent and operational evidence | shown; metrics/control bands pending S7 |
|
|
24
24
|
|
|
25
25
|
Stored `implement` and `verify` stage ids read as `build` and `test`. A write that names the old id stores the id the configuration lists, so new enabled-lifecycle receipts use the canonical ids. The default remains off, preserving existing off-mode output, receipt and schema shapes. Status, explain, console and dashboard name the playbook stage beside enabled lifecycle ids.
|
|
@@ -32,9 +32,9 @@ Stored `implement` and `verify` stage ids read as `build` and `test`. A write th
|
|
|
32
32
|
| S1 | Accepted intent/spec and spec drift | Person-only `ahub sdlc accept`, bound to the issue's body edit time; build entry needs it in enforce (see Spec acceptance below) |
|
|
33
33
|
| S2 | Accepted plan and diff conformance | Bounded proof/risks, metadata-only plan conformance and person-bound departure acceptance |
|
|
34
34
|
| S3 | Bugs, Security and Compliance review passes | Head-bound findings, configured nit cap, Important approval gate and recurring-finding amendment proposals |
|
|
35
|
-
| S4 | Red-first tests and test integrity |
|
|
35
|
+
| S4 | Red-first tests and test integrity | Bug-label metadata, source-labelled red-first proof and changed pre-existing test blockers |
|
|
36
36
|
| S5 | Continuous evals for agent configuration | Pending gate, dependent on #251/#266; no eval pass claimed |
|
|
37
|
-
| S6 | Production approval gate |
|
|
37
|
+
| S6 | Production approval gate | Person-only commit/version/docs receipt and opt-in Git tag pre-push guard; report stays read-only |
|
|
38
38
|
| S7 | Metrics, deterministic control bands and follow-up intent | Pending; no automated metric triage or security baseline claimed |
|
|
39
39
|
| S8 | Compliance acceptance-criteria checklist | Head-bound checklist retained; legacy workflow and phase compatibility deprecated; task import removed |
|
|
40
40
|
| S9 | Planner grooming and plan review | Read-only digest, current plan-review receipt at build admission, all-mode WIP and accepted-untouched return |
|
|
@@ -64,7 +64,7 @@ The acceptance-criteria checklist belongs to the Compliance pass over the same b
|
|
|
64
64
|
|
|
65
65
|
## Delivery and verification state
|
|
66
66
|
|
|
67
|
-
Head-bound review/approval gates, bounded custom definitions, read-only merge/release reports, S0/S8 vocabulary/checklist migration, S1 spec acceptance and S9 planner admission and S10 cost governance are implemented in source. S11 release-train governance ships in 0.12.37.
|
|
67
|
+
Head-bound review/approval gates, bounded custom definitions, read-only merge/release reports, S0/S8 vocabulary/checklist migration, S1 spec acceptance and S9 planner admission and S10 cost governance are implemented in source. S11 release-train governance ships in 0.12.37. S5, S7 and the native advise-through-merge/release cycle remain pending. S6 authorization and its optional tag hook are implemented in source. S4 test integrity is implemented in source. S2 plan conformance and S3 findings are implemented in source. Installation and native acceptance require separate receipts; a person authorization is consent, not native verification.
|
|
68
68
|
|
|
69
69
|
## Initial commands
|
|
70
70
|
|
|
@@ -154,7 +154,7 @@ actor = "person"
|
|
|
154
154
|
after = ["approve"]
|
|
155
155
|
```
|
|
156
156
|
|
|
157
|
-
These ids are guidance/receipt destinations. Publish neither merges nor releases. The read-only source-readiness report is implemented below. Native acceptance
|
|
157
|
+
These ids are guidance/receipt destinations. Publish neither merges nor releases. The read-only source-readiness report is implemented below. Native acceptance and research measurements remain unverified or pending; person authorization is recorded separately below.
|
|
158
158
|
|
|
159
159
|
|
|
160
160
|
# Structured documentation readiness evidence (#257)
|
|
@@ -278,3 +278,33 @@ Review/status use the same bounded PR file metadata reader as the merge queue; n
|
|
|
278
278
|
The person may instead run `ahub sdlc accept-departure <task> <head> <reason...>`. Acceptance requires a currently known departure, never unknown or already covered conformance. The hub reads and captures the complete current repo/PR/head inventory, verified task repository scope and the plan fingerprint/revision; changing the plan, repository refs/scope, link, head or inventory invalidates that acceptance. Departure consent also expires on hub restart: amend the plan or accept again in the new host lifetime. This fail-closed ceiling prevents a rejected, unpersisted readback from reviving old consent; a durable host observation journal is the upgrade path. The reason is bounded to 2048 characters, sanitized and privacy-screened. There is no peer tool or live-test delegation for this person-only operation. Private PR inventories are unavailable to this remote readback; amend the private plan instead. Public private-task projections show only whether a departure acceptance exists.
|
|
279
279
|
|
|
280
280
|
The report names "plan revisions after the first observed push". Host-authored content revisions live in task history, independently of backlog `planningRevision`. The first verified remote head records the current revision/fingerprint; earlier pushes are explicitly unknown. Pending observations persist only with successful owner/reviewer transitions; status and queue reads do not append board history. Off mode captures no S2 observation or content revision. Plan edits made while off therefore do not count in revisions after the first observed push when reporting resumes. Revoking an existing person acceptance on a plan change still persists its invalidation, including while reporting is off. If startup loses a pending observation, the earlier interval remains unknown. This observation boundary is a ceiling until a webhook or Actions push receipt provides a true push-event source.
|
|
281
|
+
|
|
282
|
+
## Test integrity (#481 S4)
|
|
283
|
+
|
|
284
|
+
When mode is enabled, the linked issue's complete label metadata decides applicability: `bug` (case-insensitive) requires S4, known non-bug labels exempt it, and unavailable labels are unknown. No issue title/body or patch is read. Enforce blocks entering review and approval for unknown applicability, missing/invalid proof, incomplete file metadata, or modified/deleted pre-existing test files. Advise exposes the same report without blocking; off adds no S4 receipt or readback.
|
|
285
|
+
|
|
286
|
+
Record `redFirst` with two legs through `hub_sdlc_record` or `ahub sdlc record`. Both use the same bounded `check` name; `red` has `result: "failed"`, `green` has `result: "passed"`, each with `source: "local" | "container" | "ci"` and a full lowercase commit SHA. The red commit must occur in this PR, have one parent, and add only recognized test paths. Its preceding single-parent ancestry inside the complete PR commit set must touch only test paths, so implementation commits cannot precede red. Merge/ambiguous ancestry is refused. The green SHA must equal the current PR head. Local/container results remain labelled claims, CI legs require the named failed/passed CheckRun observed on their exact commits; agent-posted StatusContext entries cannot establish CI evidence. `checkEvidence` labels each leg `claimed` or `observed`; `redFirst: verified` describes validated structure and supplied results, not independent observation of local/container execution. CI cancellation, timeout or skipped results do not prove red-first failure. Relinking the repo, issue or PR drops the proof unless it is explicitly supplied again. In enforce, only the person may change an established repo/issue; an owner/reviewer may fill missing identity or relink the PR. This identity boundary also holds before the first read and after restart, so an owner cannot evade S4 by swapping a bug issue for a non-bug issue. Advise/off keep existing relink authority.
|
|
287
|
+
|
|
288
|
+
Example receipt (replace both SHAs):
|
|
289
|
+
|
|
290
|
+
```json
|
|
291
|
+
{"redFirst":{"red":{"source":"local","head":"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb","check":"bun test test/regression.test.ts","result":"failed"},"green":{"source":"local","head":"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa","check":"bun test test/regression.test.ts","result":"passed"}}}
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
Status/explain and merge-queue rows expose `testIntegrity` with applicability, red-first state, file-inventory state, source labels and modified/deleted test paths. Added tests are allowed. Test paths are under `test/`, `tests/` or `__tests__/`, or have a supported `.test`/`.spec` suffix; conventional `*_test.go`, `test_*.py`, `*_test.py`, `*_spec.rb` and `*Test.java` names also count. Renames/copies, unsafe paths, missing change types and truncated inventories stay unknown. Private tasks and metadata rejected by the current host privacy policy expose a neutral unknown report; receipt metadata is screened again on public output.
|
|
295
|
+
|
|
296
|
+
Reads share the existing 20 s lifecycle/queue allowance and fixed argument/output caps. Labels and check contexts are bounded to 100 each, PR commits to 100, and the red commit to fewer than 100 changed files; larger proof is unknown rather than silently accepted. The queue revalidates every linked issue's applicability with its final PR snapshot (up to 32 distinct issues). Metadata cannot detect a later commit gutting assertions in a test added by the PR; content-aware review remains required. These metadata/claim receipts do not prove a native/container run by themselves; no live advise-through-release receipt is claimed.
|
|
297
|
+
|
|
298
|
+
## Person release authorization (#481 S6)
|
|
299
|
+
|
|
300
|
+
From the running daemon's candidate checkout, the person runs `ahub sdlc authorize-release <version>`. The console-only operation binds approval to the exact current commit, its committed package version, the origin fetch/push identity and fresh committed documentation evidence. It rereads the head and remote after the documentation check. Agent shells, including `--live-test`, cannot grant it. An append-only metadata event records the approval id, commit, version and documentation digest/count. The authoritative ledger is daemon-owned memory: restart revokes every approval; audit history cannot restore one.
|
|
301
|
+
|
|
302
|
+
`ahub sdlc release <owner/repo>` shows a matching or stale authorization receipt. Authorization removes only the person-decision blocker. Native acceptance remains unverified and `ready` remains false until separately supported. No tag, workflow or publication is changed by authorization or readback.
|
|
303
|
+
|
|
304
|
+
The optional `ahub init --release-guard` writes instructions and an executable default Git `pre-push` hook. Preview with `--dry-run --json`. An existing regular hook is renamed to `pre-push.agent-hub-original`, preserving its inode and mode, and chained with the exact original arguments and stdin only after successful preflight. Ordinary later `init` calls retain the guard. Linked/hardlinked hooks, occupied backups and custom `core.hooksPath` are refused before project writes; integrate custom hook runners manually instead. The wrapper pins the current Bun and package entry paths; run init again after moving or replacing that installation.
|
|
305
|
+
|
|
306
|
+
For every actual pushed `v*` destination, the hook requires an exact semantic version and a matching receipt for the captured source object peeled to its commit. Missing consent, another commit/version/remote, daemon downtime or a reset ledger refuses the push. Version-tag deletion is refused. Branch-only pushes do not need a daemon and still reach the user's hook. The person can bypass with Git `--no-verify`; agents must never bypass it. This is a cooperative Git guard, not an OS capability boundary.
|
|
307
|
+
|
|
308
|
+
Before other release commands, agents run `ahub sdlc release-guard -- <literal argv...>`. Supported forms are one named-remote tag push, `gh release create v<version>` (an existing GitHub tag is read back; a new one requires `--target <full-sha>`), and `npm publish` from the approved checkout. Ambiguous selectors, alternate repositories, bulk pushes, workspaces and archive publishes refuse. The npm preflight refuses tracked worktree changes before and after rechecking the committed-doc verdict and HEAD, but does not attest the eventual tarball, npm configuration or lifecycle scripts. The command performs no release operation and its answer is not an execution grant. GitHub/npm enforcement remains instruction-based until adapter integration (#312/#313); rerun preflight after changing any target or candidate. Native install, live release and migration evidence remain separate obligations.
|
|
309
|
+
|
|
310
|
+
Tracked npm cleanliness compares the cached index to HEAD and raw tracked blob bytes without `git status`, clean/process filters or text converters. It refuses unknown evidence, gitlinks, transformed files and inventories above 4,096 entries, 4 MiB per file, 32 MiB total or 250 ms; untracked files remain outside this check and the eventual tarball is not attested.
|