@staix/agent-hub 0.34.1 → 0.35.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +47 -0
- package/README.md +35 -6
- package/docs/adding-an-ai-tool.md +2 -2
- package/docs/addons/claude-mem.md +4 -4
- package/docs/addons/open-code-review.md +1 -1
- package/docs/agent-notes/README.md +6 -0
- package/docs/agent-notes/adapters.md +9 -5
- package/docs/agent-notes/budget.md +1 -1
- package/docs/agent-notes/bus.md +1 -1
- package/docs/agent-notes/daemon.md +4 -3
- package/docs/agent-notes/local-worker.md +1 -1
- package/docs/agent-notes/models.md +2 -0
- package/docs/agent-notes/tasks.md +1 -1
- package/docs/agent-notes/tests.md +5 -0
- package/docs/design/adapters.md +110 -2
- package/docs/design/agent-hub-architecture.md +63 -1
- package/docs/design/agent-hub.md +6 -0
- package/docs/design/bus.md +18 -0
- package/docs/design/execution-reference.md +146 -0
- package/docs/design/task-board.md +10 -0
- package/docs/dogfood.md +33 -12
- package/docs/events.md +38 -20
- package/docs/memory.md +21 -7
- package/docs/operations.md +539 -24
- package/docs/quickstart.md +12 -4
- package/docs/research.md +71 -13
- package/docs/roles.md +1 -1
- package/docs/sdlc.md +9 -7
- package/docs/security.md +87 -11
- package/docs/smoke.md +14 -0
- package/docs/specs/2026-09-19-agent-hub-design.md +8 -3
- package/docs/verification/2026-11-07-compat-python-startup-1248.md +51 -0
- package/docs/verification/2026-11-07-compat-receipt-harness-1248.md +105 -0
- package/docs/verification/2026-11-07-compat-receipt-producers-1248.md +96 -0
- package/docs/verification/2026-11-07-compat-workflow-1248.md +94 -0
- package/docs/verification/2026-11-07-daemon-startup-1232.md +169 -0
- package/docs/verification/2026-11-07-jcode-receipt-reconstruction-1248.md +118 -0
- package/docs/verification/2026-11-07-kimi-delayed-usage.md +34 -0
- package/docs/verification/2026-11-07-kimi-review-watch-1284.md +115 -0
- package/docs/verification/2026-11-08-agy-1.5.3.md +96 -0
- package/docs/verification/2026-11-08-agy-acp-t0.md +56 -0
- package/docs/verification/2026-11-08-hub-visual-1058.md +161 -0
- package/docs/verification/2026-11-08-jcode-0991-model-setter-1317.md +143 -0
- package/docs/verification/2026-11-08-kimi-252-model-setter-1317.md +137 -0
- package/docs/verification/2026-11-08-kimi-tui-completion-1282.md +45 -0
- package/docs/verification/2026-11-08-kimi-wire-yield-1283.md +31 -0
- package/docs/verification/2026-11-08-live-model-override-1317.md +250 -0
- package/docs/verification/2026-11-08-qwen-0269-acp.md +138 -0
- package/docs/verification/2026-11-08-qwen-0269-model-setter-1317.md +91 -0
- package/docs/verification/2026-11-09-0.35.0.md +129 -0
- package/docs/verification/2026-11-09-headless-records-1320.md +157 -0
- package/docs/verification/claude-permission-transport-native.py +10 -3
- package/docs/verification/claude-shell-wrapper-native.py +8 -8
- package/docs/verified.json +245 -15
- package/package.json +3 -3
- package/plugins/agent-hub/.claude-plugin/plugin.json +1 -1
- package/plugins/agent-hub/kimi-hook.js +20397 -0
- package/plugins/agent-hub/kimi-review-policy-worker.js +217 -0
- package/plugins/agent-hub/server.js +2701 -664
- package/scripts/check-docs.mjs +12 -1
- package/src/adapters/acp-model-policy.ts +56 -0
- package/src/adapters/acp.ts +175 -5
- package/src/adapters/agy/entry.ts +8 -5
- package/src/adapters/agy/hooks.ts +65 -15
- package/src/adapters/channel-peer.ts +33 -1
- package/src/adapters/claude-implementer.ts +16 -3
- package/src/adapters/codex-appserver.ts +118 -8
- package/src/adapters/codex-review-isolation.ts +3 -1
- package/src/adapters/compat.ts +11 -6
- package/src/adapters/definitions/builtin-metadata.ts +8 -1
- package/src/adapters/definitions/native-cli-entry-kimi.ts +76 -7
- package/src/adapters/definitions/native-cli-preview-common.ts +2 -2
- package/src/adapters/definitions/native-cli-preview-kimi.ts +9 -2
- package/src/adapters/definitions/reviewer-variants.ts +3 -1
- package/src/adapters/kimi-review-policy-worker.js +2 -0
- package/src/adapters/kimi-review-policy-worker.ts +85 -0
- package/src/adapters/kimi-review-policy.ts +68 -0
- package/src/adapters/kimi-review.ts +41 -41
- package/src/adapters/kimi-tui-facts.ts +153 -0
- package/src/adapters/kimi-wire-usage.ts +33 -8
- package/src/adapters/local-worker.ts +59 -20
- package/src/adapters/model-token.ts +3 -0
- package/src/adapters/pi.ts +27 -5
- package/src/adapters/registry-types.ts +34 -3
- package/src/adapters/registry.ts +1 -0
- package/src/adapters/reviewer-policy-watch.ts +86 -0
- package/src/adapters/reviewer-print.ts +80 -18
- package/src/cli/agents.ts +1 -1
- package/src/cli/facts-hook.ts +4 -2
- package/src/cli/help.ts +3 -2
- package/src/cli/identity.ts +3 -0
- package/src/cli/kimi-facts-hook.ts +11 -0
- package/src/cli/kimi-plugin.ts +157 -0
- package/src/cli/main.ts +48 -9
- package/src/cli/model.ts +52 -0
- package/src/cli/output.ts +23 -1
- package/src/cli/reset.ts +1 -1
- package/src/cli/status-lines.ts +8 -4
- package/src/hub/budget.ts +1 -1
- package/src/hub/bus.ts +40 -2
- package/src/hub/code-facts.ts +10 -3
- package/src/hub/completions.ts +3 -1
- package/src/hub/config-apply.ts +2 -1
- package/src/hub/control-client.ts +1 -1
- package/src/hub/daemon.ts +1050 -106
- package/src/hub/deliverable-files.ts +38 -5
- package/src/hub/dogfood-profile.ts +1 -1
- package/src/hub/envelope.ts +1 -1
- package/src/hub/events.ts +28 -18
- package/src/hub/execution-lineage.ts +120 -0
- package/src/hub/execution-reference.ts +36 -0
- package/src/hub/hub-tools.ts +21 -2
- package/src/hub/instances.ts +4 -3
- package/src/hub/kimi-events.ts +46 -0
- package/src/hub/kimi-usage.ts +132 -29
- package/src/hub/lifecycle.ts +31 -15
- package/src/hub/limits.ts +13 -4
- package/src/hub/manager.ts +15 -2
- package/src/hub/memory-policy.ts +2 -1
- package/src/hub/memory-sync-attestation.ts +54 -0
- package/src/hub/memory-sync-state.ts +20 -5
- package/src/hub/model-overrides.ts +115 -0
- package/src/hub/native-hook-launch.ts +12 -3
- package/src/hub/operational-view.ts +2 -2
- package/src/hub/peers.ts +27 -0
- package/src/hub/permission-mode.ts +1 -1
- package/src/hub/person-figures.ts +88 -0
- package/src/hub/report.ts +38 -4
- package/src/hub/research-dataset.ts +158 -0
- package/src/hub/research-memory.ts +68 -0
- package/src/hub/research-quality.ts +118 -0
- package/src/hub/research-record.ts +279 -0
- package/src/hub/research.ts +126 -27
- package/src/hub/restart.ts +14 -0
- package/src/hub/settings.ts +3 -0
- package/src/hub/startup-event-seeds.ts +51 -0
- package/src/hub/startup-readiness.ts +65 -0
- package/src/hub/startup-timing.ts +38 -0
- package/src/hub/tasks.ts +29 -9
- package/src/hub/ui.ts +9 -5
- package/src/hub/visual-assets.ts +50 -0
- package/src/hub/visual.ts +257 -0
- package/src/memory/brief.ts +169 -14
- package/src/memory/capture.ts +2 -1
- package/src/memory/recall.ts +46 -5
- package/src/memory/record-provenance.ts +82 -0
- package/src/memory/records.ts +116 -0
- package/src/models/route/adec.ts +190 -0
- package/src/models/route/config.ts +37 -3
- package/src/models/route/decision-evidence.ts +83 -0
- package/src/models/route/decision.ts +143 -0
- package/src/models/route/runtime.ts +13 -6
- package/src/ui/index.html +134 -6
- package/src/ui/plugin.ts +65 -4
- package/templates/AGENTS.block.md +1 -1
- package/templates/config.json +1 -1
- package/templates/profiles/general.json +1 -1
- package/templates/profiles/research.json +1 -1
- package/templates/profiles/writing.json +1 -1
package/docs/design/adapters.md
CHANGED
|
@@ -79,6 +79,18 @@ Older daemons retain their existing close-and-retry standby behavior. An ordinar
|
|
|
79
79
|
owner departure may release an eligible standby through normal claim admission;
|
|
80
80
|
a standby never evicts a live owner without the person's takeover operation.
|
|
81
81
|
|
|
82
|
+
The detailed status the console reads also names the current owner (#1310), so it is never
|
|
83
|
+
inferred from standby rows, process start times or attach order. `ownerAttachment` holds the
|
|
84
|
+
current socket's bounded `ownerPid` when it reported one, `attachedAt` (when the asynchronous
|
|
85
|
+
attach completed, not the earlier hello), and `nativeSessionId` only after the host bound a native
|
|
86
|
+
session through its verified native-facts path and only when it is a short plain token. It is
|
|
87
|
+
absent while a newer hello is claiming, while offline, and after a detach, roster removal or stop,
|
|
88
|
+
and a new attach replaces every field in one step, so a previous owner's pid, time or native
|
|
89
|
+
session never sits beside the new socket. It is display metadata, never authentication, delivery,
|
|
90
|
+
takeover or permission evidence. It carries no environment, argv, cwd, credential, prompt, title
|
|
91
|
+
or text, adds no event, log or memory payload, and is withheld from `status.json` and every
|
|
92
|
+
non-console reader. The field is additive and optional; no control protocol version changes.
|
|
93
|
+
|
|
82
94
|
## Accepted channel delivery settlement (#1172)
|
|
83
95
|
|
|
84
96
|
Only an attached push channel opts into explicit disposition of its own accepted delivery. An `accepted` receipt acknowledges that the notification was accepted by the channel transport; it is not a native handling or task-completion signal. The host reads `bus.accepted_settle_ms` from accepted configuration on its existing maintenance sweep, defaulting to ten minutes. A row that remains unconfirmed becomes `needs_review` with no replay. `hub_inbox` returns bounded id/revision metadata for the channel's accepted and held rows, including when an accepted push prevents the pull itself. The plugin renders that metadata and avoids both an empty-inbox claim and polling advice while there is an actionable row. Important, task and review timeouts produce one durable status-kind, status-priority conductor message containing ids only when the existing `conductor.feed` policy is on; `feed: off` remains an opt-out. Pull-only sessions do not gain the explicit accepted-disposition port.
|
|
@@ -89,16 +101,104 @@ Permission modes control whether native actions prompt; they do not widen a sand
|
|
|
89
101
|
|
|
90
102
|
When the hub starts a child, the host constructs its environment, binds its launch and generation, and owns its process-group lifecycle. Stop and recovery require current evidence for the process actually started; a PID, adapter label, successful start call, or stale session record is not enough. This keeps teardown from signaling a person's unrelated process and prevents a late native callback from acquiring a replaced session's authority ([#115](https://github.com/STAIxBWLB/agent-hub/issues/115), [#625](https://github.com/STAIxBWLB/agent-hub/issues/625)).
|
|
91
103
|
|
|
104
|
+
Fresh Kimi reviews keep the complete synchronous isolation fence before spawn and
|
|
105
|
+
at verdict/task-MCP authority boundaries. Periodic full checks use one review-owned
|
|
106
|
+
worker with expected paths and fingerprints, no serialized task text or inherited
|
|
107
|
+
environment, and boolean replies. A serialized 100 ms absolute cadence coalesces
|
|
108
|
+
missed ticks without overlapping checks or adding a fixed delay after a slow check.
|
|
109
|
+
Worker results cannot grant or restore authority. Revocation fences the exact
|
|
110
|
+
child/review sequence; worker termination and join precede private-profile removal
|
|
111
|
+
and confirmed input cleanup, including failed native teardown. An unconfirmed join
|
|
112
|
+
retains ownership and the profile for an explicit stop retry ([#1284](https://github.com/STAIxBWLB/agent-hub/issues/1284)).
|
|
113
|
+
|
|
92
114
|
Permission decisions are bound to the authenticated caller and current session. A hub CLI call inside an agent session acts as that peer, not as the person; role and task checks still apply at each tool boundary. Permission modes are person-controlled, and a conductor role does not grant them. This avoids turning a received message into user consent ([#193](https://github.com/STAIxBWLB/agent-hub/issues/193), [#242](https://github.com/STAIxBWLB/agent-hub/issues/242)).
|
|
93
115
|
|
|
94
116
|
## Model, account, and memory boundaries
|
|
95
117
|
|
|
96
|
-
Subscription-based native CLIs keep their own account authentication; those credentials are not pooled through the hub. Hub-owned inference, including internal summaries and local-worker model calls, uses the in-process model route and OmniRoute provider boundary. Prompt text may inform configured routing, but it cannot grant credential access or replace host routing policy. This separates native subscription identity from hub service credentials ([#553](https://github.com/STAIxBWLB/agent-hub/issues/553)).
|
|
118
|
+
Subscription-based native CLIs keep their own account authentication; those credentials are not pooled through the hub. Hub-owned inference, including internal summaries and local-worker model calls, uses the in-process model route and OmniRoute provider boundary. Prompt text may inform configured routing, but it cannot grant credential access or replace host routing policy. The optional local-worker adec consumer (#554) releases only bounded host-screened evidence, after campus/privacy and observer admission; native account, TUI, reviewer and task-assignment authority are unchanged. Shadow preserves the gateway model/effort and conversation; enforcement is refused at configuration load and no pair is applied. An explicit live model override bypasses the decision service. Current board/turn privacy and observer authority fence the optional request across waits and its proposal before telemetry; an authority change refuses the stale turn, and the refusal is not converted into a fixed-model fallback. There is no new gateway or native turn/spawn effort path. This separates native subscription identity from hub service credentials ([#553](https://github.com/STAIxBWLB/agent-hub/issues/553)).
|
|
97
119
|
|
|
98
120
|
The PII screen is distinct from ordinary optional inference. It may use an on-device model; a gateway screen requires positive on-campus admission and `onCampusOnly`. If no allowed path returns a closed `clear` or PII verdict before the deadline, the result is unknown and handled as private. This keeps network and model uncertainty from becoming a disclosure ([#198](https://github.com/STAIxBWLB/agent-hub/issues/198)).
|
|
99
121
|
|
|
100
122
|
Runtime memory capture and recall use the in-process `@staix/agent-mem` package, screened and invoked by host integration. claude-mem is off by default and import-only; there is no worker HTTP or model-summary path in the runtime. This avoids a parallel capture route with different privacy checks ([#752](https://github.com/STAIxBWLB/agent-hub/issues/752), [agent-mem#13](https://github.com/STAIxBWLB/agent-mem/issues/13)).
|
|
101
123
|
|
|
124
|
+
## Person-owned live model selection (#1317)
|
|
125
|
+
|
|
126
|
+
A person may store a per-peer model override in `hub.db` with `ahub model set`,
|
|
127
|
+
clear it with `ahub model clear`, or inspect it with `ahub model list`. The CLI
|
|
128
|
+
uses the settings command's identity boundary, but all model subcommands are
|
|
129
|
+
person-only, including list. Dashboard changes use the existing person settings
|
|
130
|
+
session and preview/confirm flow. No hub tool, conductor role or agent shell
|
|
131
|
+
receives this authority. Provider, account, native home and executable changes
|
|
132
|
+
remain on their existing machine-local configuration paths.
|
|
133
|
+
|
|
134
|
+
The host stores desired state independently of an active turn. A model selection
|
|
135
|
+
is captured once at the next supported turn/review boundary and stays unchanged
|
|
136
|
+
through steering and local tool rounds. Captured application callbacks bind the
|
|
137
|
+
exact adapter owner and turn; they cannot mark a newer desired revision applied.
|
|
138
|
+
Two changes before a turn leave the last desired value. Status distinguishes the
|
|
139
|
+
effective selection, its source, a pending next-turn value and unsupported live
|
|
140
|
+
selection; a desired row alone is never evidence that a native model accepted it.
|
|
141
|
+
The precedence is override, instance model, launch model, then native default,
|
|
142
|
+
where the surface already supports that source. An unknown native default stays
|
|
143
|
+
unknown rather than becoming an invented model id.
|
|
144
|
+
|
|
145
|
+
Claude headless implementers select `--model` per spawned turn; codex-review
|
|
146
|
+
selects `-m` per isolated review spawn. Supported Codex app-server `turn/start`
|
|
147
|
+
requests carry `model` only for an override, alongside the existing permission
|
|
148
|
+
policy. Both hub-delivered and client-forwarded app-server `turn/start` paths
|
|
149
|
+
support it, but an explicit client model (for example the person's native
|
|
150
|
+
`/model` choice) wins and is never rewritten. The app-server retains a
|
|
151
|
+
`turn/start` model as its thread default. Clearing the hub override returns
|
|
152
|
+
selection to that current native default; it does not reconstruct an earlier
|
|
153
|
+
thread model. Native client acceptance does not certify a conflicting hub
|
|
154
|
+
override as applied. Raw or pull-only `WsPeer` TUI attachments remain unsupported.
|
|
155
|
+
When clear retains an acknowledged former override as the thread default,
|
|
156
|
+
status labels its source `native thread default (was override)`. A rejected
|
|
157
|
+
start retires its unused capture so a later start can sample a corrected choice;
|
|
158
|
+
an older rejection cannot retire a newer accepted or pending start.
|
|
159
|
+
`turn/steer` never acquires a model field. Local uses the existing direct
|
|
160
|
+
OmniRoute model path for an explicit override while retaining budget, campus,
|
|
161
|
+
observer and generation guards. Pi reuses its model-selection path at the next
|
|
162
|
+
turn and retains a separate baseline so clear can restore normal selection.
|
|
163
|
+
Existing no-override behavior and native permission/isolation proofs stay intact.
|
|
164
|
+
|
|
165
|
+
Live ACP selection requires two independent facts: the existing native admission
|
|
166
|
+
and an exact-version model-free setter receipt. Qwen and Jcode compatibility
|
|
167
|
+
admission includes the person's existing exact-version trust; Kimi headless uses
|
|
168
|
+
its existing native-identity admission, independently of Kimi reviewer isolation
|
|
169
|
+
compatibility. Only Kimi Code CLI 2.5.2 headless is currently enabled, through
|
|
170
|
+
`session/set_config_option` with `configId: model` and the
|
|
171
|
+
[model-free setter receipt](../verification/2026-11-08-kimi-252-model-setter-1317.md).
|
|
172
|
+
Qwen remains unavailable because its native clear fixture observed A/B/B after
|
|
173
|
+
ACKs for B then A. Jcode headless A/B/A passed, but its shared-TUI turn fence
|
|
174
|
+
across failover remains unqualified; its production setter stays unavailable. A native TUI or external adapter cannot acquire a setter from an
|
|
175
|
+
advertisement or a registry label.
|
|
176
|
+
|
|
177
|
+
The host captures one selection before awaiting a setter, validates bounded
|
|
178
|
+
current-session model choices and owned process identity, then sends the prompt.
|
|
179
|
+
Setter acknowledgement and model/config notifications are not prompt admission:
|
|
180
|
+
only current prompt activity or successful completion acknowledges application.
|
|
181
|
+
An unanswered setter leaves native selection unknown and takes the peer offline
|
|
182
|
+
through its owned stop path. Trust revocation is rechecked before the prompt.
|
|
183
|
+
Clear restores the validated pre-override session baseline, with instance and
|
|
184
|
+
launch precedence retained; status does not expose a pending setter target as
|
|
185
|
+
that baseline. Unsupported no-override delivery retains its ordinary behavior;
|
|
186
|
+
a retained override instead refuses before a prompt until the person clears it
|
|
187
|
+
or starts a supported owner.
|
|
188
|
+
|
|
189
|
+
Fresh reviewer variants explicitly strip inherited model capability. Only an
|
|
190
|
+
explicit per-spawn capability, such as codex-review, receives a model getter;
|
|
191
|
+
a long-lived ACP policy never enables the reviewer print path. Unsupported
|
|
192
|
+
surfaces refuse a live set with a cause and `ahub restart <peer>` as the next
|
|
193
|
+
step, without storing a newly refused override or restarting anything.
|
|
194
|
+
|
|
195
|
+
Overrides survive daemon restart and are cleared by runtime reset. Retained
|
|
196
|
+
state must remain protected by recovery feature/integrity admission. Model ids
|
|
197
|
+
use the existing #844 bounded token rule, with no spaces or leading dash.
|
|
198
|
+
`model_change` records only peer, previous/new ids, person surface and a next-turn
|
|
199
|
+
boundary, never prompts or credentials. A future native turn id is not invented;
|
|
200
|
+
`appliesFrom: next_turn` and an existing `afterTurn` identify the boundary.
|
|
201
|
+
|
|
102
202
|
## Compatibility and external modules
|
|
103
203
|
|
|
104
204
|
Native CLI compatibility is centralized in `compat.ts`. Each gated operation asks that policy for a verified, in-contract, person-trusted, or refused result; person trust for one exact version does not skip a separate isolation or runtime proof. This lets upstream versions change without turning an untested protocol assumption into support ([#691](https://github.com/STAIxBWLB/agent-hub/issues/691)).
|
|
@@ -107,7 +207,9 @@ External adapter modules are an explicit, person-owned, machine-local opt-in. Th
|
|
|
107
207
|
|
|
108
208
|
`questionWaitMs` (#1053) is the time a `hub_ask` call waits for the person before it answers `pending`. It is a fixed-builtin field like `title`: `assertNativeCapabilityScope` refuses it on a configured or external definition, and the person overrides it per kind with `questions.wait_ms.<kind>`, never the caller. MCP peers carry 45 s, Pi and the local worker 300 s, provisional until the live timeout measurements of #1053 T1.
|
|
109
209
|
|
|
110
|
-
`settle` (#1054) is the code-verified signal that ends a peer's logical run, so the hub can create a completion for a run a person started. It is a fixed-builtin field like `questionWaitMs`: `assertNativeCapabilityScope` refuses it on a configured or external definition. **Owner decision 2026-11-04 (issue #1054):** completions exist only for adapters whose signal the T1 audit verified in code. Claude's TUI (`native-stop`: the transcript-verified Stop, never a lost channel or watchdog) and headless implementer, Codex (`turn-completed`), Pi (`agent-settled`, its own event: the `agent_end` plus retry/compaction fallback is not implemented), the local worker (`route-outcome`), ACP Kimi and Jcode headless (`prompt-response`) and the Qwen TUI (`message-stop`) declare one. **Absent means no completions:**
|
|
210
|
+
`settle` (#1054) is the code-verified signal that ends a peer's logical run, so the hub can create a completion for a run a person started. It is a fixed-builtin field like `questionWaitMs`: `assertNativeCapabilityScope` refuses it on a configured or external definition. **Owner decision 2026-11-04 (issue #1054):** completions exist only for adapters whose signal the T1 audit verified in code. Claude's TUI (`native-stop`: the transcript-verified Stop, never a lost channel or watchdog) and headless implementer, Codex (`turn-completed`), Pi (`agent-settled`, its own event: the `agent_end` plus retry/compaction fallback is not implemented), the local worker (`route-outcome`), ACP Kimi and Jcode headless (`prompt-response`) and the Qwen TUI (`message-stop`) declare one. **Absent means no completions:** agy (its declared `native-hook` signal is not verified end to end) and phase-2 person-typed Codex turns declare none, and an unattached pull-only peer starts no run. agy joins after a live receipt verifies its Stop readback and completion row; Codex person-typed turns after an origin receipt. The settle rule, outcomes and restart reconstruction live in `src/hub/completions.ts` and `src/hub/completions-store.ts`; a run settles only when the adapter signal fired AND no queued continuation, open permission or question, owned child, running check or held delivery remains.
|
|
211
|
+
|
|
212
|
+
Kimi 2.5.2's own TUI also earns completions, but only through the `ahub kimi` launcher's ephemeral `native_hook_launch` and local plugin (#1282). The plugin record binds the launch to its owner pid and process signature. A different launch may replace it only when that owner is proven gone; an active or unknown owner, including one from another project sharing the native home, is left unchanged. Replacement and cleanup share one fail-closed lock per native home, with no automatic stale-lock deletion. If begin or setup fails, the launcher reports the cause and starts the plain TUI without completion receipts. Quiet background/final-turn re-reads back off from 250 ms to 1 s, and the 2 s Stop deadline also arms them. A hook is a candidate observation, never proof. The daemon admits only the exact `kimi-tui` compat version and binds the observation to daemon, launch, native home, native session, project and current socket generation. The transcript's `turn.prompt` supplies the origin and turn id; its final `turn.ended` supplies the outcome. `prompt.completed` and `prompt.aborted`, when present, must agree with that turn; a notification may omit both id forms, so the native notification id or turn id is the fallback identity. A blocked Stop has no final row, so it cannot settle. StopFailure needs `failed`, Interrupt stays quiet with no result, and launcher loss or daemon reconstruction creates at most one `interrupted`. Every native-person result is private because the hook path cannot prove it is public. Headless ACP keeps `prompt-response`; an unverified TUI version or a launch without these readbacks keeps the old no-completion behavior. Native background task files supply the count or an explicit unknown; work or an unreadable inventory never settles. A 250 ms re-read covers missing TaskStarted/Notification hooks without turning elapsed time into evidence. No prompt, answer, error, task command or title reaches completion rows, events, logs or memory. The exact-version receipt is `docs/verification/2026-11-08-kimi-tui-completion-1282.md`.
|
|
111
213
|
|
|
112
214
|
## Session title slots
|
|
113
215
|
|
|
@@ -182,3 +284,9 @@ When a quote-bearing review reaches a peer without a stable native session ID, t
|
|
|
182
284
|
## Local review turns (#1056)
|
|
183
285
|
|
|
184
286
|
The local worker binds review observer exclusion to its actual input envelopes before awaiting model or tool work. An anchored `hub_review` submission latches that exclusion for the rest of the batch/turn, including sibling and later tool calls. While latched, `hub_remember` and `hub_task_propose` are refused before reaching the host task tools; the caller can retry them in a later ordinary turn. Such turns do not call capture, commit review messages into later model history, or put provider error text and partial model text in failure logs. A later ordinary local turn resumes ordinary history and capture without inheriting the review payload. This is distinct from the PII policy: a public review package retains ordinary task authority and does not acquire an on-campus-only model route. Vendor-native histories remain owned by their adapters; the hub's current-turn and named-parent observer provenance is described in [the bus contract](bus.md#review-observer-provenance-1056).
|
|
287
|
+
|
|
288
|
+
## Headless Record boundaries (#1320)
|
|
289
|
+
|
|
290
|
+
Only a host-owned getter supplies the imported agent-mem instruction at an admitted headless turn boundary, after owned input and busy state exist and before the native prompt/model request. Multi-call local turns keep one fixed prompt. Native-client prompts, steer, Claude hooks and isolated reviewers keep their separate surfaces. A getter failure omits optional Record guidance and does not change ordinary routing. The production getter reads the public `recordsEnabled(activeHome, executionCwd)` accessor from the exact-pinned amem package; either machine or repository false disables the optional Record path. Its boolean revision is not a privacy-policy fingerprint: current package and hub screens are rechecked separately before effects.
|
|
291
|
+
|
|
292
|
+
Model final output uses a host-only final-answer callback distinct from explicit send tools and diagnostic messages. Only normal completion can append Record rows; partial output is stripped for sharing without certifying a settled record. Capture binds immutable owner, turn, session/generation, execution cwd, profile and policy identity. Replacement, exclusion or unsafe steering revokes the frame before any later append. This grants no task, permission, native consumption or model acceptance authority.
|
|
@@ -90,14 +90,76 @@ returns an ids-only receipt and excludes its arguments/results from capture.
|
|
|
90
90
|
Its T1 authorization, revision and recovery boundaries are defined in
|
|
91
91
|
[the task-board contract](task-board.md#claim-evidence-records-931-t1).
|
|
92
92
|
|
|
93
|
+
## Bounded visual attachments (#1058)
|
|
94
|
+
|
|
95
|
+
Bounded visual attachments (#1058) are local project records in `hub.db`, separate
|
|
96
|
+
from task transitions and delivery receipts. The hub validates and privacy-screens
|
|
97
|
+
the exact acon `VisualPayload` shape; peers receive only a sanitized stub with
|
|
98
|
+
`refs.visual`, and explicitly request the source through a guarded read. acon owns
|
|
99
|
+
rendering and its sandbox; the standalone dashboard uses text/source fallback.
|
|
100
|
+
The hub imports contract types only, with no renderer or new runtime dependency.
|
|
101
|
+
Image bytes use the existing guarded deliverable reader and current hash/policy
|
|
102
|
+
checks; console asset identifiers bind their originating project and instance.
|
|
103
|
+
Raw visual tool arguments/results never enter observer capture, even on refusal.
|
|
104
|
+
The unchanged acon shape has additional hub admission ceilings: 1 MiB serialized
|
|
105
|
+
payload; UTF-8 bytes Mermaid source 20 KiB, title 300, caption 2000, alt 1000,
|
|
106
|
+
text side 20 KiB, option
|
|
107
|
+
summary 4000, each pro/con 2000, table cell 4000, key 128, path 4096 and asset
|
|
108
|
+
reference 256. These are hub limits, not a claim that acon imposes each limit;
|
|
109
|
+
validation refuses rather than truncates. acon counts Mermaid UTF-16 code units
|
|
110
|
+
and leaves captions unbounded, while the hub counts UTF-8 bytes. All 42 published
|
|
111
|
+
acon 0.1.7 visual cases are consumed directly; six named valid-acon cases are
|
|
112
|
+
rejected only by these stricter source/caption/asset-ID ceilings. Historical
|
|
113
|
+
hub-owned cases remain extra coverage, not a substitute for the shared fixture.
|
|
114
|
+
|
|
115
|
+
Periodic dashboard snapshots and task lists project bounded, screened metadata
|
|
116
|
+
only; they do not deserialize or screen complete visual payloads. Explicit show
|
|
117
|
+
and asset requests perform the full current-policy checks. A missing image does
|
|
118
|
+
not erase its visual's public explanation; asset existence and hash validation
|
|
119
|
+
belong to the guarded asset read. Non-sensitive refusals identify recovery,
|
|
120
|
+
authority, concurrent change or unavailable screening and their repair action;
|
|
121
|
+
sensitive privacy refusals keep a uniform message.
|
|
122
|
+
|
|
123
|
+
Publication does a non-consuming rate check before model screening or image
|
|
124
|
+
reads and still consumes admission once immediately before publication. Visuals
|
|
125
|
+
are explanatory output, not task progress for no-write detection.
|
|
126
|
+
Held controlled recovery compares retained visual integrity before startup
|
|
127
|
+
retention pruning; startup, periodic and tool pruning all wait until both the
|
|
128
|
+
recovery transaction and bus recovery hold are clear.
|
|
129
|
+
|
|
93
130
|
## Models and memory
|
|
94
131
|
|
|
95
|
-
|
|
132
|
+
|
|
133
|
+
Peer selection, hub-owned model routing, and provider access are distinct layers. Task routing chooses a peer; the in-process route selects a model for hub-owned inference; OmniRoute owns provider keys, provider fallback, and usage. Native CLIs retain their own account and provider configuration; subscription OAuth credentials are not pooled through the gateway. The former Switchyard sidecar is retired; routing now runs in process. An opt-in `decision` route may consult the loopback agent-decide policy service; execution and provider access remain in the hub and OmniRoute, with the existing heuristic as the consumer fallback. This keeps worker-provider credentials and provider failover in one gateway; the optional policy consult does not proxy the worker's inference traffic ([#553](https://github.com/STAIxBWLB/agent-hub/issues/553)).
|
|
134
|
+
|
|
135
|
+
Person-owned live model overrides (#1317) are runtime state in `hub.db`, not
|
|
136
|
+
configuration edits. The host owns person admission, desired-versus-applied
|
|
137
|
+
selection, next-turn fencing, status and audit; adapters acknowledge only their
|
|
138
|
+
own captured spawn/transport acceptance. The override does not grant a model,
|
|
139
|
+
provider or account authority to a peer. Unsupported surfaces remain unsupported
|
|
140
|
+
without automatic restarts. Tier 3 configuration, recovery and native isolation
|
|
141
|
+
boundaries stay in place; the [adapter contract](adapters.md#person-owned-live-model-selection-1317)
|
|
142
|
+
defines supported turn paths and evidence limits.
|
|
96
143
|
|
|
97
144
|
The hub's portable memory storage, sync, indexing, and project helpers come from the pinned first-party `@staix/agent-mem` package. `src/memory/` and `Tasks` provide hub-specific capture, recall, privacy screening, task briefs, and shared notes. Runtime memory is in-process: there is no claude-mem worker HTTP client or model summarizer. claude-mem is an off-by-default, import-only source. This removes a second capture path while keeping caller authority and task privacy in the hub ([#752](https://github.com/STAIxBWLB/agent-hub/issues/752), [agent-mem#13](https://github.com/STAIxBWLB/agent-mem/issues/13)).
|
|
98
145
|
|
|
99
146
|
Long-term hub writes and core promotion callbacks use the configured standalone sync policy plus hub narrowing. Profile readiness is independent of the current daemon's last automatic sync result. Public status exposes safe cause/count/action metadata; person-only declined inspection exposes IDs and rule categories, with explicit incomplete state when the portable core cannot supply a bounded physical view. Portable row placement and physical sync inspection remain agent-mem responsibilities.
|
|
100
147
|
|
|
148
|
+
|
|
149
|
+
The adec backend (#554) is default-off and shadow-first. A shadow pick changes
|
|
150
|
+
neither the heuristic model/effort nor the forwarded conversation. The service
|
|
151
|
+
owns question assembly, hard rules, thresholds, pins and policy fallback; the hub
|
|
152
|
+
owns allowed-pair validation, its default-off shadow switch, current turn and
|
|
153
|
+
budget/campus admission, and original gateway execution. `enforce` is refused at configuration load and
|
|
154
|
+
no pick is applied in this delivery. The bounded evidence
|
|
155
|
+
builder runs only after admission and uses the host public-view screen; it never
|
|
156
|
+
sends tool arguments, system instructions or full history. Sensitive turns are
|
|
157
|
+
campus-gated before evidence and carry dimensions only plus privacy flags.
|
|
158
|
+
Review-observer and remote inputs do not reach this optional observer. Route
|
|
159
|
+
records retain closed metadata, not evidence or service error prose. Direct
|
|
160
|
+
System One integration, the optional stage classifier and the manual triage
|
|
161
|
+
comparison remain outside this consumer slice.
|
|
162
|
+
|
|
101
163
|
## Privacy and recovery
|
|
102
164
|
|
|
103
165
|
Session titles for the two hub-owned title slots (#1055) are conditional writes
|
package/docs/design/agent-hub.md
CHANGED
|
@@ -25,6 +25,12 @@ The core loop is to propose and assign work, exchange addressed messages while p
|
|
|
25
25
|
|
|
26
26
|
The hub also owns a local worker and optional model calls for its own inference. It does not replace every native agent with that loop, pool subscription credentials, or make native behavior identical across vendors. Native adapters preserve those differences behind explicit contracts ([#625](https://github.com/STAIxBWLB/agent-hub/issues/625), [#553](https://github.com/STAIxBWLB/agent-hub/issues/553)).
|
|
27
27
|
|
|
28
|
+
Bounded local visual attachments let ordinary peers explain public work with a
|
|
29
|
+
diagram, comparison, table or before/after view. The hub stores and screens the
|
|
30
|
+
record while acon renders it; recipients receive a text stub, and the standalone
|
|
31
|
+
dashboard retains a readable source fallback. This adds no renderer, native-agent
|
|
32
|
+
authority or cross-project board to the hub ([#1058](https://github.com/STAIxBWLB/agent-hub/issues/1058)).
|
|
33
|
+
|
|
28
34
|
## Product decisions
|
|
29
35
|
|
|
30
36
|
| Current rule | Reason and deciding issue |
|
package/docs/design/bus.md
CHANGED
|
@@ -31,6 +31,18 @@ The bus applies limits to a sender, sender-recipient pair, important messages, a
|
|
|
31
31
|
|
|
32
32
|
## Queues and delivery outcomes
|
|
33
33
|
|
|
34
|
+
`hub_visual` (#1058) publishes only a bounded chat stub naming a local visual
|
|
35
|
+
record through `refs.visual`. Its default audience is the console at FYI priority;
|
|
36
|
+
explicit recipients use existing addressed-message rules. Neither Mermaid source,
|
|
37
|
+
table/comparison bodies nor image bytes are embedded in the envelope or delivery
|
|
38
|
+
journal. A source read is explicit, local to the project and privacy-guarded.
|
|
39
|
+
Visual publication grants no task, native-session, invocation or broker authority.
|
|
40
|
+
Before expensive visual screening or image reads, `Limiter.peek` uses the same
|
|
41
|
+
admission decision as `admit` without changing buckets or repeat history. The
|
|
42
|
+
final `admit` still consumes once against current state before record/publication
|
|
43
|
+
effects; a successful preflight never reserves or grants future delivery.
|
|
44
|
+
|
|
45
|
+
|
|
34
46
|
The in-memory bus schedules messages; `DeliveryJournal` durably records an individual transport attempt and the original envelopes behind any rendered output. A peer receipt such as `accepted` or `completed` describes transport, not the corresponding task's acceptance, completion, or approval. That separation lets a timeout or restart remain explicitly uncertain without inventing a task outcome ([#37](https://github.com/STAIxBWLB/agent-hub/issues/37)).
|
|
35
47
|
|
|
36
48
|
A closed bus returns an empty publication outcome before provenance, privacy,
|
|
@@ -297,3 +309,9 @@ step. Support is rechecked across awaited admission and at actual publication.
|
|
|
297
309
|
Live signed observations are scoped to the current connection and roster; saved,
|
|
298
310
|
stale or replayed presence never grants codec support. Existing native, exposure,
|
|
299
311
|
privacy and invocation authorization checks still decide whether a send is allowed.
|
|
312
|
+
|
|
313
|
+
## Record final-answer projection (#1320)
|
|
314
|
+
|
|
315
|
+
The final-answer boundary strips agent-authored `amem:` lines before invocation answer handling, ordinary publication, journaled/shared bodies, digest rendering or console envelope taps. Explicit send tools keep their existing path. Original priority and audience/hop/receipt rules are retained. Stripping runs even when optional capture is disabled or fails. Final dispatch traverses the current `onMessage` observer chain exactly once. A peer/body/options-scoped host marker identifies the final-only raw capture path, is consumed before nested messages and is restored or cleared on exit; no final marker is accepted from a wire envelope. Stale replaced owners cannot route or capture a final answer.
|
|
316
|
+
|
|
317
|
+
The raw-final capture observer is host-only and limited to a complete, currently owned public turn. Private inputs or outputs, review/observer holds, remote inputs/audiences, invocation answers and unknown parents cannot reach it. Count-only observers cannot change routing. The memory owner applies current policy before storage or selection; captured Record rows remain uncurated reference data. A bounded, ephemeral saved-ID/raw-anchor registry can prove display substitution for generated notes, with no persistence or inference from titles or prose. Restart and eviction preserve unproved old content.
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: execution-reference
|
|
3
|
+
type: module
|
|
4
|
+
title: Execution Reference and Bounded Lineage
|
|
5
|
+
status: draft
|
|
6
|
+
parent: agent-hub-architecture
|
|
7
|
+
depends-on: [task-board, bus]
|
|
8
|
+
references: [task-board, bus]
|
|
9
|
+
implements: []
|
|
10
|
+
covers: [execution-reference]
|
|
11
|
+
tags: [agent-hub]
|
|
12
|
+
paths:
|
|
13
|
+
- src/hub/execution-reference.ts
|
|
14
|
+
- src/hub/execution-lineage.ts
|
|
15
|
+
- test/execution-reference.test.ts
|
|
16
|
+
- test/execution-lineage.test.ts
|
|
17
|
+
- test/fixtures/execution-reference-v1.json
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
# ExecutionReferenceV1
|
|
21
|
+
|
|
22
|
+
Source-owner contract for [#1220](https://github.com/STAIxBWLB/agent-hub/issues/1220).
|
|
23
|
+
T1 supplies an address validator, neutral vectors and a pure reader. T2 owns
|
|
24
|
+
Tasks admission and CLI/MCP wiring; T3 owns the console and measured performance.
|
|
25
|
+
There is no new persistence, automatic resolver or runtime polling in T1.
|
|
26
|
+
|
|
27
|
+
## Address contract
|
|
28
|
+
|
|
29
|
+
An address is `{v: 1, tool, projectKey, kind, id, revision?, sha256?}`.
|
|
30
|
+
It names evidence; it does not attest to it or grant access to it.
|
|
31
|
+
|
|
32
|
+
| Field | Rule |
|
|
33
|
+
| --- | --- |
|
|
34
|
+
| `v` | Exactly the integer 1 |
|
|
35
|
+
| `tool` | Known producer id: `ahub`, `ares`, `amem`, `vmem` |
|
|
36
|
+
| `projectKey` | Opaque producer project identity, nonempty, at most 256 UTF-8 bytes |
|
|
37
|
+
| `kind` | Producer-namespaced by `(tool, kind)`, lowercase token matching `[a-z][a-z0-9._-]*`, at most 64 bytes |
|
|
38
|
+
| `id` | Opaque source identity, nonempty, at most 256 UTF-8 bytes |
|
|
39
|
+
| `revision` | Optional nonempty opaque source revision, at most 128 UTF-8 bytes |
|
|
40
|
+
| `sha256` | Optional lowercase 64-hex content hash |
|
|
41
|
+
|
|
42
|
+
Reject unknown fields, unsupported producers/versions, null optional fields,
|
|
43
|
+
control characters, unpaired surrogates, accessors, symbol keys and inherited
|
|
44
|
+
objects. Do not trim, case-fold or Unicode-normalize identity. Absent optional
|
|
45
|
+
fields stay absent. The producer vocabulary identifies owners, not enabled
|
|
46
|
+
resolvers: an unknown kind can be syntactically valid yet unsupported by its owner.
|
|
47
|
+
Consumers validate this boundary locally without importing hub internals or a new
|
|
48
|
+
shared runtime dependency. Neutral valid/invalid JSON vectors live in
|
|
49
|
+
`test/fixtures/execution-reference-v1.json`; UTF-8 limits include multibyte cases.
|
|
50
|
+
|
|
51
|
+
A path-like or URL-like id is still opaque data. Never open, execute, fetch,
|
|
52
|
+
route to another node or interpret credentials from any address field. A resolver
|
|
53
|
+
must separately select a known source owner and its authorized project; no
|
|
54
|
+
implicit node or project fallback is allowed.
|
|
55
|
+
|
|
56
|
+
## Pure source boundary
|
|
57
|
+
|
|
58
|
+
`readExecutionLineage(source, query)` receives a host-owned snapshot of an explicit
|
|
59
|
+
root neighborhood and returns values only. It does not construct a Board,
|
|
60
|
+
DeliveryJournal or CompletionStore (their constructors can write), read files,
|
|
61
|
+
call a model, spawn a process, probe, replay, fetch or write memory. T2 must reuse
|
|
62
|
+
already-open owner readers and indexed relationships to assemble the snapshot;
|
|
63
|
+
it must not scan the entire board on every inbox poll.
|
|
64
|
+
|
|
65
|
+
The host pins `id`, `revision`, `projectKey` and caller `scope`, source `health`,
|
|
66
|
+
source-read `authorized` authority and diagnostic authority. These are never
|
|
67
|
+
accepted from a producer or query. A snapshot contains metadata nodes and explicit
|
|
68
|
+
edges, already privacy-projected by the source owner. Each node carries its own
|
|
69
|
+
source reference, state token and evidence strength; no title, note, path,
|
|
70
|
+
session-native identifier or review body enters this projection. States keep
|
|
71
|
+
their owner's meaning: a completed dispatch is not a successful attempt; an
|
|
72
|
+
approved review does not change a failed attempt.
|
|
73
|
+
|
|
74
|
+
Evidence strengths are `declared`, `host-observed`, `runner-attested` and
|
|
75
|
+
`unknown`. Relations are `dispatched`, `attempted`, `produced`, `reviewed` and
|
|
76
|
+
`declared-external`. An edge is emitted only when both endpoints are visible.
|
|
77
|
+
An external declaration remains declared; a reference/hash never upgrades it.
|
|
78
|
+
The reader never infers edges from names, titles, timestamps, shared paths,
|
|
79
|
+
trace ids, current roles or matching hashes alone.
|
|
80
|
+
|
|
81
|
+
### Existing owner mappings and missing observations
|
|
82
|
+
|
|
83
|
+
| Existing relationship | Valid projection | Ceiling |
|
|
84
|
+
| --- | --- | --- |
|
|
85
|
+
| Task `offer.envelopeId` and matching journal `originals[].id` / `refs.task` | Task to dispatch | Dispatch/handout observation, not model consumption |
|
|
86
|
+
| `ExperimentAttemptRecord.attempt.taskId` | Task to research attempt | Does not identify the dispatch that caused it |
|
|
87
|
+
| Attempt id on output event and host observations | Attempt to output | Event is declared unless its stored owner observation proves more |
|
|
88
|
+
| Verified runner receipt `attemptId`, `protocolHash`, output name/hash | Attempt/output evidence | Preserve verified runner provenance; a runner output name is not a hub deliverable id |
|
|
89
|
+
| Review history `deliverables[].id/sha256`, `reviewedHead` | Output to review | Historical exact-hash/head binding, not current approval of edited bytes |
|
|
90
|
+
| Journal `previousId` | Exact predecessor metadata | `attempt` is a retry ordinal, not a research attempt id |
|
|
91
|
+
|
|
92
|
+
There is currently no persisted dispatch-to-research-attempt relationship.
|
|
93
|
+
`JournalDelivery.out` is rendered input handed to a peer, not produced output.
|
|
94
|
+
The fixture modeling current record relationships therefore leaves this gap. A separate deterministic
|
|
95
|
+
full-chain fixture supplies an explicit `declared-external` edge and keeps that
|
|
96
|
+
edge declared. This proves traversal, not native causal coverage. T1 does not
|
|
97
|
+
introduce a new relationship writer to make the gap disappear.
|
|
98
|
+
|
|
99
|
+
## Bounds, privacy and pages
|
|
100
|
+
|
|
101
|
+
Pages contain at most 100 nodes, 200 edges and 262144 UTF-8 bytes of serialized
|
|
102
|
+
JSON, including metadata and cursor. A query can lower the node/edge ceilings;
|
|
103
|
+
its byte budget is between 4096 and 262144 bytes. Nodes and edges have independent
|
|
104
|
+
continuations: a page's edge may refer to a node in another page. Consumers combine
|
|
105
|
+
pages by the complete source reference and never label a truncated page complete.
|
|
106
|
+
Traversal follows only explicit edges in either direction from the named root.
|
|
107
|
+
|
|
108
|
+
After owner privacy projection, snapshot admission bounds query-local work to 2048 nodes, 4096 edges and 4 MiB of
|
|
109
|
+
projected metadata. Oversized sources are unavailable, not an empty or silently
|
|
110
|
+
partial successful graph. The owner must supply a complete indexed neighborhood
|
|
111
|
+
within this ceiling; larger graphs require a future owner paging contract.
|
|
112
|
+
This is a bounded projection ceiling, not a performance or full-board coverage claim.
|
|
113
|
+
|
|
114
|
+
The reader checks source authority before reading health, records or the root.
|
|
115
|
+
For callers without source-read authority, absent, denied and unavailable all
|
|
116
|
+
return exactly `{state: "unavailable"}`. Ordinary authorized readers get the
|
|
117
|
+
same shape for hidden or missing roots. Only an already authorized diagnostic
|
|
118
|
+
operator can see the closed reason `missing`, `corrupt`, `unsupported`, `withheld`,
|
|
119
|
+
`cursor_invalid` or `invalid`; never a hidden id, count or source prose.
|
|
120
|
+
Host privacy applies in the source owner's indexed read before assembling this
|
|
121
|
+
snapshot, so hidden rows never enter even its bound calculations or cursor.
|
|
122
|
+
Only the host supplies these snapshots; accepting a producer-supplied graph or
|
|
123
|
+
policy flags would violate this boundary. A hidden requested root is a source
|
|
124
|
+
`withheld` result. Hidden records neither consume public page slots nor create
|
|
125
|
+
dangling edges; a dangling edge in an admitted public snapshot is corrupt.
|
|
126
|
+
|
|
127
|
+
An available page has `{state: "available", nodes, edges, truncated, cursor?}`.
|
|
128
|
+
The cursor is an opaque continuation bound to source id/revision, caller scope,
|
|
129
|
+
root, limits and the visible graph. Changed source snapshots, privacy views,
|
|
130
|
+
roots or limits invalidate it. Cursor contents grant no authority. A cursor
|
|
131
|
+
is authenticated with a host-owned ephemeral HMAC key (32 to 128 UTF-8 bytes),
|
|
132
|
+
never a key supplied by a query. This reader creates or persists no key; key
|
|
133
|
+
rotation/restart invalidates prior cursors. Edited offsets are refused.
|
|
134
|
+
A cursor
|
|
135
|
+
must be used only with the same admitted source; on invalidation refresh from
|
|
136
|
+
the root. Source health failure is never a complete empty graph. No cursor is
|
|
137
|
+
returned on a complete page.
|
|
138
|
+
|
|
139
|
+
## Verification boundary
|
|
140
|
+
|
|
141
|
+
`test/execution-reference.test.ts` consumes the neutral vectors and pins closed
|
|
142
|
+
parsing. `test/execution-lineage.test.ts` pins explicit traversal, missing edges,
|
|
143
|
+
independent states, evidence ceilings, privacy, unavailable equivalence, bounded
|
|
144
|
+
pages and source/scope/root invalidation. Fixtures run without a daemon, native
|
|
145
|
+
agent or account. CLI/MCP equivalence, admission, review currency and native
|
|
146
|
+
coverage remain T2/T3 work; these fixtures do not claim those acceptance legs.
|
|
@@ -61,6 +61,16 @@ The task board is the shared record of work and its authority, not a transcript
|
|
|
61
61
|
|
|
62
62
|
## Authority and state
|
|
63
63
|
|
|
64
|
+
Visual attachments (#1058) annotate public work without changing a task's state,
|
|
65
|
+
outcome or evidence authority. Publication checks current role, turn, task and
|
|
66
|
+
privacy admission before record/bus effects and after awaited file reads. A PII
|
|
67
|
+
task or private turn refuses publication; a task becoming private also withholds
|
|
68
|
+
its retained visual from public reads and assets. A visual id is not a verdict or
|
|
69
|
+
deliverable receipt, and visual-only calls do not count as task progress for
|
|
70
|
+
no-write detection. Ordinary shared tools and the local worker can publish where
|
|
71
|
+
their role permits; isolated fresh-reviewer MCP keeps its exact two-tool contract.
|
|
72
|
+
|
|
73
|
+
|
|
64
74
|
`Tasks` mediates task proposals, planning, owner/reviewer changes, acceptance, completion and review. `Board` persists the rows, history and typed evidence in SQLite; transport, CLI and UI layers do not independently apply task transitions. The issue remains the change spec and GitHub remains authority for PR/check/tag facts. Separating these authorities prevents a chat claim or adapter callback from bypassing task policy ([#481](https://github.com/STAIxBWLB/agent-hub/issues/481)).
|
|
65
75
|
|
|
66
76
|
A command is authorized against the current actor, role, task state and revision. An asynchronous operation can lose authority while preparing evidence, so write boundaries recheck current scope. Console actions bind the selected task ID and its observed flow revision, rather than an unstable list position. The reason is to keep an approved action attached to the row and state the person actually saw ([#424](https://github.com/STAIxBWLB/agent-hub/issues/424), [#525](https://github.com/STAIxBWLB/agent-hub/issues/525)).
|