@staix/agent-hub 0.12.15 → 0.12.17
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 +17 -0
- package/README.md +18 -5
- package/docs/agent-notes/adapters.md +1 -0
- package/docs/agent-notes/budget.md +5 -1
- package/docs/agent-notes/bus.md +2 -0
- package/docs/agent-notes/tasks.md +3 -1
- package/docs/agent-notes/tests.md +3 -1
- package/docs/operations.md +277 -11
- package/docs/quickstart.md +4 -4
- package/docs/security.md +26 -1
- package/docs/smoke.md +93 -0
- package/docs/specs/2026-09-19-agent-hub-design.md +223 -0
- package/docs/verification/2026-10-09-agent-shell-t0.md +123 -0
- package/docs/verified.json +168 -0
- package/package.json +1 -1
- package/plugins/agent-hub/.claude-plugin/plugin.json +1 -1
- package/plugins/agent-hub/server.js +18 -6
- package/src/adapters/acp.ts +2 -2
- package/src/adapters/claude-channel.ts +3 -2
- package/src/adapters/codex-appserver.ts +10 -2
- package/src/adapters/local-worker.ts +5 -5
- package/src/adapters/pi.ts +4 -14
- package/src/cli/console-state.ts +213 -0
- package/src/cli/console.ts +201 -0
- package/src/cli/facts-hook.ts +8 -1
- package/src/cli/identity-audit.ts +66 -0
- package/src/cli/identity.ts +54 -0
- package/src/cli/init.ts +40 -30
- package/src/cli/launch.ts +31 -1
- package/src/cli/main.ts +95 -39
- package/src/cli/preview.ts +80 -0
- package/src/cli/status-lines.ts +8 -2
- package/src/cli/statusline-tee.ts +14 -0
- package/src/cli/tail-render.ts +17 -0
- package/src/cli/upgrade-runtime.ts +1 -1
- package/src/hub/board.ts +9 -2
- package/src/hub/bus.ts +82 -10
- package/src/hub/child-process.ts +11 -0
- package/src/hub/conductor.ts +196 -0
- package/src/hub/context-window.ts +72 -0
- package/src/hub/control-client.ts +3 -3
- package/src/hub/daemon.ts +492 -77
- package/src/hub/envelope.ts +1 -1
- package/src/hub/events.ts +7 -1
- package/src/hub/hub-tools.ts +14 -1
- package/src/hub/report.ts +53 -4
- package/src/hub/supervision.ts +152 -0
- package/src/hub/task-sweep.ts +59 -0
- package/src/hub/tasks.ts +86 -15
- package/src/hub/usage.ts +37 -2
- package/src/models/relay.ts +6 -1
- package/src/pi/launch.ts +21 -0
- package/src/ui/index.html +6 -0
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,23 @@ Issue and pull request numbers in the entries for 0.7.7 and earlier refer to the
|
|
|
4
4
|
|
|
5
5
|
## Unreleased
|
|
6
6
|
|
|
7
|
+
## 0.12.17
|
|
8
|
+
|
|
9
|
+
- Add an operator console with confirmed approvals, bounded status polling and optional peer, approval, task, queue and event panels; open it from interactive `up` and preserve the tail renderer (#190, #191).
|
|
10
|
+
- Identify agent shell CLI calls as their peer, refuse human-only commands before connecting and record ids-only audit notices without an as-user bypass (#193).
|
|
11
|
+
- Grant steering tools only to one explicit conductor role, preserve the actor on task changes and keep conductor holds separate from human, budget and recovery holds (#194).
|
|
12
|
+
- Batch public task milestones and human-action reminders through the existing digest window, replace repeated pending notices and report completed native supervision turns with unknown usage preserved (#195).
|
|
13
|
+
- Advance the control protocol to 15 for approval lifecycle and supervision metadata, retaining controlled recovery from supported previous sources.
|
|
14
|
+
|
|
15
|
+
## 0.12.16
|
|
16
|
+
|
|
17
|
+
- Record source-verification commits for current operating documents and agent notes; fail missing coverage, invalid stamps and README version drift, and report stale source scopes deterministically (#188).
|
|
18
|
+
- Require six sequential guard checks to pass without mutation and fail their named assertion with a seeded regression. Reuse full Linux/macOS plus seeded CI only for an identical release tree (#187).
|
|
19
|
+
- Add a default-off task-idle sweep with persisted escalation steps, real-activity anchors, PII-safe notices, hold/cohort suppression and explicitly opted-in owner reassignment (#186).
|
|
20
|
+
- Preview initialization changes and native launcher arguments through the same builders, without hub writes or native startup; redact arbitrary user values and identify unresolved runtime metadata (#189).
|
|
21
|
+
- Show native Claude/Codex context-window readings with freshness and session identity. Optional pressure checkpoints do not pause quota, reassign work or replace sessions; unknown readings stay unknown and private summaries stay out of cloud memory (#185).
|
|
22
|
+
- Advance the control protocol to 14 for context status metadata while retaining controlled recovery from supported earlier protocols.
|
|
23
|
+
|
|
7
24
|
## 0.12.15
|
|
8
25
|
|
|
9
26
|
- Bind Pi tool-step ceiling diagnostics to the trusted producer's session and turn, retain the rejected pre-effect invocation count, and keep the first active failure cause frozen (#179).
|
package/README.md
CHANGED
|
@@ -4,12 +4,12 @@ Native multi-agent hub for one developer's machine: Claude Code, Codex, Kimi Cod
|
|
|
4
4
|
hub-owned local-LLM worker collaborate as peers in independent project directories, with
|
|
5
5
|
task-aware model routing (Switchyard) in front of a self-hosted gateway (OmniRoute).
|
|
6
6
|
|
|
7
|
-
Status: 0.12.
|
|
7
|
+
Status: 0.12.17, control protocol 15. Durable delivery records distinguish queued
|
|
8
8
|
work from uncertain execution. The [smoke checklist](docs/smoke.md) records
|
|
9
9
|
verified paths and remaining prerequisites.
|
|
10
10
|
|
|
11
11
|
Read the [operations guide](docs/operations.md) for the daily workflow, queue
|
|
12
|
-
reconciliation, and the staged
|
|
12
|
+
reconciliation, and the staged upgrade command for supported source protocols.
|
|
13
13
|
Controlled recovery preserves work; uncertain effects are never automatically
|
|
14
14
|
replayed and may require operator review.
|
|
15
15
|
|
|
@@ -22,13 +22,13 @@ Install from npm:
|
|
|
22
22
|
|
|
23
23
|
```bash
|
|
24
24
|
bun add -g @staix/agent-hub && ahub setup
|
|
25
|
-
cd <your project> && ahub init && ahub up
|
|
25
|
+
cd <your project> && ahub init && ahub up
|
|
26
26
|
```
|
|
27
27
|
|
|
28
28
|
Or install the same version from GitHub:
|
|
29
29
|
|
|
30
30
|
```bash
|
|
31
|
-
bun add -g github:STAIxBWLB/agent-hub#v0.12.
|
|
31
|
+
bun add -g github:STAIxBWLB/agent-hub#v0.12.17 && ahub setup
|
|
32
32
|
```
|
|
33
33
|
|
|
34
34
|
The installed commands remain `ahub` and `agent-hub`.
|
|
@@ -44,6 +44,19 @@ and agent sessions so both load the update.
|
|
|
44
44
|
- [Smoke checklist](docs/smoke.md): the live checks, and what has and has not been verified against real agents
|
|
45
45
|
- [Changelog](CHANGELOG.md), [Contributing](CONTRIBUTING.md)
|
|
46
46
|
|
|
47
|
+
## What ahub changes on your machine
|
|
48
|
+
|
|
49
|
+
`ahub init --dry-run --json` lists missing project defaults, the managed AGENTS.md
|
|
50
|
+
block, legacy CLAUDE.md cleanup and gitignore updates before writing them.
|
|
51
|
+
The preview does not register the project.
|
|
52
|
+
|
|
53
|
+
`ahub claude|codex|kimi|pi --print-command` (also `--dry-run`) prints the native
|
|
54
|
+
argv, Claude session settings and environment variable names without launching.
|
|
55
|
+
It uses the normal command builders. Arbitrary user arguments, configured commands
|
|
56
|
+
and settings are redacted; runtime-assigned endpoints and session identities are
|
|
57
|
+
explicitly unresolved. It does not check executable or account readiness.
|
|
58
|
+
See [Security notes](docs/security.md).
|
|
59
|
+
|
|
47
60
|
## Why not agent-bridge
|
|
48
61
|
|
|
49
62
|
[raysonmeng/agent-bridge](https://github.com/raysonmeng/agent-bridge) proves the
|
|
@@ -87,7 +100,7 @@ only. `--backend dgx` or `--backend mlx` explicitly pins a Pi session's backend.
|
|
|
87
100
|
Pi connects to an authenticated relay with model aliases `dgx/coding`,
|
|
88
101
|
`dgx/fast`, and `mlx/fast`; upstream gateway credentials stay in the hub.
|
|
89
102
|
Its managed tools use the existing path guards, shell sandbox and terminal
|
|
90
|
-
approval flow. Keep `ahub
|
|
103
|
+
approval flow. Keep `ahub console` open to approve write/edit/shell operations.
|
|
91
104
|
Tool-call receipts survive daemon restart; an interrupted operation with an
|
|
92
105
|
unknown outcome must be reconciled before repeating it. Cancelling a Pi turn
|
|
93
106
|
does not automatically hand its task to a cloud peer.
|
|
@@ -15,4 +15,5 @@ Scope: the Codex, ACP and Pi adapters and the Pi extension (turn `generation` an
|
|
|
15
15
|
- Native owner teardown must handle a lost shutdown acknowledgement using verified process identity. Pending launches must be revocable, and active tools/streaming output must count as watchdog activity.
|
|
16
16
|
- Pi owner identity is one shared contract, `processSignature` in `src/pi/process-signature.ts`; the startup claim check, the extension's claim, the TUI owner monitor, `recoveryReady` and the verified teardown all go through it. Its `ps` read pins LC_ALL=C and TZ=UTC (the `processTable` contract) because `lstart` follows the reader's timezone and locale, and a hub on UTC with a Pi child on system time otherwise hashes different strings for the same process and refuses the valid owner (#174). Strict pid + start + command identity stays; never accept PID-only or a fuzzy command match.
|
|
17
17
|
- Return the shared `toolResultFailed` verdict as `/tool`'s `failed`; map only `failed === true` to Pi's `isError`. Preserve text and the older bridge's absent-flag behavior.
|
|
18
|
+
- Spawn a native peer with `peerChildEnv(peer, source)` so its own `AGENTHUB_PEER_ID` replaces inherited agent markers. Sandbox tool environments carry their executing peer too. Preserve the native shell environment policy; Codex's `CODEX_THREAD_ID` supplies the fallback after filtering. Before changing marker detection or launcher environments, read `docs/verification/2026-10-09-agent-shell-t0.md` for pinned source and live-probe limits.
|
|
18
19
|
- Emit Pi's ceiling event at the pre-effect rejection boundary (`src/pi/ceiling.ts`), before `agent_end`. Accept only a valid current-session/current-generation signal during a running turn; retain the first signal and attach it to that turn's failure. Never classify a ceiling from free text.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Budget, pause and handoff
|
|
2
2
|
|
|
3
|
-
Scope: quota readings, pause, handoff and resume, and the status line tee. Read before editing `src/hub/budget.ts`, `src/cli/statusline-tee.ts`, `src/hub/bus.ts`, `src/hub/delivery-journal.ts` or `src/hub/restart.ts` (pause persistence).
|
|
3
|
+
Scope: quota and native context readings, checkpoints, pause, handoff and resume, and the status line tee. Read before editing `src/hub/budget.ts`, `src/hub/context-window.ts`, `src/cli/statusline-tee.ts`, `src/hub/bus.ts`, `src/hub/delivery-journal.ts` or `src/hub/restart.ts` (pause persistence).
|
|
4
4
|
|
|
5
5
|
- Budget: checkpoint first, pause second (a paused peer receives nothing). A handoff that fails is left unmarked so the next tick or hub run retries it; never record it as done.
|
|
6
6
|
- A handoff needs somebody to hand over to: `canHandOff` is false right after a restart, when no peer is attached yet, and the handoff waits for a later tick instead of stripping tasks of their owner.
|
|
@@ -8,3 +8,7 @@ Scope: quota readings, pause, handoff and resume, and the status line tee. Read
|
|
|
8
8
|
- On resume the notice is published before the peer is released, so it leads the first delivery.
|
|
9
9
|
- The coordinator only lifts its own pauses: `manualPaused` in the daemon keeps a `ahub pause` in place, and `ahub resume` refuses while a budget record is open.
|
|
10
10
|
- The status line tee must never fail or slow the render: no throw, original command run with the same stdin, 5 s cap.
|
|
11
|
+
|
|
12
|
+
- Keep native context occupancy in `src/hub/context-window.ts` separate from quota accounting; never use Codex's accumulated `total` as occupancy or estimate Pi counters.
|
|
13
|
+
- Context checkpoint completion requires its request id and the current attached peer/native session. Invalidate its transport generation synchronously at a new peer claim, before asynchronous recall or attachment. Never pause, reassign or replace a session on context pressure. Refuse private-turn, PII-pattern and all non-approved associated PII-task summaries (owner or reviewer, including in_review, with the current routing policy) before local persistence or cloud memory; never broadcast checkpoint text.
|
|
14
|
+
- Invalid/stale context readings expose unknown and do not rearm a crossing. Latch a crossing only after its event is accepted; reconsider paused/recovery-held crossings after release with fresh current-session readings. Tee context fields contain finite numeric values or null only, bound to daemon instance, launcher and native session.
|
package/docs/agent-notes/bus.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Bus, digests and replies
|
|
2
2
|
|
|
3
|
+
- Supervision replaces only pending, never attempted or accepted, envelopes with the same stable key. Preserve the first batch deadline and existing digest/queue ceilings; role/feed revocation withdraws pending notices only. Count supervision from actual transport admission followed by a successful native turn completion, never from enqueue or failure-to-idle.
|
|
4
|
+
|
|
3
5
|
Scope: delivery, digests and condensation, reply addressing, priority and limits. Read before editing `src/hub/bus.ts`, `src/hub/envelope.ts`, `src/hub/limits.ts`, `src/hub/delivery-journal.ts`, `src/hub/inference.ts` (digest condensation), or how an adapter addresses a reply or sets its priority.
|
|
4
6
|
|
|
5
7
|
- A failed digest is retried one envelope at a time, so a poison envelope cannot take its neighbours down with it.
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
# Task board and hub tools
|
|
2
2
|
|
|
3
|
-
Scope: the task flow, assignment, the state machine and the hub's MCP tools. Read before editing `src/hub/tasks.ts`, `src/hub/board.ts`, `src/hub/routing.ts` or `src/hub/hub-tools.ts`.
|
|
3
|
+
Scope: the task flow, assignment, the state machine and the hub's MCP tools. Read before editing `src/hub/tasks.ts`, `src/hub/board.ts`, `src/hub/routing.ts`, `src/hub/task-sweep.ts`, `src/hub/conductor.ts`, `src/hub/supervision.ts` or `src/hub/hub-tools.ts`.
|
|
4
4
|
|
|
5
5
|
- Tool callers are models: MCP `inputSchema` is not enforced on the way in. Normalize at the boundary (`cleanRefs`) before anything reaches the board, and never throw after a board write.
|
|
6
6
|
- `assign()` never defaults to the task's current owner, or a decline can only come back to the decliner.
|
|
7
7
|
- The state machine allows `in_progress -> approved` only for classes without a reviewer; `review()` checks `in_review` itself.
|
|
8
|
+
- Conductor authority requires the explicit unique role before capability checks. Assignments preserve the acting peer. A peer releases only its own conductor hold; operator release and manual, quota and recovery holds remain separate paths.
|
|
9
|
+
- Supervision reasons use structured enums, never history notes, check output or approval titles. Round signatures survive restart; later summaries count only newly joined tasks.
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
# Tests
|
|
2
2
|
|
|
3
|
-
Scope: tests, fakes and the test gate. Read before adding or changing a test or fake under `test/`, or editing `scripts/check.sh
|
|
3
|
+
Scope: tests, fakes and the test gate. Read before adding or changing a test or fake under `test/`, or editing `scripts/check.sh`, `scripts/hang-watch.sh`, `scripts/seeded-check.ts` or `scripts/seeds.json`.
|
|
4
4
|
|
|
5
5
|
- Tests that are not about batching build the bus with `batchMs: 0`; with the default 15 s window a lone status envelope looks like a lost message.
|
|
6
6
|
- In Bun 1.3.14 a test timeout that fires while `Bun.spawnSync` runs can start the next test inside spawnSync's own event loop, where another spawnSync then spins at full CPU for good (trigger not pinned down; see README). Bun 1.4.2 still runs the next test inside the outer spawnSync's event loop. `scripts/check.sh` runs tests with a 20 s timeout and under `scripts/hang-watch.sh`; a test that spawns and reads the process table gets a timeout of its own.
|
|
7
7
|
- A child process gets a scrubbed environment, so test knobs for fakes travel in a wrapper script, not in `process.env`.
|
|
8
|
+
- Bind agent identity markers explicitly in native/CLI fixture children. The full gate starts the test runner without inherited agent markers for human CLI fixtures; never weaken production marker detection to make them pass.
|
|
9
|
+
- Run `bun scripts/seeded-check.ts` before reporting the seeded-guard gate complete. Keep the six `scripts/seeds.json` cases sequential; require the same named test green before its seeded assertion fails. Seed rot, survivors, setup/compiler failures, timeout/watchdog termination and process leaks fail the gate. Never run the full seed runner from a unit test or mutate the source checkout; inspect preserved failed fixtures before removing them. CI runs this in the required Linux `seeded guards` job after the ordinary check, separately from `scripts/check.sh`.
|
package/docs/operations.md
CHANGED
|
@@ -1,8 +1,99 @@
|
|
|
1
1
|
# Operations guide
|
|
2
2
|
|
|
3
|
-
This guide describes ahub 0.12.
|
|
3
|
+
This guide describes ahub 0.12.17 and control protocol 15. Live verification
|
|
4
4
|
results and remaining prerequisites are recorded separately in [the smoke ledger](smoke.md).
|
|
5
5
|
|
|
6
|
+
## Operator console and panels
|
|
7
|
+
|
|
8
|
+
`ahub console` combines the existing tail stream with peer, quota, approval-age
|
|
9
|
+
and input rows. `ahub up` opens it when both input and output are terminals;
|
|
10
|
+
`--no-console` and redirected input/output retain the start-only behavior.
|
|
11
|
+
`ahub tail` remains available with its existing rendering.
|
|
12
|
+
|
|
13
|
+
Allowing an approval requires selection and a separate confirmation. Denying
|
|
14
|
+
does not. Only options the daemon supplied are selectable. Typing a command
|
|
15
|
+
prevents approval shortcuts from interpreting that input as an answer. Full
|
|
16
|
+
approval titles are terminal-only; expiry and answers from another console remove
|
|
17
|
+
the pending item. Approval audit records contain id, peer, option kind, response
|
|
18
|
+
time and answering surface, without the title.
|
|
19
|
+
|
|
20
|
+
Tab toggles stream and panels; `ahub console --panels` starts in panels. Peers,
|
|
21
|
+
Approvals, Tasks, Queue and Events support arrow keys or j/k, Enter for detail,
|
|
22
|
+
Escape to return and `?` for help. `:` enters a command. Assignment, delivery
|
|
23
|
+
resolution and allow decisions require confirmation; delivery resolution requires
|
|
24
|
+
a reason. Tasks use the same public redaction as the board. Panels need at least
|
|
25
|
+
80 columns by 24 rows; smaller terminals stay in stream mode. Task and queue
|
|
26
|
+
polling runs only while the corresponding panel is visible. Leaving restores
|
|
27
|
+
the terminal and returning from panels replays the bounded stream buffer.
|
|
28
|
+
|
|
29
|
+
The command input accepts existing status, board, task, review, say, pause,
|
|
30
|
+
resume, budget, queue, permit, ask, remember, route, turns, undo, check-path and
|
|
31
|
+
report operations. It executes an argument vector with closed stdin. Lifecycle,
|
|
32
|
+
launch, nested console, setup, UI, logs and tail commands are refused.
|
|
33
|
+
|
|
34
|
+
## Conducting a team from Claude Code or Codex
|
|
35
|
+
|
|
36
|
+
Start the daemon with `ahub up --no-console`, set exactly one conductor in the
|
|
37
|
+
project configuration, then open `ahub console` in a split terminal for approvals:
|
|
38
|
+
|
|
39
|
+
```json
|
|
40
|
+
{
|
|
41
|
+
"roles": { "claude": ["planner", "reviewer", "conductor"] },
|
|
42
|
+
"conductor": { "feed": "own" }
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Launch that peer with `ahub claude` for channel pushes, or select `codex` in
|
|
47
|
+
`roles` and launch `ahub codex`. The conductor splits work into owned tasks,
|
|
48
|
+
observes `hub_status`, moves stalled work and obtains review before reporting
|
|
49
|
+
results and open decisions. It does not implement the tasks it handed out.
|
|
50
|
+
`hub_peer_start` starts local, Kimi or headless Pi; requests for native TUIs
|
|
51
|
+
return the `ahub` command for the person to run, after validating it through
|
|
52
|
+
the shared launcher planner. The wrapper plans again at launch when native
|
|
53
|
+
endpoints are available. `hub_peer_hold` and `hub_peer_release`
|
|
54
|
+
manage only holds placed by that conductor. Assignment also requires `assign`
|
|
55
|
+
when the conductor has an explicit capabilities list.
|
|
56
|
+
|
|
57
|
+
Check the returned owner and task state after assignment. Routing skips paused
|
|
58
|
+
peers, so assign work before placing a delivery hold. Hand work out through the
|
|
59
|
+
board and report to the person with `hub_send` addressed to `user`, or a `[FYI]`
|
|
60
|
+
final response in the native TUI. Broadcasting implementation instructions can
|
|
61
|
+
cause an otherwise unassigned owner to claim duplicate work.
|
|
62
|
+
|
|
63
|
+
The person answers approvals in the console, resolves `needs_review` deliveries
|
|
64
|
+
with `ahub queue resolve`, and handles budget overrides and hub lifecycle.
|
|
65
|
+
Running these commands from an agent shell is refused; the CLI retains the
|
|
66
|
+
agent's identity even when invoked through a shell tool.
|
|
67
|
+
|
|
68
|
+
`conductor.feed` is `own` by default, `all` for all tasks, or `off`. Ordinary
|
|
69
|
+
milestones share the existing digest window and collapse repeated queued
|
|
70
|
+
task/kind notices. They wait behind a busy conductor. An aged approval or
|
|
71
|
+
`needs_review` hold is important, contains only peer/tool-age or delivery id,
|
|
72
|
+
and directs the conductor to ask the person. A completed task set emits one
|
|
73
|
+
round notice until a new task joins. Removing the role or switching the feed
|
|
74
|
+
off withdraws pending feed notices.
|
|
75
|
+
|
|
76
|
+
For a Claude conductor, `ahub claude` also observes native session and turn
|
|
77
|
+
boundaries when facts injection and task-idle sweeps are off. Keep the managed
|
|
78
|
+
hooks enabled to measure completion and supervision usage. Passing your own
|
|
79
|
+
`--settings` takes precedence and produces a warning when it replaces that
|
|
80
|
+
observation. The launcher records its private session identity in ordinary
|
|
81
|
+
terminals too; this does not grant terminal-recovery authority.
|
|
82
|
+
Ordinary Claude sessions with turn-free facts or task-idle sweeps enabled get the
|
|
83
|
+
same session/start observation. Other ordinary launches remain non-opt-in.
|
|
84
|
+
|
|
85
|
+
`ahub report` records conductor actions and completed native turns containing
|
|
86
|
+
supervision. Tokens describe the whole measured turn, which may also contain
|
|
87
|
+
other work; they are not a per-notice cost estimate. Missing measurements stay
|
|
88
|
+
unknown. Use the live smoke ledger to assess observed turns and tokens per
|
|
89
|
+
approved task before choosing `all`; an unmeasured run is not a cost benchmark.
|
|
90
|
+
Claude turn counts use authenticated native completion events. Older logical
|
|
91
|
+
state counts are labelled; an idle channel or approved task alone does not prove
|
|
92
|
+
that the native answer finished.
|
|
93
|
+
The Stop hook acknowledgement is not a counted completion. The daemon checks the
|
|
94
|
+
native transcript after the hook can return; missing or changed-session evidence
|
|
95
|
+
stays unknown.
|
|
96
|
+
|
|
6
97
|
## Install and start
|
|
7
98
|
|
|
8
99
|
Use Bun 1.3 or newer. Install the released package and install its Claude
|
|
@@ -14,12 +105,11 @@ ahub setup
|
|
|
14
105
|
cd <project>
|
|
15
106
|
ahub init
|
|
16
107
|
ahub up
|
|
17
|
-
ahub tail
|
|
18
108
|
```
|
|
19
109
|
|
|
20
110
|
`ahub init` writes the project configuration and managed instruction blocks.
|
|
21
111
|
Run it after an upgrade when those blocks need refreshing. `ahub setup`
|
|
22
|
-
updates the shared Claude plugin. Keep `ahub
|
|
112
|
+
updates the shared Claude plugin. Keep `ahub console` open when a local worker
|
|
23
113
|
may request an approval.
|
|
24
114
|
|
|
25
115
|
`.agenthub/config.json` can be committed and shared. The fields that choose
|
|
@@ -27,7 +117,7 @@ what the hub runs, which files it sends as credentials, where task text goes,
|
|
|
27
117
|
or how far the local worker's sandbox reaches (`kimi_cmd`, `codex_bin`,
|
|
28
118
|
`pi.cmd`, `checks`, `mlx.bin`, `mlx.runtimeDir`, `mlx.modelPath`, `omniroute.urls`,
|
|
29
119
|
`omniroute.access_hosts`, the `omniroute` key files, `memory.worker_url`,
|
|
30
|
-
`local.read_allow`, `local.bash_network`, `local.network_allow
|
|
120
|
+
`local.read_allow`, `local.bash_network`, `local.network_allow`) are machine-local:
|
|
31
121
|
they apply only from a file git confirms nobody committed. Put them in
|
|
32
122
|
`.agenthub/config.local.json` (`ahub init` adds it to `.gitignore`), which is
|
|
33
123
|
read after `config.json`; outside a git repository they keep their defaults, and
|
|
@@ -521,6 +611,13 @@ stays the default until an evaluation says otherwise (`docs/cooperbench.md`).
|
|
|
521
611
|
|
|
522
612
|
Inspect permission requests in the terminal:
|
|
523
613
|
|
|
614
|
+
```bash
|
|
615
|
+
ahub console
|
|
616
|
+
```
|
|
617
|
+
|
|
618
|
+
Select the requested option in the console and confirm an allow decision.
|
|
619
|
+
For a separate plain terminal, the existing command remains available:
|
|
620
|
+
|
|
524
621
|
```bash
|
|
525
622
|
ahub tail
|
|
526
623
|
ahub permit <request-id> allow
|
|
@@ -647,21 +744,21 @@ Rows without a live process are stale registrations; forget them with
|
|
|
647
744
|
|
|
648
745
|
Upgrade running projects with the target release's own coordinator. It accepts
|
|
649
746
|
a running source on control protocol 9 (0.6.x), 10 (0.7.0 through 0.12.0),
|
|
650
|
-
11 (0.12.1 and 0.12.2), 12 (0.12.3)
|
|
747
|
+
11 (0.12.1 and 0.12.2), 12 (0.12.3), 13 (0.12.4 through 0.12.15) 14 (0.12.16) or 15 (0.12.17), and only
|
|
651
748
|
a target on its own protocol, so the target's coordinator fits every supported
|
|
652
749
|
source and carries every recovery fix released up to it. Protocol 8 and older
|
|
653
750
|
(0.5.x and earlier) are refused as `manual-bootstrap-required`. Run from the
|
|
654
751
|
project directory, without replacing the global CLI first:
|
|
655
752
|
|
|
656
753
|
```bash
|
|
657
|
-
bunx --package @staix/agent-hub@0.12.
|
|
658
|
-
bunx --package @staix/agent-hub@0.12.
|
|
754
|
+
bunx --package @staix/agent-hub@0.12.17 ahub upgrade --to 0.12.17 --dry-run
|
|
755
|
+
bunx --package @staix/agent-hub@0.12.17 ahub upgrade --to 0.12.17 --yes
|
|
659
756
|
```
|
|
660
757
|
|
|
661
758
|
| Running now | Coordinator to use |
|
|
662
759
|
| --- | --- |
|
|
663
760
|
| 0.6.x (protocol 9) | the target's, through `bunx` as above |
|
|
664
|
-
| 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.
|
|
761
|
+
| 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 (protocol 15) | the target's, through `bunx` as above |
|
|
665
762
|
| any supported source, with the installed CLI already at the target | `ahub upgrade` below, which is the same coordinator |
|
|
666
763
|
| 0.5.x or earlier (protocol 8 and older) | not supported: bootstrap by hand with the matching CLI |
|
|
667
764
|
|
|
@@ -688,19 +785,19 @@ The coordinator verifies and retains the exact target package, preserves its
|
|
|
688
785
|
own source, and promotes the global CLI only after restored projects pass
|
|
689
786
|
readback.
|
|
690
787
|
|
|
691
|
-
Once the installed CLI
|
|
788
|
+
Once the installed CLI matches the target release, review the current project or all registered
|
|
692
789
|
projects first:
|
|
693
790
|
|
|
694
791
|
```bash
|
|
695
792
|
ahub restart --dry-run
|
|
696
|
-
ahub upgrade --to 0.12.
|
|
793
|
+
ahub upgrade --to 0.12.17 --dry-run
|
|
697
794
|
```
|
|
698
795
|
|
|
699
796
|
Apply only after reviewing the plan:
|
|
700
797
|
|
|
701
798
|
```bash
|
|
702
799
|
ahub restart --yes
|
|
703
|
-
ahub upgrade --to 0.12.
|
|
800
|
+
ahub upgrade --to 0.12.17 --yes
|
|
704
801
|
ahub recovery status <operation-id>
|
|
705
802
|
ahub recovery resume <operation-id>
|
|
706
803
|
ahub recovery abort <operation-id>
|
|
@@ -924,3 +1021,172 @@ the capability is absent. It never rewrites these settings. Explicit
|
|
|
924
1021
|
`--backend mlx`, `--model mlx/fast`, and recorded MLX recovery launches are
|
|
925
1022
|
refused before any local startup. Re-enable MLX or explicitly migrate the
|
|
926
1023
|
recorded launch before recovery.
|
|
1024
|
+
|
|
1025
|
+
## Task idle sweep
|
|
1026
|
+
|
|
1027
|
+
The between-turn task sweep (#186) is disabled by default. Set `task_sweep` in
|
|
1028
|
+
`.agenthub/config.json` (or its machine-local override) to enable it:
|
|
1029
|
+
|
|
1030
|
+
```json
|
|
1031
|
+
{
|
|
1032
|
+
"task_sweep": {
|
|
1033
|
+
"enabled": true,
|
|
1034
|
+
"interval_s": 300,
|
|
1035
|
+
"unaccepted_min": 60,
|
|
1036
|
+
"idle_min": 120,
|
|
1037
|
+
"review_min": 120,
|
|
1038
|
+
"ladder_min": 30,
|
|
1039
|
+
"auto_reassign": false
|
|
1040
|
+
}
|
|
1041
|
+
}
|
|
1042
|
+
```
|
|
1043
|
+
|
|
1044
|
+
Booleans must be actual booleans. Each time setting must be a finite number of
|
|
1045
|
+
at least 1; timeouts are bounded to the platform timer limit. Each threshold
|
|
1046
|
+
measures time since the last real task history event. A ladder record does not
|
|
1047
|
+
refresh that activity; a new event resets the ladder even at the same timestamp.
|
|
1048
|
+
|
|
1049
|
+
The first overdue sweep sends the assigned owner or reviewer one normal task
|
|
1050
|
+
reminder. After `ladder_min`, the next sweep notifies the console and available
|
|
1051
|
+
planner-role peers. After another interval it reports a reassignment suggestion
|
|
1052
|
+
from the ordinary routing function. At most one step runs per task per sweep.
|
|
1053
|
+
PII notices contain only the public task stub, never its text, refs or plan.
|
|
1054
|
+
|
|
1055
|
+
Busy, paused, offline or native-active peers, queued/in-flight deliveries and
|
|
1056
|
+
queue holds, unresolved dependencies, completion checks, recovery/shutdown and
|
|
1057
|
+
silent turn-free cohorts suppress the sweep. An offline owner remains governed
|
|
1058
|
+
by the existing `tasks.release_after_min` policy. Human reviews produce console
|
|
1059
|
+
notices. The sweep does not change route-explain output.
|
|
1060
|
+
|
|
1061
|
+
For Claude, `ahub claude` installs the existing PreToolUse/PostToolUse/Stop
|
|
1062
|
+
observation hooks when the sweep is enabled, including in advisory projects.
|
|
1063
|
+
The hooks return no facts in advisory mode. A native Stop establishes an idle
|
|
1064
|
+
boundary; a subsequent PreToolUse marks activity. A delivery acknowledgement or
|
|
1065
|
+
task approval does not establish native idle. Restart the daemon and relaunch
|
|
1066
|
+
Claude after enabling the sweep so its session receives the hooks. A caller's
|
|
1067
|
+
`--settings` still wins: the launcher warns that native idle observation is off,
|
|
1068
|
+
and the sweep cannot verify that Claude session between turns.
|
|
1069
|
+
|
|
1070
|
+
`auto_reassign: true` explicitly allows an available alternative owner selected
|
|
1071
|
+
under the existing routing, role and PII constraints to receive the task at step
|
|
1072
|
+
three. Review-pending work always produces only a reviewer suggestion. The
|
|
1073
|
+
sweep records no failed-work outcome and never weakens routing constraints.
|
|
1074
|
+
|
|
1075
|
+
Each ladder step is persisted in task history before publishing. A restart
|
|
1076
|
+
therefore does not repeat it. A crash after the history write can leave its
|
|
1077
|
+
notice unpublished or uncertain; the history records an attempted step, not a
|
|
1078
|
+
receipt. Inspect `ahub task show <id>` and the delivery journal before acting;
|
|
1079
|
+
durable-delivery retries remain the journal's responsibility.
|
|
1080
|
+
|
|
1081
|
+
## Documentation source verification
|
|
1082
|
+
|
|
1083
|
+
`docs/verified.json` maps README, the current security, operations and quickstart
|
|
1084
|
+
pages, and every agent note to a full source commit and explicit covered paths.
|
|
1085
|
+
A stamp records a human check of the cited paths, symbols, numeric limits and
|
|
1086
|
+
operational commands. It does not certify live deployment or prove prose
|
|
1087
|
+
correctness automatically. Specs, changelogs and the smoke ledger retain their
|
|
1088
|
+
own dated evidence and are outside this manifest.
|
|
1089
|
+
|
|
1090
|
+
`node scripts/check-docs.mjs` also runs in `scripts/check.sh`. Missing manifest
|
|
1091
|
+
coverage, unresolved or nonancestor commits, removed source paths and a README
|
|
1092
|
+
status version different from `package.json` fail the gate. Source commits since
|
|
1093
|
+
a stamp and uncommitted covered changes produce sorted stale notices without
|
|
1094
|
+
failing it. Counts are commits touching any covered path, rather than file or
|
|
1095
|
+
line counts; an unrelated commit leaves the document fresh. Git history must
|
|
1096
|
+
include the stamped ancestors (CI checks out full history).
|
|
1097
|
+
|
|
1098
|
+
During release preparation, source review precedes restamping. Review each stale
|
|
1099
|
+
page against its covered source, correct drift, and use the full SHA of the
|
|
1100
|
+
reviewed source commit as `verifiedAgainst`. Record any deferred page and its
|
|
1101
|
+
specific unverified claims in the release verification report before tagging.
|
|
1102
|
+
Do not advance a stamp solely to clear a notice. Source stamps can name an
|
|
1103
|
+
ancestor: the manifest-only follow-up commit need not hash or stamp itself.
|
|
1104
|
+
|
|
1105
|
+
## Seeded guard verification
|
|
1106
|
+
|
|
1107
|
+
`bun scripts/seeded-check.ts` runs six guard pairs sequentially: header quoting,
|
|
1108
|
+
Origin refusal, control-token authentication, the hop cap, PII public views and
|
|
1109
|
+
uncertain-delivery receipts. Each named test first passes on current tracked
|
|
1110
|
+
checkout bytes, then must fail an assertion with the corresponding guard weakened.
|
|
1111
|
+
Seed rot (anything other than one exact replacement), a surviving seed and an
|
|
1112
|
+
invalid detection have distinct errors. Compiler, setup, unrelated-test and timeout
|
|
1113
|
+
failures never count as detection.
|
|
1114
|
+
|
|
1115
|
+
Each seed has a private temporary checkout without Git metadata, state, output
|
|
1116
|
+
directories or user untracked files. Installed dependency packages are linked,
|
|
1117
|
+
never copied or installed by the runner. Child tests use private home, temp and
|
|
1118
|
+
registry directories and a scrubbed environment. The normal 20-second test timeout,
|
|
1119
|
+
60-second hang watchdog and current-invocation process ledger/leak scan apply to
|
|
1120
|
+
both legs. Successful fixtures are removed; a failed pair prints its preserved
|
|
1121
|
+
fixture location with test and leak evidence for inspection.
|
|
1122
|
+
|
|
1123
|
+
The required Linux CI job `seeded guards` follows the ordinary checks; it does not
|
|
1124
|
+
repeat on macOS or run recursively inside `bun test`. The runner reports every
|
|
1125
|
+
pair's elapsed seconds and the total runtime. Runtime measurement remains pending
|
|
1126
|
+
until that gate executes; a green ordinary check alone does not prove these pairs.
|
|
1127
|
+
|
|
1128
|
+
The full CI gate tests the PR head tree on Linux and macOS, followed by the
|
|
1129
|
+
sequential seeded-guard job. Main and release jobs reuse only a successful full
|
|
1130
|
+
PR or push check with the identical Git tree and all three successful jobs. An absent or
|
|
1131
|
+
unreadable result runs the main gate again and refuses release. A manual
|
|
1132
|
+
`prepare_bundle` dispatch builds reviewable plugin assets without publishing;
|
|
1133
|
+
it is never accepted as full-gate evidence.
|
|
1134
|
+
|
|
1135
|
+
## Preview initialization and native launch
|
|
1136
|
+
|
|
1137
|
+
Run `ahub init --dry-run --json` for action/path/reason metadata, including a
|
|
1138
|
+
managed-block summary. The real init applies the same plan and preserves user text
|
|
1139
|
+
and legacy symlink/hardlink safeguards. Preview creates no files or registration.
|
|
1140
|
+
|
|
1141
|
+
Use `ahub claude --print-command`, `ahub codex --dry-run`,
|
|
1142
|
+
`ahub kimi --model <alias> --print-command`, or
|
|
1143
|
+
`ahub pi --mode tui --print-command` to inspect launch JSON.
|
|
1144
|
+
Environment values and arbitrary supplied values are withheld. Native-assigned
|
|
1145
|
+
proxy/bridge endpoints and new session identity remain unresolved.
|
|
1146
|
+
Claude and Codex previews include conditional `AGENTHUB_INSTANCE_ID` and
|
|
1147
|
+
`AGENTHUB_LAUNCH_ID` environment names with unresolved reasons. Claude's existing
|
|
1148
|
+
daemon identity is read at launch; a launch identity is allocated only after
|
|
1149
|
+
verified Orca terminal readback. Codex identities are injected when that Orca
|
|
1150
|
+
launch record is made. Preview neither reads those runtime identities nor
|
|
1151
|
+
allocates them, and never displays their values. Pi's environment preview
|
|
1152
|
+
continues to describe its native builder output.
|
|
1153
|
+
These previews do not connect to the daemon, toggle permissions, record terminal
|
|
1154
|
+
ownership, bind servers or start agents, sidecars or models.
|
|
1155
|
+
|
|
1156
|
+
|
|
1157
|
+
## Native context readings and optional checkpoints
|
|
1158
|
+
|
|
1159
|
+
`ahub status`, `ahub tail` and the dashboard show native context occupancy,
|
|
1160
|
+
source and measurement freshness. Claude readings come from the status-line
|
|
1161
|
+
tee installed by `ahub claude`; Codex readings come from its current thread's
|
|
1162
|
+
native token-usage updates. Pi and other unsupported surfaces show unknown.
|
|
1163
|
+
A stale or disconnected reading is unknown, not 0%. Codex's accumulated session
|
|
1164
|
+
usage is never used as context occupancy.
|
|
1165
|
+
|
|
1166
|
+
Context-triggered checkpoints are disabled by default. To enable them, add
|
|
1167
|
+
this to `.agenthub/config.json` and restart the daemon deliberately:
|
|
1168
|
+
|
|
1169
|
+
```json
|
|
1170
|
+
{"context":{"gate":0.85,"stale_min":30}}
|
|
1171
|
+
```
|
|
1172
|
+
|
|
1173
|
+
`gate` is a fraction between 0 and 1; 0 disables checkpoint requests.
|
|
1174
|
+
`stale_min` must be positive. A reading at or above the threshold records a metadata-only
|
|
1175
|
+
event and console notice, then asks an attached Claude/Codex with active work
|
|
1176
|
+
for a checkpoint when no checkpoint request is already outstanding. The request
|
|
1177
|
+
supplies a `request_id`; include that id with
|
|
1178
|
+
`hub_checkpoint {summary, request_id}`. Repeated high readings do not repeat
|
|
1179
|
+
it until a fresh below-threshold reading or new session rearms the crossing.
|
|
1180
|
+
|
|
1181
|
+
The resulting non-private note is saved in the state directory as
|
|
1182
|
+
`context-checkpoint-<peer>.json`, mode 0600; saving to shared memory is attempted
|
|
1183
|
+
when memory is enabled. Its body is never broadcast. A private turn, an open PII
|
|
1184
|
+
task held by the peer, or PII-pattern text prevents persistence and sharing.
|
|
1185
|
+
Requests are bound to the current peer, native session and transport generation.
|
|
1186
|
+
A new connection claim invalidates the old request before asynchronous recall or
|
|
1187
|
+
attachment, even with an unchanged native session id. Requests also expire after
|
|
1188
|
+
`budget.checkpoint_timeout_s` (90 seconds by default).
|
|
1189
|
+
Quota pause and task handoff are separate; a context checkpoint neither pauses
|
|
1190
|
+
nor hands work over. Continue normally or deliberately restart into a fresh
|
|
1191
|
+
session with your chosen checkpoint as preface. No automatic restart or native
|
|
1192
|
+
compaction override is performed.
|
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.17
|
|
21
21
|
ahub setup
|
|
22
22
|
```
|
|
23
23
|
|
|
@@ -34,8 +34,8 @@ In your project directory, one terminal each:
|
|
|
34
34
|
|
|
35
35
|
```bash
|
|
36
36
|
ahub init # .agenthub/config.json, .agenthub/routing.toml, the marker block in AGENTS.md
|
|
37
|
-
ahub up # the daemon
|
|
38
|
-
ahub
|
|
37
|
+
ahub up # starts the daemon and opens the operator console in a terminal
|
|
38
|
+
ahub console # use in another terminal if up used --no-console; Tab opens panels
|
|
39
39
|
ahub kimi # Kimi, headless
|
|
40
40
|
ahub codex # Codex TUI, attached through the hub
|
|
41
41
|
ahub claude # Claude Code with the hub channel
|
|
@@ -58,7 +58,7 @@ ahub say @kimi "run the tests and report" # one peer
|
|
|
58
58
|
|
|
59
59
|
or set `OMNIROUTE_API_KEY`. Name the model in `.agenthub/routing.toml` (`[local] fixed_model`). Then `ahub local`. It works only inside the project, asks before it writes or runs anything (`ahub permit <id> allow`), and everything it executes is sandboxed.
|
|
60
60
|
|
|
61
|
-
##
|
|
61
|
+
## Commands of a working day
|
|
62
62
|
|
|
63
63
|
| Command | What for |
|
|
64
64
|
| --- | --- |
|
package/docs/security.md
CHANGED
|
@@ -6,12 +6,13 @@ agent-hub connects agents that can each run commands. This page says what the hu
|
|
|
6
6
|
|
|
7
7
|
- **Other agents' text is untrusted.** Every message that crosses from one peer to another is framed as untrusted input (a channel tag with `meta.source` for Claude, a fixed header line plus a standing instruction for the others). A message body cannot forge the hub's own headers: such lines are quoted (`sanitize`). Replies inherit a hop count capped at 3, so agents cannot ping-pong forever; neither a digest nor a steer can reset it.
|
|
8
8
|
- **The control link is loopback plus a secret.** The daemon and the Codex proxy bind 127.0.0.1 only. The control WebSocket requires a per-run token (`.agenthub/state/control-token`, mode 600), and both servers refuse any request that carries an `Origin` header: any web page can open a WebSocket to localhost, and browsers always send `Origin`. External clients cannot claim the console user's id or a hub-managed peer's id.
|
|
9
|
-
- **Permission prompts stay on.** `ahub claude` and `ahub codex` add nothing that weakens the agents' own prompts. Kimi's and `local`'s permission requests are relayed to the console and cancelled after `approvals.timeout_s` (default 120 s) of silence; the macOS notification for a waiting request carries the peer and the tool name only. The one exception is the hub's own tools (`hub_send` and the task tools, matched by exact name): Kimi's requests for them are approved once without a prompt and logged by name, the same trust Codex gets through `approval_mode` in the hub's config. They
|
|
9
|
+
- **Permission prompts stay on.** `ahub claude` and `ahub codex` add nothing that weakens the agents' own prompts. Kimi's and `local`'s permission requests are relayed to the console and cancelled after `approvals.timeout_s` (default 120 s) of silence; the macOS notification for a waiting request carries the peer and the tool name only. The one exception is the hub's own tools (`hub_send` and the task tools, matched by exact name): Kimi's requests for them are approved once without a prompt and logged by name, the same trust Codex gets through `approval_mode` in the hub's config. They invoke hub-owned operations rather than arbitrary file or shell tools, and every call passes the hub's own checks. Identity comes from the exact permission title, or from the earlier tool-call title bound to the same call id and resolved against the configured MCP servers when the permission title contains argument JSON (Qwen). Payload text and unrelated display titles never establish identity. A payload longer than the console shows is marked as cut and never offers a session-wide grant. `--unattended` turns prompts off, says so loudly, and is never the default.
|
|
10
10
|
- **A committed config cannot choose launch commands, credential files, data endpoints or a wider sandbox.** The machine-local fields (`kimi_cmd`, `codex_bin`, `pi.cmd`, `checks`, `mlx.bin`, `mlx.runtimeDir`, `mlx.modelPath`, `omniroute.urls`, `omniroute.access_hosts`, the `omniroute` key files, `memory.worker_url`, `local.read_allow`, `local.bash_network`, `local.network_allow`) apply only from a config file git confirms nobody committed: `.agenthub/config.json` or `.agenthub/config.local.json`, matched by file identity so no other spelling the file system accepts slips past, and `.agenthub` itself not a committed symlink or submodule. Without a repository, or when git fails, they keep their defaults; an empty value always means the default. "Untracked" is answered by the repository that contains the project: a checkout copied or extracted into an unrelated repository, or into an ignored directory of one, is trusted like your own files. So a cloned repository cannot choose a launch command, a completion check, a gateway to send a key file to, a memory endpoint, or a wider sandbox. A command in `checks` runs as you, outside the local worker's sandbox, like a git hook. Nothing in `routing.toml` or in task text is ever run. `routing.toml` and the other shared fields still come from the checkout, and they matter: `routing.toml` picks the models the local worker and the hub's inference use at your gateway and can turn the PII constraint off, and roles and budget shape who does what. Review them in a repository you do not trust.
|
|
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. 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.
|
|
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
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.
|
|
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.
|
|
15
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) 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, 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/hooks` or `.git/config` writes; 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.
|
|
16
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.
|
|
17
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.
|
|
@@ -27,6 +28,30 @@ agent-hub connects agents that can each run commands. This page says what the hu
|
|
|
27
28
|
- **Network-level proof for PII.** The hub proves at its own boundaries (tests search every output) that PII text does not leave; packet-level verification of your gateway path is an operations check.
|
|
28
29
|
- **Other operating systems' sandboxes.** Only macOS seatbelt is implemented.
|
|
29
30
|
|
|
31
|
+
## Agent CLI identity and conductor authority
|
|
32
|
+
|
|
33
|
+
Inside an agent session, `ahub` identifies the caller from `AGENTHUB_PEER_ID`,
|
|
34
|
+
or the native Claude/Codex shell marker when the hub marker is absent. It connects
|
|
35
|
+
as that peer in tools mode. Messages and task changes retain that actor;
|
|
36
|
+
`say` defaults to status priority and important messages still require the peer's
|
|
37
|
+
capability. Conflicting or malformed markers fail closed. There is no `--as-user`.
|
|
38
|
+
Human-only operations are refused before connecting, including permission answers,
|
|
39
|
+
queue resolution, budget overrides, lifecycle and recovery operations, and `ask`.
|
|
40
|
+
The operator uses a plain terminal or `ahub console`. A Claude `!` command that
|
|
41
|
+
inherits the agent markers follows the same rule.
|
|
42
|
+
|
|
43
|
+
This is an honest default against accidental impersonation and injected commands.
|
|
44
|
+
It does not make the token inaccessible to an agent with unrestricted project
|
|
45
|
+
shell access. The existing OS sandbox and loopback authentication boundaries apply.
|
|
46
|
+
|
|
47
|
+
Steering tools require an explicit `conductor` role, independent of default-allow
|
|
48
|
+
capabilities. Only one peer may hold that role. A conductor may inspect public
|
|
49
|
+
state, assign or escalate work, start supported headless peers and place its own
|
|
50
|
+
delivery holds. It cannot answer approvals, resolve durable deliveries, override
|
|
51
|
+
budget pauses or release a human hold. Pending approval summaries exclude titles;
|
|
52
|
+
PII tasks remain public stubs. Conduct events contain ids only. Supervision feeds
|
|
53
|
+
use structured reasons and never carry check output or approval bodies.
|
|
54
|
+
|
|
30
55
|
## Reporting
|
|
31
56
|
|
|
32
57
|
Please report vulnerabilities privately through GitHub's "Report a vulnerability" on this repository rather than in a public issue.
|