@staix/agent-hub 0.29.0 → 0.31.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 +51 -0
- package/README.md +15 -7
- package/docs/agent-notes/README.md +13 -0
- package/docs/agent-notes/adapters.md +7 -3
- package/docs/agent-notes/budget.md +1 -0
- package/docs/agent-notes/bus.md +10 -4
- package/docs/agent-notes/daemon.md +16 -8
- package/docs/agent-notes/local-worker.md +1 -0
- package/docs/agent-notes/tasks.md +10 -4
- package/docs/agent-notes/tests.md +8 -4
- package/docs/design/adapters.md +108 -0
- package/docs/design/agent-hub-architecture.md +58 -0
- package/docs/design/bus.md +147 -1
- package/docs/design/task-board.md +100 -0
- package/docs/dogfood.md +29 -8
- package/docs/events.md +3 -0
- package/docs/memory.md +17 -1
- package/docs/operations.md +410 -86
- package/docs/profiles.md +35 -0
- package/docs/quickstart.md +25 -5
- package/docs/sdlc.md +1 -1
- package/docs/security.md +182 -62
- package/docs/smoke.md +13 -2
- package/docs/specs/2026-09-19-agent-hub-design.md +84 -14
- package/docs/specs/2026-09-19-multi-project-design.md +7 -2
- package/docs/specs/2026-10-12-office-view-design.md +86 -3
- package/docs/verification/2026-11-03-0.30.0.md +54 -0
- package/docs/verification/2026-11-03-agy-1.4.12-launcher-nonce.md +42 -0
- package/docs/verification/2026-11-03-agy-1.4.12.md +90 -0
- package/docs/verification/2026-11-03-agy-tui-close.md +49 -0
- package/docs/verification/2026-11-03-grok-1.0.62-t0.md +150 -0
- package/docs/verification/2026-11-03-pi-150-compat.md +40 -0
- package/docs/verification/2026-11-03-pi-title-api.md +26 -0
- package/docs/verification/2026-11-03-qwen-0265-acp.md +55 -0
- package/docs/verification/2026-11-03-qwen-0265-dual-output.md +40 -0
- package/docs/verification/2026-11-04-1171-channel-client-evidence.md +31 -0
- package/docs/verification/2026-11-05-0.31.0.md +182 -0
- package/docs/verification/2026-11-05-claude-implementer-2.1.318.md +70 -0
- package/docs/verification/2026-11-05-hardcoded-values-classification-rules.md +257 -0
- package/docs/verification/2026-11-05-hardcoded-values-ratchet.md +55 -0
- package/docs/verification/2026-11-06-rooms-presence-cost.md +152 -0
- package/docs/verification/claude-shell-wrapper-native.py +1 -1
- package/docs/verification/dogfood/2026-11-03.md +3095 -0
- package/docs/verification/pi-150-model-free.ts +57 -0
- package/docs/verification/pi-150-native.mjs +21 -0
- package/docs/verification/pi-150-title-api.mjs +31 -0
- package/docs/verified.json +14 -14
- package/package.json +3 -4
- package/plugins/agent-hub/.claude-plugin/plugin.json +1 -1
- package/plugins/agent-hub/server.js +4565 -3617
- package/src/adapters/acp.ts +5 -4
- package/src/adapters/channel-peer.ts +72 -3
- package/src/adapters/claude-channel-evidence.ts +52 -0
- package/src/adapters/claude-channel.ts +61 -18
- package/src/adapters/claude-implementer.ts +29 -7
- package/src/adapters/claude-print-child.ts +12 -2
- package/src/adapters/codex-appserver.ts +13 -12
- package/src/adapters/compat.ts +13 -13
- package/src/adapters/definitions/builtin-metadata.ts +13 -13
- package/src/adapters/definitions/qwen.ts +1 -0
- package/src/adapters/local-worker.ts +82 -23
- package/src/adapters/pi.ts +140 -16
- package/src/adapters/registry-types.ts +16 -0
- package/src/adapters/registry.ts +4 -0
- package/src/adapters/reviewer-print.ts +50 -11
- package/src/broker/server.ts +44 -13
- package/src/broker/store.ts +38 -8
- package/src/cli/answer-args.ts +50 -0
- package/src/cli/attention.ts +17 -2
- package/src/cli/autonomy.ts +66 -1
- package/src/cli/backlog-return-args.ts +37 -0
- package/src/cli/console-question.ts +110 -0
- package/src/cli/console-state.ts +82 -17
- package/src/cli/console.ts +54 -1
- package/src/cli/handoff-args.ts +15 -5
- package/src/cli/handoff-output.ts +15 -2
- package/src/cli/help.ts +10 -5
- package/src/cli/identity.ts +21 -4
- package/src/cli/main.ts +167 -16
- package/src/cli/memory.ts +107 -3
- package/src/cli/output.ts +29 -6
- package/src/cli/pet.ts +4 -4
- package/src/cli/results-args.ts +30 -0
- package/src/cli/runtime-version-warning.ts +50 -0
- package/src/cli/status-lines.ts +41 -1
- package/src/cli/tail-render.ts +1 -0
- package/src/cli/upgrade-interactive.ts +14 -2
- package/src/cli/worktree-tidy.ts +158 -0
- package/src/cli/worktrees-output.ts +43 -0
- package/src/hub/action-class.ts +9 -1
- package/src/hub/board.ts +396 -20
- package/src/hub/bus.ts +497 -57
- package/src/hub/completion-detail.ts +50 -0
- package/src/hub/completions-store.ts +168 -0
- package/src/hub/completions.ts +120 -0
- package/src/hub/conductor.ts +4 -3
- package/src/hub/config-apply.ts +8 -5
- package/src/hub/config-reload.ts +10 -1
- package/src/hub/control-client.ts +40 -4
- package/src/hub/daemon.ts +1795 -142
- package/src/hub/delivery-failure.ts +14 -0
- package/src/hub/delivery-hints.ts +14 -4
- package/src/hub/delivery-journal.ts +751 -42
- package/src/hub/delivery-superseded.ts +4 -1
- package/src/hub/dogfood-read.ts +62 -9
- package/src/hub/envelope.ts +3 -3
- package/src/hub/events.ts +6 -0
- package/src/hub/handoff.ts +145 -6
- package/src/hub/hub-tools.ts +66 -11
- package/src/hub/manager.ts +67 -3
- package/src/hub/memory-policy.ts +44 -1
- package/src/hub/memory-sync-policy.ts +109 -0
- package/src/hub/memory-sync-state.ts +145 -0
- package/src/hub/no-writes.ts +1 -1
- package/src/hub/operational-settings.ts +11 -2
- package/src/hub/operational-view.ts +12 -1
- package/src/hub/peer-doing.ts +33 -3
- package/src/hub/peers.ts +32 -2
- package/src/hub/planning.ts +6 -1
- package/src/hub/question-desk.ts +201 -0
- package/src/hub/question-detach.ts +6 -0
- package/src/hub/questions.ts +260 -0
- package/src/hub/research-evidence.ts +106 -0
- package/src/hub/restart.ts +14 -0
- package/src/hub/review-anchor.ts +181 -0
- package/src/hub/review-brief.ts +13 -0
- package/src/hub/review-comments.ts +115 -0
- package/src/hub/review-findings.ts +7 -2
- package/src/hub/review-material.ts +76 -0
- package/src/hub/routing.ts +3 -1
- package/src/hub/settings.ts +3 -0
- package/src/hub/task-sweep.ts +2 -0
- package/src/hub/tasks.ts +607 -71
- package/src/hub/ui.ts +2 -0
- package/src/hub/worktree-prs.ts +100 -0
- package/src/hub/worktree-shelf.ts +246 -0
- package/src/memory/capture.ts +5 -2
- package/src/pet/config.ts +25 -13
- package/src/pi/extension.ts +43 -3
- package/src/rooms/link.ts +209 -21
- package/src/rooms/remote-peer.ts +186 -19
- package/src/rooms/service.ts +338 -22
- package/src/rooms/store.ts +437 -65
- package/src/rooms/wire.ts +24 -6
- package/src/ui/index.html +271 -17
- package/src/ui/needs.ts +10 -4
- package/src/ui/office-model.ts +64 -8
- package/src/ui/office-space.ts +1 -0
- package/src/ui/plugin-questions.ts +56 -0
- package/src/ui/plugin-results.ts +81 -0
- package/src/ui/plugin.ts +219 -28
- package/src/pet/window.html +0 -114
- package/src/pet/window.jxa.js +0 -122
- package/src/pet/window.ts +0 -154
package/docs/design/adapters.md
CHANGED
|
@@ -49,6 +49,40 @@ Optional ports have explicit meaning: absent keeps the generic path, while prese
|
|
|
49
49
|
|
|
50
50
|
Adapters translate different interaction surfaces without changing the peer's task identity. Claude's plugin channel connects through MCP and the hub control service; Codex is proxied through app-server; ACP peers share an ACP transport; Pi uses its extension bridge. Kimi defaults to a pull-only TUI, with headless ACP as a separate selected form under the same peer id. The TUI does not inherit headless push, session, or recovery behavior. Keeping forms distinct lets the hub preserve the native user interaction model while enforcing one role and delivery policy ([#316](https://github.com/STAIxBWLB/agent-hub/issues/316), [#625](https://github.com/STAIxBWLB/agent-hub/issues/625)).
|
|
51
51
|
|
|
52
|
+
## Channel attachment evidence (#1171)
|
|
53
|
+
|
|
54
|
+
The Claude plugin's inherited launcher marker is insufficient to enable push. In the inspected Claude Code 2.1.318 client path, MCP initialization advertises no usable channel opt-in; the plugin's server capability is not client evidence. The fallback checks the direct parent's bounded process row for the existing launcher's exact leading development-channel flag and supported target. Unknown, malformed, truncated or changed-parent evidence, print/background forms and repeated flags keep the plugin tools-only, with messages waiting for `hub_inbox`. The check does not walk ancestors or treat the marker as an authorization token.
|
|
55
|
+
|
|
56
|
+
The flattened process row is a conservative launch observation, not authentication or proof of registration or model consumption. Unsupported invocation layouts remain pull-only. An attached peer's status reports its mode and a closed evidence label without command text. Evidence belongs to that socket's attachment and is omitted when no current attachment exists. Older clients that omit the optional evidence field retain their prior behavior and report `unreported`; no control protocol version changes. The separate delivery-settlement contract handles an accepted notification that remains unconfirmed. The [investigation report](../verification/2026-11-04-1171-channel-client-evidence.md) distinguishes static client inspection, passive process observation and synthetic fixtures.
|
|
57
|
+
|
|
58
|
+
## Person takeover of a channel peer (#1174)
|
|
59
|
+
|
|
60
|
+
An opted-in channel process may retain a live, non-owning standby connection when
|
|
61
|
+
a current session holds the peer. The adapter keeps a bounded standby registry;
|
|
62
|
+
status exposes only its server-generated connection id, reported PID when present,
|
|
63
|
+
and arrival time. These values are display metadata, never native session ids,
|
|
64
|
+
launch/isolation evidence or caller authority. Every standby peer operation is
|
|
65
|
+
refused centrally until that exact socket owns the attachment.
|
|
66
|
+
|
|
67
|
+
The person's `peer_takeover` control request, used by `ahub peer takeover <peer>`
|
|
68
|
+
and the console, selects an explicit live standby id or the oldest eligible one.
|
|
69
|
+
The host checks person authority, current membership and lifecycle fences before
|
|
70
|
+
detaching the old ownership; the selected claim/preface reuses normal admission
|
|
71
|
+
and generation checks. A `requested` result means attachment is pending, not
|
|
72
|
+
completed. Socket detachment never stops the native process, grants no delivery
|
|
73
|
+
receipt and replays no work. Unconfirmed deliveries keep ordinary settlement.
|
|
74
|
+
|
|
75
|
+
The old plugin reports a fixed person-detachment cause and stops reconnecting.
|
|
76
|
+
A legacy plugin receives an already-terminal refusal so it cannot undo the
|
|
77
|
+
handover, but may report its older generic admission message until upgraded.
|
|
78
|
+
Older daemons retain their existing close-and-retry standby behavior. An ordinary
|
|
79
|
+
owner departure may release an eligible standby through normal claim admission;
|
|
80
|
+
a standby never evicts a live owner without the person's takeover operation.
|
|
81
|
+
|
|
82
|
+
## Accepted channel delivery settlement (#1172)
|
|
83
|
+
|
|
84
|
+
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.
|
|
85
|
+
|
|
52
86
|
## Permissions, execution, and process ownership
|
|
53
87
|
|
|
54
88
|
Permission modes control whether native actions prompt; they do not widen a sandbox or path grant. The local worker's file tools use path guards, and its command tools run through the host's OS sandbox. Vendor-native tools use their vendor/runtime permission and isolation boundaries; the hub does not claim to confine every ACP or TUI tool. This distinction prevents an approval-mode setting from being mistaken for filesystem or network confinement ([#242](https://github.com/STAIxBWLB/agent-hub/issues/242), [#39](https://github.com/STAIxBWLB/agent-hub/issues/39), [#270](https://github.com/STAIxBWLB/agent-hub/issues/270)).
|
|
@@ -71,6 +105,80 @@ Native CLI compatibility is centralized in `compat.ts`. Each gated operation ask
|
|
|
71
105
|
|
|
72
106
|
External adapter modules are an explicit, person-owned, machine-local opt-in. The daemon verifies and pins the captured bundle at startup, then admits only the bounded headless ACP instance contract through host-managed launch and current-owner checks. Module code runs in the daemon trust domain; pinning is integrity evidence, not a sandbox. Modules cannot supply native reviewer engines, proof ports, permission callbacks, provider selectors, or arbitrary recovery authority. This ceiling limits what imported code can claim and prevents live reload from replacing the executable catalog ([#754](https://github.com/STAIxBWLB/agent-hub/issues/754)).
|
|
73
107
|
|
|
108
|
+
`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
|
+
|
|
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:** Kimi in its own TUI (pull-only, no signal), agy (its declared `native-hook` signal is not verified end to end) and phase-2 person-typed Codex turns declare none, and the daemon starts no run for a peer attached pull-only. 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.
|
|
111
|
+
|
|
112
|
+
## Session title slots
|
|
113
|
+
|
|
114
|
+
Only fixed Pi and local definitions opt into `title: "hub"` (#1055). Their
|
|
115
|
+
standalone `hub_set_title` schema is excluded from native-peer tool lists, and
|
|
116
|
+
the daemon independently checks the resolved definition and current owner.
|
|
117
|
+
An agent fills only an unnamed slot; a person's console rename replaces it.
|
|
118
|
+
Pi's native session name is canonical and its bridge rechecks the native name,
|
|
119
|
+
owner, session and generation before writing. Local keeps its name in the
|
|
120
|
+
worker's existing in-memory session. Both expose a separate `titleSession`
|
|
121
|
+
identity for display continuity; Local's native-session/provenance authority
|
|
122
|
+
does not change. Titles pass the current metadata/privacy screen at write and
|
|
123
|
+
display. No helper inference or task/Git/instance naming path is involved.
|
|
124
|
+
|
|
125
|
+
Refusals keep the `already_named`, `private` and `invalid` reason codes and
|
|
126
|
+
include a public `error` explaining the cause and next step. Errors identify
|
|
127
|
+
length, offline/owner, session/generation and confirmation failures without
|
|
128
|
+
copying the supplied title or private details. If a write might have landed,
|
|
129
|
+
the result says it may have been applied and directs the caller to inspect
|
|
130
|
+
`ahub status` before retrying.
|
|
131
|
+
|
|
132
|
+
An unnamed label is derived from the first positively acknowledged original,
|
|
133
|
+
never stored as a name. The #1055 restart-recomputation design is amended with
|
|
134
|
+
`session-title-inputs.json` under the daemon state directory: the journal does
|
|
135
|
+
not itself bind an original delivery to the recipient's native session.
|
|
136
|
+
Only fixed definitions declaring `titlePersistence: "native"` retain restart
|
|
137
|
+
bindings. This private, atomically replaced file maps each retained peer ID
|
|
138
|
+
to exactly three opaque IDs, `session`, `delivery` and `envelope`. It contains no source body,
|
|
139
|
+
session title or derived label. Only the first positive delivery acknowledgement
|
|
140
|
+
for a peer's current title-session can create or replace its entry;
|
|
141
|
+
`hub_set_title` and person rename never write it.
|
|
142
|
+
|
|
143
|
+
The file is limited to 128 peer entries and 64 KiB of serialized UTF-8,
|
|
144
|
+
including JSON formatting and the final newline. Each stored ID is nonempty,
|
|
145
|
+
at most 512 UTF-16 code units, and excludes control and format characters.
|
|
146
|
+
An unreadable, malformed, oversized, symlinked or multiply linked input is
|
|
147
|
+
ignored. Capacity or write failure leaves delivery successful and makes that
|
|
148
|
+
new restart binding unavailable.
|
|
149
|
+
|
|
150
|
+
Native-session bindings survive daemon stop/restart until replaced by the
|
|
151
|
+
first acknowledged delivery of a later session for that peer, or until the
|
|
152
|
+
state directory is removed. Entries for removed instances are dropped when
|
|
153
|
+
their removal applies. Local's session exists only in daemon memory and gets
|
|
154
|
+
a fresh ID each start, so its binding is not retained on disk; startup removes
|
|
155
|
+
legacy Local entries. A stale native-session entry grants no display value: restore
|
|
156
|
+
requires the same title-session ID and the original still retained in that
|
|
157
|
+
project's journal. A different session or pruned original yields no inherited
|
|
158
|
+
label. There is no separate retention of message text and no timer or automatic
|
|
159
|
+
replay. The derived label remains absent from disk status, events, logs,
|
|
160
|
+
capture and rooms.
|
|
161
|
+
|
|
162
|
+
Incoming-message labels are visible only to the console and the configured
|
|
163
|
+
conductor. Other status readers receive `unnamed`. A label has its own source
|
|
164
|
+
tag and explanation: its text comes from an incoming message and is never
|
|
165
|
+
attributed as speech written by the session's peer. Public-metadata screening
|
|
166
|
+
and private stubs still apply to authorized label viewers.
|
|
167
|
+
|
|
74
168
|
## Evidence boundary
|
|
75
169
|
|
|
76
170
|
Compatibility probes and fake transports verify source contracts, not an account login, live model turn, native permission prompt, or operating-system isolation. Those receipts remain separate because protocol inventory alone cannot prove runtime behavior ([#625](https://github.com/STAIxBWLB/agent-hub/issues/625), [#754](https://github.com/STAIxBWLB/agent-hub/issues/754)).
|
|
171
|
+
|
|
172
|
+
## Owned print input admission (#1056)
|
|
173
|
+
|
|
174
|
+
A trusted owned adapter can accept an envelope before it has chosen the actual model-input session. Reviewer print children choose a fresh isolated context per review; the Claude implementer selects a persisted task-session UUID and may replace it after verified missing-transcript evidence. Their host-only input guard runs with that final target identity before prompt data can reach the backend or native child. It persists quote-bearing provenance before exposure. A failed guard releases no prompt and retains the adapter's owned teardown rules.
|
|
175
|
+
|
|
176
|
+
Owned observer-context IDs identify the history the host controls. They do not populate `nativeSession` or grant budget, resume, permission or task authority; an unrelated title or socket identity is not a substitute. Local's observer identity belongs to its in-memory history. Retained external native sessions keep their confirmed native identity, including across a launch change. Persistent implementer input keeps the same observer identity when its task session is resumed.
|
|
177
|
+
|
|
178
|
+
A successful stdin handout may confirm ordinary-input replacement for the matching context and input token. This is metadata about handing over bytes, not native handling, task completion or a new transport ACK. Old callbacks cannot release a newer input hold. The bus journal keeps its original transport receipts separately from this actual native-input observation. A fresh reviewer context may discard its own observer receipt only after its process group is confirmed gone, its task MCP bridge is closed and launch cleanup succeeds. The host retains the turn exclusion through remaining diagnostics. Persistent implementer and retained native histories do not acquire that disposal rule.
|
|
179
|
+
|
|
180
|
+
When a quote-bearing review reaches a peer without a stable native session ID, the host commits a peer-scoped incomplete marker before handoff and keeps the observer exclusion in daemon memory. A failed marker write refuses the handoff. An ordinary input within the review's active turn is staged and cannot release that turn's final outputs; the host clears only the peer marker at the next turn boundary while that ordinary input remains current. An ordinary input in a later turn, or while no turn is active, clears only that peer marker after verified handoff when the peer has no earlier SID-specific hold or incomplete record. If any earlier positive hold or SID-specific incomplete marker exists and the current SID is unknown, ordinary input cannot release the hold; status asks the person to reconnect so the native session ID can be confirmed. A confirmed native session change clears only the peer marker, then the host checks the exact-session receipt. If the current daemon has RAM evidence of a quote handed out while unbound, it first stores a positive receipt under the newly confirmed SID. Other SID receipts remain intact. The daemon keeps the quote's admission-turn fence in RAM separately from the active turn id, which adapters may rebind. No launch, attachment, socket or runtime UUID is persisted as a substitute session ID. Positive held receipts for a known pull-only session remain sticky until a confirmed session change. Positive held receipts are expected state, not a health failure. Status reports incomplete or corrupt provenance with a bounded cause and next step; repair guidance preserves delivery and task state.
|
|
181
|
+
|
|
182
|
+
## Local review turns (#1056)
|
|
183
|
+
|
|
184
|
+
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).
|
|
@@ -44,6 +44,27 @@ Authority is role-scoped: the person retains decisions requiring judgment or con
|
|
|
44
44
|
|
|
45
45
|
Native tools keep their vendor permission and execution boundaries. The local worker applies path and permission checks to its tools, and runs command execution through a host-supported sandbox; the hub does not sandbox vendor-native tools or claim all ACP commands are isolated. This avoids confusing a hub permission mode with execution confinement ([#39](https://github.com/STAIxBWLB/agent-hub/issues/39), [#270](https://github.com/STAIxBWLB/agent-hub/issues/270)).
|
|
46
46
|
|
|
47
|
+
Channel takeover keeps the same separation: optional adapter-owned takeover and
|
|
48
|
+
socket-ownership ports hold transport state, while the daemon supplies person
|
|
49
|
+
admission and current roster/launch/generation fences. A live standby has no peer
|
|
50
|
+
tool or delivery authority. Its public connection id is not a native conversation
|
|
51
|
+
id and cannot release observer provenance or establish execution isolation. A
|
|
52
|
+
person takeover detaches ownership without terminating the process, and normal
|
|
53
|
+
delivery uncertainty remains independent ([#1174](https://github.com/STAIxBWLB/agent-hub/issues/1174)).
|
|
54
|
+
|
|
55
|
+
## Console presentation surfaces
|
|
56
|
+
|
|
57
|
+
The floating pet belongs to acon Mini (#1012). The compatibility command
|
|
58
|
+
`ahub pet --window [--close]` prints the `acon ui` pointer and succeeds for
|
|
59
|
+
person, agent and live-test identities, without starting a host or window.
|
|
60
|
+
The retired `ahub pet --palette <value>` validates its argument and prints the
|
|
61
|
+
same pointer without writing configuration. Legacy `pet.palette` remains
|
|
62
|
+
validated compatibility input with no rendering effect.
|
|
63
|
+
Legacy `pet.window` input is ignored with one notice and cannot change authority
|
|
64
|
+
or re-enable an inherited disabled terminal pet by itself. Terminal pet frames
|
|
65
|
+
remain local TUI presentation. The acon plugin's existing **Console message**
|
|
66
|
+
view owns the composer through its established `send` action (#935).
|
|
67
|
+
|
|
47
68
|
## Board, assignment, and delivery
|
|
48
69
|
|
|
49
70
|
`Tasks` is the task state machine and policy boundary; `Board` is its SQLite persistence. Proposals, assignments, acceptance, completion, and review flow through `Tasks`, which checks roles, state, privacy, and revisions before writes. Pure candidate selection keeps route explanations aligned with actual assignment. This prevents adapters or CLIs bypassing invariants with direct board writes ([#424](https://github.com/STAIxBWLB/agent-hub/issues/424), [#481](https://github.com/STAIxBWLB/agent-hub/issues/481)).
|
|
@@ -52,16 +73,53 @@ The message bus is separate from task state. `Bus` frames and routes envelopes;
|
|
|
52
73
|
|
|
53
74
|
Encrypted rooms are an optional message transport between project hubs. They do not federate task boards, roles, approvals, or memory; each receiving project makes its own local admission decision. This prevents a remote room membership from becoming local authority ([#446](https://github.com/STAIxBWLB/agent-hub/issues/446)).
|
|
54
75
|
|
|
76
|
+
Room applications add bounded at-least-once sending with receiver admission
|
|
77
|
+
deduplicated by immutable application id under the existing retention and cap
|
|
78
|
+
contract. Retry and restart retain the original queue
|
|
79
|
+
TTL and revalidate current membership and privacy. ACK deadlines trigger resend;
|
|
80
|
+
late signed recipient receipts may settle unresolved ordinary remote holds but
|
|
81
|
+
never a person-disposed row. Invocation uncertainty keeps its person-only ledger hold. Receipt ciphertext is locally durable before chat transport
|
|
82
|
+
ACK, and remains in its outbox until broker storage confirmation. These room-only
|
|
83
|
+
transitions do not grant native completion or task-offer read evidence ([#1204](https://github.com/STAIxBWLB/agent-hub/issues/1204)).
|
|
84
|
+
|
|
85
|
+
Claim evidence (#931 T1) uses the same Tasks/Board boundary and #901's canonical
|
|
86
|
+
claim identity and ordered-list revision. Evidence links are append-only
|
|
87
|
+
provenance proposals; they create no separate claim/verdict store and do not
|
|
88
|
+
establish entailment or synthesis readiness. The research-only record tool
|
|
89
|
+
returns an ids-only receipt and excludes its arguments/results from capture.
|
|
90
|
+
Its T1 authorization, revision and recovery boundaries are defined in
|
|
91
|
+
[the task-board contract](task-board.md#claim-evidence-records-931-t1).
|
|
92
|
+
|
|
55
93
|
## Models and memory
|
|
56
94
|
|
|
57
95
|
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. This keeps provider credentials and fallback policy in one gateway while avoiding a second routing service ([#553](https://github.com/STAIxBWLB/agent-hub/issues/553)).
|
|
58
96
|
|
|
59
97
|
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)).
|
|
60
98
|
|
|
99
|
+
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
|
+
|
|
61
101
|
## Privacy and recovery
|
|
62
102
|
|
|
103
|
+
Session titles for the two hub-owned title slots (#1055) are conditional writes
|
|
104
|
+
to the current adapter session, under the same open-PII-task/private-turn and
|
|
105
|
+
public-metadata screens as DOING. Person rename remains console-only. Live
|
|
106
|
+
unnamed labels are computed from acknowledged source messages and shown only
|
|
107
|
+
to the console and configured conductor; other readers see `unnamed`.
|
|
108
|
+
Their source note identifies incoming text, not speech by the recipient.
|
|
109
|
+
Only opaque
|
|
110
|
+
session/delivery/envelope bindings persist in `session-title-inputs.json`, never
|
|
111
|
+
copied labels. Its fields, bounds and lifetime are defined by the
|
|
112
|
+
[session-title storage contract](adapters.md#session-title-slots). Native title,
|
|
113
|
+
task title, Git branch and instance identity remain independent.
|
|
114
|
+
|
|
63
115
|
Privacy decisions are made at hub boundaries, not delegated to model routing. A private task or turn is represented by a private envelope and a restricted public view; task text is screened before it enters memory, shared notices, or model calls. The PII screen can run on-device; its gateway path requires positive campus admission, so an unknown network result is not treated as safe. This makes each downstream observer consume the same host decision rather than infer privacy from a label or vendor ([#198](https://github.com/STAIxBWLB/agent-hub/issues/198), [#752](https://github.com/STAIxBWLB/agent-hub/issues/752)).
|
|
64
116
|
|
|
65
117
|
Recovery is a coordinated daemon operation over separately persisted board, delivery, and native-session evidence. A restart or upgrade can continue only with compatible feature evidence from the verified target and host-held proofs that still match the project and actor. Adapters report native evidence; they do not certify their own recovery authority. This avoids treating a stale status file or an unverified receipt as proof that a native process is safe to resume ([#37](https://github.com/STAIxBWLB/agent-hub/issues/37), [#625](https://github.com/STAIxBWLB/agent-hub/issues/625), [#900](https://github.com/STAIxBWLB/agent-hub/issues/900)).
|
|
66
118
|
|
|
67
119
|
The architecture does not claim that a fixture proves a real provider account, native session, campus network, or operating-system sandbox. Those are distinct runtime evidence and remain separate from source-level and automated checks ([#625](https://github.com/STAIxBWLB/agent-hub/issues/625), [#754](https://github.com/STAIxBWLB/agent-hub/issues/754)).
|
|
120
|
+
|
|
121
|
+
## Person review packages (#1056)
|
|
122
|
+
|
|
123
|
+
The task-board module owns anchored findings and person-authored comment lifecycles. Transport carries one explicit review package only after `Tasks` admits the selected draft set; drafting and editing do not start peer turns. acon supplies the shared review kit and a server-verified person identity, while the standalone dashboard reads counts and bounded placements only. Neither surface writes the Board directly.
|
|
124
|
+
|
|
125
|
+
The host-only review package reference is an observer exclusion, not PII authority. Durable open comment/finding scope protects memory notes naming that task after restart or intervening input. Capture, progress and session-title exclusion follows the current review input, not unrelated board history. ID-only current-input holds survive daemon restart. An intact, readable, complete store with no matching held record admits a new session as clean. Unreadable or corrupt storage and unconfirmed coverage for the current identity remain excluded. A validated release receipt confirms that identity without declaring other legacy identities clean. For an identified pull-only session, a positive held row remains sticky across restart until confirmed native identity changes. Its own incomplete marker excludes until verified ordinary replacement or a confirmed new session clears that marker; legacy coverage alone does not create a sticky hold. Missing native identity permits handout under an in-RAM unknown-held scope. A never-identified peer can release it with verified ordinary replacement in that daemon run; earlier positive or incomplete SID rows instead keep unidentified observer state held until a real SID is confirmed. First confirmation persists any current RAM quote under that SID before clearing the peer marker, without discarding other SID rows. It does not invent a native identity or weaken write-failure refusal. Legacy coverage completes from settled journal evidence, after which NULL clean receipts can be pruned; corrupt state remains excluded and is named in status with a repair next step. The hold grants no authority; the task-bound recipient summary and check output remain distinct from observer projections. Explicit publication recovery uses the saved immutable envelope and retained journal evidence, never automatic effect replay. Its intended recipient may read a public package, but memory capture, operational views, delivery logging and incoming-message labels exclude its body. Local-worker capture latches exclusion before any tool in a batch that submits an anchored verdict, including a refused verdict, and applies it to subsequent capture, final summaries and retained history. A delayed response cannot become capturable when another turn starts. Recovery advertises the conditional `review_comments` feature when retained comment/package records require it. It also requires `review_observer_input_state` when held or unknown session-input provenance could otherwise be lost. See [the task-board contract](task-board.md#anchored-review-packages-1056) for bounds, immutable snapshot placement and lifecycle authority.
|
package/docs/design/bus.md
CHANGED
|
@@ -33,16 +33,162 @@ The bus applies limits to a sender, sender-recipient pair, important messages, a
|
|
|
33
33
|
|
|
34
34
|
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
35
|
|
|
36
|
+
A closed bus returns an empty publication outcome before provenance, privacy,
|
|
37
|
+
journal preflight, observers or queue mutation. Deferred publication has the same
|
|
38
|
+
fence. A storage failure while the bus is open still fails rather than becoming
|
|
39
|
+
an apparently successful empty send.
|
|
40
|
+
|
|
41
|
+
For #1055, `Bus.onDelivered(peer, originals, deliveryId?)` exposes the existing
|
|
42
|
+
journal delivery ID to the observer at the first positive transport ACK. The
|
|
43
|
+
optional argument accompanies the original envelopes, including when the
|
|
44
|
+
rendered delivery was condensed. Queueing supplies no positive-ACK evidence,
|
|
45
|
+
and an observer exception cannot alter delivery settlement. This supports the
|
|
46
|
+
[ID-only session-title restart binding](adapters.md#session-title-slots) without
|
|
47
|
+
changing dispatch, retry, task acceptance or task-completion authority.
|
|
48
|
+
|
|
49
|
+
A successful nonempty inbox handout records current-input and bounded named-parent review provenance through `Bus.onPulled(peer, originals)`. This metadata hook does not invoke `onDelivered`, certify native consumption, start a session-title receipt or change completion authority. Presence-only handouts do not release review exclusion, and a mixed quote-bearing batch cannot seed a title binding from its ordinary member. A previously saved binding to an ordinary member of such a batch is also rejected on status and delivery recovery; a fresh ordinary input can establish a safe source. It follows the existing pull handout ceiling: the transport result may still be lost before the client reads it. The separate metadata-only `onSteering(peer, originals)` hook latches quote-bearing input immediately before an actual steer attempt, without creating a native ACK or task/completion evidence. Ordinary additional steer input cannot clear an active review turn's exclusion.
|
|
50
|
+
|
|
51
|
+
The latest pulled input is kept separately from the last pushed delivery. Observer reads use the pull slot while it is current, but invocation answer matching retains its pushed request through an intervening inbox read; an explicit reply can still name the correct pushed or pulled invocation. A later push replaces the pull slot. Only `resetLastDelivery` after a confirmed native-session change clears both slots; adapter metadata reset/removal preserves the latest pulled input.
|
|
52
|
+
|
|
36
53
|
Push peers receive bounded batches. Condensation is optional, excludes important, remote, and invocation messages, and keeps `originals` separate from `out` so replies, safe failures, and recovery still refer to what the peer was actually given. On an eligible safe retry, a failed batch falls back to individual envelopes, and a previously failed envelope goes alone so a poison item cannot block its neighbors. These bounds preserve queue progress when summarization or one recipient fails ([#713](https://github.com/STAIxBWLB/agent-hub/issues/713), [#553](https://github.com/STAIxBWLB/agent-hub/issues/553)).
|
|
37
54
|
|
|
38
55
|
Pull-only peers catch up oldest-first under a byte budget, but the first envelope always goes even when it exceeds that budget so one oversized item cannot starve the queue; push peers use the digest batch limit. Pull records returned envelopes as completed at handout because the tool result is the readback, not a later native receipt. A busy Claude channel can also pull its own messages through `hub_inbox`; that avoids making a long-running turn an unbounded queue lock ([#493](https://github.com/STAIxBWLB/agent-hub/issues/493), [#713](https://github.com/STAIxBWLB/agent-hub/issues/713)).
|
|
39
56
|
|
|
40
57
|
Delivery uncertainty normally holds the original and is never an automatic replay. The narrow exception is a hub-authored presence or workflow notice proven moot by current task evidence; mixed, unknown, or requested-stop rows remain held. This removes stale notices without treating arbitrary peer messages as seen ([#434](https://github.com/STAIxBWLB/agent-hub/issues/434)). Safe pre-acceptance failures may retry within a bounded attempt policy; uncertain results remain `needs_review` until an explicit resolution. A peer may retry only its own eligible row and only once per immutable retry lineage; an invocation uses its own ledger and is not replayed as an ordinary message retry ([#37](https://github.com/STAIxBWLB/agent-hub/issues/37), [#991](https://github.com/STAIxBWLB/agent-hub/issues/991)).
|
|
41
58
|
|
|
42
|
-
|
|
59
|
+
Failure diagnostics use the bounded, public-safe `failureCause` classes `peer
|
|
60
|
+
offline`, `adapter refused`, `push error`, `turn aborted`, and `timeout`, never
|
|
61
|
+
message text. A legacy absent cause remains unknown. Queue inspection exposes
|
|
62
|
+
this metadata without changing the receipt's state or proving that retry is
|
|
63
|
+
safe. Status counts only unresolved failed rows per peer, excluding rows with
|
|
64
|
+
an explicit resolution even when a retry leaves its parent in `failed`; the
|
|
65
|
+
metadata-only aggregate does not hydrate delivery payloads ([#1178](https://github.com/STAIxBWLB/agent-hub/issues/1178)).
|
|
66
|
+
|
|
67
|
+
A peer may settle its own local `needs_review` row as completed or discard while busy, with the observed revision and a public-safe reason; this records a delivery decision and never changes task state or redelivers the original. Another peer or a remote-room actor remains refused. Active `dispatching` rows remain refused; an `accepted` row is settleable only by its explicit push channel owner as described below. Invocation-bearing rows also remain person-settled because a transport action cannot assert the outcome of an invoked operation. `hub_inbox` may pass a `needs_review` hold to return newer queued messages and bounded id/revision metadata naming the held row, while leaving the uncertain originals held. Pause, recovery, lifecycle, storage, and active-delivery fences still apply. This lets the current recipient make progress without treating uncertain work as delivered ([#1079](https://github.com/STAIxBWLB/agent-hub/issues/1079), [#445](https://github.com/STAIxBWLB/agent-hub/issues/445), [#991](https://github.com/STAIxBWLB/agent-hub/issues/991)).
|
|
68
|
+
|
|
69
|
+
An explicit push channel may settle or discard its own `accepted` row with the observed revision and a public-safe reason. `accepted` means the channel transport accepted the notification, not that the session handled it. If neither a native completion nor an explicit disposition arrives within the configured `bus.accepted_settle_ms` window, the host moves the row to `needs_review` with a fixed timeout cause and never replays it. The channel's `hub_inbox` metadata includes its own accepted and held rows, with ids and revisions, even while an active accepted delivery blocks pulling. An important, task, or review timeout adds one ids-only status notice when a conductor is configured and its existing `conductor.feed` policy is on; `feed: off` remains an explicit opt-out. Timed-out rows stay held until a person or the explicit channel session records a disposition; task state does not settle them ([#1172](https://github.com/STAIxBWLB/agent-hub/issues/1172)).
|
|
70
|
+
|
|
71
|
+
An `answer` envelope (#1053) is a person's late answer to a question a peer asked with `hub_ask`. The hub builds it: `kind: "answer"`, `from: user`, addressed to the asking peer only, with the deterministic id `answer-<set>` (a republish after a crash is dropped by the bus's own dedupe) and `refs.question`. Code keys on `kind`, never on the sender, and an `answer` never supersedes the question it answers. Its body is the person's text, so the log line, the console tail and the dashboard feed show a fixed stub; only the recipient reads it. A question expiry is a hub `status` notice, never an answer.
|
|
43
72
|
|
|
44
73
|
Invocation requests and results are single-envelope deliveries, not digest material. A reply is correlated to the request handed to that peer and is captured by the invocation path before ordinary publishing; uncertain outcomes stay with the invocation ledger because a missing result cannot be inferred from a transport receipt ([#445](https://github.com/STAIxBWLB/agent-hub/issues/445), [#991](https://github.com/STAIxBWLB/agent-hub/issues/991)).
|
|
45
74
|
|
|
46
75
|
## Cross-project transport
|
|
47
76
|
|
|
48
77
|
Encrypted rooms add a screened message transport between local project hubs. Room identity, deadlines, and remote provenance stay bound to each delivery; traffic is not merged into a shared board. A separately pinned read-only invocation relay cannot transfer task or approval authority. This keeps remote delivery from acquiring the receiving project's roles or memory ([#941](https://github.com/STAIxBWLB/agent-hub/issues/941), [#992](https://github.com/STAIxBWLB/agent-hub/issues/992)).
|
|
78
|
+
|
|
79
|
+
## Review observer provenance (#1056)
|
|
80
|
+
|
|
81
|
+
An admitted person comment package or anchored-finding review request carries the host-only opaque `refs.reviewPackage`. The intended recipient keeps its public body; observer projections show an IDs-only stub. A PII task still uses its existing private stub and authority rules. Peer-supplied review markers are discarded. The bus derives `refs.reviewResponse` for a response to the current delivered review input or a retained named parent, so a direct echo cannot enter logs, stream projections or memory observers as ordinary chat. This marker grants no task, console or PII capability.
|
|
82
|
+
|
|
83
|
+
The provenance cache retains at most 128 delivered parent IDs per peer and a globally bounded response cache; peer removal drops its parent binding. It holds identifiers only, not excerpts. This boundary attributes current turns and named parents. Arbitrary paraphrases from later vendor-native session history need a native session/turn provenance protocol; content matching is not used to guess them.
|
|
84
|
+
|
|
85
|
+
Person comment packages retain their terminal delivery evidence for explicit idempotent publication recovery. Reviewer requests use the distinct `reviewer-request-` marker and their terminal rows remain prunable. A saved person package whose latest delivery failed or was discarded refuses explicit resend with that state and queue inspection guidance; it never reports queued success or replays the effect. Owner-addressed review packages and verdicts stay uncertain until an explicit disposition; task or reviewer movement alone is not consumption proof. Durable open sent comments and anchored finding scope protect memory notes naming that task after a restart or intervening chat; they grant no task or PII authority. Capture and other turn-wide observers follow the current delivered review input or an anchored-verdict submission latched to that input, not peer-wide board history. Ordinary new input releases that turn exclusion only where the transport supplies replacement evidence; the restored pull-only rule below still applies. Separate delivery holds retain their own dispositions. The journal retains bounded peer/session hold and release receipts using session/input ID hashes, never text. Completeness and integrity metadata confirm whether absence is meaningful: no matching held record in an intact, readable, complete store is clean, including a new session after restart. Unreadable or corrupt storage remains unknown and excluded. A validated matching release confirms only its own session while legacy coverage is incomplete.
|
|
86
|
+
|
|
87
|
+
A missing stable native session id does not refuse a review handout. The host records a peer-scoped incomplete marker and keeps an unknown-held scope in RAM, without turning launch, attach or socket ids into a native identity. For a never-identified peer with no positive or incomplete SID row, the next verified ordinary replacement in that daemon run can release that RAM scope and its peer marker. If any earlier positive or incomplete SID row exists while the current SID cannot be matched, delivery still proceeds but the observer state stays unknown and held; an ordinary RAM proof cannot release it. Status names that peer as unidentified and directs reconnection so its real session id can be known. A newly confirmed SID uses its own state; another SID's retained rows are not cleared. Journal write failure still refuses before handout. Presence-only traffic and additional input within a known active held turn cannot clear exclusion.
|
|
88
|
+
|
|
89
|
+
Legacy coverage becomes complete only when journal evidence shows no unsettled pre-upgrade review-scoped delivery remains; this changes provenance metadata, never delivery disposition or replay. Its bounded candidate set is fixed from preexisting handed work at open/import; guarded deliveries created after that capture do not prolong the current daemon's fence. Reopen/import while coverage is incomplete conservatively recaptures every handed non-terminal row present then, including a newer guarded B; after the original A settles, coverage may therefore remain incomplete and a fresh SID without its own receipt remains unknown until B also reaches a terminal disposition. A timeout to needs_review still requires explicit resolution. This accepted recapture ceiling neither refuses handout nor creates a sticky hold from legacy coverage alone. If this window matters in operation, the upgrade path is a persisted ids-only legacy fence carried across recovery. Legacy coverage alone does not create a sticky restored pull-only hold. For an identified session, a positive held row or that peer's own incomplete marker can restore exclusion. A verified ordinary replacement or confirmed native-session change clears only that peer's incomplete marker; a session change does not discard another session's positive held row. On the first confirmed SID after a sessionless period, any current RAM quote hold is persisted under that SID before the peer marker is cleared. Positive session-bound restored holds remain excluded until confirmed native identity changes. Sessionless peers do not acquire an unbound sticky hold.
|
|
90
|
+
|
|
91
|
+
Once coverage is complete, NULL clean-session receipts may be pruned because complete absence preserves clean state. Positive and uncertain holds are not evicted to satisfy the 4096-row bound. Integrity metadata and counts are updated atomically with these changes. Public status names unavailable provenance and its next step without exposing note text or raw database errors. There is no automatic corrupt-state reset. Recovery preserves the receipts, integrity metadata and session-bound exclusion.
|
|
92
|
+
|
|
93
|
+
Role reassignment cannot clear the original recipient's observer exclusion while a review envelope remains queued, recovery-deferred or unsettled. The journal supplies recipient/task-scoped metadata independently of current task roles; explicit disposition ends that delivery scope. Sent person comments independently retain their saved package recipient until resolution or person dismissal.
|
|
94
|
+
|
|
95
|
+
## Room presence and broker backpressure (#1204 T1)
|
|
96
|
+
|
|
97
|
+
Ordinary observations reuse an already scheduled coalesced republish instead of
|
|
98
|
+
cancelling it and sealing a new frame on every awaited state flip. Responses and
|
|
99
|
+
forced refresh requests retain priority. A chat flushes earlier deferred presence
|
|
100
|
+
and reserves its own serial slot before yielding, preserving concurrent chat and
|
|
101
|
+
durable-outbox FIFO. Receipts retain their existing durable-commit/ACK path and do
|
|
102
|
+
not wait behind an additional ordinary observation. Actual-send exposure,
|
|
103
|
+
recipient, currency and capacity fences remain unchanged.
|
|
104
|
+
|
|
105
|
+
Presence carries a signed optional `ephemeral: true` frame header. The broker can
|
|
106
|
+
read this metadata but cannot decrypt the presence body. It retains only the
|
|
107
|
+
latest ephemeral frame per sender for currently connected, ready recipients;
|
|
108
|
+
disconnect and broker restart remove ephemeral recipients. Durable frames keep
|
|
109
|
+
the existing queue caps, TTL and exactly-once receiver admission.
|
|
110
|
+
|
|
111
|
+
A link skips an unchanged local presence snapshot, except explicit peer refresh
|
|
112
|
+
requests/responses and a fresh connection. One sealed frame is sent at a time
|
|
113
|
+
until its broker storage response, so a refused sequence cannot be overtaken.
|
|
114
|
+
A correlated `queue_full` retains the frame (applications remain in the local
|
|
115
|
+
outbox) and retries after 250 ms, doubling to a 30 s ceiling. Stop/refresh clears
|
|
116
|
+
connection timers; no recipient receipt or application completion is inferred.
|
|
117
|
+
T1 does not change acknowledgement deadlines, restart replay or receipt outbox
|
|
118
|
+
persistence, which belong to T2. Existing layer caps remain authoritative.
|
|
119
|
+
|
|
120
|
+
### Room wire compatibility (#1204 T1)
|
|
121
|
+
|
|
122
|
+
The link requests only the ephemeral feature with the WebSocket upgrade header
|
|
123
|
+
`x-agent-hub-ephemeral: 1`. A supporting broker includes `ephemeral: true` in its
|
|
124
|
+
ready response only to an opted-in client, preserving the exact legacy ready
|
|
125
|
+
shape for older hubs. Each new connection starts with the feature disabled.
|
|
126
|
+
Without the advertisement, presence retains the legacy frame shape; dedupe and
|
|
127
|
+
queue_full backoff still apply, but that broker retains presence for offline
|
|
128
|
+
members under its old queue rules. Upgrade the broker for ephemeral retention.
|
|
129
|
+
|
|
130
|
+
A supporting broker forwards ephemeral presence only to ready members that
|
|
131
|
+
opted in. Older members do not see upgraded members' presence until they upgrade. Application
|
|
132
|
+
chat frames keep the legacy shape. This is the one-bit compatibility bridge;
|
|
133
|
+
full codec feature advertisement belongs to #1204 T4.
|
|
134
|
+
|
|
135
|
+
Ephemeral replacement preserves a recipient's outstanding one-packet transport
|
|
136
|
+
slot until its matching ACK or the original TTL/grace bound expires. Only the
|
|
137
|
+
pending replacement coalesces; a newer observation never refreshes the handed
|
|
138
|
+
packet's deadline. Unsupported recipients never receive the new frame shape.
|
|
139
|
+
|
|
140
|
+
A refresh request
|
|
141
|
+
remains on non-reply snapshots until all asked members supply validated presence;
|
|
142
|
+
replies never request a reply. The bounded round resets on reconnect or roster
|
|
143
|
+
change. The latest-per-sender crossing ceiling and its #736 upgrade path are
|
|
144
|
+
recorded in the rooms spec.
|
|
145
|
+
|
|
146
|
+
## Room application retry and settlement (#1204 T2)
|
|
147
|
+
|
|
148
|
+
Room sends retain one immutable application id and original queue expiry across
|
|
149
|
+
fresh ciphertext attempts. A distinct root delivery may reuse a retained application
|
|
150
|
+
only with the same canonical content hash and peer/recipient tuple, no person
|
|
151
|
+
disposition or permanent hold, and the original creation/expiry times. Legacy
|
|
152
|
+
NULL content hashes refuse cross-root reuse. Receiver admission keeps the existing application-id
|
|
153
|
+
dedupe horizon (30 days / 10,000 identities with settled-first eviction).
|
|
154
|
+
This is exactly once within dedupe ceiling. Automatic resend can reach that
|
|
155
|
+
ceiling after a settled identity is evicted, permitting duplicate admission under
|
|
156
|
+
a fresh ciphertext sequence. Pinning retryable identities or #737 receipt
|
|
157
|
+
confirmation is the upgrade path.
|
|
158
|
+
A typed refusal before durable enqueue requeues the original without uncertainty
|
|
159
|
+
or poison retry accounting. Online readiness and the ACK deadline trigger retries;
|
|
160
|
+
the ACK deadline is not a terminal disposition. Queue TTL or a permanent refusal
|
|
161
|
+
ends automatic sending. An ordinary remote chat uncertainty row does not block later queued work.
|
|
162
|
+
Invocation uncertainty retains its person-only ledger hold and is never automatically
|
|
163
|
+
replayed or settled from late transport evidence. Active invocation receipts update
|
|
164
|
+
only transport metadata, never native execution or task-offer read evidence.
|
|
165
|
+
|
|
166
|
+
Each retry rechecks current room/member identity, exposure and privacy against the
|
|
167
|
+
saved immutable application. A restart reconstructs active remote deliveries under
|
|
168
|
+
their existing ids rather than treating transport loss as native consumption. A
|
|
169
|
+
late authenticated recipient receipt can settle an unresolved remote hold once,
|
|
170
|
+
with an ids-only event. Person dispositions, stale adapters and changed membership
|
|
171
|
+
remain authoritative; native delivery and task-offer read evidence are unaffected.
|
|
172
|
+
|
|
173
|
+
Roster, pause, lifecycle and global recovery fences also apply to resends. A
|
|
174
|
+
readiness loss after durable enqueue retains that delivery's id and original TTL;
|
|
175
|
+
confirmed precommit absence can requeue. A restored active journal row with no
|
|
176
|
+
matching row in an intact RoomStore becomes `needs_review` for inspection and is
|
|
177
|
+
never replayed from missing evidence. A failed payload-proof read never schedules
|
|
178
|
+
an immediate retry: transient failures wait for an online or ACK-deadline wake,
|
|
179
|
+
and permanently unavailable ciphertext is held for review with a metadata-only
|
|
180
|
+
transition. Metadata settlement and quarantine remain available while sending is held.
|
|
181
|
+
Authoritative Bus person dispositions are reconciled into RoomStore before
|
|
182
|
+
startup replay and incoming receipt processing. A local transport result may
|
|
183
|
+
remain as evidence beside that disposition, but cannot override it or restart
|
|
184
|
+
sending. Status reads remain read-only.
|
|
185
|
+
|
|
186
|
+
A completed inbound admission commits its signed receipt ciphertext to the local
|
|
187
|
+
RoomStore outbox before transport ACK of the chat. Pending receipts replay on
|
|
188
|
+
reconnect until broker storage confirmation. Waiting for broker storage before
|
|
189
|
+
chat ACK would deadlock at capacity one. The durable outbox removes T1's RAM-loss
|
|
190
|
+
exception; broker storage and transport ACK still do not prove native execution.
|
|
191
|
+
ACK after durable local commit of either the receipt or the inbox entry.
|
|
192
|
+
Deferred application admission may ACK its durable crypto inbox entry so it does
|
|
193
|
+
not pin broker capacity; later admission commits and replays the same durable
|
|
194
|
+
receipt path before retiring its local work.
|
|
@@ -30,6 +30,9 @@ paths:
|
|
|
30
30
|
- src/hub/task-repository.ts
|
|
31
31
|
- src/hub/no-writes.ts
|
|
32
32
|
- src/hub/review-findings.ts
|
|
33
|
+
- src/hub/review-anchor.ts
|
|
34
|
+
- src/hub/review-comments.ts
|
|
35
|
+
- src/hub/review-material.ts
|
|
33
36
|
- src/hub/workflow.ts
|
|
34
37
|
- src/hub/deliverables.ts
|
|
35
38
|
- src/hub/deliverable-files.ts
|
|
@@ -39,6 +42,7 @@ paths:
|
|
|
39
42
|
- src/hub/ci-watch.ts
|
|
40
43
|
- src/hub/research-campaign.ts
|
|
41
44
|
- src/hub/research-experiments.ts
|
|
45
|
+
- src/hub/research-evidence.ts
|
|
42
46
|
- src/hub/research-runner.ts
|
|
43
47
|
- src/hub/task-approval.ts
|
|
44
48
|
- src/hub/schedules.ts
|
|
@@ -47,6 +51,8 @@ paths:
|
|
|
47
51
|
- src/cli/handoff-args.ts
|
|
48
52
|
- src/cli/handoff-output.ts
|
|
49
53
|
- src/hub/task-list-page.ts
|
|
54
|
+
- src/hub/worktree-shelf.ts
|
|
55
|
+
- src/hub/worktree-prs.ts
|
|
50
56
|
---
|
|
51
57
|
|
|
52
58
|
# Task Board
|
|
@@ -69,6 +75,14 @@ Automatic offer and backlog paths respect `plannedStart`; a future card becomes
|
|
|
69
75
|
|
|
70
76
|
Urgent acceptance can reclaim only enough unaccepted, unstarted, non-pinned and non-urgent offers to fit the limit. It does so after other admission checks and immediately before the accept write; if insufficient, it reclaims none. Accepted work is never displaced merely to satisfy a new urgent request, because an offer and an active commitment have different costs ([#1080](https://github.com/STAIxBWLB/agent-hub/issues/1080)).
|
|
71
77
|
|
|
78
|
+
Untouched returns may atomically update `reserved` while moving eligible proposed or accepted work back to Backlog. `Tasks` retains the existing authority, execution-evidence, pin, release and reservation gates, including post-screen rechecks. An explicit reservation patch advances planning revision and records its prior value in the same state/history write, before capacity publication can trigger auto-pull. Clearing it therefore parks the card; omitting fields preserves its planning. Assignment and auto-pull selection remain the existing rules, with no time-based suppression ([#1154](https://github.com/STAIxBWLB/agent-hub/issues/1154)).
|
|
79
|
+
|
|
80
|
+
## Source-backed plans and request intake
|
|
81
|
+
|
|
82
|
+
For a profile that supports `plan.sources`, `Tasks` validates every retained source ID against the source registry at proposal and acceptance, before board writes, admission effects or peer notices. Unknown IDs are refused with the ID and `ahub source list` guidance. Overlap notices compare the registry IDs; private task plans remain withheld by the shared public view.
|
|
83
|
+
|
|
84
|
+
Natural-language intake from the CLI or dashboard enters the same `Tasks.intake` path and creates held draft Backlog cards, not offers. Dashboard task replies use the public view, and a ticket-bound live-test session cannot create these person-attributed drafts. Approval and discard retain their existing authority. Read-only source snapshots carry only ID, kind, byte size, hash prefix and registration time, with no content or origin paths ([#1144](https://github.com/STAIxBWLB/agent-hub/issues/1144)).
|
|
85
|
+
|
|
72
86
|
## Completion, review and evidence
|
|
73
87
|
|
|
74
88
|
Completion binds the submitted full head and any verified deliverable records. It may run a configured check before requesting review. A review records a verdict against that evidence; it does not itself merge a PR. An unmerged approved task can receive a new owner submission, superseding the earlier review binding rather than treating old approval as authority for changed code ([#1047](https://github.com/STAIxBWLB/agent-hub/issues/1047)). A re-file cannot silently inherit an old head after the linked PR moves, and an approval with no supplied head refuses known-stale evidence. Refusals name the recorded and supplied or read heads and direct the owner to re-file `hub_task_done` with the new full SHA in `refs.commit`; summary text is not head evidence. This prevents stale approval from being presented as review of changed code ([#1121](https://github.com/STAIxBWLB/agent-hub/issues/1121)).
|
|
@@ -77,6 +91,70 @@ Review independence and declared scope are different controls. Selection exclude
|
|
|
77
91
|
|
|
78
92
|
Task text and private-turn words can reach owners, reviewers, overlap notices and memory. Public views use the host's current privacy projection; PII tasks remain stubs for unauthorized observers, and private turns cannot write ordinary shared task text. The projection belongs at the shared boundary because filtering individual callers would leave another observer exposed ([#198](https://github.com/STAIxBWLB/agent-hub/issues/198), [#230](https://github.com/STAIxBWLB/agent-hub/issues/230)).
|
|
79
93
|
|
|
94
|
+
## Claim evidence records (#931 T1)
|
|
95
|
+
|
|
96
|
+
The #901 owner boundary exposes one canonical `taskClaimIdentity(task, slot)`.
|
|
97
|
+
`claimId` is `claim:<task id>:<created>:<1-based slot>`, so a reset that reuses a
|
|
98
|
+
task number cannot inherit an earlier task's evidence. `claimRevision` is the
|
|
99
|
+
existing `claimListId(task.plan?.claims)`, the opaque 16-hex ordered-list hash
|
|
100
|
+
already stamped in person verdicts. `recordClaimVerdict` and the evidence writer
|
|
101
|
+
use that same helper; neither a second claim/verdict store nor a numeric claim
|
|
102
|
+
counter is introduced. Exact-list restoration retains #901's existing verdict
|
|
103
|
+
semantics. The list-level ceiling is conservative: any claim edit, reorder or
|
|
104
|
+
replacement stales every link bound to the changed list. Per-claim revisions
|
|
105
|
+
would be the upgrade path if that over-invalidation becomes a problem.
|
|
106
|
+
|
|
107
|
+
Existing `hub_task_show` and `ahub task show --json` views expose a research
|
|
108
|
+
task's current text-free `claims: [{slot, claimId, claimRevision}]` bindings,
|
|
109
|
+
derived only from that canonical helper. PII tasks expose none, and dev views
|
|
110
|
+
keep their existing shape. A caller copies the returned binding rather than
|
|
111
|
+
reimplementing plan hashing; a changed list requires a fresh view before record.
|
|
112
|
+
|
|
113
|
+
`EvidenceLinkV1` carries exactly `id`, `claimId`, `claimRevision`, `sourceId`,
|
|
114
|
+
`rawSha256`, `projectionSha256`, `projectionVersion`, `locator`, `relation`,
|
|
115
|
+
`recordedBy`, `taskId` and `revision`. Relations are `supports`, `contradicts` or
|
|
116
|
+
`context`, all declared provenance rather than an entailment decision. `locator`
|
|
117
|
+
stores proposed zero-based, half-open Unicode scalar-value `start`/`end` bounds
|
|
118
|
+
with a nonempty span of at most 4096. T1 does not convert offsets, resolve text,
|
|
119
|
+
accept page/section/excerpt fields or claim a projection is verified.
|
|
120
|
+
|
|
121
|
+
The flat `hub_evidence_record` input omits host-owned `recordedBy`; `revision`
|
|
122
|
+
defaults to 1 and `id` is optional for initial writes. A later revision names
|
|
123
|
+
its existing ID and the next revision number. Initial IDs are deterministic for
|
|
124
|
+
the same normalized input and actor. Replaying identical canonical bytes at an
|
|
125
|
+
existing ID/revision writes nothing; conflicting bytes or an out-of-sequence
|
|
126
|
+
revision refuse. Every accepted revision remains in the append-only evidence
|
|
127
|
+
table. #901 person-verdict history and scorecard counts remain the sole judgment
|
|
128
|
+
record, unaffected by evidence relation labels.
|
|
129
|
+
|
|
130
|
+
Tasks prechecks sequence and claim association before screening and immediately
|
|
131
|
+
before append; the Board transaction repeats them as the race fence. Ordinary
|
|
132
|
+
sequence/association refusals are pre-effect and name the expected next revision
|
|
133
|
+
when applicable. Invalid stored evidence directs the person to stop the hub,
|
|
134
|
+
restore a trusted project `hub.db` backup, restart and retry; T1 does not name an
|
|
135
|
+
unimplemented evidence-read command.
|
|
136
|
+
|
|
137
|
+
`Tasks.evidenceRecord` admits only the current in-progress owner of a stored
|
|
138
|
+
research-profile task, with current claim binding and registered source/raw hash.
|
|
139
|
+
Standalone tasks do not need a campaign, and role-catalog guidance grants no
|
|
140
|
+
authority. Recovery/shutdown holds, private turns, PII tasks, private sources,
|
|
141
|
+
unknown sources, stale claims and foreign-task writes refuse before effects.
|
|
142
|
+
Every awaited preparation is followed by current task/source/actor checks; the
|
|
143
|
+
append transaction also fences task incarnation, owner, flow and claim revision.
|
|
144
|
+
Current metadata privacy is checked again after asynchronous screening and immediately before append; a failed or unavailable policy refuses. Successful evidence receipts, including replay, are owner task effects for the existing no-write advisory.
|
|
145
|
+
Public receipts contain only link ID, revision and task ID. The tool is excluded
|
|
146
|
+
from argument/result capture and from read-only publication; dev-profile tool
|
|
147
|
+
lists retain their existing shape.
|
|
148
|
+
|
|
149
|
+
Projection hashes/version are caller-declared T1 bindings; only the raw source
|
|
150
|
+
hash is checked against registry metadata. Locator resolution, Unicode offset
|
|
151
|
+
conversion and current-privacy public revalidation are T2. Evidence read/CLI
|
|
152
|
+
surfaces, complete inventory bindings and synthesis readiness remain later work.
|
|
153
|
+
Stored evidence adds a conditional `research_evidence` recovery feature and
|
|
154
|
+
`{links, revisions, digest}` integrity section. An absent section is the empty
|
|
155
|
+
store, preserving older recovery records; an empty database requires no new
|
|
156
|
+
feature. Provenance never manufactures a person verdict or readiness result.
|
|
157
|
+
|
|
80
158
|
## Read models and policy extensions
|
|
81
159
|
|
|
82
160
|
Agent list reads return bounded, newest-updated compact pages built from public rows, with a keyset cursor and explicit detail/ID reads. Console compatibility is separate. Pagination is not a frozen snapshot during concurrent edits; its purpose is bounded communication without bypassing private-row projection ([#1083](https://github.com/STAIxBWLB/agent-hub/issues/1083)).
|
|
@@ -84,3 +162,25 @@ Agent list reads return bounded, newest-updated compact pages built from public
|
|
|
84
162
|
Lifecycle policy can be off, advisory or enforced; this is separate from always-applicable role and privacy invariants. Plans, cost/check scope, review findings and external evidence retain their own typed provenance. Research campaigns and experiments likewise distinguish declared, host-observed and runner-attested facts instead of promoting prose to a signed result ([#481](https://github.com/STAIxBWLB/agent-hub/issues/481), [#932](https://github.com/STAIxBWLB/agent-hub/issues/932), [#1018](https://github.com/STAIxBWLB/agent-hub/issues/1018)). Detailed research contracts remain in the [campaign design](../specs/2026-11-01-research-campaigns-design.md).
|
|
85
163
|
|
|
86
164
|
When the specs policy is enabled, covering design specs participate in proposal/accept notices and completion/review reports. Report mode informs; require mode needs an updated spec or a recorded acknowledgement for each applicable unchanged spec. Commitless and verified no-change work remains quiet, and private evidence is withheld rather than exposed to satisfy a report. These modes preserve owner choice while making design drift visible ([#1064](https://github.com/STAIxBWLB/agent-hub/issues/1064)).
|
|
165
|
+
|
|
166
|
+
## Worktree shelf (#1057)
|
|
167
|
+
|
|
168
|
+
The board stores facts about worktrees and never a verdict. `worktree_override` holds only a person's Park (`settled`) or Pin (`active`) per absolute path and its time; whether a worktree is settled is derived on every read by the pure `partition` from the git facts, the bound task (the open or latest task whose `refs.branch` is the worktree branch, never a PII task), the PR state and those overrides. An override counts only while no newer activity exists, and a later write removes an inert one.
|
|
169
|
+
|
|
170
|
+
The PR state has two sources and no others. The board's own evidence says `merged` only through the guarded merge's record (`sdlc.merge`); a cancelled task or a task with no record says nothing about its PR and reads `unknown`. The person's explicit refresh (`worktrees_refresh_prs`, `src/hub/worktree-prs.ts`) reads the PR through `readSdlcPr`, bounded and one at a time, and keeps `open`, `merged` or `closed` with GitHub's own change time in the daemon's memory. `worktree-shelf.ts` holds no GitHub access, so a panel read, `ahub worktrees` and the inbox alert make no GitHub call.
|
|
171
|
+
|
|
172
|
+
A worktree whose activity could not be read is live and never settled. The shelf reads git asynchronously under a total budget and answers `complete: false` when it is cut; the daemon's event loop is never held. The daemon deletes no worktree and no local branch: its git port allows three read argv shapes, and removal exists only in the person's own `ahub worktrees tidy --confirm`, which is console class and issues `git worktree remove` and `git branch -d`, never `--force` or `-D`. Operations: `docs/operations.md`, "The worktree shelf (#1057)".
|
|
173
|
+
|
|
174
|
+
## Anchored review packages (#1056)
|
|
175
|
+
|
|
176
|
+
`ReviewFinding.anchor` uses the exact-pinned `@staix/agent-console` 0.1.3 DOM-free `./contract` entry through type-only imports. The generated declaration bridge is removed. `test/acon-review-contract.test.ts` checks the unchanged shared fixtures against both the published acon conformance functions and the hub validator; the project retains its Bun-only TypeScript libraries. Contract conformance and hub writes are separate: hub writes allow 1-4 selectors, 512 UTF-8 bytes for an exact quote, 64 each for prefix and suffix, 256 for a hunk header, 2048 for a comment body and 64 comments per task. The hub additionally caps paths at 4096 bytes, projection name/version and structural scheme at 128 each, structural ref at 512 and verified author identity at 512. These bounds keep each stored thread within its fixed read bound. Quote selector text remains exact in storage; `sanitize()` applies when it is rendered beside hub headers. The hub limits count UTF-8 bytes, independently of acon's character limits: 171 Hangul syllables exceed the 512-byte exact-quote cap. Refusals identify the field, bound and next step. Unknown fields and selectors refuse before effects. A finding path, when present, must equal its anchor path. Findings without anchors retain the existing head buckets and Important carry-over rule.
|
|
177
|
+
|
|
178
|
+
All person comment writes go through `Tasks`. The console can put or delete a draft without a peer envelope. An explicit send binds the selected immutable anchors and bodies to one package, changes their lifecycle to sent, appends one count-only task history entry and attempts one review envelope. A failed or uncertain notification never retries automatically. Its receipt distinguishes queued from unconfirmed delivery; neither means the owner read it. The saved package retains its immutable body, envelope identity, original visibility binding and versioned publication-evidence contract. Its serialized record must fit 32768 UTF-8 bytes before any sent write. A previously unpublished package is admitted only while every selected comment remains sent and its originally visible text remains public under current policy; a missing binding, dismissal or privacy change refuses without rewriting or publishing the old body. An explicit confirmed Send with `packageId` recovers only that saved package. Durable queue or delivery evidence makes this idempotent, including after restart; failed or discarded deliveries refuse with their actual state and `ahub queue` inspection guidance rather than reporting queued or replaying the effect. Unknown evidence and legacy packages refuse with inspection guidance. Person-package terminal receipts are retained alongside the package rather than pruned with ordinary delivery history. Quote-bearing reviewer requests use a distinct `reviewer-request-` marker and their terminal rows follow ordinary pruning. This retains a full receipt per package; package archival with an IDs-only tombstone is the upgrade path. Deleting a sent comment dismisses it without rewriting its anchor. Only a final successful owner completion may claim resolved comment IDs; a queued or failed check leaves them sent. That claim is not person verification or a review verdict.
|
|
179
|
+
|
|
180
|
+
The actor is the console person, not a conductor or a peer. acon authorship comes only from the server-built `ActionMeta` argument. Client body fields cannot supply an author, timestamp or authority. The standalone dashboard is read-only; acon's shared `ui.review` kit owns selection and Send. Older acon hosts without the kit retain the read-only view.
|
|
181
|
+
|
|
182
|
+
Placement is computed before reads and sends, never persisted over the stored anchor. Equal content hashes are anchored; a different hash with a uniquely matching exact quote is moved, with context breaking ties; unresolved changes are outdated. Missing, denied, private or over-budget material is unavailable. Projection identity mismatches are outdated before hash comparison. A display range from moved placement never becomes a new stored selector. An unavailable public comment retains its stored thread in the person view, labelled unavailable. Send refuses before any effect and names each unavailable selected comment. Actual PII/private comments remain count-only. Carried finding placement belongs to one asynchronous review admission. Rare synchronous role re-offers without that material report unavailable until the next refresh, rather than reusing old coordinates.
|
|
183
|
+
|
|
184
|
+
Periodic dashboard snapshots perform no comment-material Git or GitHub reads. Explicit task open or refresh requests the review section; a failed read marks only that section unavailable. Material uses the recorded task head and never substitutes the worktree HEAD for a missing commit. Material comes only from guarded immutable Git snapshots in the task's declared refs, plan paths or sections, or complete same-head verified PR paths. Every operation shares eight distinct files, eight seconds including head/PR preparation and 12000 serialized presentation bytes. Both sides share the budget. Truncated material cannot establish placement. Raw hashes bind bytes; projected hashes bind only UTF-8 projected text. The projection name is `text-projection:<extension>` and its version is the existing configured converter fingerprint. This is an opaque configuration identity, not an upstream semantic version; a converter version protocol would be the upgrade path.
|
|
185
|
+
|
|
186
|
+
PII comments remain board-local and public views expose counts only. Private paths retain only supplied lineRange or structural selectors; no coordinate is invented when unsafe selectors are removed. Public review packets carry a host-only opaque package marker so their intended owner receives the packet while logs, operational tails, incoming labels, capture and memory observers receive no quote or body. This marker does not turn an ordinary task into a PII turn. Structured anchored verdicts retain the GitHub verdict mirror with a verdict-only headline when quote provenance is present. Decision metadata, contradiction and safe recurring criteria retain their existing paths; quote-bearing finding proposals remain excluded. The configured PII screen checks reviewer prose before owner-facing publication without receiving source quote selectors. Durable open sent comments and outstanding anchored findings bind shared-memory admission only to the task a note names and its recipient, across restart and intervening chat. Sent comments hold those task-bound writes until resolution or person dismissal; resolved or dismissed comments alone do not retain reviewer history scope. They do not hold notes for an unrelated task or an untagged note after ordinary new input. Anchored-finding scope is conservatively held until the task closes, including later fixed dispositions; a persisted review-package epoch is the path to narrower closure. The metadata scope read is cached against database change stamps and fails closed above 500 role tasks or 16 MiB of UTF-8 history. This exclusion does not hide the owner's summary or check output from its reviewer or owner. Review requests retain trusted observer provenance whenever historical anchors or non-draft comments can be reflected in the completion text, including after comment resolution. Current input provenance separately holds all shared-memory writes and observer sinks for an actually delivered quote-bearing review input or a newly submitted anchored verdict, even if the verdict is refused or immediately closes the task. This exclusion is latched for the input turn until a permitted ordinary next-turn handoff replaces it; restored pull-only sessions instead require a changed native identity. Resolving comments or ending the task alone does not clear it. Bounded ID-only journal receipts preserve held session/input provenance across daemon restart. No matching held record in a complete, intact and readable store is clean; missing expected prior-session records and unreadable, corrupt or unconfirmed session coverage remain unknown. A validated matching release receipt confirms only its own identity. Restored pull-only sessions retain their hold until the native identity changes, regardless of inbox handout. An empty in-memory map alone is not replacement proof. Presence-only traffic and additional inputs within the same active turn cannot clear a latched exclusion. Committed inbox handouts carry the same current-input provenance as push input without claiming a native ACK. Local-worker batches latch before executing any tool, and their final answer and retained history obey the same exclusion. Owner-addressed review outcomes cannot be automatically settled merely because task or reviewer state moved. Original saved-package recipients retain comment scope while comments remain sent, and queued/deferred or unsettled delivery records retain their actual recipients independently of current task roles. A comment dismissal is not a delivery-consumption receipt; any separate uncertainty hold requires explicit disposition. Recovery treats an absent comment section as empty and checks the optional section's counts and digest when present.
|