@adhdev/mesh-shared 1.0.60-rc.9 → 1.0.60
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/dist/brain-routing.d.ts +6 -8
- package/dist/git-diff.d.ts +21 -0
- package/dist/index.d.ts +12 -1
- package/dist/index.js +2876 -77
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2625 -72
- package/dist/index.mjs.map +1 -1
- package/dist/interpolation.d.ts +0 -9
- package/dist/json.d.ts +4 -0
- package/dist/keyed-doc-delta.d.ts +105 -0
- package/dist/mesh-tool-names.d.ts +31 -2
- package/dist/mesh-vocabulary.d.ts +66 -0
- package/dist/mission-brief.d.ts +62 -0
- package/dist/outbound-message.d.ts +201 -0
- package/dist/path-ownership.d.ts +101 -0
- package/dist/protocol/daemon-server.d.ts +356 -0
- package/dist/protocol/dashboard-daemon-p2p.d.ts +213 -0
- package/dist/protocol/dashboard-server.d.ts +240 -0
- package/dist/protocol/dashboard-wire-version.d.ts +21 -0
- package/dist/protocol/envelope.d.ts +55 -0
- package/dist/protocol/index.d.ts +16 -0
- package/dist/session-launch.d.ts +105 -0
- package/dist/session-status.d.ts +75 -0
- package/dist/slot-proposal.d.ts +2 -28
- package/dist/turn-evidence.d.ts +434 -0
- package/dist/turn-ipc-guards.d.ts +18 -0
- package/dist/turn-ipc-mission.d.ts +250 -0
- package/dist/turn-ipc-queue.d.ts +196 -0
- package/dist/turn-ipc-stats.d.ts +72 -0
- package/dist/turn-ipc-turn.d.ts +176 -0
- package/dist/turn-ipc.d.ts +90 -0
- package/dist/types.d.ts +11 -0
- package/dist/worker-protocol.d.ts +69 -0
- package/dist/ws-protocol.d.ts +69 -41
- package/package.json +1 -1
- package/src/brain-routing.ts +9 -11
- package/src/git-diff.ts +48 -0
- package/src/index.ts +12 -1
- package/src/interpolation.ts +0 -18
- package/src/json.ts +10 -0
- package/src/keyed-doc-delta.ts +413 -0
- package/src/mesh-tool-names.ts +66 -25
- package/src/mesh-vocabulary.ts +94 -0
- package/src/mission-brief.ts +153 -0
- package/src/outbound-message.ts +319 -0
- package/src/path-ownership.ts +271 -0
- package/src/protocol/daemon-server.ts +510 -0
- package/src/protocol/dashboard-daemon-p2p.ts +273 -0
- package/src/protocol/dashboard-server.ts +340 -0
- package/src/protocol/dashboard-wire-version.ts +27 -0
- package/src/protocol/envelope.ts +75 -0
- package/src/protocol/index.ts +17 -0
- package/src/session-launch.ts +245 -0
- package/src/session-status.ts +164 -0
- package/src/slot-proposal.ts +2 -48
- package/src/turn-evidence.ts +596 -0
- package/src/turn-ipc-guards.ts +61 -0
- package/src/turn-ipc-mission.ts +647 -0
- package/src/turn-ipc-queue.ts +493 -0
- package/src/turn-ipc-stats.ts +193 -0
- package/src/turn-ipc-turn.ts +453 -0
- package/src/turn-ipc.ts +137 -0
- package/src/types.ts +8 -0
- package/src/worker-protocol.ts +164 -0
- package/src/ws-protocol.ts +98 -93
- package/dist/magi.d.ts +0 -281
- package/src/magi.ts +0 -310
|
@@ -0,0 +1,434 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* turn-evidence — the ONE vocabulary for "what happened to a turn".
|
|
3
|
+
*
|
|
4
|
+
* Wiring-unification Phase C1 (docs/design/2026-09-23-wiring-unification.md §5).
|
|
5
|
+
*
|
|
6
|
+
* Every producer that today decides "done" on its own (completion flush, stall
|
|
7
|
+
* rescue, reconcile synthesis, MCP probes, worker report tools, …) instead
|
|
8
|
+
* submits one of these evidence records to the turn ledger, whose pure reducer
|
|
9
|
+
* is the only authority for a turn's state. Worker daemons and the MCP server
|
|
10
|
+
* build them, so the types live here (a dependency-free leaf).
|
|
11
|
+
*
|
|
12
|
+
* CONTENT-FREE BY CONSTRUCTION
|
|
13
|
+
* ----------------------------
|
|
14
|
+
* Evidence crosses machines (seqscribe `mesh.<id>.events` replication) and must
|
|
15
|
+
* never carry anything a user or an agent wrote. Every field is one of: an
|
|
16
|
+
* identifier, a closed enum, a boolean, a number, or a `SummaryRef` — a pointer
|
|
17
|
+
* `{topic, writer, seq}` to a content-class topic entry (`mesh.<id>.handoff`)
|
|
18
|
+
* where the text actually lives. `TURN_EVIDENCE_FIELD_SPECS` declares the class
|
|
19
|
+
* of every field of every member (the compiler forces it to stay total and
|
|
20
|
+
* exact), the runtime guard validates against it, and a test walks it to prove
|
|
21
|
+
* no free-text field exists.
|
|
22
|
+
*/
|
|
23
|
+
import { type WorkerBranchState, type WorkerReportOutcome } from './mesh-vocabulary';
|
|
24
|
+
import { type SessionStatus } from './session-status';
|
|
25
|
+
import { type SendRefusal } from './outbound-message';
|
|
26
|
+
/** Protocol version stamped on every `mesh.<id>.events` entry written by the turn ledger. */
|
|
27
|
+
export declare const MESH_TOPIC_PROTOCOL_VERSION: 2;
|
|
28
|
+
export declare const EVIDENCE_SOURCE_IDS: readonly ["fsm_edge", "short_gen_inline", "completion_flush_genuine", "completion_flush_weak", "monitor_final_summary", "pre_cleanup_transcript", "stall_transcript", "startup_grace_collapse", "acp_prompt_response", "cdp_state", "approval_gate", "modal_button", "mesh_stall_watchdog", "status_monitor", "pty_exit", "provider_error", "coordinator_probe", "mcp_probe", "worker_tool", "dispatch", "input_service", "operator", "intentional_cleanup", "scheduler", "git_probe", "session_registry"];
|
|
29
|
+
export type EvidenceSourceId = typeof EVIDENCE_SOURCE_IDS[number];
|
|
30
|
+
export declare const TURN_SCOPES: readonly ["mesh_queue", "mesh_direct", "plain"];
|
|
31
|
+
export type TurnScope = typeof TURN_SCOPES[number];
|
|
32
|
+
/**
|
|
33
|
+
* Refusals (D1 `SendRefusal`, owned by ./outbound-message) that mean the target
|
|
34
|
+
* can never take this dispatch, so the attempt is reclaimed (R3). Every other
|
|
35
|
+
* refusal is retried by the sender and only recorded.
|
|
36
|
+
*/
|
|
37
|
+
export declare const RECLAIMING_SEND_REFUSALS: readonly ["session_exited", "no_target", "unsupported_input"];
|
|
38
|
+
export type ReclaimingSendRefusal = typeof RECLAIMING_SEND_REFUSALS[number];
|
|
39
|
+
export declare const DELIVERY_OUTCOMES: readonly ["delivered", "queued"];
|
|
40
|
+
export type DeliveryOutcome = typeof DELIVERY_OUTCOMES[number];
|
|
41
|
+
export declare const DELIVERY_VIAS: readonly ["local", "p2p"];
|
|
42
|
+
export type DeliveryVia = typeof DELIVERY_VIAS[number];
|
|
43
|
+
export declare const DISPATCH_FAILURE_REASONS: readonly ["worker_absent", "transport_error", "spawn_failed", "rejected_by_worker", "timeout"];
|
|
44
|
+
export type DispatchFailureReason = typeof DISPATCH_FAILURE_REASONS[number];
|
|
45
|
+
/**
|
|
46
|
+
* Normalize a worker's own refusal code (e.g. `session_busy_with_task`,
|
|
47
|
+
* `mesh_sender_not_on_roster`, `provider_quota_exhausted`) into the shape
|
|
48
|
+
* `dispatch_failed.refusalCode` accepts: lowercase ascii + underscore, capped
|
|
49
|
+
* at 64 chars. Returns undefined for anything that yields no usable token, so
|
|
50
|
+
* a malformed/foreign code degrades to "no refusalCode" rather than smuggling
|
|
51
|
+
* arbitrary text through what must stay a closed-enum-like identifier slot
|
|
52
|
+
* (see the field's doc comment — this evidence replicates cross-machine).
|
|
53
|
+
*/
|
|
54
|
+
export declare function sanitizeRefusalCode(value: unknown): string | undefined;
|
|
55
|
+
export declare const CONSUME_PROFILES: readonly ["default", "native_source"];
|
|
56
|
+
export type ConsumeProfile = typeof CONSUME_PROFILES[number];
|
|
57
|
+
export declare const SESSION_REBOUND_REASONS: readonly ["restart", "live_holder"];
|
|
58
|
+
export type SessionReboundReason = typeof SESSION_REBOUND_REASONS[number];
|
|
59
|
+
export declare const SUSPENSION_MODALS: readonly ["approval", "choice"];
|
|
60
|
+
export type SuspensionModal = typeof SUSPENSION_MODALS[number];
|
|
61
|
+
export declare const SUSPENSION_RESOLUTIONS: readonly ["approved", "rejected", "answered"];
|
|
62
|
+
export type SuspensionResolution = typeof SUSPENSION_RESOLUTIONS[number];
|
|
63
|
+
export declare const SUSPENSION_RESOLUTION_VIAS: readonly ["modal_button", "auto_approve", "prompt_answer"];
|
|
64
|
+
export type SuspensionResolutionVia = typeof SUSPENSION_RESOLUTION_VIAS[number];
|
|
65
|
+
export declare const TURN_END_STRENGTHS: readonly ["genuine", "weak"];
|
|
66
|
+
export type TurnEndStrength = typeof TURN_END_STRENGTHS[number];
|
|
67
|
+
/** Why a provider-side weak end was released (was free text `blockReason`). */
|
|
68
|
+
export declare const TURN_END_BLOCK_REASONS: readonly ["missing_final_assistant", "finalization_timeout", "terminal_block_hard_cap", "decoupled_completion"];
|
|
69
|
+
export type TurnEndBlockReason = typeof TURN_END_BLOCK_REASONS[number];
|
|
70
|
+
export declare const NATIVE_TURN_OUTCOMES: readonly ["completed", "aborted"];
|
|
71
|
+
export type NativeTurnOutcome = typeof NATIVE_TURN_OUTCOMES[number];
|
|
72
|
+
export declare const LIVENESS_RESULTS: readonly ["alive", "unknown", "read_failed", "dead"];
|
|
73
|
+
export type LivenessResult = typeof LIVENESS_RESULTS[number];
|
|
74
|
+
export declare const PROVIDER_FAILURES: readonly ["auth_failed", "billing_failed"];
|
|
75
|
+
export type ProviderFailure = typeof PROVIDER_FAILURES[number];
|
|
76
|
+
/**
|
|
77
|
+
* `daemon_restart` (wiring-unification follow-up, design §5): a boot-time
|
|
78
|
+
* reconciliation observes this for a plain attempt whose session is gone
|
|
79
|
+
* after a restart — the daemon never saw the session's own exit, so it is
|
|
80
|
+
* not `provider_error`/`adapter_error`/etc.; it is the daemon itself
|
|
81
|
+
* reporting "this session no longer exists".
|
|
82
|
+
*/
|
|
83
|
+
export declare const SESSION_ERROR_REASONS: readonly ["provider_error", "adapter_error", "spawn_failed", "auth_failed", "billing_failed", "unknown", "daemon_restart"];
|
|
84
|
+
export type SessionErrorReason = typeof SESSION_ERROR_REASONS[number];
|
|
85
|
+
export declare const CANCEL_REASONS: readonly ["operator_cancel", "intentional_cleanup", "task_removed", "mission_abandoned", "superseded"];
|
|
86
|
+
export type CancelReason = typeof CANCEL_REASONS[number];
|
|
87
|
+
export declare const OPERATOR_STATUSES: readonly ["completed", "failed"];
|
|
88
|
+
export type OperatorStatus = typeof OPERATOR_STATUSES[number];
|
|
89
|
+
export declare const OPERATOR_STATUS_REASONS: readonly ["operator_update", "refine_terminal", "validation_terminal"];
|
|
90
|
+
export type OperatorStatusReason = typeof OPERATOR_STATUS_REASONS[number];
|
|
91
|
+
export declare const COORDINATOR_ACK_OUTCOMES: readonly ["delivered", "queued", "duplicate"];
|
|
92
|
+
export type CoordinatorAckOutcome = typeof COORDINATOR_ACK_OUTCOMES[number];
|
|
93
|
+
/** Observed status as a no-progress monitor saw it (canonical session status or `unknown`). */
|
|
94
|
+
export declare const NO_PROGRESS_OBSERVED_STATUSES: readonly ["idle", "generating", "waiting_approval", "waiting_choice", "finalizing", "error", "stopped", "starting", "panel_hidden", "not_monitored", "disconnected", "unknown"];
|
|
95
|
+
export type NoProgressObservedStatus = SessionStatus | 'unknown';
|
|
96
|
+
/**
|
|
97
|
+
* Reasons a turn hold exists. Holds are attempt-scoped only (C2: delivery-side
|
|
98
|
+
* waits are consumer deferral on the `turn.deliver` cursor, not hold rows).
|
|
99
|
+
*/
|
|
100
|
+
export declare const HOLD_REASONS: readonly ["await_delivery", "await_consume", "await_turn", "liveness", "hard_ceiling", "live_pending", "transcript_quiet", "weak_candidate", "suspension_before_consumed", "await_report", "await_end"];
|
|
101
|
+
export type HoldReason = typeof HOLD_REASONS[number];
|
|
102
|
+
export declare const TURN_OUTCOMES: readonly ["completed", "failed", "cancelled"];
|
|
103
|
+
export type TurnOutcome = typeof TURN_OUTCOMES[number];
|
|
104
|
+
export declare const COMMIT_STRENGTHS: readonly ["genuine", "weak", "tool_report", "operator"];
|
|
105
|
+
export type CommitStrength = typeof COMMIT_STRENGTHS[number];
|
|
106
|
+
/** Every terminal or reclaim reason the ledger writes. Closed: no free-text reasons. */
|
|
107
|
+
export declare const TURN_REASONS: readonly ["turn_end", "weak_end_confirmed", "transcript_final", "worker_reported", "finalization_timeout_no_response", "session_error", "provider_auth_failed", "provider_billing_failed", "operator_cancel", "intentional_cleanup", "task_removed", "mission_abandoned", "superseded", "operator_update", "refine_terminal", "validation_terminal", "hard_ceiling", "reclaim_budget_exhausted", "hollow_max_retries", "migration_orphan", "dispatch_refused_session_exited", "dispatch_refused_no_target", "dispatch_refused_unsupported_input", "dispatch_failed", "session_exit", "session_exit_before_turn", "session_dead", "hollow_completion", "assigned_stranded_dispatch_unconfirmed", "delivered_not_consumed_redrive", "delivered_no_turn_deadline"];
|
|
108
|
+
export type TurnReason = typeof TURN_REASONS[number];
|
|
109
|
+
/**
|
|
110
|
+
* What a `turn.notify` entry tells a coordinator.
|
|
111
|
+
*
|
|
112
|
+
* `late_completion` (C1 R27, owner revision 2026-09-23): a superseded
|
|
113
|
+
* generation finished while the current one was already running; the
|
|
114
|
+
* coordinator decides whether to salvage it (the entry carries the g−1
|
|
115
|
+
* summary as its append `ref`). `mesh_event`: a non-turn coordinator notice
|
|
116
|
+
* (refine terminal, worktree bootstrap, …) whose text lives only in the
|
|
117
|
+
* owner's local `turn_events.payload_json` and is rendered at deliver time.
|
|
118
|
+
*/
|
|
119
|
+
export declare const NOTIFY_KINDS: readonly ["completed", "failed", "cancelled", "stopped", "approval", "choice", "approval_resolved", "candidate", "no_progress", "progress", "late_completion", "mesh_event"];
|
|
120
|
+
export type NotifyKind = typeof NOTIFY_KINDS[number];
|
|
121
|
+
export interface TurnAttemptRef {
|
|
122
|
+
attemptId: string;
|
|
123
|
+
generation: number;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Pointer to text that lives in a content-class topic entry (`mesh.<id>.handoff`).
|
|
127
|
+
* Text never travels inside evidence; the deliver side renders it from the ref.
|
|
128
|
+
*/
|
|
129
|
+
export interface SummaryRef {
|
|
130
|
+
topic: string;
|
|
131
|
+
writer: string;
|
|
132
|
+
seq: number;
|
|
133
|
+
}
|
|
134
|
+
/** Live-state observations that make a transcript end premature (admission input). */
|
|
135
|
+
export interface LiveTurnPending {
|
|
136
|
+
modal: boolean;
|
|
137
|
+
adapterPending: boolean;
|
|
138
|
+
trailingTool: boolean;
|
|
139
|
+
newestActivityAt?: number;
|
|
140
|
+
}
|
|
141
|
+
/** Structural copy of daemon-core's `CoordinatorIdentity` (this package cannot import daemon-core). */
|
|
142
|
+
export interface EvidenceCoordinatorIdentity {
|
|
143
|
+
daemonId: string;
|
|
144
|
+
coordinatorRunId: string;
|
|
145
|
+
sessionId?: string;
|
|
146
|
+
}
|
|
147
|
+
export interface NativeTurnMarkerRef {
|
|
148
|
+
outcome: NativeTurnOutcome;
|
|
149
|
+
turnId?: string;
|
|
150
|
+
}
|
|
151
|
+
export interface EvidenceEnvelope {
|
|
152
|
+
/** Stable id of this observation; dedupe key across republish/replication. */
|
|
153
|
+
eventId: string;
|
|
154
|
+
/** Producer clock, epoch ms. */
|
|
155
|
+
at: number;
|
|
156
|
+
source: EvidenceSourceId;
|
|
157
|
+
/** The session that produced / is the subject of the observation. */
|
|
158
|
+
sessionId: string;
|
|
159
|
+
attemptRef?: TurnAttemptRef;
|
|
160
|
+
/** Only when attemptRef is absent (legacy relay / MCP probe). */
|
|
161
|
+
taskId?: string;
|
|
162
|
+
/** Daemon id that observed it. */
|
|
163
|
+
observedBy: string;
|
|
164
|
+
}
|
|
165
|
+
/** Kind-specific bodies. `TurnEvidence = EvidenceEnvelope & TurnEvidenceBody`. */
|
|
166
|
+
export type TurnEvidenceBody = {
|
|
167
|
+
kind: 'dispatch_accepted';
|
|
168
|
+
scope: TurnScope;
|
|
169
|
+
messageId: string;
|
|
170
|
+
meshId?: string;
|
|
171
|
+
nodeId?: string;
|
|
172
|
+
providerType?: string;
|
|
173
|
+
attemptNo?: number;
|
|
174
|
+
dispatchNonce?: number;
|
|
175
|
+
consumeProfile?: ConsumeProfile;
|
|
176
|
+
maxTaskRetries?: number;
|
|
177
|
+
coordinator?: EvidenceCoordinatorIdentity;
|
|
178
|
+
} | {
|
|
179
|
+
kind: 'delivered';
|
|
180
|
+
messageId: string;
|
|
181
|
+
outcome: DeliveryOutcome;
|
|
182
|
+
via: DeliveryVia;
|
|
183
|
+
} | {
|
|
184
|
+
kind: 'delivery_refused';
|
|
185
|
+
messageId: string;
|
|
186
|
+
reason: SendRefusal;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* `refusalCode` (wiring-unification live-gap fix, 2026-09-25): the worker's own
|
|
190
|
+
* refusal code for an application-level `{success:false}` answer (e.g.
|
|
191
|
+
* `session_busy_with_task`, `mesh_sender_not_on_roster`,
|
|
192
|
+
* `mesh_node_bootstrap_pending`, `provider_quota_exhausted`) — optional and
|
|
193
|
+
* ONLY ever populated for `reason: 'rejected_by_worker'`. Deliberately an `id`
|
|
194
|
+
* (short enum-like token), never free text: this evidence replicates across
|
|
195
|
+
* machines over `mesh.<id>.events` (CONTENT-FREE BY CONSTRUCTION above), so a
|
|
196
|
+
* human-readable detail string must NOT travel here — it stays local (owner
|
|
197
|
+
* WARN log, MCP tool JSON response). Producers sanitize to `[a-z_]{1,64}`
|
|
198
|
+
* before emitting so a stray free-text code can never smuggle prose through
|
|
199
|
+
* this slot.
|
|
200
|
+
*/
|
|
201
|
+
| {
|
|
202
|
+
kind: 'dispatch_failed';
|
|
203
|
+
workerAbsent: boolean;
|
|
204
|
+
reason: DispatchFailureReason;
|
|
205
|
+
refusalCode?: string;
|
|
206
|
+
} | {
|
|
207
|
+
kind: 'duplicate_dispatch_refusal';
|
|
208
|
+
holderSessionId: string;
|
|
209
|
+
holderAttemptId?: string;
|
|
210
|
+
} | {
|
|
211
|
+
kind: 'session_rebound';
|
|
212
|
+
toSessionId: string;
|
|
213
|
+
reason: SessionReboundReason;
|
|
214
|
+
} | {
|
|
215
|
+
kind: 'turn_started';
|
|
216
|
+
retro: boolean;
|
|
217
|
+
} | {
|
|
218
|
+
kind: 'suspension';
|
|
219
|
+
modal: SuspensionModal;
|
|
220
|
+
modalKey?: string;
|
|
221
|
+
} | {
|
|
222
|
+
kind: 'suspension_resolved';
|
|
223
|
+
resolution: SuspensionResolution;
|
|
224
|
+
via: SuspensionResolutionVia;
|
|
225
|
+
} | {
|
|
226
|
+
kind: 'turn_end';
|
|
227
|
+
strength: TurnEndStrength;
|
|
228
|
+
afterFinalizationTimeout?: boolean;
|
|
229
|
+
hollow?: boolean;
|
|
230
|
+
summary?: SummaryRef;
|
|
231
|
+
blockReason?: TurnEndBlockReason;
|
|
232
|
+
releasedByHardCap?: boolean;
|
|
233
|
+
nativeOutcome?: NativeTurnOutcome;
|
|
234
|
+
live?: LiveTurnPending;
|
|
235
|
+
/**
|
|
236
|
+
* Stamped (true only) by the WORKER's daemon when the session holds a live
|
|
237
|
+
* worker-MCP session bind, i.e. the worker can call report_completion. The
|
|
238
|
+
* owner then treats a genuine end as a report-awaiting candidate (R9r), not
|
|
239
|
+
* a commit. Absent = no reporting surface = today's genuine-end commit.
|
|
240
|
+
*/
|
|
241
|
+
reportExpected?: boolean;
|
|
242
|
+
} | {
|
|
243
|
+
kind: 'transcript_final';
|
|
244
|
+
selfAttributing: boolean;
|
|
245
|
+
nativeRead: boolean;
|
|
246
|
+
nativeMarker?: NativeTurnMarkerRef;
|
|
247
|
+
live: LiveTurnPending;
|
|
248
|
+
summary?: SummaryRef;
|
|
249
|
+
messageAt?: number;
|
|
250
|
+
} | {
|
|
251
|
+
kind: 'transcript_activity';
|
|
252
|
+
newestActivityAt: number;
|
|
253
|
+
} | {
|
|
254
|
+
kind: 'no_progress';
|
|
255
|
+
stalledMs: number;
|
|
256
|
+
observedStatus: NoProgressObservedStatus;
|
|
257
|
+
finalAssistantPresent: boolean;
|
|
258
|
+
} | {
|
|
259
|
+
kind: 'liveness';
|
|
260
|
+
result: LivenessResult;
|
|
261
|
+
} | {
|
|
262
|
+
kind: 'process_exit';
|
|
263
|
+
exitCode: number | null;
|
|
264
|
+
providerFailure?: ProviderFailure;
|
|
265
|
+
} | {
|
|
266
|
+
kind: 'session_error';
|
|
267
|
+
reason: SessionErrorReason;
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* `summary` is the handoff-topic pointer when the report's text was published;
|
|
271
|
+
* a report the owner daemon accepted itself carries its text in the evidence
|
|
272
|
+
* row's local envelope instead (never published), so the pointer is optional.
|
|
273
|
+
*/
|
|
274
|
+
| {
|
|
275
|
+
kind: 'worker_report';
|
|
276
|
+
outcome: WorkerReportOutcome;
|
|
277
|
+
summary?: SummaryRef;
|
|
278
|
+
hasHandoffNotes: boolean;
|
|
279
|
+
branchState?: WorkerBranchState;
|
|
280
|
+
touchedFileCount?: number;
|
|
281
|
+
} | {
|
|
282
|
+
kind: 'worker_progress';
|
|
283
|
+
note?: SummaryRef;
|
|
284
|
+
} | {
|
|
285
|
+
kind: 'git_side_effect';
|
|
286
|
+
dirty: boolean;
|
|
287
|
+
commitsSinceDispatch: number;
|
|
288
|
+
attributable: boolean;
|
|
289
|
+
} | {
|
|
290
|
+
kind: 'cancel';
|
|
291
|
+
reason: CancelReason;
|
|
292
|
+
} | {
|
|
293
|
+
kind: 'operator_status';
|
|
294
|
+
status: OperatorStatus;
|
|
295
|
+
reason: OperatorStatusReason;
|
|
296
|
+
} | {
|
|
297
|
+
kind: 'coordinator_ack';
|
|
298
|
+
notify: NotifyKind;
|
|
299
|
+
outcome: CoordinatorAckOutcome;
|
|
300
|
+
} | {
|
|
301
|
+
kind: 'hold_expired';
|
|
302
|
+
holdId: string;
|
|
303
|
+
reason: HoldReason;
|
|
304
|
+
};
|
|
305
|
+
export type TurnEvidence = EvidenceEnvelope & TurnEvidenceBody;
|
|
306
|
+
export type TurnEvidenceKind = TurnEvidenceBody['kind'];
|
|
307
|
+
export type TurnEvidenceOf<K extends TurnEvidenceKind> = EvidenceEnvelope & Extract<TurnEvidenceBody, {
|
|
308
|
+
kind: K;
|
|
309
|
+
}>;
|
|
310
|
+
/**
|
|
311
|
+
* The class of every declared field. There is deliberately NO free-text class:
|
|
312
|
+
* `id` strings are length-bounded and whitespace-free, so prose cannot be
|
|
313
|
+
* smuggled through an identifier slot either.
|
|
314
|
+
*/
|
|
315
|
+
export type EvidenceFieldSpec = {
|
|
316
|
+
t: 'id';
|
|
317
|
+
optional?: true;
|
|
318
|
+
} | {
|
|
319
|
+
t: 'enum';
|
|
320
|
+
values: readonly string[];
|
|
321
|
+
optional?: true;
|
|
322
|
+
} | {
|
|
323
|
+
t: 'bool';
|
|
324
|
+
optional?: true;
|
|
325
|
+
} | {
|
|
326
|
+
t: 'int';
|
|
327
|
+
optional?: true;
|
|
328
|
+
nullable?: true;
|
|
329
|
+
} | {
|
|
330
|
+
t: 'ms';
|
|
331
|
+
optional?: true;
|
|
332
|
+
} | {
|
|
333
|
+
t: 'summary_ref';
|
|
334
|
+
optional?: true;
|
|
335
|
+
} | {
|
|
336
|
+
t: 'attempt_ref';
|
|
337
|
+
optional?: true;
|
|
338
|
+
} | {
|
|
339
|
+
t: 'live';
|
|
340
|
+
optional?: true;
|
|
341
|
+
} | {
|
|
342
|
+
t: 'native_marker';
|
|
343
|
+
optional?: true;
|
|
344
|
+
} | {
|
|
345
|
+
t: 'coordinator';
|
|
346
|
+
optional?: true;
|
|
347
|
+
};
|
|
348
|
+
type FieldsOf<K extends TurnEvidenceKind> = Exclude<keyof Extract<TurnEvidenceBody, {
|
|
349
|
+
kind: K;
|
|
350
|
+
}>, 'kind'>;
|
|
351
|
+
/** Exact per-kind registry: a missing or extra field fails to compile. */
|
|
352
|
+
export type TurnEvidenceFieldSpecs = {
|
|
353
|
+
readonly [K in TurnEvidenceKind]: {
|
|
354
|
+
readonly [F in FieldsOf<K>]-?: EvidenceFieldSpec;
|
|
355
|
+
};
|
|
356
|
+
};
|
|
357
|
+
export declare const EVIDENCE_ENVELOPE_FIELD_SPECS: {
|
|
358
|
+
readonly [F in keyof EvidenceEnvelope]-?: EvidenceFieldSpec;
|
|
359
|
+
};
|
|
360
|
+
export declare const TURN_EVIDENCE_FIELD_SPECS: TurnEvidenceFieldSpecs;
|
|
361
|
+
export declare const TURN_EVIDENCE_KINDS: readonly TurnEvidenceKind[];
|
|
362
|
+
/** Evidence kinds that, on their own, can end a turn (the ones R18/R19/R27 reason about). */
|
|
363
|
+
export declare const TERMINAL_CLASS_EVIDENCE_KINDS: readonly ["turn_end", "transcript_final", "no_progress", "worker_report", "session_error", "process_exit", "cancel", "operator_status"];
|
|
364
|
+
export declare const isTurnEvidenceKind: (value: unknown) => value is "no_progress" | "delivered" | "liveness" | "turn_end" | "transcript_final" | "session_error" | "dispatch_failed" | "dispatch_accepted" | "delivery_refused" | "duplicate_dispatch_refusal" | "session_rebound" | "turn_started" | "suspension" | "suspension_resolved" | "transcript_activity" | "process_exit" | "worker_report" | "worker_progress" | "git_side_effect" | "cancel" | "operator_status" | "coordinator_ack" | "hold_expired";
|
|
365
|
+
export declare const isTurnReason: (value: unknown) => value is "intentional_cleanup" | "operator_cancel" | "task_removed" | "mission_abandoned" | "superseded" | "operator_update" | "refine_terminal" | "validation_terminal" | "hard_ceiling" | "turn_end" | "weak_end_confirmed" | "transcript_final" | "worker_reported" | "finalization_timeout_no_response" | "session_error" | "provider_auth_failed" | "provider_billing_failed" | "reclaim_budget_exhausted" | "hollow_max_retries" | "migration_orphan" | "dispatch_refused_session_exited" | "dispatch_refused_no_target" | "dispatch_refused_unsupported_input" | "dispatch_failed" | "session_exit" | "session_exit_before_turn" | "session_dead" | "hollow_completion" | "assigned_stranded_dispatch_unconfirmed" | "delivered_not_consumed_redrive" | "delivered_no_turn_deadline";
|
|
366
|
+
export declare const isNotifyKind: (value: unknown) => value is "stopped" | "failed" | "no_progress" | "completed" | "cancelled" | "approval" | "choice" | "approval_resolved" | "candidate" | "progress" | "late_completion" | "mesh_event";
|
|
367
|
+
export declare const isTurnOutcome: (value: unknown) => value is "failed" | "completed" | "cancelled";
|
|
368
|
+
export declare const isCommitStrength: (value: unknown) => value is "operator" | "genuine" | "weak" | "tool_report";
|
|
369
|
+
export declare function isEvidenceIdentifier(value: unknown): value is string;
|
|
370
|
+
export declare function isSummaryRef(value: unknown): value is SummaryRef;
|
|
371
|
+
export declare function isTurnAttemptRef(value: unknown): value is TurnAttemptRef;
|
|
372
|
+
/**
|
|
373
|
+
* Strict structural guard: known kind, every declared field of the right class,
|
|
374
|
+
* and NO undeclared field (an unknown key is how free text would sneak in).
|
|
375
|
+
*/
|
|
376
|
+
export declare function isTurnEvidence(value: unknown): value is TurnEvidence;
|
|
377
|
+
export declare const TURN_EVIDENCE_FLAGS: readonly ["hollow", "afterFinalizationTimeout", "nativeMarker", "selfAttributing"];
|
|
378
|
+
export type TurnEvidenceFlag = typeof TURN_EVIDENCE_FLAGS[number];
|
|
379
|
+
/** Scalar-only payload for `mesh.record` (the existing allow-list projection's output). */
|
|
380
|
+
export type ProjectedScalars = Readonly<Record<string, string | number | boolean | null>>;
|
|
381
|
+
export declare const MESH_TOPIC_ENTRY_KINDS: readonly ["turn.evidence", "turn.committed", "turn.notify", "mesh.record"];
|
|
382
|
+
export type MeshTopicEntryKind = typeof MESH_TOPIC_ENTRY_KINDS[number];
|
|
383
|
+
export type MeshTopicEntry = {
|
|
384
|
+
v: typeof MESH_TOPIC_PROTOCOL_VERSION;
|
|
385
|
+
eventId: string;
|
|
386
|
+
at: number;
|
|
387
|
+
} & ({
|
|
388
|
+
k: 'turn.evidence';
|
|
389
|
+
attemptId: string;
|
|
390
|
+
generation: number;
|
|
391
|
+
ownerDaemonId: string;
|
|
392
|
+
taskId?: string;
|
|
393
|
+
sessionId: string;
|
|
394
|
+
ev: TurnEvidenceKind;
|
|
395
|
+
strength?: TurnEndStrength;
|
|
396
|
+
flags?: Partial<Record<TurnEvidenceFlag, boolean>>;
|
|
397
|
+
/** The full (content-free) evidence, so a foreign `turn.ingest` can re-observe it losslessly. */
|
|
398
|
+
evidence?: TurnEvidence;
|
|
399
|
+
} | {
|
|
400
|
+
k: 'turn.committed';
|
|
401
|
+
attemptId: string;
|
|
402
|
+
generation: number;
|
|
403
|
+
taskId?: string;
|
|
404
|
+
outcome: TurnOutcome;
|
|
405
|
+
strength: CommitStrength;
|
|
406
|
+
reason: TurnReason;
|
|
407
|
+
} | {
|
|
408
|
+
k: 'turn.notify';
|
|
409
|
+
attemptId?: string;
|
|
410
|
+
notify: NotifyKind;
|
|
411
|
+
targetDaemonId: string;
|
|
412
|
+
targetSessionId?: string;
|
|
413
|
+
taskId?: string;
|
|
414
|
+
} | {
|
|
415
|
+
k: 'mesh.record';
|
|
416
|
+
ledgerKind: string;
|
|
417
|
+
nodeId?: string;
|
|
418
|
+
sessionId?: string;
|
|
419
|
+
taskId?: string;
|
|
420
|
+
payload: ProjectedScalars;
|
|
421
|
+
});
|
|
422
|
+
export declare function isMeshTopicEntry(value: unknown): value is MeshTopicEntry;
|
|
423
|
+
/**
|
|
424
|
+
* Project evidence onto its `turn.evidence` topic entry. Pure; the attempt
|
|
425
|
+
* identity comes from the resolved attempt (the evidence may lack attemptRef).
|
|
426
|
+
*/
|
|
427
|
+
export declare function projectTurnEvidenceEntry(evidence: TurnEvidence, attempt: {
|
|
428
|
+
attemptId: string;
|
|
429
|
+
generation: number;
|
|
430
|
+
ownerDaemonId: string;
|
|
431
|
+
}): Extract<MeshTopicEntry, {
|
|
432
|
+
k: 'turn.evidence';
|
|
433
|
+
}>;
|
|
434
|
+
export {};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* turn-ipc shared runtime-guard primitives (the protocol version stamp and the
|
|
3
|
+
* small structural checks every command decoder composes). Part of the turn-ipc
|
|
4
|
+
* wire contract (./turn-ipc.ts).
|
|
5
|
+
*/
|
|
6
|
+
/** Every request in this file is versioned so a responder can reject a shape it predates. */
|
|
7
|
+
export declare const TURN_IPC_PROTOCOL_VERSION: 1;
|
|
8
|
+
export declare function isFiniteNumber(value: unknown): value is number;
|
|
9
|
+
export declare function isNonNegativeInt(value: unknown): value is number;
|
|
10
|
+
export declare function isOptionalId(value: unknown): boolean;
|
|
11
|
+
export declare function hasOnlyKeys(value: Record<string, unknown>, allowed: readonly string[]): boolean;
|
|
12
|
+
export declare function makeGuard<T extends readonly string[]>(values: T): (value: unknown) => value is T[number];
|
|
13
|
+
export declare function isStringArray(value: unknown): value is readonly string[];
|
|
14
|
+
export declare function isOptionalShortString(value: unknown, max?: number): boolean;
|
|
15
|
+
export declare function isRecordArray(value: unknown): value is readonly Record<string, unknown>[];
|
|
16
|
+
export declare function isOptionalRecord(value: unknown): boolean;
|
|
17
|
+
export declare function isOptionalBoolean(value: unknown): boolean;
|
|
18
|
+
export declare function isOptionalString(value: unknown): boolean;
|