@staix/agent-hub 0.12.31 → 0.12.33
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 +20 -1
- package/README.md +14 -7
- package/docs/agent-notes/adapters.md +7 -4
- package/docs/agent-notes/bus.md +3 -0
- package/docs/agent-notes/daemon.md +13 -8
- package/docs/agent-notes/local-worker.md +1 -1
- package/docs/agent-notes/tasks.md +4 -3
- package/docs/agent-notes/tests.md +1 -0
- package/docs/cooperbench.md +1 -1
- package/docs/gsd-collaboration-analysis.md +1 -1
- package/docs/memory.md +1 -1
- package/docs/operations.md +141 -25
- package/docs/quickstart.md +10 -6
- package/docs/security.md +18 -9
- package/docs/smoke.md +34 -0
- package/docs/specs/2026-09-19-agent-hub-design.md +204 -0
- package/docs/specs/2026-09-20-upgrade-recovery-design.md +211 -0
- package/docs/verification/2026-10-18-0.12.32.md +54 -0
- package/docs/verification/2026-10-18-0.12.33.md +42 -0
- package/docs/verified.json +24 -16
- package/package.json +2 -2
- package/plugins/agent-hub/.claude-plugin/plugin.json +1 -1
- package/plugins/agent-hub/server.js +1296 -26
- package/src/adapters/acp.ts +5 -6
- package/src/adapters/definitions/builtin-metadata.ts +121 -0
- package/src/adapters/definitions/kimi-native.ts +4 -0
- package/src/adapters/definitions/qwen-native.ts +24 -0
- package/src/adapters/definitions/qwen.ts +71 -0
- package/src/adapters/pi.ts +6 -2
- package/src/adapters/registry-types.ts +174 -0
- package/src/adapters/registry.ts +36 -0
- package/src/cli/console-state.ts +74 -5
- package/src/cli/console.ts +35 -2
- package/src/cli/help.ts +3 -1
- package/src/cli/identity.ts +13 -3
- package/src/cli/launch.ts +1 -6
- package/src/cli/main.ts +200 -39
- package/src/cli/output.ts +2 -0
- package/src/cli/preview.ts +8 -5
- package/src/cli/recovery-guidance.ts +137 -0
- package/src/cli/recovery-presentation-options.ts +8 -0
- package/src/cli/recovery-session-file.ts +18 -0
- package/src/cli/reset.ts +13 -1
- package/src/cli/terminal-recovery.ts +48 -0
- package/src/cli/upgrade-interactive.ts +129 -75
- package/src/cli/upgrade-labels.ts +30 -0
- package/src/cli/upgrade-presentation-data.ts +41 -0
- package/src/cli/upgrade-presentation-flags.ts +31 -0
- package/src/cli/upgrade-presentation.ts +227 -0
- package/src/cli/upgrade-restore-state.ts +6 -2
- package/src/cli/upgrade-runtime.ts +360 -199
- package/src/cli/upgrade.ts +278 -25
- package/src/hub/bus.ts +144 -14
- package/src/hub/cohorts.ts +2 -2
- package/src/hub/config-apply.ts +242 -0
- package/src/hub/config-reload.ts +120 -0
- package/src/hub/config-trust.ts +11 -2
- package/src/hub/control-client.ts +1 -1
- package/src/hub/crash.ts +8 -6
- package/src/hub/daemon.ts +577 -179
- package/src/hub/deferred-hub.ts +60 -0
- package/src/hub/delivery-journal.ts +6 -0
- package/src/hub/events.ts +2 -2
- package/src/hub/manager.ts +1 -1
- package/src/hub/peer-catalog.ts +10 -13
- package/src/hub/peers.ts +12 -2
- package/src/hub/permission-mode.ts +5 -3
- package/src/hub/recovery-continuity.ts +152 -0
- package/src/hub/recovery-store.ts +10 -4
- package/src/hub/restart.ts +12 -1
- package/src/hub/sdlc.ts +5 -1
- package/src/hub/settings.ts +50 -36
- package/src/hub/settled-roles.ts +35 -0
- package/src/hub/supervision.ts +3 -2
- package/src/hub/tasks.ts +29 -9
- package/src/hub/ui.ts +1 -1
- package/src/memory/brief.ts +6 -5
- package/src/pi/session.ts +23 -4
- package/src/ui/index.html +23 -7
package/docs/operations.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Operations guide
|
|
2
2
|
|
|
3
|
-
This guide describes ahub 0.12.
|
|
3
|
+
This guide describes ahub 0.12.33 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
|
|
@@ -120,7 +120,7 @@ sounds on an action-count transition from zero, at most once per minute, never
|
|
|
120
120
|
for a message alone. Plain mode prints the line only when the action count changes.
|
|
121
121
|
Messages addressed to `user` remain attention items until the next key. Drawing
|
|
122
122
|
adds no timer, network request or writable settings path.
|
|
123
|
-
|
|
123
|
+
The operational tabs change with digits 1 to 5 or Left and Right (wrapping at both
|
|
124
124
|
ends), never while a command is being edited or a choice is open; under a
|
|
125
125
|
confirmation an arrow dismisses it like any key but y, without moving a tab. A pasted
|
|
126
126
|
chunk can only edit the command line, but a read that holds nothing but arrow or
|
|
@@ -135,7 +135,7 @@ the stream; only the header is tab-flattened before tokenizing. Body lines retai
|
|
|
135
135
|
the previous rendering and stay plain, as does command output; colour never changes
|
|
136
136
|
what the panel's text says.
|
|
137
137
|
|
|
138
|
-
Peers, Approvals, Tasks and
|
|
138
|
+
Peers, Approvals, Tasks, Queue and Settings are tables with a header row. A column is as
|
|
139
139
|
wide as its widest cell, up to a third of the terminal; the last column takes
|
|
140
140
|
the rest and is cut with `...`. In Tasks, TITLE takes the rest and the STAGE
|
|
141
141
|
meter keeps a fixed column at the right edge.
|
|
@@ -146,6 +146,7 @@ meter keeps a fixed column at the right edge.
|
|
|
146
146
|
| Approvals | ID PEER LEFT TITLE |
|
|
147
147
|
| Tasks | ID STATE OWNER REVIEWER CLASS AGE TITLE STAGE |
|
|
148
148
|
| Queue | ID PEER STATE REV AGE |
|
|
149
|
+
| Settings | GROUP KEY VALUE SOURCE APPLIES |
|
|
149
150
|
|
|
150
151
|
The MODE column appears only when at least one peer has a non-`ask` mode.
|
|
151
152
|
Zero counters and unknown values read `-`. Durations read `45s`, `12m`, `3h05m`
|
|
@@ -1436,6 +1437,16 @@ override them.
|
|
|
1436
1437
|
|
|
1437
1438
|
## Settings from the dashboard and the terminal
|
|
1438
1439
|
|
|
1440
|
+
In `ahub console`, press `6` for Settings. Existing operational-tab arrow cycling
|
|
1441
|
+
is unchanged; from Settings, Left returns to Events and Right to Peers. Select a
|
|
1442
|
+
row and press `e` to edit: value, daemon preview, nonempty reason, then `y`. Press
|
|
1443
|
+
`u` to preview and confirm undo. Undo binds the key and exact undo-record digest;
|
|
1444
|
+
if another write replaces that record, preview again. For busy roster removal,
|
|
1445
|
+
the panel names `ahub roster remove <peer> --now`, which explicitly stops an owned
|
|
1446
|
+
runtime or detaches a native session during its active turn; the panel does not force it.
|
|
1447
|
+
Esc cancels, and pasted confirmation text cannot
|
|
1448
|
+
write. This panel uses the current authenticated daemon connection.
|
|
1449
|
+
|
|
1439
1450
|
The dashboard's Settings section and `ahub settings` show and change the same
|
|
1440
1451
|
closed list of settings (issue #269). Run them from a plain terminal:
|
|
1441
1452
|
|
|
@@ -1447,17 +1458,21 @@ ahub settings set routing.classes.implement.peers codex,kimi,pi
|
|
|
1447
1458
|
ahub settings set permission_modes.kimi ask-when-needed
|
|
1448
1459
|
ahub settings set research.enabled inherit # remove the machine-local value
|
|
1449
1460
|
ahub settings undo # put back the file the last write changed
|
|
1461
|
+
ahub settings reload # validate and apply the complete four-file candidate
|
|
1450
1462
|
ahub ui --settings # dashboard with a 15-minute settings session
|
|
1451
1463
|
```
|
|
1452
1464
|
|
|
1453
1465
|
| Group | Keys | Stored in | Applies |
|
|
1454
1466
|
| --- | --- | --- | --- |
|
|
1455
1467
|
| Permissions | `permission.<peer>` (the mode now) | the running hub only | at once |
|
|
1456
|
-
| Permissions | `permission_modes.<peer>` (the mode
|
|
1468
|
+
| Permissions | `permission_modes.<peer>` (the default mode) | `config.local.json` | next peer start |
|
|
1457
1469
|
| Start | `peers.pi.start_mode`, `peers.codex.start_mode`, `peers.kimi.start_mode` (`tui` or `headless`) | `config.local.json` | that peer's next start |
|
|
1458
|
-
| Start | `pi.auto_start` | `config.local.json` | next
|
|
1470
|
+
| Start | `pi.auto_start` | `config.local.json` | next startup/recovery auto-start decision; never starts a peer merely on reload |
|
|
1459
1471
|
| Routing | `routing.stay_switch`, `routing.classes.<class>.peers`, `.escalate_to`, `.route`, `.pi_backend` | `routing.local.toml` | at once |
|
|
1460
|
-
| Switches | `research.enabled`, `approvals.notify`, `snapshots.enabled
|
|
1472
|
+
| Switches | `research.enabled`, `approvals.notify`, `snapshots.enabled` | `config.local.json` | live, without disturbing an active turn |
|
|
1473
|
+
| Switches | `coordination` | `config.local.json` | newly created tasks only |
|
|
1474
|
+
| Switches | `task_sweep.enabled`, `.auto_reassign`, `.interval_s`, `.unaccepted_min`, `.idle_min`, `.review_min`, `.ready_min`, `.ladder_min` | `config.local.json` | live; reschedules the sweep timer |
|
|
1475
|
+
| Routing | `tasks.wip_limits.<peer>` | `config.local.json` | live |
|
|
1461
1476
|
| Roles | `planner` (the one peer that plans) | `config.local.json` | at once |
|
|
1462
1477
|
|
|
1463
1478
|
- Writes go only to `.agenthub/config.local.json` and `.agenthub/routing.local.toml`,
|
|
@@ -1470,8 +1485,28 @@ ahub ui --settings # dashboard with a 15-minute settings session
|
|
|
1470
1485
|
file each value comes from. `--preview`, and the dashboard's Preview button,
|
|
1471
1486
|
show `ahub route explain` for the open tasks before and after, or what a
|
|
1472
1487
|
permission mode grants, and save nothing.
|
|
1473
|
-
- A row shows
|
|
1474
|
-
|
|
1488
|
+
- A row shows running and file values, source and apply class (`live`, `next use`,
|
|
1489
|
+
or `restart`). Pending restart keys and reasons also appear in status, console
|
|
1490
|
+
and dashboard, including startup-only blocks outside the editable registry.
|
|
1491
|
+
- Settings writes and undo, the dashboard Reload configuration button and
|
|
1492
|
+
`ahub settings reload` use one complete validation/apply path. Debounced changes
|
|
1493
|
+
of config.json, config.local.json, routing.toml and routing.local.toml use it too,
|
|
1494
|
+
including atomic file replacement. Invalid candidates apply nothing and emit
|
|
1495
|
+
one bounded error notice. Valid but unauthorized keys retain their accepted value and are reported per key; other eligible changes still apply. Recovery/shutdown hold reloads.
|
|
1496
|
+
- Individual writes and undo publish only the named setting. Other file edits remain unapplied.
|
|
1497
|
+
- `ahub settings reload` lists guarded keys with complete before -> after values (including full argv) and any planner/conductor holder effect. It requires an interactive terminal and exact `y` within 30 seconds before adopting them. Oversized previews remain unapplied and must be split or reduced. Candidate bytes or accepted state changes invalidate that confirmation. Watchers and ordinary dashboard reloads never confirm a raise.
|
|
1498
|
+
- Privacy tightening (local PII constraints/screening, added PII patterns, nonholder role reductions and explicit capability-list narrowing) is automatic, including tracked files. A planner/conductor holder change is guarded even when a role list shrinks; deleting a restricted capability entry restores all capabilities and is guarded. Reload checks the actual files' Git provenance. Changed machine-local or raising
|
|
1499
|
+
values from tracked/unverifiable files are refused; an ordinary dashboard or
|
|
1500
|
+
watcher cannot adopt unrelated raising local edits. A settings session cannot
|
|
1501
|
+
adopt routing fields outside its editable registry. Existing confirmation and
|
|
1502
|
+
roster lifecycle fences remain; use the confirmed roster setting for membership.
|
|
1503
|
+
Pi relay model aliases (`pi.dgx_coding`, `pi.dgx_fast`) and `routing.pi` retain their running values until restart, because existing native sessions use the published relay catalogue and context contract. Routing policy changes apply to future decisions; local model/target changes apply at the next peer or sidecar creation.
|
|
1504
|
+
|
|
1505
|
+
- Runtime/client ownership still requires restart for memory handles and sync,
|
|
1506
|
+
gateway/MLX, runner/check commands, profile/tool contracts, converters, existing
|
|
1507
|
+
session privacy/sandbox policies, the terminal provider and benchmark environment.
|
|
1508
|
+
The exhaustive reasons are in the issue #439 spec amendment. A pending file value
|
|
1509
|
+
is not applied to the running consumer. Coordination creation pins last for the daemon lifetime; a restart re-pins retained rows to its startup mode.
|
|
1475
1510
|
- `ahub settings undo` (the dashboard's "Undo last write") puts back the one
|
|
1476
1511
|
previous version of the file the last write changed. It refuses when that
|
|
1477
1512
|
file was edited since, and when it would put a stored never-ask back (set it
|
|
@@ -1484,10 +1519,11 @@ ahub ui --settings # dashboard with a 15-minute settings session
|
|
|
1484
1519
|
`.agenthub/routing.local.toml`: run `ahub init` again, or add it. A
|
|
1485
1520
|
`permission_modes` value is read only from a file git confirms nobody
|
|
1486
1521
|
committed (config trust); where the hub will not read what was written, the
|
|
1487
|
-
|
|
1522
|
+
reload refuses the guarded candidate and the Settings row identifies the file.
|
|
1488
1523
|
- Authority: a dashboard opened with `ahub ui` reads settings, lowers a mode to
|
|
1489
|
-
`ask`, turns `pi.auto_start` off, sets a start mode back to `tui
|
|
1490
|
-
|
|
1524
|
+
`ask`, turns `pi.auto_start` off, sets a start mode back to `tui`, sets a WIP
|
|
1525
|
+
limit to 0, turns `task_sweep.enabled` or `.auto_reassign` off and changes
|
|
1526
|
+
the other Switches. Everything
|
|
1491
1527
|
else needs `ahub ui --settings`, whose session may raise for 15 minutes, or
|
|
1492
1528
|
`ahub settings` in a terminal. `never-ask` needs the peer id typed in the
|
|
1493
1529
|
dashboard, or `--yes` in the terminal, and a stored never-ask default still
|
|
@@ -1801,6 +1837,9 @@ The runtime reset (the default):
|
|
|
1801
1837
|
through the delivery journal, one `resolution_history` entry each. Work
|
|
1802
1838
|
that was dispatching or accepted when the hub stopped is held as
|
|
1803
1839
|
`needs_review` first, so it is discarded too;
|
|
1840
|
+
- discards hub notices a recovery hold kept back the same way, one entry per
|
|
1841
|
+
recipient, without delivering them; the dry run lists them as
|
|
1842
|
+
`q:<peer>:<id>`;
|
|
1804
1843
|
- clears manual peer holds (`ahub pause`), budget pauses and conductor holds;
|
|
1805
1844
|
- drops the agent session resume pointers `sessions.json`,
|
|
1806
1845
|
`claude-session.json` and `claude-context.json`, so the next launch starts
|
|
@@ -1913,21 +1952,21 @@ section is what they run.
|
|
|
1913
1952
|
|
|
1914
1953
|
Upgrade running projects with the target release's own coordinator. It accepts
|
|
1915
1954
|
a running source on control protocol 9 (0.6.x), 10 (0.7.0 through 0.12.0),
|
|
1916
|
-
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.12.
|
|
1955
|
+
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.12.33), and only
|
|
1917
1956
|
a target on its own protocol, so the target's coordinator fits every supported
|
|
1918
1957
|
source and carries every recovery fix released up to it. Protocol 8 and older
|
|
1919
1958
|
(0.5.x and earlier) are refused as `manual-bootstrap-required`. Run from the
|
|
1920
1959
|
project directory, without replacing the global CLI first:
|
|
1921
1960
|
|
|
1922
1961
|
```bash
|
|
1923
|
-
bunx --package @staix/agent-hub@0.12.
|
|
1924
|
-
bunx --package @staix/agent-hub@0.12.
|
|
1962
|
+
bunx --package @staix/agent-hub@0.12.33 ahub upgrade --to 0.12.33 --dry-run
|
|
1963
|
+
bunx --package @staix/agent-hub@0.12.33 ahub upgrade --to 0.12.33 --yes
|
|
1925
1964
|
```
|
|
1926
1965
|
|
|
1927
1966
|
| Running now | Coordinator to use |
|
|
1928
1967
|
| --- | --- |
|
|
1929
1968
|
| 0.6.x (protocol 9) | the target's, through `bunx` as above |
|
|
1930
|
-
| 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.12.
|
|
1969
|
+
| 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.12.33 (protocol 16) | the target's, through `bunx` as above |
|
|
1931
1970
|
| any supported source, with the installed CLI already at the target | `ahub upgrade` below, which is the same coordinator |
|
|
1932
1971
|
| 0.5.x or earlier (protocol 8 and older) | not supported: bootstrap by hand with the matching CLI |
|
|
1933
1972
|
|
|
@@ -1959,17 +1998,18 @@ projects first:
|
|
|
1959
1998
|
|
|
1960
1999
|
```bash
|
|
1961
2000
|
ahub restart --dry-run
|
|
1962
|
-
ahub upgrade --to 0.12.
|
|
2001
|
+
ahub upgrade --to 0.12.33 --dry-run
|
|
1963
2002
|
```
|
|
1964
2003
|
|
|
1965
2004
|
Apply only after reviewing the plan:
|
|
1966
2005
|
|
|
1967
2006
|
```bash
|
|
1968
2007
|
ahub restart --yes
|
|
1969
|
-
ahub upgrade --to 0.12.
|
|
2008
|
+
ahub upgrade --to 0.12.33 --yes
|
|
1970
2009
|
ahub recovery status [<operation-id>]
|
|
1971
2010
|
ahub recovery resume [<operation-id>]
|
|
1972
2011
|
ahub recovery abort [<operation-id>]
|
|
2012
|
+
ahub recovery reattach <operation-id> codex|claude|pi
|
|
1973
2013
|
ahub recovery dispose [<operation-id>] --fresh-session <peer> --reason <text>
|
|
1974
2014
|
ahub recovery dispose [<operation-id>] --stop-and-archive --reason <text>
|
|
1975
2015
|
```
|
|
@@ -1992,6 +2032,15 @@ line of its own to `hub.log`), and until no task command or dashboard action is
|
|
|
1992
2032
|
still running. A check the commit's stop kills writes to the board after the
|
|
1993
2033
|
commit has recorded it, and the operation stays blocked.
|
|
1994
2034
|
|
|
2035
|
+
From 0.12.33, while an operation holds a source of that release or later, and
|
|
2036
|
+
while a restored target waits for release, the notices the hub writes itself
|
|
2037
|
+
(other than `[FYI]` ones) are kept apart from the carried queues, durably in
|
|
2038
|
+
the delivery journal and the restart snapshot, so the queue comparison still
|
|
2039
|
+
matches exactly. Release queues them in order and saves each move before
|
|
2040
|
+
anything is delivered. A target that does not advertise `recovery_deferred_hub`
|
|
2041
|
+
gets them in its ordinary queues before commit instead. At most 2048 such
|
|
2042
|
+
notices wait; a further one is refused, and none already kept is dropped.
|
|
2043
|
+
|
|
1995
2044
|
0.9.0 turns on for every project with a config file, whether or not it has the
|
|
1996
2045
|
block: `limits` (12 messages a minute per sender, 6 per recipient, 6
|
|
1997
2046
|
`[IMPORTANT]` an hour, 120 s repeats) and `budget.wait_max_min` (30). Set them
|
|
@@ -2070,6 +2119,16 @@ through a pipe, the JSON plan, the `ahub: blocker:` lines and the exit codes are
|
|
|
2070
2119
|
unchanged. The screens add no way to change an operation: every choice runs one
|
|
2071
2120
|
of the commands in this section for you, so that command's refusals decide.
|
|
2072
2121
|
|
|
2122
|
+
The screens use the console palette and `--color=auto|always|never`, with the
|
|
2123
|
+
same `NO_COLOR` and `TERM=dumb` precedence. Auto colours a suitable TTY; explicit
|
|
2124
|
+
always has the console's override behaviour. Raw JSON bypasses colour and width
|
|
2125
|
+
handling. Default and never preserve the existing pipe, dry-run, status and
|
|
2126
|
+
dispose output byte for byte. Presentation flags go after the command, for
|
|
2127
|
+
example `ahub recovery --color=never` or
|
|
2128
|
+
`ahub recovery status <operation-id> --json`. An explicit `--json` returns only
|
|
2129
|
+
the raw document, without a human suffix. `upgrade --json` reviews a JSON plan;
|
|
2130
|
+
`--yes` is still needed to apply it without the interactive review.
|
|
2131
|
+
|
|
2073
2132
|
The plan screen lists each project with its hub version and, per attached peer,
|
|
2074
2133
|
its state, how it runs (`TUI` in a terminal the plan bound to its session,
|
|
2075
2134
|
`headless` as the hub's own process, `own` for a session the hub did not
|
|
@@ -2102,23 +2161,35 @@ plan shows the ended agents as offline.
|
|
|
2102
2161
|
|
|
2103
2162
|
After apply the command stays attached and prints each step as the receipt
|
|
2104
2163
|
records it, and while a source is being prepared, what it still waits for.
|
|
2164
|
+
Each reported step has a status mark and elapsed observation time. Resume lists
|
|
2165
|
+
only steps observed on that attempt and says `resuming from ...` once. Its stage
|
|
2166
|
+
step really runs again and is labelled `checking retained release`. Waits use
|
|
2167
|
+
the coordinator's actual recorded start and deadline, for example
|
|
2168
|
+
`[waiting] alpha: restoring Codex and Pi sessions (waiting 2m10s of 10m)`.
|
|
2169
|
+
Older receipts without timing metadata say `timing unknown`; updatedAt is never
|
|
2170
|
+
used as a substitute. Timing-only save failures log a warning and do not fail
|
|
2171
|
+
the operation. Stable waits print only on change and at most once per minute.
|
|
2172
|
+
Approval waits point to `ahub console`; native attachment waits point to the
|
|
2173
|
+
recorded launch and conversation. Korean text and
|
|
2174
|
+
long paths wrap to the measured width on plan, progress and menu screens.
|
|
2105
2175
|
Enter opens the operation's screen while the runner works on. Ctrl+C leaves the
|
|
2106
2176
|
command, at any prompt and while following, and never stops the runner: the
|
|
2107
|
-
`left:` line names
|
|
2108
|
-
operation's
|
|
2109
|
-
until the upgrade ends. A Ctrl+C between `a` and the start of the operation
|
|
2177
|
+
`left:` line names `ahub recovery status <operation-id>`. Use `--verbose` for
|
|
2178
|
+
the internal command with the operation's retained coordinator, because the
|
|
2179
|
+
installed `ahub` may still be the older release until the upgrade ends. A Ctrl+C between `a` and the start of the operation
|
|
2110
2180
|
starts nothing. A prompt for a reason that is answered with
|
|
2111
2181
|
Ctrl+C or the end of input ends nothing.
|
|
2112
2182
|
|
|
2113
2183
|
The operation's screen also opens first whenever an operation holds the lock,
|
|
2114
2184
|
and for bare `ahub recovery`. It shows the phase and step, each project's phase
|
|
2115
|
-
and
|
|
2185
|
+
and human outcome labels, then What happened / Why / What to do and the choices that `status` lists under
|
|
2116
2186
|
`next` for the same receipt and live state:
|
|
2117
2187
|
|
|
2118
2188
|
| Key | Runs | Offered when |
|
|
2119
2189
|
| --- | --- | --- |
|
|
2120
2190
|
| `r` | `recovery resume`, then follows | resume can get past what is live |
|
|
2121
2191
|
| `c` | `recovery abort` | no runtime was stopped and no terminal effect or commit request is recorded |
|
|
2192
|
+
| `a` | `recovery reattach <id> <peer>` | the recorded detached session is eligible for reattachment |
|
|
2122
2193
|
| `f` | `recovery dispose --fresh-session <peer>`, after a reason | a Codex or Claude restoration failed |
|
|
2123
2194
|
| `e` | `recovery dispose --stop-and-archive`, after a confirmation and a reason | every unverified project reads as running, stopped or missing |
|
|
2124
2195
|
| `x` | `e`, then the reset below | as `e` |
|
|
@@ -2128,6 +2199,31 @@ When more than one restoration failed, the second and later peers get
|
|
|
2128
2199
|
`f-<peer>`. `s` refreshes the screen, `j` prints the receipt as JSON and `q`
|
|
2129
2200
|
leaves the operation as it is.
|
|
2130
2201
|
|
|
2202
|
+
The marked recommendation is a read-only Enter default: refresh the plan, follow
|
|
2203
|
+
an active runner, read the receipt or refresh the operation. Apply, resume and
|
|
2204
|
+
reattach require their explicit keys; buffered Enter never starts them. Unknown failures recommend
|
|
2205
|
+
reading `j` before retrying effects. A wait whose runner cannot be verified is
|
|
2206
|
+
shown disabled with its reason, and cannot run a command. Stop, archive, reset
|
|
2207
|
+
and fresh-session choices carry a warning and name the consequence before the
|
|
2208
|
+
person confirms. Raw receipt keys and the original recorded error are available
|
|
2209
|
+
with `j` or `--verbose`. The four preservation failures name the actual failed
|
|
2210
|
+
queue, manual-pause, board or budget comparison; an older untyped cause remains
|
|
2211
|
+
unknown rather than being guessed from its text. When nothing more specific
|
|
2212
|
+
applies (no typed cause, reattachment or `database_busy`), Why shows the first
|
|
2213
|
+
line of the recorded error, with control characters removed and cut at 512
|
|
2214
|
+
characters, marked `typed cause unknown`. What to do then says to resolve that
|
|
2215
|
+
error, then resume or choose an offered action. Nothing is classified from that
|
|
2216
|
+
text, and JSON and piped output are unchanged.
|
|
2217
|
+
|
|
2218
|
+
Completion and stop-and-archive use a human summary on a TTY. It separates the
|
|
2219
|
+
outcome, recorded plugin/global installation effects, remaining work and the
|
|
2220
|
+
per-peer session commands. An optional fresh read-only inspection names the
|
|
2221
|
+
current hub version; a failed reading says `runtime unknown`, never a guessed
|
|
2222
|
+
version from the plan. The summary performs no lifecycle action. Use `j` or
|
|
2223
|
+
`--json` for the full receipt; JSON is intentionally exempt from human wrapping.
|
|
2224
|
+
For a long command, copy the exact single-line value from `j` or the status JSON;
|
|
2225
|
+
the width-wrapped human preview is for reading.
|
|
2226
|
+
|
|
2131
2227
|
While a runner is only waiting for its source to get quiet (step `prepare`, no
|
|
2132
2228
|
effect recorded), `c` stops that runner and then aborts. It is offered only for
|
|
2133
2229
|
a runner whose claim carries a process signature that still matches; a claim
|
|
@@ -2177,7 +2273,10 @@ each receipt allows, given what is live, is tabulated in the recovery spec
|
|
|
2177
2273
|
(`docs/specs/2026-09-20-upgrade-recovery-design.md`, "Receipts, evidence and
|
|
2178
2274
|
next actions").
|
|
2179
2275
|
|
|
2180
|
-
- The source hold lapses after 10 minutes.
|
|
2276
|
+
- The source hold lapses after 10 minutes. If releasing it fails because the
|
|
2277
|
+
source's delivery storage fails, the hold stays and the expiry is retried
|
|
2278
|
+
every second until storage recovers; restore the storage before `abort`.
|
|
2279
|
+
A later `resume` prepares the same
|
|
2181
2280
|
source again and checks its peers again, keeping the receipts, so no terminal
|
|
2182
2281
|
is closed twice. It refuses, naming the next step, when the source daemon was
|
|
2183
2282
|
replaced, when another operation holds it, or when a peer changed: a peer whose
|
|
@@ -2239,7 +2338,11 @@ next actions").
|
|
|
2239
2338
|
that session. A target that dies again in the same `resume` stops it with the
|
|
2240
2339
|
restart count; look at its `hub.log` before resuming again. Without the
|
|
2241
2340
|
snapshot, or for an operation started by a coordinator older than 0.12.21,
|
|
2242
|
-
the way out is stop-and-archive.
|
|
2341
|
+
the way out is stop-and-archive. A snapshot whose kept hub notices fail
|
|
2342
|
+
validation blocks that restart with `restart snapshot deferred hub notices
|
|
2343
|
+
are invalid; restore is blocked`. The hub still reads as stopped, so
|
|
2344
|
+
stop-and-archive (and abort, where it applies) stays offered; nothing
|
|
2345
|
+
repairs the snapshot or offers to resume from it.
|
|
2243
2346
|
- A Codex conversation comes back only when a rollout file naming its thread
|
|
2244
2347
|
exists under `sessions/` of the store the restored terminal uses (the
|
|
2245
2348
|
recorded `CODEX_HOME`, else `~/.codex`). Codex writes that file with the
|
|
@@ -2281,11 +2384,23 @@ next actions").
|
|
|
2281
2384
|
unpinned signature too, so it counts as running when this command runs in
|
|
2282
2385
|
the same time zone and locale as the launcher did. `resume` is refused while a stop-and-archive is partway. A lifecycle command refused by the lock names
|
|
2283
2386
|
the operation's own `status` command, which lists what to do next.
|
|
2387
|
+
- `ahub recovery reattach <operation-id> codex|claude|pi` is person-only, including during live verification: an agent shell cannot delegate it. Name the operation and exactly one peer; session, backend, model and terminal overrides are not accepted. Use the exact operation-coordinator command printed by status or its blocked guidance. It repairs only that peer and leaves the operation blocked; run the offered `recovery resume` command to continue the remaining steps.
|
|
2388
|
+
The CLI delegates only when the retained coordinator supports reattach. An existing older coordinator without that action uses this release's implementation instead; a missing receipt, retained coordinator path or coordinator file prints inspection/recovery guidance and starts no session.
|
|
2389
|
+
A peer that attached and later went offline can be re-restored once when its saved terminal is positively orphaned or missing and no current or older operation launcher may still run. The recorded session id and Pi session file stay fixed; the new terminal binding is saved before waiting for authenticated attachment. A second detach blocks. An unreadable terminal, changed incarnation or worktree, disconnected-only evidence, truncated inventory or live/unknown launcher does not authorize another terminal.
|
|
2390
|
+
Recovery status names the saved Codex thread, Pi session file and Claude session, the terminal evidence, and the applicable reattach command. A different attached conversation remains a strict refusal.
|
|
2284
2391
|
- `ahub recovery dispose <operation-id> --fresh-session <peer> --reason <text>`
|
|
2285
2392
|
applies to a Codex or Claude peer whose restoration failed (Pi is refused: a
|
|
2286
2393
|
restored hub resumes Pi's recorded session). It records the lost session or
|
|
2287
2394
|
thread id (status shows it under `lostContinuity`) and resumes: the peer
|
|
2288
2395
|
starts without its old conversation, and the rest is verified as usual.
|
|
2396
|
+
A session the operation already reattached keeps that repaired provenance
|
|
2397
|
+
across target restarts and is never replaced automatically. Its
|
|
2398
|
+
loss can be accepted only after the restoration reported the recorded Claude
|
|
2399
|
+
transcript or Codex rollout as positively missing, naming the checked path;
|
|
2400
|
+
dispose checks that path again before saving the choice and otherwise refuses
|
|
2401
|
+
with "recorded conversation is not positively missing". Under `--live-test`
|
|
2402
|
+
this repaired-session choice is refused even where an ordinary fresh session
|
|
2403
|
+
may be delegated.
|
|
2289
2404
|
- `ahub recovery dispose <operation-id> --stop-and-archive --reason <text>`
|
|
2290
2405
|
abandons the operation. It checks every project first and refuses while a
|
|
2291
2406
|
hub is unreachable, starting, stopping or of another control protocol; `next`
|
|
@@ -2332,7 +2447,8 @@ next actions").
|
|
|
2332
2447
|
again.
|
|
2333
2448
|
Start a project whose target ran with that release's CLI (`bunx --package
|
|
2334
2449
|
@staix/agent-hub@<version> ahub up`), since it may have changed the task
|
|
2335
|
-
database. The global CLI was not promoted.
|
|
2450
|
+
database. The global CLI was not promoted. The archive summary distinguishes completed target startup and plugin installation from remaining global CLI installation, and prints recorded-session commands: `ahub codex resume <thread-id>`, `ahub pi --session-file <path>`, and the Claude reconnect command. On the next `ahub up`, `pi.auto_start` resumes the archived operation's recorded Pi session rather than choosing a fresh conversation. Unknown or conflicting archived identity refuses that automatic resume.
|
|
2451
|
+
That session is kept as a bookmark, `.agenthub/state/recovery-continuity.json`. When its session file can no longer be resumed or does not match it, the hub archives the bookmark and starts no fresh session in that start; the error names `ahub pi --mode <mode> --session-file <managed-file>` for choosing one. An invalid or unreadable bookmark, or session storage that cannot be verified, starts nothing, keeps the bookmark and prints the `mv -n` command that archives it after inspection. The bookmark is retired once Pi attaches with a different authenticated session.
|
|
2336
2452
|
- Both choices are for a person in a terminal; an agent shell is refused, and
|
|
2337
2453
|
the reason is kept in the operation's audit. Run each with the command
|
|
2338
2454
|
`next` or the error prints: the operation's own coordinator, or the release
|
|
@@ -2556,7 +2672,7 @@ ahub task cancel <id> --reason <text> [--superseded-by <ref>] [--revision N]
|
|
|
2556
2672
|
|
|
2557
2673
|
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 its own unaccepted backlog/proposed work; previously accepted work 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.
|
|
2558
2674
|
|
|
2559
|
-
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 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.
|
|
2675
|
+
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.
|
|
2560
2676
|
|
|
2561
2677
|
## Task idle sweep
|
|
2562
2678
|
|
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.12.
|
|
20
|
+
bun add -g github:STAIxBWLB/agent-hub#v0.12.33
|
|
21
21
|
ahub setup
|
|
22
22
|
```
|
|
23
23
|
|
|
@@ -30,9 +30,11 @@ 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.12.
|
|
33
|
+
## Upgrading to 0.12.33
|
|
34
34
|
|
|
35
|
-
|
|
35
|
+
The upgrade runs with the target release's own coordinator, so an upgrade from 0.12.32 with cancelled tasks and a managed terminal, or with a notice the target sends right after it starts, no longer blocks (#478). If the operation blocks because a restored Codex, Claude or Pi terminal disappeared, the person runs `ahub recovery reattach <operation-id> codex|claude|pi` to relaunch that peer with its recorded session (one relaunch per receipt), then `ahub recovery resume` to finish.
|
|
36
|
+
|
|
37
|
+
From 0.12.30 or earlier, existing Jcode project MCP entries need one refresh before conductor or dashboard starts. Once per project, the person runs:
|
|
36
38
|
|
|
37
39
|
```bash
|
|
38
40
|
ahub jcode --mode headless
|
|
@@ -83,6 +85,7 @@ or set `OMNIROUTE_API_KEY`. Name the model in `.agenthub/routing.toml` (`[local]
|
|
|
83
85
|
| `ahub board` | who has what; `ahub task show <id>` for one task |
|
|
84
86
|
| `ahub task cancel <id> --reason <text>` | close obsolete work without approving it or stopping a native turn |
|
|
85
87
|
| `ahub settings set planner <peer>` | pin the planner; status reports whether it came from settings, roles or the automatic choice |
|
|
88
|
+
| `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 |
|
|
86
89
|
| `ahub status` | peers, queues, pauses; `ahub budget` for quota windows |
|
|
87
90
|
| `ahub memory profile-check` | a person's read-only check of running memory bindings in the current registry |
|
|
88
91
|
| `ahub ask <question>` | what the board, shared memory and the log say, with the ids the answer rests on |
|
|
@@ -93,7 +96,7 @@ More: `ahub help`. How it is built and why: [`docs/specs/2026-09-19-agent-hub-de
|
|
|
93
96
|
|
|
94
97
|
## Shared memory
|
|
95
98
|
|
|
96
|
-
The hub exact-pins the first-party `@staix/agent-mem` 0.3.
|
|
99
|
+
The hub exact-pins the first-party `@staix/agent-mem` 0.3.1 core. Existing shared-v1 memory remains the default; upgrading does not migrate it. Managed agents use screened `hub_memory_search`, `hub_memory_show` and `hub_memory_graph` tools, or propose a correction with `hub_memory_correct`; only a person accepts candidates through the supported `amem review` path. Generation candidate acceptance is still refused.
|
|
97
100
|
|
|
98
101
|
Before any real generation migration, upgrade every hub sharing that memory home to 0.12.30 or later and check its authenticated binding with `ahub memory profile-check` in each custom registry. Ready bindings prove compatibility, not an atomic live cutover: quiesce consumers and close their handles before migrating, then reopen through the supported session-preserving lifecycle. Invalid or changed profiles disable native memory without falling back to legacy writes; the bus and board continue. See [memory operations](operations.md#hub-memory) for the remaining rollout gates.
|
|
99
102
|
|
|
@@ -110,8 +113,9 @@ contents: inspect them with `ahub tail`, then use `ahub permit <id> <option>` to
|
|
|
110
113
|
allow. They can be denied on the page. PII task details remain available only via
|
|
111
114
|
`ahub task show <id>` in the terminal. The page also starts a peer in its start
|
|
112
115
|
mode (a TUI opens in a terminal when the hub has a terminal provider) and shows
|
|
113
|
-
the settings; raising one needs `ahub ui --settings`
|
|
114
|
-
|
|
116
|
+
the settings with a Reload configuration button; raising one needs `ahub ui --settings`
|
|
117
|
+
or `ahub settings` in a terminal, and guarded values from an edited file need
|
|
118
|
+
`ahub settings reload` there. See the operations guide, "Settings from the dashboard and the
|
|
115
119
|
terminal" and "Start modes".
|
|
116
120
|
|
|
117
121
|
`ahub ui --no-open` prints a one-time link instead of launching a browser. Open it
|
package/docs/security.md
CHANGED
|
@@ -11,7 +11,7 @@ agent-hub connects agents that can each run commands. This page says what the hu
|
|
|
11
11
|
- **Telemetry holds no bodies.** `.agenthub/state/events.jsonl` (issue #40) records envelope ids, routing and sizes, task ids and states, overlapping paths and token counts, and the task id (with a PII flag) that each usage and token record is attributed to. It never records a message body, a task title or detail, and marks private (PII) envelopes and tasks as such. It stays on the machine; `ahub export` only prints it. Two opt-in stores copy numbers from it into your home directory, shared by every project on the machine (directories mode 700, files 600): research records (issue #247, `research.enabled`) in `~/.agenthub/research/` hold per approved task the ids, states, counts, tokens, times and PII flag the events hold, a person's label from a closed list, and a hash in place of the project id; benchmark runs (issue #251) in `~/.agenthub/bench/` hold suite name and hash, arm label, the attached peers' ids, models and permission modes, task ids, outcomes, exit codes, counts, tokens and times, never suite text or a command's output.
|
|
12
12
|
- **Snapshots stay in your repository.** Per-turn snapshots (issue #33) are git objects in the project's own object store, written through a temporary index; nothing is referenced, pushed or copied elsewhere, and `git gc` prunes them. They hold what the work tree held, including untracked files that are not ignored, so keep secrets in ignored files. They carry the repository's own permissions, and nothing caps their disk use but `git gc`. A turn of a peer holding an open PII task is not snapshotted; a PII file left in the project is snapshotted by later turns like any other file. `ahub undo` restores only files whose current content is exactly what the turn left.
|
|
13
13
|
- **The edit hook reads, never decides.** `ahub check-path --hook` (issue #32) reads hub.db and returns context for Claude and a line for you; it sets no permission decision, so your permission rules stay in charge. It names other owners' task ids, titles and states, which then reach Claude's model; PII tasks are left out.
|
|
14
|
-
- **The session record holds identities only.** `.agenthub/state/sessions.json` (issue #37, mode 600) keeps each attached peer's recovery metadata: launch options, session and thread ids, Pi's session file path. No message or task text; loss notices name deliveries by id, sender and public task title.
|
|
14
|
+
- **The session record holds identities only.** `.agenthub/state/sessions.json` (issue #37, mode 600) keeps each attached peer's recovery metadata: launch options, session and thread ids, Pi's session file path. No message or task text; loss notices name deliveries by id, sender and public task title. The Pi continuity bookmark that recovery keeps across stop and archive (`.agenthub/state/recovery-continuity.json`, mode 600, at most 16 KiB) holds identities only too: operation and project ids, the project root, and Pi's session id, session file, backend and model name; a bookmark that is not a private regular file, is larger than that or names another project or operation reads as invalid, which is kept distinct from no bookmark.
|
|
15
15
|
- **Context checkpoints have a separate text record.** Native occupancy readings carry numeric metadata only. An optional context checkpoint persists its summary in `.agenthub/state/context-checkpoint-<peer>.json` with mode 0600 and attempts shared-memory storage when enabled. Completion requires the outstanding request id, current peer/native session and transport generation; new connection claims invalidate old requests. Private turns, every open PII task associated with the peer as owner or reviewer (including pending review), and PII-pattern summaries are refused before persistence or cloud memory. Its text is never broadcast, and context pressure does not pause, reassign or replace the session.
|
|
16
16
|
- **The local worker is boxed in.** Paths are resolved through symlinks and must stay inside the project; a secrets denylist (`.env*`, keys, credential files, the hub's own state and the state archives `ahub reset --all` leaves) applies to its file tools, its git arguments and its memory capture alike; `.git` and `.agenthub` are not writable. Writes, edits, shell commands and mutating git wait for approval unless the operator's permission mode grants them (writes and edits inside the grant filter in `ask-when-needed`, all four in `never-ask`; see below), and the approver sees what will be written or run, with control characters escaped. Everything it executes runs under the macOS sandbox, attended or not. Since 0.10 the profile starts from deny default (issue #39): commands run and read only the system, toolchain and project directories (and the project's git dir and the selected developer dir; with network on, the public CA bundles); no writes outside the project, its git dir and a temp dir of its own (`TMPDIR`, made for each command and removed when it ends; issue #63); no `.git` name at any depth, closing the creation, rename, symlink and gitfile routes to a planted repository, no `config` or `hooks` directly under one nor below the discovered modules root of the project's own `.git` (a submodule's git directory, nested submodules included; every term is anchored below that root, so a directory named `refs`, `config` or `hooks` above the project neither disables the rule nor trips it; a `/refs/` or `/logs/` segment below it keeps refs named `config` or `hooks` writable, and leaves a submodule whose own path contains such a segment uncovered; a submodule whose path has `hooks` as a whole component (`tools/hooks` included) fares worse: the rule matches its whole git directory, so every write there is refused; the discovered git directories, the modules root and every component in between are also refused as targets, closing the rename, replace and symlink routes to the same files), no `commondir` at any depth below one, with every such name matched folded against the code points HFS+ ignores (the fold covers the security-relevant names; on a volume that folds names, folded spellings of the components between `.git` and a submodule's git directory are not matched — the 1024-byte SBPL literal cannot hold a folded path — the same residual the external git dir rules carry since #270), and no `.agenthub` anywhere in the project (in an external git dir the `config`/`hooks` rules cover only its own children and the hooks directory's contents, so refs named `config` or `hooks` still work); a nested repository in bare layout stays open — the directory is the git dir, with no `.git` name to anchor a rule on, and the hub never runs git there, whatever the project root is: its calls are all `-C <project root>` or `--no-index` on temp files, and none descends into a nested directory's git layout, so a planted hook fires only if a person or another tool runs git in that directory themselves; the rules are probed on HFS+, which folds the 16 code points the patterns tolerate, and on a case-sensitive APFS image, which folds nothing (a folded spelling is an inert new file there and the real names stay refused); the cost is that `git init`, `git clone` and `git worktree add` do not run inside the sandbox (add, commit, stash, checkout and gc still do), `git submodule update --init` does not either (its git directory's `config` write is refused), and neither do `git worktree remove`, `git worktree prune` of a stale record, `git clean -ffd` in a project with a nested repository, or `rm -rf` of a directory that holds a `.git` (refusing the unlink is what stops the rename-out route); no network, loopback included, unless `local.bash_network`; with it, only through the hub's egress proxy to the hosts in `local.network_allow` (issue #65), which refuses names that resolve to internal addresses (behind NAT64 with the well-known prefix, by the IPv4 address the answer carries; a network-specific prefix is not recognised), so claude-mem and the Codex app-server stay out of reach (`"direct"` opens everything, until 0.13.0). One channel stays open: `trustd`, which TLS clients need, can fetch a certificate's AIA or OCSP URL on a command's behalf, outside the proxy. The allow-default profile of 0.9 and earlier was removed in 0.12.0 (issue #83); a `local.sandbox` setting is ignored with a note. The shared temp dirs (the user's and `/private/tmp`) are closed. Without the sandbox there is no `bash` tool.
|
|
17
17
|
- **Capabilities are enforced, not suggested.** `capabilities` (issue #39) is checked by the daemon where task operations and messages arrive, so a peer cannot get round it by phrasing. A peer can never answer a permission request: the control link takes `permit` from the console role only, and a message that quotes a permit command is just text. Both bind the hub's own tool paths: a vendor agent with its own shell in the project (Codex, Claude, Kimi) can read `.agenthub/state/control-token` and connect as the console, which only the local worker's and Pi's sandbox prevents.
|
|
@@ -23,7 +23,7 @@ agent-hub connects agents that can each run commands. This page says what the hu
|
|
|
23
23
|
|
|
24
24
|
## Native memory authority and profile selection
|
|
25
25
|
|
|
26
|
-
The portable core is the exact-pinned first-party `@staix/agent-mem` 0.3.
|
|
26
|
+
The portable core is the exact-pinned first-party `@staix/agent-mem` 0.3.1 package; it does not replace the hub's caller identity, PII policy or task-write authority. Deny, hardened git, real paths and process identity are single-sourced in its Node-safe platform entry. Current project privacy is applied by the hub before promotion and again before model-facing reads. Standalone person reads are unscreened, and the standalone `--policy-free` acknowledgement grants no hub or peer authority.
|
|
27
27
|
|
|
28
28
|
`hub_memory_search`, `hub_memory_show` and `hub_memory_graph` take the project from the daemon, require `memory_read`, refuse private turns and validate UTF-8 input before logs or storage work. Complete records and graph metadata are screened before counts and truncation. Search is at most 20 lines/4 KiB (default 8); show accepts at most 8 ids and returns at most 8 KiB; graph is at most 120 nodes/240 edges/6 KiB (default 60 nodes), with no edge lacking an endpoint. Unknown, ambiguous and withheld ids share one neutral refusal. Arguments and results are excluded from hub-managed capture; this does not govern a vendor's independent transcript or memory hooks.
|
|
29
29
|
|
|
@@ -98,8 +98,11 @@ if that audit cannot be written, the command refuses. The current daemon emits
|
|
|
98
98
|
`agent_cli` with `delegated: true` and `refused: false`. Allowed-class commands retain the peer identity and capability checks, including
|
|
99
99
|
messages, proposals and reviews. Peer starts, pause and resume may delegate
|
|
100
100
|
operational console authority; task assign/escalate under the flag refuse. `--as-user`, person task labels,
|
|
101
|
-
person-authored planning/release/memory/goal writes, SDLC record, benchmark run
|
|
102
|
-
|
|
101
|
+
person-authored planning/release/memory/goal writes, SDLC record, benchmark run,
|
|
102
|
+
`ahub recovery reattach`, a `--fresh-session` dispose that would replace a repaired
|
|
103
|
+
session's conversation (or whose scope cannot be read), and the pet
|
|
104
|
+
composer are refused; presentation flags such as `--color` or `--verbose` before
|
|
105
|
+
the recovery action do not hide it from this check. No argument text is copied into this audit.
|
|
103
106
|
Delegated dashboard restrictions are bound to its server-issued ticket/session:
|
|
104
107
|
operational settings/start/stop controls remain, but message, proposal and
|
|
105
108
|
workflow-history actions refuse even if the body tries to clear the restriction.
|
|
@@ -116,7 +119,12 @@ The operator uses a plain terminal or `ahub console`. A Claude `!` command that
|
|
|
116
119
|
inherits the agent markers follows the same rule. The console strips control
|
|
117
120
|
sequences from agent and daemon text before it quotes forged headers, and its
|
|
118
121
|
colors come only from a fixed palette applied afterwards, so message text cannot
|
|
119
|
-
set styles or operate the terminal.
|
|
122
|
+
set styles or operate the terminal. The recovery blocked screen shows a recorded
|
|
123
|
+
error only when no typed cause exists: its first line, passed through the
|
|
124
|
+
console's terminal sanitizer with control characters removed, capped at 512
|
|
125
|
+
code points and marked as an untyped recorded error. A restart snapshot whose
|
|
126
|
+
kept hub notices fail validation is reported with a fixed message, never with
|
|
127
|
+
its content.
|
|
120
128
|
|
|
121
129
|
This is an honest default against accidental impersonation and injected commands.
|
|
122
130
|
It does not make the token inaccessible to an agent with unrestricted project
|
|
@@ -150,16 +158,17 @@ Please report vulnerabilities privately through GitHub's "Report a vulnerability
|
|
|
150
158
|
- Every request must have the exact listener Host. Every data or action request, including the ticket exchange and snapshot polling, must be POST with the exact listener Origin and JSON content type. Foreign and missing origins, missing or expired sessions, oversized bodies and unknown actions are rejected. There is no CORS support. The only unauthenticated GET is the fixed, data-free HTML shell. No files or paths are served dynamically.
|
|
151
159
|
- Responses are non-cacheable, cannot be framed, suppress referrers, and use a content security policy restricting scripts/styles to the shipped inline content and connections to this origin. Browser text is rendered with textContent, never interpreted as HTML.
|
|
152
160
|
- The browser receives a bounded redacted event stream, peer states and queue counts, public task views, budget windows, pending approvals, the settings rows (closed values and ids, the file each comes from) and each startable peer's start plan (issue #269), benchmark run summaries (issue #251): the newest runs in `~/.agenthub/bench/`, whichever project on this machine ran them, by suite name, arm label, state, the task id in progress, counts, tokens and times, never suite text, and the office view's optional fields (issue #264): each peer's open turn (start time, attributed task id, attribution kind), a `checking` flag on tasks whose check is running, and warning `links` of overlapping, conflicting or cohort tasks (task and peer ids only, never paths, symbols or reasons; a PII task never joins a link, and a private or PII-attributed turn exposes no task id). Private envelope bodies and PII task text never cross this endpoint. Local-worker and Pi approval titles can contain PII, so their details remain terminal-only; the dashboard identifies the request and directs the operator to `ahub tail` before allowing it. Budget checkpoint summaries are also omitted.
|
|
153
|
-
- The closed action list includes permission response, peer pause/resume, console message, task proposal/assignment and the settings actions below (set, undo, preview). Project-board actions add revision-fenced planning, Backlog pull/return/split/undo and release planning/state changes through Tasks; they do not tag, publish or write GitHub state. These use the existing daemon/task paths and budget pause rules. `start_peer` (issue #269) starts a peer from a closed list in the mode a person set, with a command the hub assembles: the request carries a peer id and nothing else. There is no generic control proxy, task-detail read, shell, file access, free-form configuration edit, budget override, launch of a caller-chosen command or daemon shutdown API.
|
|
161
|
+
- The closed action list includes permission response, peer pause/resume, console message, task proposal/assignment and the settings actions below (set, undo, preview, reload). Project-board actions add revision-fenced planning, Backlog pull/return/split/undo and release planning/state changes through Tasks; they do not tag, publish or write GitHub state. These use the existing daemon/task paths and budget pause rules. `start_peer` (issue #269) starts a peer from a closed list in the mode a person set, with a command the hub assembles: the request carries a peer id and nothing else. There is no generic control proxy, task-detail read, shell, file access, free-form configuration edit, budget override, launch of a caller-chosen command or daemon shutdown API.
|
|
154
162
|
- The listener stops with the daemon. Expired sessions must be reopened with `ahub ui`; the page does not silently obtain new credentials.
|
|
155
163
|
|
|
156
164
|
## Dashboard settings and the settings session (issue #269)
|
|
157
165
|
|
|
158
166
|
- Settings are a closed registry (`src/hub/settings.ts`). The dashboard and `ahub settings` can write only its keys, each checked against its own closed values, and only to `.agenthub/config.local.json` and `.agenthub/routing.local.toml`. A file git tracks is never written, so the shared `config.json` and `routing.toml` stay byte-identical; in a repository where git cannot answer, nothing is written either. Commands and binaries (`kimi_cmd`, `codex_bin`, `pi.cmd`, `checks`, `mlx`), credential files and gateway URLs (`omniroute`, `memory.worker_url`), the local worker's reach (`local.read_allow`, `local.bash_network`, `local.network_allow`), `bench.enabled` and `terminal` are refused by name from every surface: they choose what the hub runs or where secrets and task text go.
|
|
159
167
|
- `routing.local.toml` holds `stay_switch` and, per class, `peers`, `escalate_to`, `route` (an id `routing.toml` defines) and `pi_backend`, and nothing else: targets, routes, signals and the PII constraint cannot be set through it. A write is read by the hub's own loader before it replaces the file (temp file and rename), and one previous version is kept for undo.
|
|
160
|
-
- An ordinary dashboard session (`ahub ui`) reads settings, lowers a mode to `ask`, turns `pi.auto_start` off and changes the safe switches (`research.enabled`, `approvals.notify`, `snapshots.enabled`, `coordination`). Whatever can widen what agents do without asking needs a settings session: a non-ask mode now or at hub start, routing, starting Pi with the hub, removing a machine-local value, and undo. `ahub ui --settings` opens one: its ticket marks the session for 15 minutes, after which it is an ordinary session. `never-ask` also needs the peer's id typed as the confirmation, and a stored never-ask default still waits for the console's `y` at each hub start. An undo never puts never-ask back, and removing a machine-local value that uncovers a never-ask in the shared file needs the same confirmation. "Lowering to `ask`" means handing the decision back to the agent's own rules: for Codex that is the approval policy the person configured natively, which the hub does not judge.
|
|
168
|
+
- An ordinary dashboard session (`ahub ui`) reads settings, lowers a mode to `ask`, turns `pi.auto_start`, `task_sweep.enabled` or `task_sweep.auto_reassign` off, sets a start mode back to `tui` or a WIP limit to 0, and changes the safe switches (`research.enabled`, `approvals.notify`, `snapshots.enabled`, `coordination`). Whatever can widen what agents do without asking needs a settings session: a non-ask mode now or at hub start, routing, starting Pi with the hub, removing a machine-local value, and undo. `ahub ui --settings` opens one: its ticket marks the session for 15 minutes, after which it is an ordinary session. `never-ask` also needs the peer's id typed as the confirmation, and a stored never-ask default still waits for the console's `y` at each hub start. An undo never puts never-ask back, and removing a machine-local value that uncovers a never-ask in the shared file needs the same confirmation. "Lowering to `ask`" means handing the decision back to the agent's own rules: for Codex that is the approval policy the person configured natively, which the hub does not judge.
|
|
161
169
|
- A settings session is as strong as the console for these settings and no stronger elsewhere. A mode change is the console's own request with the same refusals; tool approvals stay deny-only for Pi and local; there is still no shell, file, task-detail or launch-command API. `ahub ui --settings` and `ahub settings` pass the same identity gate as `ahub permission`, which is an operating policy, not authentication. The hostile-agent boundary above applies unchanged: an agent with an unrestricted shell as the same user can impersonate the console, and so can open a settings session.
|
|
162
170
|
- Every change writes a `settings` event (the key, the value before and after, the source `dashboard` or `terminal`) and a line in `hub.log` and open consoles; opening a settings session is logged too. The unified dashboard (`ahub ui --all`) forwards settings actions as an ordinary session and opens no settings session.
|
|
171
|
+
- Configuration reload (issue #439). The daemon watches `config.json`, `config.local.json`, `routing.toml` and `routing.local.toml` and re-reads the complete candidate after a change, as the dashboard's Reload configuration and `ahub settings reload` do; an invalid candidate applies nothing. Each changed key is then authorized on its own against its file's actual git provenance. A privacy tightening (local-only PII, the model screen on, added PII patterns, narrower roles or capability lists, unless it moves the planner or conductor) and a safe registered setting apply from any file. Every other change, machine-local fields included, keeps its running value when its file is tracked or git cannot answer. From an untracked file such a guarded change is adopted only by `ahub settings reload` in an interactive terminal, after it lists each guarded key with its full before and after values and the person types `y` within 30 seconds; the confirmation is bound to the file contents and accepted state it was shown for. File watches and dashboard reloads, a settings session's included, never confirm, and no reload changes the roster: membership moves only through the roster setting. Keys whose consumers are bound at start (memory, the gateway and MLX, checks, the privacy and sandbox policy of existing sessions, the terminal provider and others) stay pending until a restart.
|
|
163
172
|
- Start modes. A start the hub makes itself (the dashboard's Start control, `peer_start` from a console child, the conductor's `hub_peer_start`, `pi.auto_start`) takes the peer's start mode. Through settings only a settings session or the terminal can set it to headless; a config file can also set `peers.<id>.start_mode`, the shared one included (it is not a machine-local field: headless was the only form for Pi, Kimi and the local worker before this change, a hub-made headless Codex start is the app-server the hub already ran for it, and a start mode grants nothing a permission mode or a capability controls). For a TUI the hub opens a terminal running `<runtime> <its own entry point> --project <this project> <peer>` (and `--mode tui` for Pi): every word is the hub's own, the command line is those words each quoted for a POSIX shell, and no request field, tool argument or agent message is part of it. In a `terminal.open` template `{command}` is that quoted line and `{title}` and `{cwd}` are raw text for argv elements of their own; each placeholder is substituted once, so a project path that itself contains a placeholder, a quote or `$` stays one word. A provider's own error text goes to `hub.log`, not to the caller. The terminal comes from `terminal.open`, a machine-local command template that config trust refuses from a committed file and that no settings surface can write, or from Orca. The opened terminal's environment carries no agent marker, so `ahub` there has the console's identity. Without a provider the start is refused with the command to run by hand; it is never downgraded to headless. A conductor can start a peer but cannot choose its mode.
|
|
164
173
|
|
|
165
174
|
## Multi-project manager (protocol 7)
|
|
@@ -192,7 +201,7 @@ conductor holder is refused. Local and Pi scoped tools cannot write `.agenthub`.
|
|
|
192
201
|
Claude, Codex and Kimi still follow their own file permissions and can edit a
|
|
193
202
|
config file; such an edit changes participation only at the next hub start. A
|
|
194
203
|
live settings write or undo applies its own roster key and does not adopt other
|
|
195
|
-
file edits. External ids outside the known native catalog keep their prior
|
|
204
|
+
file edits, and a configuration reload refuses roster changes. External ids outside the known native catalog keep their prior
|
|
196
205
|
admission rules.
|
|
197
206
|
|
|
198
207
|
Kimi's pull-only TUI owns its tool approvals and session. The person's launcher
|
|
@@ -215,7 +224,7 @@ are in [the configuration inventory](verification/2026-10-11-agent-config-invent
|
|
|
215
224
|
Instruction files `AGENTS.md`, `CLAUDE.md` and `QWEN.md` remain grantable by default.
|
|
216
225
|
A person can set `scoped_grants.protect_instructions` to true to require approval
|
|
217
226
|
for scoped writes and edits through original or resolved spellings. It applies
|
|
218
|
-
live after a settings write or
|
|
227
|
+
live after a settings write, undo or reload (turning it off from an edited file needs the confirmed terminal reload), never changes reads or never-ask, and cannot
|
|
219
228
|
be set through an agent, tools or conductor surface. Claude's daemon response
|
|
220
229
|
withholds the scoped mode on these writes so an older hook grants nothing too.
|
|
221
230
|
|
package/docs/smoke.md
CHANGED
|
@@ -1901,3 +1901,37 @@ The current source fixture at 6d311a51dccd41d3703079175cac65a487189b15 used the
|
|
|
1901
1901
|
This supersedes earlier phone-fixture pending statements only for this source. The old 1bbced04 captures remain historical; no later byte-identity premise is used. Native planner/two-release, accounts, model ingestion and measured effects remain unverified.
|
|
1902
1902
|
|
|
1903
1903
|
The later bounded release-audit preview text is verified by DOM tests, not by a refreshed phone capture. The6d311a51 PNGs remain evidence for their pinned source; see the later-audit note in the phone verification report.
|
|
1904
|
+
|
|
1905
|
+
|
|
1906
|
+
## Settings reload and console fixture (#439, 2026-10-17)
|
|
1907
|
+
|
|
1908
|
+
Native real-terminal smoke is **UNVERIFIED**. The admitted remote install/test
|
|
1909
|
+
attempt exited 75 before running because Python pid 6672 (parent 6671) had no
|
|
1910
|
+
verified repository owner. No retry, process kill, user-hub settings change,
|
|
1911
|
+
installation or restart was performed. A scripted ConsoleTerminal is fixture
|
|
1912
|
+
evidence, not a native PTY or account result.
|
|
1913
|
+
|
|
1914
|
+
The implementation fixtures cover the following in disposable projects and temp
|
|
1915
|
+
memory homes:
|
|
1916
|
+
|
|
1917
|
+
- Console Settings tab, daemon preview, bounded reason, explicit y, undo, stale
|
|
1918
|
+
preview fencing and pasted-y refusal.
|
|
1919
|
+
- Dashboard reload/context, running/file values, pending restart reasons and
|
|
1920
|
+
stable drafts; older snapshots remain readable.
|
|
1921
|
+
- Real fixture daemon: live switches/WIP and undo, retained pause/queue/instance,
|
|
1922
|
+
actual sweep timer cancellation/rescheduling, atomic rename watcher, snapshot
|
|
1923
|
+
capture on a later turn and pending memory restart without opening a consumer.
|
|
1924
|
+
- Whole-candidate JSON/TOML/unknown-key refusal, one error notice, per-key retention
|
|
1925
|
+
of valid unauthorized edits, automatic privacy tightening, scoped write/undo,
|
|
1926
|
+
fingerprint-bound guarded reload confirmation and agent-role request refusals.
|
|
1927
|
+
|
|
1928
|
+
To complete the native leg, use a disposable project from a person terminal (or
|
|
1929
|
+
an explicitly authorized per-invocation delegation under docs/security.md).
|
|
1930
|
+
Open `ahub console`, select Settings with 6, edit a safe switch, inspect its
|
|
1931
|
+
preview, enter a reason, confirm y and verify running/file values. Preview and
|
|
1932
|
+
confirm undo; verify the restored value through `ahub settings get`. Paste y at
|
|
1933
|
+
confirmation and verify no write. Change a sweep interval and confirm the same
|
|
1934
|
+
hub instance stays running with its queue and pauses intact. Record the source
|
|
1935
|
+
head, terminal and daemon readbacks separately before claiming AC5 native smoke.
|
|
1936
|
+
|
|
1937
|
+
For the guarded CLI leg, edit a disposable untracked WIP limit, run `ahub settings reload`, inspect its complete before -> after preview, decline and verify the running limit is retained. Repeat and confirm y, then verify the same instance and queue/pause state. Record this separately from the scripted CLI fixture; the token proves freshness within console authority, and the CLI supplies the person-presence checks.
|