@staix/agent-hub 0.17.0 → 0.19.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 +35 -0
- package/README.md +4 -4
- package/docs/agent-notes/README.md +11 -0
- package/docs/agent-notes/adapters.md +10 -6
- package/docs/agent-notes/benchmarks.md +1 -0
- package/docs/agent-notes/daemon.md +6 -2
- package/docs/agent-notes/local-worker.md +3 -1
- package/docs/agent-notes/tasks.md +11 -2
- package/docs/agent-notes/tests.md +7 -3
- package/docs/dogfood.md +22 -2
- package/docs/memory.md +1 -1
- package/docs/operations.md +162 -35
- package/docs/profiles.md +36 -0
- package/docs/quickstart.md +15 -5
- package/docs/sdlc.md +29 -3
- package/docs/security.md +44 -13
- package/docs/smoke.md +3 -3
- package/docs/specs/2026-09-19-agent-hub-design.md +31 -10
- package/docs/verification/2026-10-25-0.18.0.md +76 -0
- package/docs/verification/2026-10-25-codex-review-live-verdict.md +35 -0
- package/docs/verification/2026-10-25-remote-docker-transport.md +56 -0
- package/docs/verification/2026-10-26-agy-1.4.7.md +69 -0
- package/docs/verification/2026-10-26-claude-implementer-2.1.310.md +69 -0
- package/docs/verification/2026-10-26-headless-claude-shell-context.md +62 -0
- package/docs/verification/2026-10-26-jcode-0.99.1.md +49 -0
- package/docs/verification/2026-10-26-kimi-232-reviewer-compat.md +53 -0
- package/docs/verification/2026-10-26-pi-140-compat.md +41 -0
- package/docs/verification/2026-10-26-qwen-0261-acp.md +60 -0
- package/docs/verification/2026-10-27-0.19.0.md +86 -0
- package/docs/verification/claude-permission-transport-native.py +187 -0
- package/docs/verification/claude-shell-wrapper-host.ts +20 -0
- package/docs/verification/claude-shell-wrapper-native.py +145 -0
- package/docs/verification/pi-140-model-free.ts +57 -0
- package/docs/verification/pi-140-native.mjs +21 -0
- package/docs/verification/profiles/YYYY-MM-DD-general.md +46 -0
- package/docs/verification/profiles/YYYY-MM-DD-research.md +61 -0
- package/docs/verification/profiles/YYYY-MM-DD-writing.md +46 -0
- package/docs/verified.json +24 -18
- package/package.json +2 -2
- package/plugins/agent-hub/.claude-plugin/plugin.json +1 -1
- package/plugins/agent-hub/server.js +364 -98
- package/src/adapters/agy/entry.ts +1 -1
- package/src/adapters/claude-channel.ts +7 -3
- package/src/adapters/claude-implementer.ts +5 -3
- package/src/adapters/compat.ts +32 -18
- package/src/adapters/conformance/fakes/pi-rpc.ts +1 -0
- package/src/adapters/definitions/builtin-metadata.ts +3 -3
- package/src/adapters/definitions/native-factories.ts +7 -2
- package/src/adapters/definitions/reviewer-variants.ts +2 -2
- package/src/adapters/local-worker.ts +5 -3
- package/src/adapters/pi.ts +39 -3
- package/src/adapters/qwen-dual.ts +25 -0
- package/src/adapters/registry-types.ts +6 -2
- package/src/adapters/registry.ts +1 -0
- package/src/cli/agents.ts +69 -7
- package/src/cli/claude-shell-wrapper.ts +54 -0
- package/src/cli/console-state.ts +9 -2
- package/src/cli/help.ts +29 -28
- package/src/cli/identity.ts +87 -6
- package/src/cli/main.ts +198 -71
- package/src/cli/output.ts +11 -2
- package/src/cli/sdlc-output.ts +242 -0
- package/src/cli/task-output.ts +212 -0
- package/src/cli/upgrade-output.ts +57 -0
- package/src/hub/agent-drift.ts +61 -0
- package/src/hub/board.ts +31 -2
- package/src/hub/check-runner.ts +385 -25
- package/src/hub/claude-shell-wrapper.ts +349 -0
- package/src/hub/conductor.ts +5 -0
- package/src/hub/config-apply.ts +16 -7
- package/src/hub/config-edit-host.ts +1 -1
- package/src/hub/config-edit.ts +2 -2
- package/src/hub/config-tier.ts +3 -3
- package/src/hub/daemon.ts +530 -87
- package/src/hub/dogfood-profile.ts +248 -0
- package/src/hub/dogfood-read.ts +77 -14
- package/src/hub/dogfood.ts +5 -1
- package/src/hub/events.ts +1 -1
- package/src/hub/host-executable.ts +21 -1
- package/src/hub/hub-tools.ts +2 -2
- package/src/hub/instances.ts +18 -2
- package/src/hub/lifecycle.ts +1 -1
- package/src/hub/operational-authority.ts +67 -0
- package/src/hub/operational-view.ts +137 -0
- package/src/hub/orphan-process.ts +69 -0
- package/src/hub/permission-mode.ts +1 -1
- package/src/hub/read-only-shell-proof.ts +81 -0
- package/src/hub/read-only-shell.ts +162 -0
- package/src/hub/review-scope.ts +13 -0
- package/src/hub/reviewer-pool-config.ts +3 -2
- package/src/hub/reviewer-pool.ts +3 -0
- package/src/hub/routing.ts +23 -6
- package/src/hub/sdlc-merge.ts +299 -0
- package/src/hub/sdlc-metrics.ts +6 -4
- package/src/hub/sdlc-mirror.ts +129 -0
- package/src/hub/sdlc.ts +58 -12
- package/src/hub/settings.ts +11 -5
- package/src/hub/snapshots.ts +60 -0
- package/src/hub/task-repository.ts +31 -5
- package/src/hub/task-shell-command.ts +85 -0
- package/src/hub/task-shell-default.ts +78 -0
- package/src/hub/task-shell-proof.ts +171 -0
- package/src/hub/task-shell-sandbox.ts +61 -0
- package/src/hub/tasks.ts +378 -27
- package/src/local/deny.ts +91 -11
- package/src/local/sandbox.ts +67 -28
- package/src/local/shell-environment.ts +10 -0
- package/src/local/tools.ts +17 -4
- package/src/ui/index.html +3 -1
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.19.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
|
|
@@ -67,6 +67,9 @@ smoke ledger; the presence of this option proves no outstanding #273 live leg.
|
|
|
67
67
|
`status --all` uses the projects table. `queue show`, `models status` and `budget execution status` show labelled fields; add `--json` for the raw fetched document.
|
|
68
68
|
`report --by task` keeps the attribution and coverage sentences with section headings and aligned counters.
|
|
69
69
|
Use `--json` for scripts; it returns the fetched data without color, and `status --json` keeps its existing document.
|
|
70
|
+
`sdlc status`, `sdlc explain`, `sdlc queue`, `sdlc release`, `sdlc metrics`, `sdlc costs` and `sdlc authorize-release` print readable output by default (#814: aligned columns, wrapped text, readable times, `--color=auto|always|never`). A script that parsed their JSON must pass `--json`, which prints exactly the document they printed before. `sdlc export` is a data format and stays JSON, as do `export`, `research export` and `bench export`.
|
|
71
|
+
`restart` and `upgrade` off an interactive terminal (a pipe, `--dry-run`), `recovery status` and the results of `recovery reattach`, `resume`, `abort` and `dispose`, `models setup` and `start`, `queue resolve`, and `budget execution configure` and `disable` print readable text by default (#814); a script that parsed their JSON must pass `--json`, which prints exactly the document they printed before, including `restart --json --yes`. A readable plan lists each project, each peer with how it runs and what happens to it, every blocker, every reconnect-only session and every fresh start, and says nothing was changed; `--json` keeps those as stderr lines. A pipe wraps at `COLUMNS` when it is set, else at 80 columns.
|
|
72
|
+
`task show`, `task cancel`, `backlog groom`, `backlog return|plan|pin|split|undo|pull-ready` and the `release` commands (`list`, `show`, `new`, `plan`, `activate|freeze|ship|drop`) print a readable block by default (#814): the task or release as the hub holds it, a table for lists, every identifier whole, long text wrapped to the terminal. A script that parsed their JSON must pass `--json`, which prints the hub tool's text exactly as before. A private task arrives from the hub as its stub and is shown as that stub. Because these commands also take free text, `--json` and `--color=` count as flags only at the start or the end of the arguments: `--json` in the middle of a reason is part of the reason, and a value flag's value (`task cancel --reason --json`) is never a flag. A reason that ends in a bare `--json` loses it to the flag. `backlog add|pull`, `task escalate|assign|unassign` already answered one sentence and are unchanged.
|
|
70
73
|
In `projects --json` and `status --all --json`, an unavailable hub that explicitly refuses an inspection for SQLite contention also carries `failure: { "code": "database_busy" }`; it is additive metadata alongside the neutral `error` sentence.
|
|
71
74
|
Text columns are a human interface, not a scripting contract. An identifier accepted as a command argument is whole wherever its available column can hold its own length:
|
|
72
75
|
turn ids, queue ids, project ids, execution budget ids and ids in labelled views. Only status's informational settlement and hold ids are shortened;
|
|
@@ -136,6 +139,12 @@ asking, under the same path guard and sandbox; a Pi restart or replacement, or a
|
|
|
136
139
|
hub restart, drops it. The hub log records each granted call by tool name only.
|
|
137
140
|
The dashboard can only deny Pi's requests.
|
|
138
141
|
|
|
142
|
+
In `ask-when-needed`, Pi and the local worker also grant bounded read-only shell calls at the host permit boundary (#816). The command must parse as one literal command and satisfy a closed program/flag table, trusted executable lookup and the existing root/path guard. Unknown flags, operators, expansions, pipelines, output files, unsafe helper/follow/file-list options and outside-root paths keep the ordinary approval path. Single quotes preserve literal data; double quotes containing `$`, backticks or backslashes are not automatically granted.
|
|
143
|
+
|
|
144
|
+
The fixed program set is `ls`, `cat`, `head`, `tail`, `wc`, `rg`, `grep`, `stat`, `file`, `tree`, `pwd`, `find` and supported read-only `git` forms. Git patch forms need both `--no-ext-diff` and `--no-textconv` where supported; a configured helper-bearing key (`core.fsmonitor`, `log.showSignature`, `gpg.program`, `gpg.<format>.program`, `diff.external`, `diff.<driver>.command` or `diff.<driver>.textconv`, `format.pretty` or `pretty.<name>`) outside the hub's own command scope keeps every git form asking. Custom `--format` and `--pretty` options also ask because signature placeholders can invoke the default GPG program. The host revalidates executable and path proof after each await, immediately before execution. A changed proof requires an explicit approval, including in unattended mode; persistent instability runs nothing. Neither argv nor environment is rewritten. Scoped read-only grants log the tool and class without command arguments.
|
|
145
|
+
|
|
146
|
+
`ask` retains shell approval behavior; `never-ask`, existing Pi tool-wide grants and the always-ask action policy retain their precedence. Seatbelt, the path guard, read allowlists, home and network access are unchanged. The person's Pi setting and live triage receipt are separate AC4 work; this feature's tests do not certify that rollout.
|
|
147
|
+
|
|
139
148
|
Tab toggles stream and panels; `ahub console --panels` starts in panels. A panel
|
|
140
149
|
screen has a header (the project's directory name, then the tabs), the panel and
|
|
141
150
|
a three-line footer, separated by ASCII `-` rules; the stream has one rule above
|
|
@@ -518,6 +527,41 @@ resume, budget, queue, permit, permission, ask, remember, route, turns, undo,
|
|
|
518
527
|
check-path and report operations. It executes an argument vector with closed stdin. Lifecycle,
|
|
519
528
|
launch, nested console, setup, UI, logs and tail commands are refused.
|
|
520
529
|
|
|
530
|
+
## Authority by command
|
|
531
|
+
|
|
532
|
+
`classifyPeerCommand` (src/cli/identity.ts) is the gate for an `ahub` command
|
|
533
|
+
run from an agent shell. It gives every command one of three classes:
|
|
534
|
+
**Allowed** means any agent may run it; **Conductor** means only the
|
|
535
|
+
configured conductor peer may (actor-preserving and audited); **Console** means
|
|
536
|
+
only the person's own terminal. A command the gate does not name is Console,
|
|
537
|
+
and so is every help entry the gate has no class for yet;
|
|
538
|
+
`test/identity.test.ts` pins each classed form below.
|
|
539
|
+
|
|
540
|
+
### Allowed (any agent)
|
|
541
|
+
|
|
542
|
+
| Command | Class | Why |
|
|
543
|
+
| --- | --- | --- |
|
|
544
|
+
| `ahub doctor [--json] [--full] [--color=...]` | Allowed | a read-only check of tools, daemon, plugin, gateway, models and memory |
|
|
545
|
+
| `ahub doctor --stale-anchors [--json]` | Allowed | a bounded read-only report of memory symbol anchors at current HEAD |
|
|
546
|
+
| `ahub queue list [--peer <id>] [--json] [--full] [--color=...]` | Allowed | public queue metadata only; held bodies and resolution remain conductor operations |
|
|
547
|
+
| `ahub roster [--json] [--color=...]` | Allowed | public roster status; add/remove retain conductor admission |
|
|
548
|
+
| `ahub settings [list] [--json]`, `ahub settings get <key> [--json]` | Allowed | public registry values; secret-locating values, paths, undo records and config-editor details are withheld |
|
|
549
|
+
| `ahub sdlc status\|explain [<task>] [--json] [--color=...]` | Allowed | public lifecycle status; private tasks stay stubs, without private evidence or receipts |
|
|
550
|
+
| `ahub sdlc queue <owner/repo> [--json] [--color=...]`, `ahub sdlc release <owner/repo> [live-issue...] [--json] [--color=...]` | Allowed | public delivery/release readback for the checkout's GitHub origin, explicit SDLC config repos or person-imported public external records; no release authorization or mutation |
|
|
551
|
+
| `ahub release show <name>` | Allowed | public release metadata; private scope and internal history remain withheld |
|
|
552
|
+
| `ahub projects [--json] [--color=...]` | Allowed | lists registered projects; `projects remove` stays Console |
|
|
553
|
+
| `ahub models status [--json] [--color=...]` | Allowed | reads local model state; `setup\|start\|stop` stay Console |
|
|
554
|
+
| `ahub recovery status [<op-id>] [--json]` | Allowed | reads a preflight operation; the bare interactive screen, `resume`, `abort` and `reattach` stay Console |
|
|
555
|
+
| `ahub upgrade ... --dry-run` (no `--yes`) | Allowed | reviews the upgrade plan and applies nothing; `--yes` stays Console |
|
|
556
|
+
| `ahub restart --dry-run [--json]` (no `--yes`) | Allowed | reviews the restart plan and applies nothing; `--yes` stays Console |
|
|
557
|
+
|
|
558
|
+
`backlog list`, `release list` and `sdlc costs|metrics` retain their existing
|
|
559
|
+
planner/person policy. Their CLI forms stay Console for ordinary agents; a
|
|
560
|
+
configured planner can use the existing planner tools without borrowing console
|
|
561
|
+
authority. All newly admitted reads use the ordinary tools connection and public
|
|
562
|
+
views, never console identity. The person's full readback stays unchanged.
|
|
563
|
+
Conductor operations are listed in [the operational command table](#conductor-operations-812-t2).
|
|
564
|
+
|
|
521
565
|
## Conducting a team from Claude Code or Codex
|
|
522
566
|
|
|
523
567
|
Start the daemon with `ahub up --no-console`, set exactly one conductor in the
|
|
@@ -594,6 +638,11 @@ Pi starts in its TUI by default; `ahub pi --headless`, or the start mode
|
|
|
594
638
|
setting (`ahub settings set peers.pi.start_mode headless`), asks for the
|
|
595
639
|
background peer instead. The project uses its existing OmniRoute connection for DGX;
|
|
596
640
|
`pi.dgx_coding` and `pi.dgx_fast` select the gateway's configured model IDs.
|
|
641
|
+
Every Pi start (headless, TUI, console or auto start) first runs the configured
|
|
642
|
+
`pi.cmd` with `--version` (#847). Pi 1.4.0 is verified
|
|
643
|
+
([model-free receipt](verification/2026-10-26-pi-140-compat.md)); another
|
|
644
|
+
version, or one that cannot be read, is refused before Pi starts, unless the
|
|
645
|
+
person trusts that exact version with `ahub agents trust pi <version>`.
|
|
597
646
|
|
|
598
647
|
```bash
|
|
599
648
|
ahub models setup # prepare bounded Qwen3.5 4B MLX in an existing Ollama service
|
|
@@ -623,13 +672,17 @@ does not automatically hand its task to a cloud peer.
|
|
|
623
672
|
For assigned, non-private work, `hub_task_spec` reads the named GitHub issues
|
|
624
673
|
through the hub's authenticated, bounded read path. `hub_check_start` runs an
|
|
625
674
|
exact Git ref's permitted tests or typecheck in the opt-in isolated container
|
|
626
|
-
runner (`checks.runner: "container"`); `hub_check_result` and `hub_check_cancel`
|
|
675
|
+
runner (`checks.runner: "container"`, or the optional `"remote"` backend); `hub_check_result` and `hub_check_cancel`
|
|
627
676
|
read or cancel that owned run. Missing spec/check capability refuses the
|
|
628
677
|
assignment early; it never grants host commands, credentials or broader sandbox
|
|
629
678
|
access. Receipts distinguish exact source/tree/lockfile, platform, exit and
|
|
630
679
|
uncertain or cancelled outcomes. See [bounded spec and check access](security.md#bounded-task-specs-and-isolated-checks-418)
|
|
631
680
|
for the authorization and resource bounds.
|
|
632
681
|
|
|
682
|
+
Remote runner configuration (#793) is permitted only in the person's untracked `config.local.json`: select `checks.runner = "remote"` and supply `checks.remote.host`, `checks.remote.image` (immutable SHA-256 image reference) and `checks.remote.root` (reserved absolute metadata, unused by any current command). No remote destination belongs in tracked project files. The runner uses the person's host SSH capability (including the hub's authentication agent socket) in BatchMode, with TTY allocation, agent/X11 forwarding, configured forwardings and local SSH commands disabled, and fixed Docker argv; it never installs host tools, mounts host paths or falls back to this Mac. A failed SSH, Docker, image or hardened network-none/transfer probe marks sandboxed test capability unavailable with a generic remote-runner reason. A successful platform line names only Linux architecture and numeric Docker version.
|
|
683
|
+
|
|
684
|
+
The remote source is the recorded Git commit, streamed into a hardened non-root container. Mac dependencies are excluded. Before a check, the runner proves or prepares a Docker volume named from the commit's lockfile hash, its manifests and install configuration (`package.json`, `bunfig.toml`, `.npmrc`, `patches/`), the Bun version and architecture of the pinned image, and its digest (#793b): the first run for a new lockfile spends extra time and is the only moment a container has a network, running exactly `bun install --frozen-lockfile` into the volume. Later runs find the volume, verify it read-only offline and install nothing. The check itself never installs, has no network and mounts the volume read-only. The ten-minute run budget includes preparation, so a very large first install can time out and is simply retried. A commit whose root or workspace `package.json` declares an install lifecycle script (`preinstall`, `install`, `postinstall`, `prepublish`, `preprepare`, `prepare`, `postprepare`) is refused the same way, since such a script can read source the volume key does not cover. If the volume cannot be proven the run ends with `remote dependencies unavailable`; there is no writable shared cache and no fallback to this Mac. The newest three prepared volumes per project are kept and older ones removed after a verified run. Remote `root` is validated but unused because no host path operation is needed. The bounded [local Docker transport receipt](verification/2026-10-25-remote-docker-transport.md) records the extraction, cleanup and dependency-volume legs. Actual remote-host opt-in, SSH and pi's live check receipt remain unverified follow-up work. Existing local Apple-container behavior remains available by explicit selection.
|
|
685
|
+
|
|
633
686
|
Retention bounds inactive valid check receipts to 200 records and the newest 20
|
|
634
687
|
full outputs, excluding active runs. Full output is also consumed by the owner
|
|
635
688
|
result read or expires after 24 hours.
|
|
@@ -852,12 +905,16 @@ the OS temp cleanup), and nothing else; the shared temp dirs are closed.
|
|
|
852
905
|
Some names stay closed to those commands, and to Pi's, wherever they may
|
|
853
906
|
otherwise write: anything named `.git` at any depth, the `config` and `hooks`
|
|
854
907
|
directly under a `.git`, `commondir` below it, and `.agenthub` anywhere in the
|
|
855
|
-
project
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
908
|
+
project, plus `config.worktree` beside each such `config`. A submodule's git
|
|
909
|
+
directory gets the same `config` and `hooks` refusal under every `modules/`
|
|
910
|
+
tree the project can reach: the common dir's, the worktree's own and every
|
|
911
|
+
linked worktree's (#281, #518). Nothing else may be written under such a tree
|
|
912
|
+
outside a discovered submodule git dir (#865). A command can therefore not
|
|
913
|
+
create, rename or remove a `.git`: `git init`, `git clone` and
|
|
914
|
+
`git worktree add` do not run inside the sandbox, and neither do
|
|
915
|
+
`git worktree remove`, `git worktree prune` of a stale record,
|
|
916
|
+
`git submodule update --init`, `git clean -ffd` over a nested repository or
|
|
917
|
+
`rm -rf` of a directory that holds a `.git`. `git add`, `commit`, `stash`, `checkout` and `gc` work, and
|
|
861
918
|
`.gitignore` and `.github/` stay writable; a commit that your git configuration
|
|
862
919
|
signs with a key under `~/.ssh` or `~/.gnupg` fails, because the sandbox cannot
|
|
863
920
|
read those directories. Run a refused command yourself, in a terminal.
|
|
@@ -1028,7 +1085,9 @@ includes), read the check result, and list what is
|
|
|
1028
1085
|
unmet (`hub_review` takes `unmet`, `ahub review ... --unmet <item>`). A reviewer
|
|
1029
1086
|
that missed the request, and the owner, read the done summary and check result
|
|
1030
1087
|
with `hub_task_show {id}`: the task's public view with its history, as the
|
|
1031
|
-
conductor sees it, and only a stub for a PII task.
|
|
1088
|
+
conductor sees it, and only a stub for a PII task. The configured planner reads any
|
|
1089
|
+
task outside the backlog the same way (#812); a staged backlog row stays hidden from agent
|
|
1090
|
+
task tools and is read through the planner tools. Other peers are refused. Each
|
|
1032
1091
|
request also carries the hub's review brief for the task's commit: reviewable and
|
|
1033
1092
|
excluded files with reasons, the `REVIEW.md` and `ahub-review-rules` rules read at
|
|
1034
1093
|
the merge base, and a cross-check list; `ahub review brief <id>` prints it.
|
|
@@ -1304,7 +1363,7 @@ ahub memory forget 1a2b3c4d # a person's; also promote, demote, sup
|
|
|
1304
1363
|
|
|
1305
1364
|
`"memory": { "native": false }` in `.agenthub/config.json` turns it off for a project.
|
|
1306
1365
|
|
|
1307
|
-
The exact-pinned `@staix/agent-mem` 0.
|
|
1366
|
+
The exact-pinned `@staix/agent-mem` 0.10.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.
|
|
1308
1367
|
|
|
1309
1368
|
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).
|
|
1310
1369
|
|
|
@@ -1654,7 +1713,7 @@ denylist (Pi and local), or native vendor boundaries (Claude and Codex).
|
|
|
1654
1713
|
| Kimi Code CLI | ACP yolo | ACP auto | ACP default |
|
|
1655
1714
|
| Codex | on-request for every outgoing turn/start | never for every outgoing turn/start | Restore the known native policy once, then stop overriding |
|
|
1656
1715
|
| Claude | Allow resolving project file tools outside .agenthub/.git/.claude/.codex/.qwen/.kimi/.kimi-code/.jcode/.pi/.mcp.json/.agents/.agent/_agents/_agent/.gemini/.grok/.claude.json | Hook allow for every tool | No hook decision |
|
|
1657
|
-
| Pi and local | Grant write/edit outside native agent configuration paths
|
|
1716
|
+
| Pi and local | Grant write/edit outside native agent configuration paths and proven read-only shell calls; other shell/git writes ask | Grant each tool once within the existing sandbox/guard | Normal approval handling |
|
|
1658
1717
|
|
|
1659
1718
|
Kimi's map applies only to the actual Kimi Code CLI identity, not another ACP
|
|
1660
1719
|
agent configured in kimi_cmd. Qwen and other ACP agents start fresh/resumed
|
|
@@ -1922,8 +1981,8 @@ Instances, the review and approval blocks and the lifecycle can be edited withou
|
|
|
1922
1981
|
|
|
1923
1982
|
1. **Registry settings** (everything above) are unchanged.
|
|
1924
1983
|
2. **Structural keys**, editable in the console and in a dashboard settings session:
|
|
1925
|
-
- `instances.<id>` with `kind`, `roles`, `start_mode`, `review_mode`, `readOnly`, `worktree` and `permission_mode`, in `config.local.json
|
|
1926
|
-
- `review.adaptive`, `review.min_reviews`, `review.pool`, `review.rerotate`, `snapshots.keep`, `approvals.timeout_s` and `context.gate`, in `config.local.json`;
|
|
1984
|
+
- `instances.<id>` with `kind`, `roles`, `start_mode`, `review_mode`, `readOnly`, `worktree` and `permission_mode`, in `config.local.json` (`review_scope` is tier 3 and not editable here);
|
|
1985
|
+
- `review.adaptive`, `review.min_reviews`, `review.pool`, `review.rerotate`, `review.same_family`, `snapshots.keep`, `approvals.timeout_s` and `context.gate`, in `config.local.json`;
|
|
1927
1986
|
- `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.
|
|
1928
1987
|
|
|
1929
1988
|
`roster.*`, `tasks.wip_limits.*`, `permission_modes`, `peers` and the rest of the registry keep their own `ahub settings set` path.
|
|
@@ -2341,6 +2400,15 @@ moves, reviews and assignments are recorded at `fyi` weight (no turn), at most
|
|
|
2341
2400
|
once per planner per ten minutes. A newer notice replaces an unsettled copy, and
|
|
2342
2401
|
the hub's own bookkeeping tells nobody.
|
|
2343
2402
|
|
|
2403
|
+
A task write also wakes the task's rostered planners when it frees capacity or
|
|
2404
|
+
releases backlog work (#785): a lower WIP for the owner or reserved peer adds a
|
|
2405
|
+
`capacity_released: <peer> WIP <n>; reserved ready #<id>|none` line, and an
|
|
2406
|
+
approval that leaves a backlog card with no unresolved dependency adds
|
|
2407
|
+
`backlog_ready: #<id>`. The lines go in one `Planner work ready:` task notice
|
|
2408
|
+
per planner, ids only; a newer one merges and replaces the unsettled copy, which
|
|
2409
|
+
survives a restart. Nothing is pulled automatically: the planner reads the
|
|
2410
|
+
board and decides.
|
|
2411
|
+
|
|
2344
2412
|
## Resetting a project's hub
|
|
2345
2413
|
|
|
2346
2414
|
`ahub reset` returns a project's hub to a clean state. Without `--yes` it is a
|
|
@@ -2459,7 +2527,7 @@ Rows without a live process are stale registrations; forget them with
|
|
|
2459
2527
|
|
|
2460
2528
|
## Agent CLI versions
|
|
2461
2529
|
|
|
2462
|
-
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
|
|
2530
|
+
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, the headless Claude implementer, Jcode, agy, Qwen and Pi (#691, #847). Qwen has two entries: `qwen` for headless ACP and `qwen-dual` for the dual-output TUI (#286).
|
|
2463
2531
|
|
|
2464
2532
|
- `ahub agents [--json]` lists each gated CLI with its version, verdict and verified versions.
|
|
2465
2533
|
- **verified:** a receipt exists.
|
|
@@ -2471,7 +2539,9 @@ Agent CLIs update themselves often, and a hub release cannot follow every one. O
|
|
|
2471
2539
|
- 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.
|
|
2472
2540
|
- What trust cannot prove is printed when you trust.
|
|
2473
2541
|
- `ahub doctor` shows one line for each installed CLI that is not on a verified version.
|
|
2474
|
-
- A
|
|
2542
|
+
- A daily workflow (`.github/workflows/agent-compat.yml`) runs `scripts/agent-compat-watch.ts`, which reads the latest published version of every gated CLI that has a public source: the npm packages `@anthropic-ai/claude-code`, `@openai/codex`, `@moonshot-ai/kimi-code`, `@qwen-code/qwen-code` (for both `qwen` and `qwen-dual`) and `@earendil-works/pi-coding-agent` (for `pi`, since #847 gave it a COMPAT entry), and the GitHub releases of Jcode. agy has no public source, so its row reads "no public source; local drift only" and is never a failure. Every COMPAT entry names the receipt to repeat (`receipt`), and a test requires that file to exist and the entry to have a watcher source. A version that cannot be read reads as unknown, not as a crash. The workflow keeps one `agent-compat` issue current while a source is ahead and closes it when none is.
|
|
2543
|
+
- **Maintenance loop (#843):** the daily upstream watch is the trigger; `ahub doctor` is the local drift notice for versions installed on a machine, and the hub itself tells the planner (below). The planner files one receipt task per (id, version): the implementer repeats the procedure in the entry's last `docs/verification/` receipt, writes a new one, and adds the version to `verified` in that same PR; the next release ships the bump. A person's `ahub agents trust` stays the stopgap that keeps a machine running meanwhile, and the person may revoke it once the bump lands.
|
|
2544
|
+
- **Local drift notice (#843 AC3):** at hub start and once a day the daemon reads each gated CLI's installed version with the probe `ahub agents` uses (no network, no install). For every installed CLI on a version that is not `verified` (in-line, trusted or refused) the effective planner gets one notice per (id, version): the id, the version, the state and the last receipt path, nothing the CLI printed. A CLI that is not installed, or whose version cannot be read, is not drift. The marker is kept per (id, version, planner) in `hub.db` (`agent_drift_notices`), so a restart repeats nothing, a planner whose notice could not be queued (or who joins later) is retried alone without telling the others again, and a new version is a new notice; with no rostered planner nothing is recorded. `ahub status` shows one `agent CLI drift` attention line per drifted id until the installed version is verified.
|
|
2475
2545
|
|
|
2476
2546
|
## Upgrade and crash recovery
|
|
2477
2547
|
|
|
@@ -2492,7 +2562,7 @@ section is what they run.
|
|
|
2492
2562
|
|
|
2493
2563
|
Upgrade running projects with the target release's own coordinator. It accepts
|
|
2494
2564
|
a running source on control protocol 9 (0.6.x), 10 (0.7.0 through 0.12.0),
|
|
2495
|
-
11 (0.12.1 and 0.12.2), 12 (0.12.3), 13 (0.12.4 through 0.12.15), 14 (0.12.16), 15 (0.12.17 through 0.12.19) or 16 (0.12.20 through 0.
|
|
2565
|
+
11 (0.12.1 and 0.12.2), 12 (0.12.3), 13 (0.12.4 through 0.12.15), 14 (0.12.16), 15 (0.12.17 through 0.12.19) or 16 (0.12.20 through 0.19.0), and only
|
|
2496
2566
|
a target on its own protocol, so the target's coordinator fits every supported
|
|
2497
2567
|
source and carries every recovery fix released up to it. Protocol 8 and older
|
|
2498
2568
|
(0.5.x and earlier) are refused as `manual-bootstrap-required`. Run from the
|
|
@@ -2506,7 +2576,7 @@ bunx --package @staix/agent-hub@0.12.43 ahub upgrade --to 0.12.43 --yes
|
|
|
2506
2576
|
| Running now | Coordinator to use |
|
|
2507
2577
|
| --- | --- |
|
|
2508
2578
|
| 0.6.x (protocol 9) | the target's, through `bunx` as above |
|
|
2509
|
-
| 0.7.0 through 0.12.0 (protocol 10), 0.12.1 and 0.12.2 (protocol 11), 0.12.3 (protocol 12), 0.12.4 through 0.12.15 (protocol 13), 0.12.16 (protocol 14), 0.12.17 through 0.12.19 (protocol 15), 0.12.20 through 0.
|
|
2579
|
+
| 0.7.0 through 0.12.0 (protocol 10), 0.12.1 and 0.12.2 (protocol 11), 0.12.3 (protocol 12), 0.12.4 through 0.12.15 (protocol 13), 0.12.16 (protocol 14), 0.12.17 through 0.12.19 (protocol 15), 0.12.20 through 0.19.0 (protocol 16) | the target's, through `bunx` as above |
|
|
2510
2580
|
| any supported source, with the installed CLI already at the target | `ahub upgrade` below, which is the same coordinator |
|
|
2511
2581
|
| 0.5.x or earlier (protocol 8 and older) | not supported: bootstrap by hand with the matching CLI |
|
|
2512
2582
|
|
|
@@ -2655,15 +2725,14 @@ plugin, daemon, or terminal mutation.
|
|
|
2655
2725
|
|
|
2656
2726
|
`ahub upgrade` and `ahub restart` are interactive when standard input and output
|
|
2657
2727
|
are a terminal and neither `--dry-run` nor `--yes` is given. With either flag, or
|
|
2658
|
-
through a pipe, the JSON plan
|
|
2659
|
-
unchanged. The screens add no way to change an operation: every choice runs one
|
|
2728
|
+
through a pipe, the plan is printed as readable text (#814) and `--json` keeps the JSON plan and the `ahub: blocker:` lines; the exit codes are unchanged. The screens add no way to change an operation: every choice runs one
|
|
2660
2729
|
of the commands in this section for you, so that command's refusals decide.
|
|
2661
2730
|
|
|
2662
2731
|
The screens use the console palette and `--color=auto|always|never`, with the
|
|
2663
2732
|
same `NO_COLOR` and `TERM=dumb` precedence. Auto colours a suitable TTY; explicit
|
|
2664
2733
|
always has the console's override behaviour. Raw JSON bypasses colour and width
|
|
2665
|
-
handling. Default and never
|
|
2666
|
-
dispose
|
|
2734
|
+
handling. Default and never print the same readable pipe, dry-run, status and
|
|
2735
|
+
dispose text, and `--json` keeps the previous documents byte for byte. Presentation flags go after the command, for
|
|
2667
2736
|
example `ahub recovery --color=never` or
|
|
2668
2737
|
`ahub recovery status <operation-id> --json`. An explicit `--json` returns only
|
|
2669
2738
|
the raw document, without a human suffix. `upgrade --json` reviews a JSON plan;
|
|
@@ -3271,7 +3340,7 @@ The person can retain superseded work as closed history:
|
|
|
3271
3340
|
ahub task cancel <id> --reason <text> [--superseded-by <ref>] [--revision N]
|
|
3272
3341
|
```
|
|
3273
3342
|
|
|
3274
|
-
The console also offers cancellation with the selected task's flow revision. Approved tasks cannot be cancelled. The planner's `hub_task_cancel` tool is limited to
|
|
3343
|
+
The console also offers cancellation with the selected task's flow revision. Approved tasks cannot be cancelled. The planner's `hub_task_cancel` tool is limited to work it proposed that is in backlog or proposed with no execution evidence: never started, or accepted by an owner and then declined or returned untouched (no branch, commit, PR, local check, done, verdict or reopen, the same test as `hub_backlog_return_untouched`, #812). Work with any such evidence requires the person. Cancellation sends the former owner/reviewer a stop notice, releases overlap/reservation participation and keeps dependents blocked with a cancelled-dependency notice. It does not stop a native turn, delete a worktree or write an outcome memory note. Cancelled work is closed history, counted separately from approved work; it does not satisfy an approval dependency. A still-running private turn keeps its privacy fence after cancellation. Use the displayed revision to avoid acting on a task that changed while it was selected.
|
|
3275
3344
|
|
|
3276
3345
|
The daemon advertises `task_cancel`; a current CLI refuses cancellation against older daemons. Recovery retains verified target features beside its immutable root/digest, reuses them on resume and on each lease renewal before a terminal is closed, and checks only sources not yet past commit; a legacy receipt without that evidence needs a target probe only before commit. Upgrade/restart refuses a target without this feature while cancelled rows exist and names their ids. No cancelled row is rewritten as approved. An old binary launched by hand remains unsupported: it can count cancelled work as open or fail to move it. Use a compatible coordinator instead. Live task cancellation and sweep enablement are separate post-release operations.
|
|
3277
3346
|
|
|
@@ -3404,9 +3473,15 @@ unreadable result runs the main gate again and refuses release. A manual
|
|
|
3404
3473
|
`prepare_bundle` dispatch builds reviewable plugin assets without publishing;
|
|
3405
3474
|
it is never accepted as full-gate evidence. A `timing_runs=20` dispatch runs only the daemon, PII screen and ACP
|
|
3406
3475
|
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).
|
|
3407
|
-
`scripts/check.sh`
|
|
3408
|
-
|
|
3409
|
-
|
|
3476
|
+
`scripts/check.sh` runs the suite under `scripts/hang-watch.sh`, which stops it when
|
|
3477
|
+
no test result line (`(pass)`, `(fail)`, `(skip)` or `(todo)`) and no test file header
|
|
3478
|
+
has appeared for `AHUB_CHECK_QUIET_S` seconds (300 by default, set to 300 in CI), so a
|
|
3479
|
+
slow suite that is still passing tests is never cut. `scripts/progress-tee.sh` passes bun's
|
|
3480
|
+
output through unchanged and appends one byte to a progress file for each of those lines;
|
|
3481
|
+
the watchdog polls that file's size. On a stop it prints where the run is and the process
|
|
3482
|
+
table below it first. `AHUB_CHECK_HANG_S` (960 by default) is only the backstop for a run
|
|
3483
|
+
that keeps printing results while hung; hosted CI sets 1500 on Linux inside a 35-minute
|
|
3484
|
+
job limit and 1800 on macOS inside a 40-minute one (#378, #593, #752, #516).
|
|
3410
3485
|
The `closing-refs` workflow fails a PR whose title, body or commit messages would make
|
|
3411
3486
|
GitHub close an issue the text only mentions (`Refs #N`, a negated or qualified keyword);
|
|
3412
3487
|
an issue linked only in the sidebar passes (#760).
|
|
@@ -3666,13 +3741,13 @@ selected roster and existing capabilities; the TUI is always a person's start.
|
|
|
3666
3741
|
`ahub qwen --mode tui` runs `qwen --input-file <in> --json-file <out> --mcp-config <hub server> --approval-mode default` in the terminal you ran it from. The daemon prepares the two files (mode 0600, under `<state dir>/qwen/qwen-dual/`) and returns the launch; the hub then appends one `submit` line per delivery and tails the event file from a saved offset. It needs a Qwen the dual-output compat entry verifies (`ahub agents` shows `qwen-dual`, verified 0.26.1 only; the headless `qwen` entry is separate and unchanged) and refuses another version before it creates a file. The TUI is explicit only: `ahub qwen` without `--mode` is still headless, Qwen is not a start-mode peer, and the hub never opens this terminal by itself. The TUI start is refused for an extra Qwen instance, off roster, outside a terminal, and while a headless Qwen runs (`ahub stop qwen` first); a headless start is refused while the TUI holds its terminal.
|
|
3667
3742
|
|
|
3668
3743
|
- What the hub does: a delivery becomes a `submit`; the last assistant message of the turn (an `assistant` event whose `stop_reason` is not `tool_use`, then `message_stop`) is shared as the answer; busy and idle follow the events. A `can_use_tool` request goes to the console approval path (`ahub permit`, the dashboard), and the hub's own tools are approved only by their exact `mcp__agent-hub__<tool>` name. If you answer a prompt in the Qwen terminal first, the hub's pending approval is withdrawn.
|
|
3669
|
-
- **Limit 1, a deny ends the turn without an answer.** Qwen emits nothing when the hub denies: it cancels the whole turn. The hub ends the turn itself, shares no answer, settles the delivery as `completed` (a deny is a known outcome, and a `needs_review` would hold every later message to Qwen until a person resolved it) and says so in a notice. A turn whose outcome is not known (Qwen exited, an Esc followed by a new prompt, an event file that became unreadable) is the one that settles `needs_review`.
|
|
3744
|
+
- **Limit 1, a deny ends the turn without an answer.** Qwen emits nothing when the hub denies: it cancels the whole turn. The hub ends the turn itself, shares no answer, settles the delivery as `completed` (a deny is a known outcome, and a `needs_review` would hold every later message to Qwen until a person resolved it) and says so in a notice. A turn whose outcome is not known (Qwen exited, an Esc followed by a new prompt, an event file that became unreadable) is the one that settles `needs_review`. Qwen's own notice that a background shell finished (a `user` event that is wholly one or more `<task-notification>` envelopes) is not a new prompt: it ends no hub turn and leaves an idle peer idle (#517).
|
|
3670
3745
|
- **Limit 2, the hub cannot stop a Qwen turn.** The input protocol has only `submit` and `confirmation_response`, and a signal does not stop a running turn. The inactivity watchdog therefore never cancels: after `watchdog_ms` of silence it marks the turn stalled (`ahub status`, the console and the dashboard say "press Esc in the Qwen terminal") and keeps the peer busy. The hub never types into your terminal and never signals Qwen to stop a turn.
|
|
3671
3746
|
- A Qwen write or shell command that names the hub state directory is refused (see [security](security.md): the input file is a prompt channel).
|
|
3672
3747
|
- If the hub cannot read the event file the peer is `detached`, shown as offline with a notice, never idle: Qwen itself keeps working, and the hub reattaches when the file is readable again.
|
|
3673
3748
|
- Restart: if the hub restarts while your Qwen keeps running, it reads on from its saved offset (no event twice, no launch). If Qwen is gone, `ahub qwen --mode tui` starts `qwen -r <session id>` on the same two files; the earlier submits are not replayed and the recorded answers are not shared again. Recovery never restores this terminal as a headless worker, and `ahub stop qwen` refuses: end Qwen in its own terminal.
|
|
3674
3749
|
|
|
3675
|
-
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
|
|
3750
|
+
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)) and 0.26.1 ([0.26.1 receipt](verification/2026-10-26-qwen-0261-acp.md)). A CLI version label alone
|
|
3676
3751
|
is insufficient: startup verifies its native identity/version and advertised mode
|
|
3677
3752
|
ids before any prompt. The earlier local installation reported CLI 0.25.0 while
|
|
3678
3753
|
its package/ACP source said 0.24.1; that was not a ready identity. The 0.26.0 receipt
|
|
@@ -3709,11 +3784,11 @@ TUI input may interleave with an ACP turn; there is no single-writer guard. Clos
|
|
|
3709
3784
|
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.
|
|
3710
3785
|
|
|
3711
3786
|
|
|
3712
|
-
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.
|
|
3787
|
+
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, 0.98.1 and 0.99.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.
|
|
3713
3788
|
|
|
3714
3789
|
## Optional Antigravity (agy) peer
|
|
3715
3790
|
|
|
3716
|
-
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
|
|
3791
|
+
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 and 1.4.7 are the verified versions ([1.4.7 receipt](verification/2026-10-26-agy-1.4.7.md)), 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.
|
|
3717
3792
|
|
|
3718
3793
|
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`.
|
|
3719
3794
|
|
|
@@ -3952,7 +4027,12 @@ Capacity defaults to one per peer. Each declared instance has its own `tasks.wip
|
|
|
3952
4027
|
uses the existing machine-local registry path; integers 0..32 apply live (the next
|
|
3953
4028
|
admission reads the current value), with 0 disabling planner admission for that
|
|
3954
4029
|
peer. Status and the agent legend count
|
|
3955
|
-
owned unfinished work plus unowned planner-pull reservations
|
|
4030
|
+
owned unfinished work plus unowned planner-pull reservations, and show how that
|
|
4031
|
+
count splits (#784): `ahub status` prints `<peer> planner WIP 3/3 (active 2, review-wait 1, reserved 0)`,
|
|
4032
|
+
the console Peers detail (Enter) has a `planner WIP` line, and the dashboard legend shows the same split.
|
|
4033
|
+
`active` is owned work that is not waiting for review, `review-wait` is owned work in review (it still
|
|
4034
|
+
holds its slot), `reserved` is a planner-pull reservation nobody owns yet; the three add up to the count
|
|
4035
|
+
admission reads, and the split changes no admission decision. An older hub shows the plain count. The same limit gates
|
|
3956
4036
|
acceptance and self-claim in every lifecycle mode, so 0 refuses new acceptances; a
|
|
3957
4037
|
current owner's redo of sent-back work keeps its slot (#481 S9).
|
|
3958
4038
|
|
|
@@ -4209,6 +4289,15 @@ restart the hub. For example, a reviewer can use:
|
|
|
4209
4289
|
Start them with `ahub codex --as codex-review` and
|
|
4210
4290
|
`ahub kimi --as kimi-review`. Codex keeps its native TUI and its own hub-owned
|
|
4211
4291
|
app-server proxy; extra Kimi, Qwen, Jcode, Pi and local instances use headless starts.
|
|
4292
|
+
|
|
4293
|
+
An extra instance of any kind that holds the `implementer` role needs its own
|
|
4294
|
+
registered worktree on an attached branch, at exactly `.worktrees/<id>`
|
|
4295
|
+
(`"worktree": ".worktrees/<id>"`). Configuration validation refuses a missing one
|
|
4296
|
+
only for Claude channel instances and headless writers. For other kinds, Codex and
|
|
4297
|
+
Jcode included, the hub accepts the declaration at startup and then refuses the start
|
|
4298
|
+
with `an extra implementer requires an explicit managed worktree`. Create and
|
|
4299
|
+
register the worktree before the start; the hub never creates it.
|
|
4300
|
+
|
|
4212
4301
|
Extra Jcode instances are supported (#685), in `.agenthub/config.local.json` only:
|
|
4213
4302
|
|
|
4214
4303
|
```json
|
|
@@ -4276,11 +4365,21 @@ A headless Claude implementer (#525-4) is declared separately:
|
|
|
4276
4365
|
"claude-impl": { "kind": "claude", "roles": ["implementer"], "start_mode": "headless", "worktree": ".worktrees/claude-impl", "permission_mode": "ask" }
|
|
4277
4366
|
```
|
|
4278
4367
|
|
|
4368
|
+
A headless Claude implementer may name its model (#844): `"model": "claude-sonnet-5-5"` on its declaration passes `--model <value>` on every native turn, resumed ones included. It is one bounded word (letters, digits and `._:/@+-`, up to 128 bytes, no spaces and no leading dash) and is accepted only on a headless implementer, only from the untracked `config.local.json`. A tracked-file declaration is ignored with a reason, and the key is tier 3: the dashboard and a settings session cannot read or change it, only the console or your editor. Unset, the argv is unchanged and Claude uses its own default. `ahub status` shows the model on the instance row as `model source`. Declarations are captured once when the hub daemon starts, so a changed or newly added `model` takes effect after a hub daemon restart (`ahub restart`); restarting only the instance keeps the old model.
|
|
4369
|
+
|
|
4279
4370
|
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.
|
|
4280
4371
|
|
|
4281
|
-
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
|
|
4372
|
+
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. For Bash, #845 also permits proven read-only commands and the closed task command forms below, through a host-owned execution wrapper. Protected configuration, paths outside that worktree and unproven shell commands 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.
|
|
4373
|
+
|
|
4374
|
+
Under #845, automatic Bash grants require a current public task and the instance's registered worktree. The exact task forms are `scripts/check.sh --changed`, `bun run build`, `bun test <explicit test/*.test.ts paths>`, `git add <named paths>`, `git commit -m <message>`, `git push origin <bound branch>` or `git push -u origin <bound branch>`, and `gh pr view|checks <bound branch>`. `gh pr create` requires `--base <default> --head <bound branch> --title <title>` and exactly one `--body <text>` or `--body-file <relative path>`. Operators, expansion, extra flags, force/refspec/delete pushes, another remote/branch, background execution or a model-supplied cwd ask. Enabled publish/destroy/install/external-write policy classes still ask. Unknown default-branch evidence also asks.
|
|
4282
4375
|
|
|
4283
|
-
The
|
|
4376
|
+
The task's `refs.branch` is authoritative. Otherwise the first eligible task-command request records the current non-default/non-main/master attached branch through `Tasks`, provided no other open task uses it. A host history entry binds the worktree too; restarting preserves it, and a changed branch or root asks rather than rebinding. Each automatic allow contains only the fixed wrapper and one short-lived single-use ticket. The host rechecks the task, child, root, branch and command proof before executing with its fixed environment and absolute executable; native shell cwd/PATH/config variables do not carry over. Unknown, expired, reused or stale tickets run nothing. Read-only and executable code commands (check/test/build) use the existing local-worker Seatbelt profile: writes only in the worktree and own temp, with all project Git metadata read-only, credential/hub-state denial and the configured network policy. These commands ask if macOS sandbox-exec is unavailable. Only closed host Git add/commit/push and gh operations run outside that profile. Push execution pins both source and destination as refs/heads/<bound>:refs/heads/<bound>; configured remote.origin.push/mirror asks. PATH excludes project/worktree directories, gh child Git uses the core hardening config, and body-file uploads use bounded screened snapshots. An older plugin without the wrapper protocol keeps person approval. [The native context receipt](verification/2026-10-26-headless-claude-shell-context.md) records which native legs have actually been observed.
|
|
4377
|
+
|
|
4378
|
+
Check/test/build cannot write the project Git common/current directory at all, including objects, HEAD/index, refs/logs, other worktrees and either submodule tree. Closed host add/commit reuse core Git hardening, ask with configured filters/external drivers/textconv, and force signing/automatic maintenance off. A global Git LFS installation does not disable push/gh grants; only add/commit keep person approval so LFS conversions are not silently bypassed. Automatic push still does not run pre-push hooks. Config includes and partial clones refuse privileged Git/gh. Their command/paths/current task/branch are re-proved before execution. The host pins the default branch from the remote at startup, using a bounded isolated-config Git symref probe against the captured GitHub repository. Local origin/HEAD changes cannot redefine it. No credentials are supplied to that probe; unavailable/private-remote evidence or an unsupported Git layout asks. local.bash_network "direct" gives code direct network access. A setsid-detached code child can outlive owned-group cleanup while retaining its sandbox and permitted worktree writes.
|
|
4379
|
+
|
|
4380
|
+
Project Git retains the core policy that clears credential.helper and core.askpass; an HTTPS push needing those helpers may fail, rather than importing credentials or relaxing that policy. Task branch/config proof reads are bounded synchronous reads (1.5 seconds per reader); slow or unknown evidence asks. The existing sandbox profile discovery is also synchronous; moving it to an asynchronous inventory proof with a shared deadline remains a follow-up. The nonce is visible in a permission response, so it proves a bounded grant rather than native-dispatch provenance.
|
|
4381
|
+
|
|
4382
|
+
The [native permission receipt](verification/2026-10-23-headless-claude-permissions.md) covers Claude Code 2.1.309, and the [2.1.310 receipt](verification/2026-10-26-claude-implementer-2.1.310.md) repeats it on 2.1.310 (with 2.1.309 as a control), each 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.
|
|
4284
4383
|
|
|
4285
4384
|
A headless Claude reviewer is run by the hub instead (#223): declare
|
|
4286
4385
|
`"claude-review": { "kind": "claude", "roles": ["reviewer"], "start_mode": "headless" }`
|
|
@@ -4308,15 +4407,19 @@ From 0.12.37 reviews can rotate across fresh headless Claude and Codex reviewers
|
|
|
4308
4407
|
"codex-review": { "kind": "codex", "roles": ["reviewer"], "start_mode": "headless", "review_mode": "fresh" },
|
|
4309
4408
|
"kimi-review": { "kind": "kimi", "roles": ["reviewer"], "start_mode": "headless", "review_mode": "fresh" }
|
|
4310
4409
|
},
|
|
4311
|
-
"review": { "pool": ["claude", "codex", "kimi"], "rerotate": false }
|
|
4410
|
+
"review": { "pool": ["claude", "codex", "kimi"], "rerotate": false, "same_family": "fallback" }
|
|
4312
4411
|
}
|
|
4313
4412
|
```
|
|
4314
4413
|
|
|
4414
|
+
`review.same_family` (#820) is `"fallback"` (the default) or `"never"`. With `"fallback"` a reviewer of the owner's family is chosen only when no other family is eligible, and the board records a same-family fallback. With `"never"` routing never selects one, in the pool and in the legacy path: the planner reviews when it holds the reviewer role, is not the owner, is of another family and is not blocked, otherwise the person does (`reviewer = "user"`, recorded as blocked), including when every reviewer is offline: an approval without review never happens under `"never"`. A manual `ahub task assign <id> <peer> --role reviewer` of a same-family peer is refused with `same family as <owner>; review.same_family is never`. `ahub route explain <id>` names the rule in its trace. Use `"never"` when the workspace review gate needs the reviewer to be a different AI than the implementer; a Jcode running a Claude model is still family `jcode`.
|
|
4415
|
+
|
|
4416
|
+
A reviewer has a review scope (#852): `full` (reads the code, runs the affected tests, reads CI) or `code` (reads the code only). The fresh Codex and Kimi reviewers run in a sandbox that cannot run `bun test` or read CI, so they default to `code`; every other reviewer is `full`. A `code` reviewer's review request replaces the check and exact-head CI lines with one: its sandbox cannot run tests or read CI, review the code against the plan, and the merger gates on exact-head CI. Findings are only defects in the reviewed code, docs or tests; a missing check result, CI result, test run or PR/branch identity belongs in `unmet`, never in `findings`. A `code` reviewer's approval and verdicts record `reviewScope: "code"` in the task history. Its `changes_requested` is always recorded and never refused: with at least one structured finding whose disposition is `open` it counts as a rejection as usual; without one it is recorded as evidence-only, which does not count toward `rejections` or escalation, still returns the task to its owner, and sends the conductor one task notice with ids only. The review request therefore asks a `code` reviewer to report every code defect as a structured finding with an id. A person's verdict is never evidence-only. The scope is a fixed property of the definition. To change it for one instance, set `"review_scope": "full"` or `"code"` on that fresh-reviewer instance in the untracked `config.local.json` (a tracked declaration is ignored with a reason; the key is tier 3, so the dashboard and settings sessions cannot read or change it, and a hub daemon restart applies it). `ahub status` shows `review scope` on each reviewer row. A task approved by a `code` reviewer is merged only after exact-head CI is green and no review thread is unresolved, and the merge note names the CI run.
|
|
4417
|
+
|
|
4315
4418
|
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.
|
|
4316
4419
|
|
|
4317
4420
|
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). Each launch approves exactly `hub_review` and `hub_task_show` per tool (`approval_mode = "approve"`), never through a server-wide default: without it Codex 0.164.0 listed the tools but refused the call, so reviews ended with no verdict (#783). A model-free receipt proves the inventory, not that a verdict reaches the hub; a [model-backed 0.164.0 run](verification/2026-10-25-codex-0164-reviewer-tool-call.md) recorded one verdict through that path. 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.
|
|
4318
4421
|
|
|
4319
|
-
Kimi requires a compat-admitted Kimi Code on the hub's PATH (receipt-verified 2.2.0, 2.3.0 and 2.3.
|
|
4422
|
+
Kimi requires a compat-admitted Kimi Code on the hub's PATH (receipt-verified 2.2.0, 2.3.0, 2.3.1 and 2.3.2), 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](verification/2026-10-22-kimi-qwen-compat.md), [2.3.1](verification/2026-10-25-kimi-231-reviewer-compat.md) and [2.3.2](verification/2026-10-26-kimi-232-reviewer-compat.md) receipts are model-free and do 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.
|
|
4320
4423
|
|
|
4321
4424
|
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.
|
|
4322
4425
|
|
|
@@ -4397,7 +4500,7 @@ Native launcher connections retry transport timeouts/unclean closes with bounded
|
|
|
4397
4500
|
|
|
4398
4501
|
## amem runtime (agent-mem#13 P4)
|
|
4399
4502
|
|
|
4400
|
-
The hub exact-pins @staix/agent-mem 0.
|
|
4503
|
+
The hub exact-pins @staix/agent-mem 0.10.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.
|
|
4401
4504
|
|
|
4402
4505
|
## Backlog issue identity and notes
|
|
4403
4506
|
|
|
@@ -4426,3 +4529,27 @@ In the dashboard Memory view (#684 phase 4), select a symbol and enable Code nei
|
|
|
4426
4529
|
`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.
|
|
4427
4530
|
|
|
4428
4531
|
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.
|
|
4532
|
+
|
|
4533
|
+
## Authority by command
|
|
4534
|
+
|
|
4535
|
+
### Conductor operations (#812 T2)
|
|
4536
|
+
|
|
4537
|
+
The selected project's configured conductor may run the commands below through its ordinary peer identity. Other peers retain the guidance "the person runs it in ahub console or a terminal". A missing or dead descriptor refuses promptly. For a live descriptor the connect and local authorization handshakes each keep a 3-second bound; connection unavailability is not presented as proof that the peer lacks the conductor role. Actual authority refusals are audited as refused, while ordinary operation failures retain their original cause. The daemon checks the authenticated connection, current role and project membership before effects and after asynchronous boundaries. Roster handoffs carry that same authority check through plan admission, owner delivery and each later task; a saved assignment is never rolled back when delivery is interrupted. Effectful operations and operational history reads retain an `agent_cli` admission with the initiating peer; audit failure refuses those operations. Authorization negotiation, `settings_preview` and `queue show` still check current authority but emit no extra admission record or conductor notice. Admission records are not a unique invocation counter.
|
|
4538
|
+
|
|
4539
|
+
| Command | Conductor scope |
|
|
4540
|
+
| --- | --- |
|
|
4541
|
+
| roster add/remove | Existing roster lifecycle and confirmations; no role or permission-mode grant |
|
|
4542
|
+
| stop peer | Existing hub-owned peer stop, ownership and recovery guards |
|
|
4543
|
+
| queue show/resolve/discard | Public queue projection and existing revision/confirmation guards |
|
|
4544
|
+
| task cancel | Existing hub_task_cancel with the real peer; eligibility follows the task-board policy |
|
|
4545
|
+
| doctor --orphans --kill | Selected project's positively identified hub-owned process only; no cross-project registrations or unsigned process files |
|
|
4546
|
+
| logs / export | Bounded daemon projections, with unsupported/private records withheld; logs -f ends when authority ends |
|
|
4547
|
+
| settings set | Only the twelve existing live registry keys listed below |
|
|
4548
|
+
|
|
4549
|
+
The exact settings keys are `task_sweep.enabled`, `task_sweep.auto_reassign`, `task_sweep.no_writes_turns`, `task_sweep.interval_s`, `task_sweep.unaccepted_min`, `task_sweep.idle_min`, `task_sweep.review_min`, `task_sweep.ready_min`, `task_sweep.ladder_min`, `snapshots.enabled`, `research.enabled` and `approvals.notify`. New keys receive no authority by prefix. Generic roster setting writes still use the dedicated roster lifecycle. Conductor setting records name the initiating peer, and conductor writes preserve the person's pending undo record. An intervening write can still invalidate that undo through the existing file-digest guard; preserving the record does not bypass that guard. Permission modes, roles, `pet.window`, arbitrary configuration reload and undo remain person commands.
|
|
4550
|
+
|
|
4551
|
+
Log history is limited to the last 100 retained lines and export to the last 1000 retained events, each within a 128 KiB read. Truncation is explicit. An incomplete public projection reports one bounded reason on stderr, preserving export JSON on stdout. The complete privacy inventory has no 500-task cutoff and is cached until board or privacy/config revisions change, so log-follow does not rebuild it for every line. Export accepts closed metadata shapes; unknown fields and nested records are withheld rather than copied. Task titles, paths and private delivery bodies are not part of this projection. It does not change the person's ordinary logs/export output.
|
|
4552
|
+
|
|
4553
|
+
Orphan cleanup requires a missing selected root, signed process identity and the host-known hub executable/entrypoint and argv. An inaccessible root or unavailable proof remains unknown; there is no offline config-based role grant. The daemon rechecks authority and process ownership before signals. A confirmed self candidate uses the existing lifecycle stop after its reply. A roster write already committed before authority ends is acknowledged as saved, without authorizing further lifecycle work or commands.
|
|
4554
|
+
|
|
4555
|
+
`restart --yes` and `recovery resume/abort` await a project-scoped continuation proof. `task unassign` follows #481, and legacy models start/stop awaits a project that needs it. This slice adds no task eligibility rule and no MLX/recovery-driver changes. Person authority and the separately authorized `--live-test` path retain their existing behavior.
|
package/docs/profiles.md
CHANGED
|
@@ -56,3 +56,39 @@
|
|
|
56
56
|
- `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.
|
|
57
57
|
- `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.
|
|
58
58
|
- 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.
|
|
59
|
+
|
|
60
|
+
# Profile scorecard (#799)
|
|
61
|
+
|
|
62
|
+
The existing ahub report --dogfood command adds a profile section when the selected profile is non-dev, or bound non-dev tasks have evidence in the requested window. Dev-only JSON and readable output retain their prior bytes. Existing flow, quality, cost and other fields keep their meanings; the profile section does not require merged PRs.
|
|
63
|
+
|
|
64
|
+
Rows include profile totals and class-alias groups with the stored base class. A task keeps its recorded profile across later configuration changes. Public custom aliases remain bounded identifiers; private custom aliases are withheld. Task titles, paths, notes, checklist prose and model text are not exported. Private pii/pii_path tasks are counted by id and number.
|
|
65
|
+
|
|
66
|
+
A missing, incomplete or unsupported source produces JSON null, rendered as unknown in the readable report. A complete source can prove zero recorded events; it cannot prove zero events for a category that has no recorder. Source completeness and flow scope distinguish history-backed totals from recorded-window observations. Profile bindings, including event-only fallback, are capped at 500; a capped window reports incomplete/unknown totals rather than extrapolating. Automatic approvals are flow transitions, not reviewer rounds or first-pass review samples.
|
|
67
|
+
|
|
68
|
+
| Row group | Existing evidence | Unmeasured ceiling |
|
|
69
|
+
| --- | --- | --- |
|
|
70
|
+
| Flow | Bound task history and complete task-event windows; observed automatic approvals | Undated approvals, incomplete history and first-pass review without history remain unknown |
|
|
71
|
+
| Review | Explicit verdicts and structured public unmet-criteria ids | Profile checklist prose has no item-id recorder; private criterion ids are withheld |
|
|
72
|
+
| Overlap | Recorded path/section notices and later matching pair/path edit facts | Observed path-edit pairs imply no authorship or causation; section edit confirmation remains unknown |
|
|
73
|
+
| Deliverables | Deduplicated ids in recorded deliverable histories | No new file reads; changed-since-approval and current unknown states remain unknown |
|
|
74
|
+
| Privacy | Private task flags and generic attributed PII note-screen records | Screen records do not identify the operation; memory drops, refusals and capture totals remain unknown without operation-specific counters |
|
|
75
|
+
| Undo | No additional recorder introduced | Request, completion and guard-refusal totals remain unknown |
|
|
76
|
+
| Snapshots | Already-recorded, attributed snapshot durations | No new recording; budget exhaustion and absent durations remain unknown |
|
|
77
|
+
| Profile errors | No additional recorder introduced | Unknown/foreign alias-refusal totals remain unknown |
|
|
78
|
+
| Cost | Existing task-attributed token/usage summaries | Missing usage and attribution remain unknown; no provider/model prose is exported |
|
|
79
|
+
|
|
80
|
+
Research rows also expose bounded current-plan source and claim counts per task. Claim slots are anonymous ordinal numbers; declaration text and identifiers are never exported. In a stored board plan a key the plan omits counts as zero declarations, as an explicit empty list does; a cut or malformed plan leaves that one task's declarations unknown without affecting the rest of the board. These are current-plan counts, not a reconstruction of past plans.
|
|
81
|
+
|
|
82
|
+
Each research class alias retains its own recorded task-check pass/fail counts under `observedCheckOutcomes`. Those history events do not record which check key ran. Consequently `factCheck` pass/fail, check selection and missing-key counts per run remain unknown until that provenance is recorded. No new telemetry is collected. Model labels, person verdicts, claims reaching a person verdict and per-label agreement also remain unknown because no claim-level verdict source exists. Task approval never supplies a claim verdict. Research uses the same recorded section-overlap rows as writing.
|
|
83
|
+
|
|
84
|
+
The weekly writing, general and research receipt templates are in the verification/profiles directory. Copy only the emitted profile subsection, preserve null values, and include no project/person names or paths. A template is not a completed measurement or a live acceptance claim.
|
|
85
|
+
|
|
86
|
+
The following verification claim ids collect the still-unverified statements above. A weekly receipt gives each a verdict of supported, partly supported or not supported, tied to recorded ids and remaining unknowns. Profile counts alone do not prove native ingestion, context retention or account acceptance; those verdicts need corresponding native/account receipt ids and independent judgment. None becomes verified merely because this reporting section exists:
|
|
87
|
+
|
|
88
|
+
- writing-live-example: an observed writing workflow.
|
|
89
|
+
- general-live-example: an observed general workflow.
|
|
90
|
+
- research-live-example: the live three-source/two-agent research example.
|
|
91
|
+
- native-model-ingestion: native peers consuming profile guidance and tasks.
|
|
92
|
+
- context-retention: profile/task context retained through the relevant native turns.
|
|
93
|
+
- native-account-research: a real native/model/account research workflow.
|
|
94
|
+
- research-measurement: observed research-profile measurements.
|