@staix/agent-hub 0.12.39 → 0.12.40
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 +26 -0
- package/README.md +15 -10
- package/docs/agent-notes/adapters.md +4 -1
- package/docs/agent-notes/budget.md +2 -0
- package/docs/agent-notes/bus.md +2 -2
- package/docs/agent-notes/daemon.md +10 -6
- package/docs/agent-notes/models.md +4 -4
- package/docs/agent-notes/tasks.md +3 -0
- package/docs/agent-notes/tests.md +1 -1
- package/docs/memory.md +1 -1
- package/docs/operations.md +152 -28
- package/docs/quickstart.md +19 -5
- package/docs/security.md +19 -7
- package/docs/smoke.md +2 -2
- package/docs/specs/2026-09-19-agent-hub-design.md +158 -70
- package/docs/specs/2026-10-04-switchyard-source-port-design.md +12 -7
- package/docs/verification/2026-10-20-0.12.40.md +63 -0
- package/docs/verified.json +38 -19
- package/package.json +1 -1
- package/plugins/agent-hub/.claude-plugin/plugin.json +1 -1
- package/plugins/agent-hub/server.js +413 -147
- package/src/adapters/acp.ts +34 -1
- package/src/adapters/claude-channel.ts +35 -4
- package/src/adapters/codex-appserver.ts +12 -3
- package/src/adapters/definitions/builtin-metadata.ts +2 -0
- package/src/adapters/definitions/native-cli-doctor.ts +8 -5
- package/src/adapters/definitions/native-cli-entry-claude.ts +7 -2
- package/src/adapters/definitions/native-cli-entry-codex.ts +13 -14
- package/src/adapters/definitions/native-cli-entry-jcode.ts +13 -3
- package/src/adapters/definitions/native-cli-entry-pi.ts +9 -7
- package/src/adapters/definitions/native-cli-entry-types.ts +2 -0
- package/src/adapters/definitions/native-cli-jcode-mcp.ts +55 -1
- package/src/adapters/jcode.ts +110 -4
- package/src/adapters/local-worker.ts +21 -37
- package/src/adapters/pi.ts +7 -0
- package/src/cli/console-state.ts +1 -0
- package/src/cli/console.ts +11 -1
- package/src/cli/help.ts +13 -8
- package/src/cli/identity-audit.ts +33 -7
- package/src/cli/jcode-mcp.ts +1 -1
- package/src/cli/main.ts +134 -24
- package/src/cli/output.ts +5 -2
- package/src/cli/status-lines.ts +1 -1
- package/src/cli/terminal-recovery.ts +54 -4
- package/src/cli/upgrade-interactive.ts +5 -0
- package/src/cli/upgrade-runtime.ts +13 -1
- package/src/cli/upgrade.ts +67 -1
- package/src/hub/board.ts +4 -2
- package/src/hub/bus.ts +8 -3
- package/src/hub/checks.ts +15 -5
- package/src/hub/conductor.ts +2 -1
- package/src/hub/config-apply.ts +20 -2
- package/src/hub/config-reload.ts +2 -8
- package/src/hub/control-client.ts +26 -3
- package/src/hub/daemon.ts +155 -68
- package/src/hub/delivery-superseded.ts +19 -2
- package/src/hub/events.ts +4 -1
- package/src/hub/hub-tools.ts +4 -4
- package/src/hub/inference.ts +4 -8
- package/src/hub/lifecycle.ts +3 -3
- package/src/hub/main-checkout.ts +36 -0
- package/src/hub/memory-profile-check.ts +6 -2
- package/src/hub/memory-profile.ts +18 -1
- package/src/hub/peers.ts +2 -0
- package/src/hub/ports.ts +1 -0
- package/src/hub/routing.ts +24 -14
- package/src/hub/settings.ts +1 -1
- package/src/hub/task-repository.ts +136 -0
- package/src/hub/tasks.ts +101 -21
- package/src/hub/terminal-launch.ts +130 -0
- package/src/hub/usage.ts +44 -18
- package/src/models/route/config.ts +1 -1
- package/src/omniroute/client.ts +7 -19
- package/templates/AGENTS.block.md +1 -0
- package/templates/routing.toml +10 -44
- package/src/switchyard/config.ts +0 -45
- package/src/switchyard/sidecar.ts +0 -136
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.40 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
|
|
@@ -32,9 +32,27 @@ Person verdicts and user-authored workflow writes are not delegated. Dashboard
|
|
|
32
32
|
sessions issued through the flag retain operational controls but refuse message
|
|
33
33
|
and task/planning content writes. Use native peer tools for agent-authored work.
|
|
34
34
|
|
|
35
|
-
Use a CLI/coordinator containing this feature throughout the experiment.
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
Use a CLI/coordinator containing this feature throughout the experiment. Ordinary
|
|
36
|
+
delegation requires `cli_audit_delegated` in the authenticated running daemon's
|
|
37
|
+
welcome, rather than its protocol number or disk status. Execution reuses that
|
|
38
|
+
connection; all helper connections are pinned to its authenticated instance, and
|
|
39
|
+
local commands check that instance before dispatch. Replacement control
|
|
40
|
+
connections refuse. Before effects, the same daemon must acknowledge the exact
|
|
41
|
+
audit UUID after successfully appending its event; a feature claim or spool write
|
|
42
|
+
alone is insufficient. That retained event survives later consumer replacement,
|
|
43
|
+
including a delayed local setup confirmation. Missing or unavailable
|
|
44
|
+
support refuses before command effects with an upgrade remedy; its refused audit
|
|
45
|
+
uses an outcome older consumers retain. The private pending audit is reserved
|
|
46
|
+
before connecting, so an unavailable outbox still refuses before any connection.
|
|
47
|
+
Upgrade/recovery uses a compatible `run` spool row and stores the authoritative
|
|
48
|
+
delegation in the operation's `delegatedAudits`: peer, closed command label,
|
|
49
|
+
timestamp and operation id. Creation, resume handoff, runner, abort and disposal
|
|
50
|
+
persist this evidence before runtime/target effects, independently of the source
|
|
51
|
+
daemon's drain. Schema-1 receipts retain it through source replacement and resume;
|
|
52
|
+
stored evidence never grants a later invocation authority. The journal is capped
|
|
53
|
+
at 256 entries and refuses further delegated attempts rather than evicting its
|
|
54
|
+
initiator. Local bootstrap commands with no daemon manifest use the compatible
|
|
55
|
+
`run` row too. This policy does not
|
|
38
56
|
change external computer-use restrictions. Recovery staging refuses old targets
|
|
39
57
|
without live-test support before source effects. Delegated headless recovery restores through the ordinary target CLI, carrying
|
|
40
58
|
its operationId on the delegated console connection; existing native ownership
|
|
@@ -195,7 +213,7 @@ In Tasks, `a` assigns the owner in ordinary open states and the reviewer in
|
|
|
195
213
|
the corresponding role, and `r` reviews only in `in_review`. In Queue, `r`
|
|
196
214
|
prefills `discard` for a queued row and `retry` for a needs_review row, with the
|
|
197
215
|
action still editable before confirmation. `completed` is never the default.
|
|
198
|
-
Status, console notices and `route explain` show every held row with its id, sender, kind and age. The hub completes rows made entirely of superseded hub workflow notices or presence items, recording an ids-only reason and the hub actor. Mixed messages, live
|
|
216
|
+
Status, console notices and `route explain` show every held row with its id, sender, kind and age. The hub completes rows made entirely of superseded hub workflow notices or presence items, recording an ids-only reason and the hub actor. An owner task offer with its structured offer marker also settles when the recipient still owns the task, has reached in-progress, in-review or changes-requested state, and its own acceptance follows the last ownership change. A person's acceptance and an unread replacement-owner offer do not count; missing or older-than-4096-entry proof keeps the hold. This runs on hold entry, hub startup, recovery release and task changes, with an ids-only accepted-task reason and the hub actor; it is a disposition, never proof that the offer was read. Mixed messages, unaccepted offers, unmarked live reminders and unknown references remain held. A requested-stop hold still needs the person. A Claude session without channel support safely returns unseen pushes for `hub_inbox`; a thrown notification write remains uncertain.
|
|
199
217
|
|
|
200
218
|
Claude channel/pull sessions, Codex and Pi may call `hub_delivery_retry { delivery_id }` for their own
|
|
201
219
|
`needs_review` row once. Its tool results show held-row count, ids, senders,
|
|
@@ -783,13 +801,21 @@ A class can carry a completion check in `.agenthub/config.json`, for example
|
|
|
783
801
|
`"checks": { "implement": "scripts/check.sh", "timeout_s": 600 }`. When the owner
|
|
784
802
|
marks such a task done, the tool answers at once, the hub runs the command in the
|
|
785
803
|
project root (one at a time; what it left in its process group is killed when it
|
|
786
|
-
exits, at the timeout or on shutdown
|
|
804
|
+
exits, at the timeout or on shutdown, and a check killed at its timeout or on
|
|
805
|
+
shutdown settles within one second even if its exit is never reported), and then either
|
|
787
806
|
sends the task to review with the command, exit code and output tail, or keeps it
|
|
788
807
|
with its owner and tells it what failed. `checks` is machine-local (see Install
|
|
789
808
|
and start): a committed file must not choose commands the hub runs. Keys that
|
|
790
809
|
are not task classes are ignored with a log line. A hub stopped mid-check leaves
|
|
791
810
|
the task in progress (`check interrupted`); the owner marks it done again.
|
|
792
811
|
|
|
812
|
+
While the project root checkout is on a branch other than its default
|
|
813
|
+
(`origin/HEAD`, else `main`), finishing a task adds `the main checkout is on
|
|
814
|
+
<branch>; move the work to a worktree under .worktrees/` to the owner's result
|
|
815
|
+
and the reviewer's request, and `ahub status` shows it as `main checkout`
|
|
816
|
+
(#572). It is advice only. A branch name that fails the hub's public-text screen
|
|
817
|
+
is withheld from the sentence.
|
|
818
|
+
|
|
793
819
|
A task reaching `approved` is a board transition. It is not proof that an
|
|
794
820
|
external side effect happened unless the task's refs and a live readback show
|
|
795
821
|
that effect. After `tasks.escalate_after` consecutive `changes_requested` verdicts
|
|
@@ -832,7 +858,12 @@ open tasks on the same paths or symbols get a message with the changed files,
|
|
|
832
858
|
the plan's signatures and the first line of the summary, each left out when it
|
|
833
859
|
matches a PII pattern (the summary also when `signals.pii_screen = "local"` did
|
|
834
860
|
not clear it); nobody else does. PII
|
|
835
|
-
tasks are left out on both sides.
|
|
861
|
+
tasks are left out on both sides. Overlap is compared only between tasks in the
|
|
862
|
+
same repository (#476): a task's repository is its `refs.repo` (an `owner/name`
|
|
863
|
+
slug or a checkout path, accepted by `hub_task_propose` and `hub_task_accept`),
|
|
864
|
+
else the common git top-level (or common parent) of its absolute paths outside
|
|
865
|
+
the project, else the project. A board with one repository behaves as before. `refs.repo` is metadata
|
|
866
|
+
only: it grants no file access and changes no execution root.
|
|
836
867
|
|
|
837
868
|
A task can wait for others: `hub_task_propose` takes `after: [ids]` (`ahub task
|
|
838
869
|
propose ... --after <id>`). Until every one of them is approved, the task is
|
|
@@ -858,7 +889,10 @@ reservation was passed over and why, and the assignment's history note keeps
|
|
|
858
889
|
it, unless it is no news (the reserved peer is the owner the task moves away
|
|
859
890
|
from, or it already refused the task). A peer the task was declined for (by
|
|
860
891
|
itself or by the console) or escalated away from after repeated
|
|
861
|
-
changes_requested or by hand stays excluded on every later reroute
|
|
892
|
+
changes_requested or by hand stays excluded on every later reroute. A decline
|
|
893
|
+
with `capacity: true` (`hub_task_decline`, "no room right now") is the
|
|
894
|
+
exception: it skips that owner for this move only, and a later reroute or
|
|
895
|
+
planner pull may offer the task to it again (#531). An owner
|
|
862
896
|
released as gone, or moved by the hub after a failed delivery or inference, is
|
|
863
897
|
excluded only from that move and may get the task again from its reservation
|
|
864
898
|
later. Your own `ahub task assign` is not blocked by those exclusions, and it
|
|
@@ -979,7 +1013,7 @@ Run `ahub memory profile-check [--json]` from the person's terminal for the read
|
|
|
979
1013
|
|
|
980
1014
|
Before real migration, first upgrade every hub sharing the home to 0.12.30 or later. Obtain positive ready or unbound/quiesced receipts in every relevant registry; then quiesce consumers and close bound handles before changing the selector. A matching ready handle proves compatibility but is still an open handle. Verify synthetic cross-writes before the separately approved real migration, then reopen through the supported session-preserving lifecycle afterward. Merely installing this release does not authorize migration or provide live capture/device-sync evidence.
|
|
981
1015
|
|
|
982
|
-
A curated split (`amem migrate --shards`) writes `M/shards.json`; from 0.12.37 the hub then opens this project's shard, with the user shard as its overlay, under the alias-resolved project key the `amem` CLI binds (#534, #537). Before splitting, upgrade or stop every hub using the home: a hub on 0.12.36 or earlier does not detect the split and keeps writing the old layout, which reaches the shards only through `amem migrate --shards --resume`. A split that is not active (captured, malformed, or a dangling or unreadable `shards.json`) makes native memory unavailable with that resume command as the remedy. An `amem alias add` that remaps a running hub's key latches its memory unavailable until a restart. `ahub memory profile-check` is
|
|
1016
|
+
A curated split (`amem migrate --shards`) writes `M/shards.json`; from 0.12.37 the hub then opens this project's shard, with the user shard as its overlay, under the alias-resolved project key the `amem` CLI binds (#534, #537). Before splitting, upgrade or stop every hub using the home: a hub on 0.12.36 or earlier does not detect the split and keeps writing the old layout, which reaches the shards only through `amem migrate --shards --resume`. A split that is not active (captured, malformed, or a dangling or unreadable `shards.json`) makes native memory unavailable with that resume command as the remedy. An `amem alias add` that remaps a running hub's key latches its memory unavailable until a restart. `ahub memory profile-check` is split-aware: each running hub is compared with the shard profile of its own project, and an inactive split reports that resume command (#536). See [the shard binding](memory.md#selected-memory-profile).
|
|
983
1017
|
|
|
984
1018
|
Managed agents read through `hub_memory_search`, `hub_memory_show` and `hub_memory_graph`, with the server's project identity, the `memory_read` capability and current privacy screening. They cannot supply another project; private turns are refused. The tools bound UTF-8 input/output, screen before counts and truncation, and exclude their arguments/results from hub-managed capture. `hub_memory_correct` has its own `memory_correct` capability and records a screened correction candidate, not a note change. See [the complete memory contract](memory.md) for caps and refusal semantics.
|
|
985
1019
|
|
|
@@ -1512,7 +1546,7 @@ A guarded file edit that the daemon keeps at its accepted value remains visible
|
|
|
1512
1546
|
watcher cannot adopt unrelated raising local edits. A settings session cannot
|
|
1513
1547
|
adopt routing fields outside its editable registry. Existing confirmation and
|
|
1514
1548
|
roster lifecycle fences remain; use the confirmed roster setting for membership.
|
|
1515
|
-
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
|
|
1549
|
+
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 changes apply at the next peer creation.
|
|
1516
1550
|
|
|
1517
1551
|
- Runtime/client ownership still requires restart for memory handles and sync,
|
|
1518
1552
|
gateway/MLX, runner/check commands, profile/tool contracts, converters, existing
|
|
@@ -1794,6 +1828,27 @@ but cannot show pushes, so it attaches tools-only (protocol 16, issue #205):
|
|
|
1794
1828
|
started while an `ahub claude` session holds the peer stands by and attaches
|
|
1795
1829
|
only after that session leaves.
|
|
1796
1830
|
|
|
1831
|
+
When a hub reconnect changes the hub tools (names or schemas), the plugin asks
|
|
1832
|
+
Claude Code to list them again (`tools/list_changed`), so a session that listed
|
|
1833
|
+
them while the hub was down does not keep the short list (#490). A status probe
|
|
1834
|
+
that is unavailable right after a restart is retried, then the list is
|
|
1835
|
+
announced anyway.
|
|
1836
|
+
|
|
1837
|
+
### Replaced or ended Claude sessions (#551)
|
|
1838
|
+
|
|
1839
|
+
A replaced session says it is standing by. Its reconnect requests cannot reclaim
|
|
1840
|
+
an attached or claiming peer, even if its status-file read missed that holder. A
|
|
1841
|
+
channel-capable session may still replace a pull-only holder once its claim has
|
|
1842
|
+
finished. Starting a new session intentionally keeps the newest-hello behavior.
|
|
1843
|
+
|
|
1844
|
+
A plugin carrying an older launch id than this daemon's current per-peer Claude
|
|
1845
|
+
launch is refused with close 4430. It stops reconnecting, and hub tools report that
|
|
1846
|
+
the launch ended. Start a new session with `ahub claude`, or use a plain session
|
|
1847
|
+
with the tools and `hub_inbox`. A session with no launch id, or a hub with no
|
|
1848
|
+
current launch record, keeps the existing behavior. The marker alone cannot
|
|
1849
|
+
prove that a nested host loaded this specific MCP server as a channel; the
|
|
1850
|
+
bridge currently receives no positive per-server activation signal.
|
|
1851
|
+
|
|
1797
1852
|
### Claude channel sessions while busy (#493)
|
|
1798
1853
|
|
|
1799
1854
|
A Claude session started with `ahub claude` receives pushes when it is idle. While it is busy:
|
|
@@ -1802,7 +1857,7 @@ A Claude session started with `ahub claude` receives pushes when it is idle. Whi
|
|
|
1802
1857
|
- `hub_inbox` reads the daemon queue (and any local failed-push buffer) in a channel session too. A read is one `completed` delivery, like a tools-only read; holds refuse it the same way.
|
|
1803
1858
|
- An important message is pushed into the running turn (steered) instead of waiting for the turn to end. Mid-turn reading was verified on Claude Code 2.1.302; an older client that drops it leaves the delivery `accepted` until a person resolves it. Ordinary messages still wait for the idle push or `hub_inbox`.
|
|
1804
1859
|
- Do not use `[FYI]` for PR ready, done, submitted, ruling-needed, blocker or changed-contract messages: they need action. `hub_task_done` and `hub_review` already notify their recipients.
|
|
1805
|
-
- Turn completion is read
|
|
1860
|
+
- Turn completion is read backwards in 4 MiB chunks, up to 64 MiB plus one row-boundary byte, whatever the transcript's size. A row crossing chunks is reconstructed whole; a row starting outside the bound stays unavailable. When no completed turn is found within that bound, the console says once per turn that the peer stays busy and its messages wait in its queue (#517).
|
|
1806
1861
|
|
|
1807
1862
|
## Graceful shutdown
|
|
1808
1863
|
|
|
@@ -1989,21 +2044,21 @@ section is what they run.
|
|
|
1989
2044
|
|
|
1990
2045
|
Upgrade running projects with the target release's own coordinator. It accepts
|
|
1991
2046
|
a running source on control protocol 9 (0.6.x), 10 (0.7.0 through 0.12.0),
|
|
1992
|
-
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.
|
|
2047
|
+
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.40), and only
|
|
1993
2048
|
a target on its own protocol, so the target's coordinator fits every supported
|
|
1994
2049
|
source and carries every recovery fix released up to it. Protocol 8 and older
|
|
1995
2050
|
(0.5.x and earlier) are refused as `manual-bootstrap-required`. Run from the
|
|
1996
2051
|
project directory, without replacing the global CLI first:
|
|
1997
2052
|
|
|
1998
2053
|
```bash
|
|
1999
|
-
bunx --package @staix/agent-hub@0.12.
|
|
2000
|
-
bunx --package @staix/agent-hub@0.12.
|
|
2054
|
+
bunx --package @staix/agent-hub@0.12.40 ahub upgrade --to 0.12.40 --dry-run
|
|
2055
|
+
bunx --package @staix/agent-hub@0.12.40 ahub upgrade --to 0.12.40 --yes
|
|
2001
2056
|
```
|
|
2002
2057
|
|
|
2003
2058
|
| Running now | Coordinator to use |
|
|
2004
2059
|
| --- | --- |
|
|
2005
2060
|
| 0.6.x (protocol 9) | the target's, through `bunx` as above |
|
|
2006
|
-
| 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.
|
|
2061
|
+
| 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.40 (protocol 16) | the target's, through `bunx` as above |
|
|
2007
2062
|
| any supported source, with the installed CLI already at the target | `ahub upgrade` below, which is the same coordinator |
|
|
2008
2063
|
| 0.5.x or earlier (protocol 8 and older) | not supported: bootstrap by hand with the matching CLI |
|
|
2009
2064
|
|
|
@@ -2035,14 +2090,14 @@ projects first:
|
|
|
2035
2090
|
|
|
2036
2091
|
```bash
|
|
2037
2092
|
ahub restart --dry-run
|
|
2038
|
-
ahub upgrade --to 0.12.
|
|
2093
|
+
ahub upgrade --to 0.12.40 --dry-run
|
|
2039
2094
|
```
|
|
2040
2095
|
|
|
2041
2096
|
Apply only after reviewing the plan:
|
|
2042
2097
|
|
|
2043
2098
|
```bash
|
|
2044
2099
|
ahub restart --yes
|
|
2045
|
-
ahub upgrade --to 0.12.
|
|
2100
|
+
ahub upgrade --to 0.12.40 --yes
|
|
2046
2101
|
ahub recovery status [<operation-id>]
|
|
2047
2102
|
ahub recovery resume [<operation-id>]
|
|
2048
2103
|
ahub recovery abort [<operation-id>]
|
|
@@ -2282,6 +2337,35 @@ Ending a peer's running turn is not part of these screens: finish or interrupt
|
|
|
2282
2337
|
it in that peer's terminal, answer approvals with `ahub permit` or the console,
|
|
2283
2338
|
or cancel and upgrade later.
|
|
2284
2339
|
|
|
2340
|
+
Terminal recovery records a launch only after that native session owns the peer
|
|
2341
|
+
(#482). Capturing an Orca terminal or receiving `start: ok` creates only a pending
|
|
2342
|
+
candidate; a second launcher that exits or is refused cannot replace the live
|
|
2343
|
+
owner's row. A running hub without `terminal_owner` support leaves the new launch
|
|
2344
|
+
unrecorded and prints an upgrade remedy. The plan names an attached native TUI
|
|
2345
|
+
without a live launcher or exact Orca session proof as `attached, launcher
|
|
2346
|
+
unrecorded`: end it in its terminal or use its native resume flow in an Orca
|
|
2347
|
+
terminal, then refresh the plan. Plain Claude's same-protocol reconnect-only
|
|
2348
|
+
session still reconnects by itself without a terminal restart.
|
|
2349
|
+
|
|
2350
|
+
Background Orca identity reads are limited to 30 seconds and 1 MiB of output.
|
|
2351
|
+
Shutdown cancels their owned query process groups and waits for reconciliation.
|
|
2352
|
+
A query whose termination cannot be confirmed is logged as incomplete; the
|
|
2353
|
+
remaining peer and daemon teardown still runs. Native terminal execution keeps
|
|
2354
|
+
its foreground TTY behavior. Unknown terminal evidence is shown as unverified
|
|
2355
|
+
ownership, with end or native resume guidance.
|
|
2356
|
+
|
|
2357
|
+
An Orca pane that is orphaned but still connected needs reattachment, not turn
|
|
2358
|
+
cancellation: run `orca terminal switch --terminal <handle>` yourself, then refresh.
|
|
2359
|
+
The coordinator never switches panes. Such a pane is not evidence that its native
|
|
2360
|
+
process ended and never authorizes a duplicate restore. Disconnected terminals
|
|
2361
|
+
keep their existing guidance.
|
|
2362
|
+
|
|
2363
|
+
The ledger retains historical and invalid rows; it does not prune them on launch.
|
|
2364
|
+
Only this project, current daemon instance and peer can supply ownership evidence,
|
|
2365
|
+
and a successful publication replaces only its matching valid row. Old-instance
|
|
2366
|
+
rows cannot claim the current terminal. Older binaries that directly write
|
|
2367
|
+
`terminal-recovery.json` are outside the new writer guarantee.
|
|
2368
|
+
|
|
2285
2369
|
### A partial operation
|
|
2286
2370
|
|
|
2287
2371
|
`ahub recovery status <operation-id>` reads the receipt without changing it:
|
|
@@ -2610,10 +2694,38 @@ config with `provider: "legacy"`; Ollama errors never launch Python.
|
|
|
2610
2694
|
|
|
2611
2695
|
### In-process model routes
|
|
2612
2696
|
|
|
2613
|
-
`routing.toml` supports `[hub_routes."hub/<id>"]
|
|
2614
|
-
|
|
2615
|
-
|
|
2616
|
-
|
|
2697
|
+
`routing.toml` supports in-process `[hub_routes."hub/<id>"]`.
|
|
2698
|
+
A task uses a hub route when `[local] route` or its class's `route` names one.
|
|
2699
|
+
A new `routing.toml` from `ahub init` sets `[local]` and `implement` to `hub/stage`
|
|
2700
|
+
(fixed model `coding` as the fallback) and gives the lighter classes
|
|
2701
|
+
`fixed_model = "fast"`. The shipped examples use OmniRoute `fast` and `coding`; `fixed_model` remains the fallback.
|
|
2702
|
+
`--model` pins the worker and bypasses route selection. A class with `fixed_model`
|
|
2703
|
+
and no `route` also calls that alias directly, even when `[local]` names a route.
|
|
2704
|
+
|
|
2705
|
+
The Switchyard sidecar is retired (#553). No binary or generated model-router
|
|
2706
|
+
config is used, and its reserved port offset remains unused. Existing `[targets]`
|
|
2707
|
+
and `[routes]` tables are ignored and listed as retired settings in startup logs
|
|
2708
|
+
and doctor. Every route without the `hub/` prefix, including named legacy routes
|
|
2709
|
+
and `sy/` selections, uses the fixed alias with one warning. Loading or reloading
|
|
2710
|
+
never rewrites the operator's routing files.
|
|
2711
|
+
|
|
2712
|
+
Migrate the retired settings as follows:
|
|
2713
|
+
|
|
2714
|
+
| Retired setting or route | In-process replacement |
|
|
2715
|
+
| --- | --- |
|
|
2716
|
+
| `stage_router` | `[hub_routes."hub/<id>"]` with `type = "stage"`; select it with `route = "hub/<id>"` |
|
|
2717
|
+
| `efficient_target` / `capable_target` | Put the targets' model aliases in `efficient` / `capable` |
|
|
2718
|
+
| `confidence_threshold` | Keep the same value on the hub stage route |
|
|
2719
|
+
| Passthrough class route | Put its target model alias in the class's `fixed_model` and remove the class's `route` |
|
|
2720
|
+
| Former unshipped classifier escalation | Use the existing hub `escalation` policy |
|
|
2721
|
+
| `[targets]` / `[routes]` | Remove these retired tables after migrating their selections |
|
|
2722
|
+
|
|
2723
|
+
Doctor inventories all local/class fixed aliases and effective efficient/capable/judge aliases, reporting
|
|
2724
|
+
each missing alias once or aggregate success when all are served. A
|
|
2725
|
+
`routing.toml` or `routing.local.toml` that does not parse gets its own `routing`
|
|
2726
|
+
row naming the file and the parse error, without the file's contents, and the
|
|
2727
|
+
alias check is skipped (#563). Hub summaries
|
|
2728
|
+
and triage use their fixed model directly.
|
|
2617
2729
|
|
|
2618
2730
|
Route types: `stage` scores recent tools and holds capable recovery for two calls;
|
|
2619
2731
|
`plan_execute` plans on capable until the first mutation and then stays efficient;
|
|
@@ -3104,9 +3216,15 @@ Qwen controlled recovery and automatic crash resume load the recorded conversati
|
|
|
3104
3216
|
|
|
3105
3217
|
Use `ahub roster add jcode`, then `ahub jcode [--model <alias>] [--provider-profile <name>]`. It opens the native TUI attached to the hub-owned ACP session by default. Use `--mode headless` or `ahub settings set peers.jcode.start_mode headless` to keep headless startup. The launcher reads roster membership from the hub's status reply; a hub older than 0.12.35 does not send it, so the launcher stops with an upgrade-or-restart remedy and starts nothing (#484). The person launcher configures only agent-hub-jcode in .jcode/mcp.json; run ahub init afterwards to ignore the untracked machine-path file. It writes the plugin bundle the running hub reports in `status`, so a CLI from another install no longer leaves a stale entry; `ahub kimi` does the same for Kimi's TUI entry (#502). Conductor/dashboard starts read that entry without editing it. Preview starts nothing, and ahub stop jcode stops only the owned private daemon/ACP groups. jcode_cmd, jcode_home and jcode_provider_profile are machine-local and never editable from settings.
|
|
3106
3218
|
|
|
3107
|
-
The native TUI opens only after Jcode has saved the selected session. On 0.98.1, `session/new` does not save it; the first real hub turn does. The launcher prints `jcode's TUI opens after its first hub turn; send it work, or Ctrl-C` once and waits for the same owned launch's saved session. Send Jcode work from the hub, or press Ctrl-C to end only the wait. No artificial prompt is sent. A console
|
|
3219
|
+
The native TUI opens only after Jcode has saved the selected session. On 0.98.1, `session/new` does not save it; the first real hub turn does. The launcher prints `jcode's TUI opens after its first hub turn; send it work, or Ctrl-C` once and waits for the same owned launch's saved session. Send Jcode work from the hub, or press Ctrl-C to end only the wait. No artificial prompt is sent. A console `peer_start` uses a terminal provider to run the same launcher, even while ACP is running; a conductor or dashboard start of an attached Jcode answers `already` and opens nothing (#559). Without a provider, run its displayed command in your own terminal. Options with no terminal need that manual path.
|
|
3220
|
+
|
|
3221
|
+
`ahub jcode --dry-run` stays pure and redacted. A person's `--print-command` can show the actual top-level native argv and closed native environment for an already-saved running session; it starts nothing, and like the launch it names a `--model`, `--provider-profile` or `--session-id` that differs from the running session (#574). The private socket/session tuple is not returned to hub tools or status. Native saved-session evidence is read-only and capped at 32 MiB; unsafe, mismatched or larger evidence refuses the TUI launch.
|
|
3222
|
+
|
|
3223
|
+
A busy jcode takes an `important` message into its running turn (#572): the hub sends it as a soft interrupt through jcode's own private server socket, which jcode injects at its next tool boundary, so the message no longer waits for the turn to end. The hub never cancels a turn to deliver. Headless Kimi and Qwen have no such path: an `important` message waits, and `ahub status` and the console show `important messages waiting on a busy ACP peer for N min` once it has waited past `budget.stale_min`, so you can decide to stop the peer.
|
|
3224
|
+
|
|
3225
|
+
jcode has no switch to choose which MCP servers its `serve` and `acp` load, so the hub-owned jcode starts every server named in `<JCODE_HOME>/mcp.json` and the project's `.jcode/mcp.json`, `.mcp.json` and `.claude/mcp.json`, besides the hub's own (#572). `ahub doctor` lists their names in its `jcode MCP servers` row (names only, from those four files only). To keep a server out, remove it from those files, or point `jcode_home` at a separate home.
|
|
3108
3226
|
|
|
3109
|
-
|
|
3227
|
+
Known ceiling (#559): jcode 0.98.1's top-level TUI spawns a shared server, without `--temporary-server` or `--owner-pid`, when nothing answers on the dialed socket at startup or on its reload-handoff reconnect, and no native flag prevents it. A hub stop or an owned-server crash between the launcher's confirm and the TUI's check can leave an unowned jcode server on the private socket under the person's `JCODE_HOME`; stop it by hand. Revisit if upstream adds an owner flag. An option that differs from the running session (`--model`, `--provider-profile`, `--session-id`) is refused by name.
|
|
3110
3228
|
|
|
3111
3229
|
TUI input may interleave with an ACP turn; there is no single-writer guard. Closing the TUI leaves the owned ACP session running, and native policy remains unmanaged. The isolated 0.98.1 transport receipt is [recorded separately](verification/2026-10-20-jcode-tui-0.98.1.md); it is not personal account or real provider verification.
|
|
3112
3230
|
|
|
@@ -3410,10 +3528,16 @@ built-ins and off for the current console only. `?` lists this under Pet, even
|
|
|
3410
3528
|
while drawing is off. The command prompt keeps its original row and width.
|
|
3411
3529
|
|
|
3412
3530
|
`pet.glyphs` selects auto/ascii/blocks; unsupported locales and dumb/linux
|
|
3413
|
-
terminals retain the ASCII floor. `pet.blink:false` is static.
|
|
3414
|
-
|
|
3415
|
-
|
|
3416
|
-
|
|
3531
|
+
terminals retain the ASCII floor. `pet.blink:false` is static. `pet.palette`
|
|
3532
|
+
selects blue, teal (default), violet or ochre (`a`/`b`/`c`/`d`), and `pet.window`
|
|
3533
|
+
controls standalone window opt-in; both `pet` (`false` or an option block) and its
|
|
3534
|
+
fields validate identically at startup and reload in `.agenthub/config.json` and
|
|
3535
|
+
`.agenthub/config.local.json`, apply live as console-local presentation (including
|
|
3536
|
+
an open console's next refresh and the standalone pet window), and grant no
|
|
3537
|
+
authority (#483). Neither
|
|
3538
|
+
choosing nor drawing a character changes authority, config files, task state or
|
|
3539
|
+
polling. Explicit `ahub pet` and text status use the configured line face; prompt
|
|
3540
|
+
tokens remain character-independent. Native glyph width and tmux are unverified.
|
|
3417
3541
|
|
|
3418
3542
|
## Dashboard views and attention (#391, replaces the #280 in-page character)
|
|
3419
3543
|
|
|
@@ -3466,7 +3590,7 @@ a fresh peer status read on the same authenticated connection.
|
|
|
3466
3590
|
|
|
3467
3591
|
Integer WIP editors save a value, including zero and inheritance; it applies at the next admission. GitHub intake accepts dot-prefixed repository names within the existing bounded owner/repository identity. Split undo also refuses children referenced by another task's persisted phase checklist.
|
|
3468
3592
|
|
|
3469
|
-
Declining rework returns changes_requested to To Do before rerouting. When a planner-pulled task has no eligible destination capacity, it remains ownerless in To Do and is retried after capacity clears, preserving the declined-owner exclusion.
|
|
3593
|
+
Declining rework returns changes_requested to To Do before rerouting. When a planner-pulled task has no eligible destination capacity, it remains ownerless in To Do and is retried after capacity clears, preserving the declined-owner exclusion. A planner pull that finds no owner names the cause by peer id: a lasting exclusion, WIP full (with wip/limit), a held queue or needs_review deliveries; a capacity-only decline is not an exclusion (#531).
|
|
3470
3594
|
|
|
3471
3595
|
With no release cut, outside approved tasks are reported under unknown cut evidence, including tasks with a known approval time. A child task execution budget also prevents split undo until the person disables that budget.
|
|
3472
3596
|
|
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.40
|
|
21
21
|
ahub setup
|
|
22
22
|
```
|
|
23
23
|
|
|
@@ -30,9 +30,23 @@ 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.40
|
|
34
|
+
|
|
35
|
+
Restart Claude sessions after upgrading: each keeps the plugin server it started with until restarted, so a restart loads the 0.12.40 plugin. That plugin asks Claude Code to list the hub tools again when a hub reconnect changes them (#490), and one from an older `ahub claude` launch is refused and stops reconnecting instead of reclaiming the peer (#551).
|
|
36
|
+
|
|
37
|
+
`ahub jcode` opens its TUI again; on 0.12.39 it stopped after the first hub turn (#564). A busy Jcode now takes an `important` message into its running turn (#572), and `ahub doctor` lists the extra MCP servers the hub-owned Jcode loads from its config files. See [Jcode operations](operations.md#optional-jcode-peer).
|
|
38
|
+
|
|
39
|
+
The Switchyard sidecar is retired (#553). An existing `routing.toml` keeps working: its `[targets]` and `[routes]` tables are ignored and reported as retired settings, and a route without the `hub/` prefix (such as `sy/coding`) uses the fixed model with one warning. Migrate with the table in [in-process model routes](operations.md#in-process-model-routes); the hub never rewrites the file.
|
|
40
|
+
|
|
41
|
+
Run `ahub init` once per project to refresh the hub block in `AGENTS.md`: it adds the line that tells agents to report a pushed PR with `hub_task_done` and end the turn instead of waiting for CI (#572). Finishing a task now also says when the project root checkout is on a branch other than its default.
|
|
34
42
|
|
|
35
|
-
|
|
43
|
+
`hub_task_decline` takes `capacity: true` for "no room right now", which does not exclude the owner for good (#531). Task overlap compares only tasks in the same repository; set `refs.repo` on `hub_task_propose` or `hub_task_accept` for work in another repository (#476). Pi and the local worker report a reply stopped by the hop cap as not delivered (#550).
|
|
44
|
+
|
|
45
|
+
Live-test delegated CLI commands and terminal-recovery launch records need the upgraded daemon (`cli_audit_delegated`, `terminal_owner`): against an older running hub the first refuses with an upgrade remedy and the second leaves the launch unrecorded, so upgrade running hubs with `ahub upgrade` (#410, #482).
|
|
46
|
+
|
|
47
|
+
Upgrading from 0.12.38 or earlier, the 0.12.39 notes below also apply.
|
|
48
|
+
|
|
49
|
+
## Upgrading to 0.12.39
|
|
36
50
|
|
|
37
51
|
`ahub jcode` now opens Jcode's native TUI on the hub-owned ACP session by default (#464). The TUI opens after Jcode's first hub turn saves the session; until then the launcher prints one waiting line, and Ctrl-C ends only the wait. Hub-made starts (the dashboard's Start control, the conductor's `hub_peer_start`) follow the start mode too, so they open a terminal for Jcode through a terminal provider. To keep the old headless default, run `ahub settings set peers.jcode.start_mode headless`, or pass `--mode headless`. See [Jcode operations](operations.md#optional-jcode-peer).
|
|
38
52
|
|
|
@@ -52,7 +66,7 @@ The restarted Claude planner gets the release-train tools (`hub_release_new`, `h
|
|
|
52
66
|
|
|
53
67
|
Jcode must be 0.98.0 or later, below 1.0.0; 0.94.0 is no longer accepted, so `ahub doctor` fails its Jcode row for an older install and the peer does not start (#529). Every owned jcode process runs with `JCODE_NO_TELEMETRY=1`.
|
|
54
68
|
|
|
55
|
-
Since 0.12.37 the hub pins `@staix/agent-mem` 0.4.0 and opens a split memory home through its shards (#534). Before anyone runs `amem migrate --shards` on a memory home, every hub using that home must run 0.12.37 or later: an older hub does not see the split and keeps writing the old layout. `ahub memory profile-check` is
|
|
69
|
+
Since 0.12.37 the hub pins `@staix/agent-mem` 0.4.0 and opens a split memory home through its shards (#534). Before anyone runs `amem migrate --shards` on a memory home, every hub using that home must run 0.12.37 or later: an older hub does not see the split and keeps writing the old layout. `ahub memory profile-check` is split-aware and compares each hub with its own project's shard (#536). See [memory profiles and rollout](memory.md#selected-memory-profile).
|
|
56
70
|
|
|
57
71
|
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:
|
|
58
72
|
|
|
@@ -94,7 +108,7 @@ ahub say @kimi "run the tests and report" # one peer
|
|
|
94
108
|
{ "omniroute": { "urls": ["http://your-gateway:20128/v1"], "api_key_file": "/path/to/key" } }
|
|
95
109
|
```
|
|
96
110
|
|
|
97
|
-
or set `OMNIROUTE_API_KEY`.
|
|
111
|
+
or set `OMNIROUTE_API_KEY`. The `.agenthub/routing.toml` that `ahub init` writes asks the gateway for the model aliases `fast` and `coding` (the in-process `hub/stage` route, with `[local] fixed_model` as its fallback); serve those aliases or name yours there, and `ahub doctor` lists any alias the gateway does not serve. Then `ahub local`. It works only inside the project, asks before it writes or runs anything (`ahub permit <id> allow`) unless you chose a permission mode for it (`ahub permission`), and everything it executes is sandboxed. Keep `ahub console` open while it works: a request nobody answers expires, and after two in a row its turn ends.
|
|
98
112
|
|
|
99
113
|
## Commands of a working day
|
|
100
114
|
|
package/docs/security.md
CHANGED
|
@@ -18,7 +18,7 @@ agent-hub connects agents that can each run commands. This page says what the hu
|
|
|
18
18
|
- **PII has an enforced path.** A task matching `signals.pii_patterns` goes to `local` or to nobody; its text is absent from other peers' envelopes, the console stream, the log and the board listing; the console user reviews it; `local` answers such a turn to the console only, keeps it out of its history, refuses it when the only gateway is off campus, and may not save notes or spin off tasks during it. Nothing about it is sent to claude-mem, whose observer is a cloud model.
|
|
19
19
|
- **A model screen can add to the patterns (issue #198).** With `signals.pii_screen = "local"` in `routing.toml` (default `off`; it applies while `constraints.pii = "local_only"`), a newly proposed task is read by a model before the hub does anything else with it: until the verdict it is on no board, in no envelope, before no triage model, and the hub makes no brief or note call for it. The local worker's claude-mem capture leaves its hub tool calls out (issue #230), so a proposal it makes in an ordinary turn cannot reach claude-mem ahead of the verdict that way. The screen runs on the model on this machine (MLX or Ollama, loopback only) or, without one, on the gateway only while `onCampus()` holds, and the gateway call is refused once more right before transport if the gateway is behind Access; task text never goes off campus to be screened. When the on-device generation slot is taken (Pi generating, another screen), the screen goes to the campus gateway instead of waiting, and on campus a device that fails or is still loading after 60% of the deadline hands over to the gateway too; off campus it waits for the slot and the device within the deadline. With the legacy MLX provider the screen may start an `mlx_lm.server`, as Pi's relay does, and it stays running until `ahub models stop`. Its answer is `pii` or `clear` plus a category from a closed list (name, student id, phone, address, grade, health, other). Anything else, a timeout (8 s, one call and one generation slot per item), a missing or off-campus model, or text longer than 6000 UTF-8 bytes (about 2000 Hangul syllables) is `unknown`, and an unknown task is a PII task: this is the hub's one model call that fails closed, so with the screener down every new task waits for `local`. An unknown verdict has the costs of any PII task, even when a second look clears it later: opening it lifts every silent turn-free cohort for good and turns facts off while it is open, and off campus a proposal without a class is refused (triage is not asked for a PII task there), with an error that says so. Off campus with the on-device slot taken, a task stays `unknown` until it is screened again: while it is still proposed and no peer ever owned it, the hub's release timer (every 60 s, one task at a time, the least tried first, at most 10 times per task in a hub run; never text too long to read) asks again, and `clear` lifts its `pii` signal and routes it through the class peers (a named owner is not remembered; a reserved one is offered first, as always). A task `local` took keeps its PII path, also once it is declined back to nobody. A pattern match is PII without a call. The task's history records the source of its `pii` signal (`regex`, `screen` with the category, or `unknown` with the reason), an unknown verdict is a console line naming the task id only, and `events.jsonl` gets a `pii_screen` record with the item kind, label, source, category, reason and latency, never the text. A routing explanation of a draft does not call the screen and says so.
|
|
20
20
|
- **Free text is screened too.** On an ordinary task, a done summary (with its check output: a match withholds the whole note), a review note, an unmet item or a budget handoff that matches a PII pattern (issue #69) is not saved to claude-mem, and every peer, `local` included, gets a stub naming `ahub task show <id>`; the board keeps the text, `hub.log` notes the withholding by task id only, and `ahub ask` shows such a note only when its model is reached on campus. `hub_remember` refuses a match; what a vendor agent writes to its own memory is not screened. With the model screen on, the same items (and `hub_remember` notes) go through it as well, one call each and only after the call's own checks (owner, state, verdict, a running check, memory enabled) pass: a `pii` or `unknown` verdict withholds the item exactly like a pattern match, and the board marks the history entry (`withheld`) so later views (task lists, completed-change notices, `ahub ask`, a reviewer replaced after a restart) keep withholding it. A budget hand-off is screened once per hand-off, whatever the number of tasks it moves; an escalation's reason is the hub's own text and is not screened. Pattern-only, without the model: the check output tail in a done note (only the summary is screened), a plan given with `hub_task_accept`, a decline reason, a task's refs (paths, branch), and context checkpoint summaries. Not screened at all (an existing gap, not new with the screen): the local worker's claude-mem capture records its file, shell and git tool calls in ordinary turns with their raw arguments and output, and the closing answer of a turn that used tools, without a pattern or model check. Its hub tool calls (`hub_send`, the task tools, the conductor tools) are not captured (issue #230), so a title, detail, done summary, review note or `hub_remember` text it writes reaches claude-mem only through the screened paths above.
|
|
21
|
-
- **Secrets stay where they are read.** The gateway key and Cloudflare Access values are read inside the gateway client and go only into request headers: never into logs, errors, envelopes, tool output, memory
|
|
21
|
+
- **Secrets stay where they are read.** The gateway key and Cloudflare Access values are read inside the gateway client and go only into request headers: never into logs, errors, envelopes, tool output, memory. Subscription logins of Claude, Codex and Kimi are never proxied or pooled.
|
|
22
22
|
- **The hub's own model calls are fenced.** Digest condensation, task triage and the PII screen read agent-written text as data; their output is capped text framed as untrusted, or a value checked against a closed list. It is never used as a route, a peer id, a tool call or an instruction.
|
|
23
23
|
|
|
24
24
|
## Native memory authority and profile selection
|
|
@@ -33,7 +33,7 @@ The hub binds the selected root/profile at open. Invalid/missing generation meta
|
|
|
33
33
|
|
|
34
34
|
Before migrating any real home, every hub sharing it must first be on 0.12.30 or later with positive authenticated binding or unbound/quiesced proof from `ahub memory profile-check` in each relevant registry. An unknown or unreadable runtime is not proof of absence, and a matching ready binding still holds a handle that must be closed. Profile-check reports only its named registry inventory. Root paths, selector receipts and malformed-legacy counts are person-local diagnostics, excluded from ordinary peer status and allowed agent CLI reads. Source/fixture checks do not establish native capture, real migration or account/device-sync success.
|
|
35
35
|
|
|
36
|
-
On a home split by `amem migrate --shards`, the hub opens only its own project's shard, with the user shard as overlay, under the alias-resolved project key (#534, #537); other projects' private notes are not in that store. Each memory entry rechecks the shard identity, and an alias that later remaps the key latches the binding unavailable. A split that is not active refuses and is never read as an empty or legacy store. A hub on 0.12.36 or earlier does not detect a split and keeps writing the old layout, so every hub on the home must run 0.12.37 or later, or be stopped, before splitting. `ahub memory profile-check` is
|
|
36
|
+
On a home split by `amem migrate --shards`, the hub opens only its own project's shard, with the user shard as overlay, under the alias-resolved project key (#534, #537); other projects' private notes are not in that store. Each memory entry rechecks the shard identity, and an alias that later remaps the key latches the binding unavailable. A split that is not active refuses and is never read as an empty or legacy store. A hub on 0.12.36 or earlier does not detect a split and keeps writing the old layout, so every hub on the home must run 0.12.37 or later, or be stopped, before splitting. `ahub memory profile-check` is split-aware (#536): it compares each running hub with its own project's shard and reports an inactive split with the resume remedy.
|
|
37
37
|
|
|
38
38
|
## What is not defended
|
|
39
39
|
|
|
@@ -95,9 +95,21 @@ the existing console authority for console-class operations and conductor-class
|
|
|
95
95
|
settings, roster and lifecycle operations. It does not restrict effects to a
|
|
96
96
|
scratch project: the agent must stay within the authorized commands and targets.
|
|
97
97
|
Malformed or conflicting caller markers still refuse. The original peer and
|
|
98
|
-
closed command label are
|
|
99
|
-
|
|
100
|
-
|
|
98
|
+
closed command label are audited before execution. Ordinary delegation requires
|
|
99
|
+
the authenticated welcome feature `cli_audit_delegated` before publishing that
|
|
100
|
+
outcome. The negotiated connection is reused, helper connections are pinned to
|
|
101
|
+
its authenticated instance, and local dispatch checks that instance. Replacement
|
|
102
|
+
control connections refuse. Before command effects, a console-only acknowledgement
|
|
103
|
+
must confirm the exact UUID was retained by a successful event append in that
|
|
104
|
+
instance; an unavailable acknowledgement refuses. Later local work therefore does
|
|
105
|
+
not depend on a future consumer draining the spool. An older or unavailable consumer gets a compatible `refused` row and the
|
|
106
|
+
command refuses with an upgrade remedy. An unwritable outbox refuses before the
|
|
107
|
+
connection; an event append failure refuses before command effects. Upgrade/recovery instead records compatible `run` spool rows and
|
|
108
|
+
keeps authoritative ids-only `delegatedAudits` in its operation receipt before
|
|
109
|
+
runtime effects, including resume through an older retained coordinator. Local bootstrap commands with no daemon manifest use `run` too. Stored attribution
|
|
110
|
+
never grants authority; the current invocation still needs its own validated peer
|
|
111
|
+
and flag. The current daemon emits `agent_cli` with `delegated: true` and
|
|
112
|
+
`refused: false` for the negotiated outcome. Allowed-class commands retain the peer identity and capability checks, including
|
|
101
113
|
messages, proposals and reviews. Peer starts, pause and resume may delegate
|
|
102
114
|
operational console authority; task assign/escalate under the flag refuse. `--as-user`, person task labels,
|
|
103
115
|
person-authored planning/release/memory/goal writes, SDLC record, benchmark run,
|
|
@@ -240,7 +252,7 @@ never-ask still requires the person's confirmation. qwen_cmd is machine-local an
|
|
|
240
252
|
never editable through settings. Legacy benchmark adapters remain unmanaged by
|
|
241
253
|
this production table. Startup diagnostics withhold native host/payload details.
|
|
242
254
|
|
|
243
|
-
Jcode is optional, source/version-fenced and runs native tools without a hub sandbox or hub permission-mode mapping. .jcode joins the scoped-grant exclusion, including lexical/resolved aliases. Only a person writes its unique project MCP entry; foreign/override/symlink entries refuse. The hub owns a private daemon/socket and ACP group, never the global daemon, and copies no credentials. It accepts only a plain jcode release from 0.98.0 up to, not including, 1.0.0 (#529), and runs every owned jcode process (probe, serve, ACP and TUI) with `JCODE_NO_TELEMETRY=1`, because jcode's telemetry can report the provider account's email. Native diagnostics withhold payloads/hosts. Unproved conversation loads refuse; no fresh replacement is called a restore. Native TUI launch exposes its private socket/session tuple only to the authenticated console, bound to the same live owned socket and session after read-only native persistence proof. Tools/status do not receive it. The TUI has no single-writer guard: person input may interleave with ACP. Native policy remains unmanaged and closing the frontend does not stop ACP.
|
|
255
|
+
Jcode is optional, source/version-fenced and runs native tools without a hub sandbox or hub permission-mode mapping. .jcode joins the scoped-grant exclusion, including lexical/resolved aliases. Only a person writes its unique project MCP entry; foreign/override/symlink entries refuse. The hub owns a private daemon/socket and ACP group, never the global daemon, and copies no credentials. It accepts only a plain jcode release from 0.98.0 up to, not including, 1.0.0 (#529), and runs every owned jcode process (probe, serve, ACP and TUI) with `JCODE_NO_TELEMETRY=1`, because jcode's telemetry can report the provider account's email. Native diagnostics withhold payloads/hosts. Unproved conversation loads refuse; no fresh replacement is called a restore. A finished task's advisory about the project root checkout names the branch only after the hub's whole public-text screen (`Tasks.publicMetadataText`: a PII pattern, a secret shape and a project-private path) passes it and it is a plain ref name; otherwise a generic sentence carries no part of it (#572). Native TUI launch exposes its private socket/session tuple only to the authenticated console, bound to the same live owned socket and session after read-only native persistence proof. Tools/status do not receive it. The TUI has no single-writer guard: person input may interleave with ACP. Native policy remains unmanaged and closing the frontend does not stop ACP. An `important` message reaches a busy Jcode as a soft interrupt written to the hub's own private server socket for the owned session (#572); the hub never cancels a turn to deliver, and a steer that was sent but not acknowledged, or whose turn ended first, is held as `needs_review`, never replayed. Jcode has no switch to choose its MCP servers, so the owned serve and ACP processes load every server named in `<JCODE_HOME>/mcp.json` and the project's `.jcode/mcp.json`, `.mcp.json` and `.claude/mcp.json`, besides the hub's own; `ahub doctor` lists their names only. Point `jcode_home` at a separate home, or remove a server from those files, to keep it out.
|
|
244
256
|
|
|
245
257
|
Antigravity (`agy`, #485) is optional, cloud and off roster by default. It runs native tools under its own unmanaged permissions, without a hub sandbox or hub permission-mode mapping; headless, resume, unattended and native permission flags are refused. Its roles are capped at implementer and verifier, so it never plans, reviews or receives PII work. Only the person's `ahub agy` launcher writes its three plugin files in `.agents/plugins/agent-hub/` (`plugin.json`, `mcp_config.json`, `hooks.json`): linked or foreign entries refuse before any write, cleanup removes only that launch's matching files, and it never writes project-level `.agents/hooks.json` or the person's `~/.gemini` settings. Conductor starts are refused. Hook authority (`native_hook_launch`) comes only from that launcher, belongs to the console socket that began it and ends when that socket closes; hook input over 1 MiB is refused, and observations are bound to the daemon, launch, native session and project.
|
|
246
258
|
|
|
@@ -355,7 +367,7 @@ The review brief (#520) withholds private changes whole (both sides of a move) a
|
|
|
355
367
|
|
|
356
368
|
## Bounded task specs and isolated checks (#418)
|
|
357
369
|
|
|
358
|
-
`hub_task_spec` reads only the GitHub issues named by a current owner's or reviewer's task in this project's origin repository, including the validated canonical GitHub intake source when its title/body has no issue token. Bare `#N` references count only in the title; detail references require `owner/repo#N` or `https://github.com/owner/repo/issues/N`. Bare detail numbers denote hub tasks, and arbitrary file paths are not parsed as issue references. A qualified reference cannot begin after a slash or a name character, so `src/hub/tasks.ts#12` is a file path. Routing uses this same parser. Without a GitHub project identity, bare title numbers do not require spec access, but explicit qualified/URL references, `refs.repo` and imported GitHub identity still fail closed. The daemon resolves authenticated and container executables outside the project, pins their absolute paths and uses fixed arguments; repository-writable PATH shims are refused. Runner Git resolves its host executable through a restricted PATH. For specs, the model receives no credential or arbitrary authenticated URL capability. Foreign/transferred issues, more than three references, bodies over 64 KiB and aggregate results over 80 KiB fail explicitly. Spec fetches share a 25-second budget inside the control client's 30-second cap; each gh call remains bounded to 15 seconds. Current PII, secret and private-path policy withholds the complete spec rather than returning a partial contract. PII turns and PII tasks refuse these tools. The independent `spec_read` and `check_run` capabilities apply when a peer has a narrowed capability list. Arguments and results are excluded from capture. Proven deterministic pre-effect guards return PreEffectToolRefusal so Pi settles the exact refusal receipt; generic transport/storage failures and failures after durable receipt/output changes remain uncertain, never reclassified from error text.
|
|
370
|
+
`hub_task_spec` reads only the GitHub issues named by a current owner's or reviewer's task in this project's origin repository, including the validated canonical GitHub intake source when its title/body has no issue token. Bare `#N` references count only in the title; detail references require `owner/repo#N` or `https://github.com/owner/repo/issues/N`. Bare detail numbers denote hub tasks, and arbitrary file paths are not parsed as issue references. A qualified reference cannot begin after a slash or a name character, so `src/hub/tasks.ts#12` is a file path. Routing uses this same parser. Without a GitHub project identity, bare title numbers do not require spec access, but explicit qualified/URL references, `refs.repo` and imported GitHub identity still fail closed. `refs.repo`, which `hub_task_propose` and `hub_task_accept` take since #476 to scope overlap per repository, is metadata only: it grants no file access or execution root, and a spec read for a task naming another repository refuses. The daemon resolves authenticated and container executables outside the project, pins their absolute paths and uses fixed arguments; repository-writable PATH shims are refused. Runner Git resolves its host executable through a restricted PATH. For specs, the model receives no credential or arbitrary authenticated URL capability. Foreign/transferred issues, more than three references, bodies over 64 KiB and aggregate results over 80 KiB fail explicitly. Spec fetches share a 25-second budget inside the control client's 30-second cap; each gh call remains bounded to 15 seconds. Current PII, secret and private-path policy withholds the complete spec rather than returning a partial contract. PII turns and PII tasks refuse these tools. The independent `spec_read` and `check_run` capabilities apply when a peer has a narrowed capability list. Arguments and results are excluded from capture. Proven deterministic pre-effect guards return PreEffectToolRefusal so Pi settles the exact refusal receipt; generic transport/storage failures and failures after durable receipt/output changes remain uncertain, never reclassified from error text.
|
|
359
371
|
|
|
360
372
|
`hub_check_start` accepts only a current owner's in-progress task, its recorded branch/commit and either `typecheck` or one to 32 existing `test/*.test.ts` paths. `checks.runner = "container"` is a person opt-in in an untracked config file; a tracked config cannot grant it. Missing service/image, an unverified internal network, stale task/owner/native generation, unavailable dependencies or an invalid path fails closed. There is no host-shell, network or Seatbelt fallback.
|
|
361
373
|
|
package/docs/smoke.md
CHANGED
|
@@ -626,9 +626,9 @@ In the project directory, one terminal each:
|
|
|
626
626
|
|
|
627
627
|
Needs a model gateway in `omniroute.urls` (for the owner: the campus gateway over VPN, or the Access-protected public URL with its two header files) and a key: `OMNIROUTE_API_KEY`, or `omniroute.api_key_file` in `.agenthub/config.json`.
|
|
628
628
|
|
|
629
|
-
1. `ahub doctor`: `omniroute` healthy, `omniroute key` present,
|
|
629
|
+
1. `ahub doctor`: `omniroute` healthy, `omniroute key` present, every routing model alias served; no Switchyard row.
|
|
630
630
|
2. In a scratch git repo: `ahub up`, `ahub local`, `ahub tail`, then `ahub say @local "fix the typos in <file>, run git diff --stat and report"`. `ahub tail` shows a permission request for the edit; `ahub permit <id> allow`. The file changes, the answer is a short conclusion, `ahub status` shows the served model in the local row's `MODEL` column and `vllm` in the backend table's `PROVIDER` column.
|
|
631
|
-
3.
|
|
631
|
+
3. In an isolated scratch project, use `[local] route = "hub/stage"` with served `fast` and `coding` aliases. Confirm the in-process route event and gateway provider. Try a legacy `sy/` selection: it uses `fixed_model` with one warning, starts no sidecar, and leaves the routing file unchanged. The older Switchyard receipts below describe the retired integration.
|
|
632
632
|
4. claude-mem: `sqlite3 -readonly ~/.claude-mem/claude-mem.db "select agent_id, agent_type, project, title from observations order by id desc limit 3"` shows `local | local-worker` rows a minute or two later (claude-mem's observer runs asynchronously).
|
|
633
633
|
|
|
634
634
|
## M4: task board
|