@adhdev/mesh-shared 1.0.60-rc.44 → 1.0.60-rc.46
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/index.js +17 -3
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +16 -3
- package/dist/index.mjs.map +1 -1
- package/dist/turn-evidence.d.ts +36 -5
- package/package.json +1 -1
- package/src/turn-evidence.ts +44 -4
package/dist/turn-evidence.d.ts
CHANGED
|
@@ -42,6 +42,16 @@ export declare const DELIVERY_VIAS: readonly ["local", "p2p"];
|
|
|
42
42
|
export type DeliveryVia = typeof DELIVERY_VIAS[number];
|
|
43
43
|
export declare const DISPATCH_FAILURE_REASONS: readonly ["worker_absent", "transport_error", "spawn_failed", "rejected_by_worker", "timeout"];
|
|
44
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;
|
|
45
55
|
export declare const CONSUME_PROFILES: readonly ["default", "native_source"];
|
|
46
56
|
export type ConsumeProfile = typeof CONSUME_PROFILES[number];
|
|
47
57
|
export declare const SESSION_REBOUND_REASONS: readonly ["restart", "live_holder"];
|
|
@@ -87,7 +97,7 @@ export type NoProgressObservedStatus = SessionStatus | 'unknown';
|
|
|
87
97
|
* Reasons a turn hold exists. Holds are attempt-scoped only (C2: delivery-side
|
|
88
98
|
* waits are consumer deferral on the `turn.deliver` cursor, not hold rows).
|
|
89
99
|
*/
|
|
90
|
-
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"];
|
|
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"];
|
|
91
101
|
export type HoldReason = typeof HOLD_REASONS[number];
|
|
92
102
|
export declare const TURN_OUTCOMES: readonly ["completed", "failed", "cancelled"];
|
|
93
103
|
export type TurnOutcome = typeof TURN_OUTCOMES[number];
|
|
@@ -174,10 +184,25 @@ export type TurnEvidenceBody = {
|
|
|
174
184
|
kind: 'delivery_refused';
|
|
175
185
|
messageId: string;
|
|
176
186
|
reason: SendRefusal;
|
|
177
|
-
}
|
|
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
|
+
| {
|
|
178
202
|
kind: 'dispatch_failed';
|
|
179
203
|
workerAbsent: boolean;
|
|
180
204
|
reason: DispatchFailureReason;
|
|
205
|
+
refusalCode?: string;
|
|
181
206
|
} | {
|
|
182
207
|
kind: 'duplicate_dispatch_refusal';
|
|
183
208
|
holderSessionId: string;
|
|
@@ -240,10 +265,16 @@ export type TurnEvidenceBody = {
|
|
|
240
265
|
} | {
|
|
241
266
|
kind: 'session_error';
|
|
242
267
|
reason: SessionErrorReason;
|
|
243
|
-
}
|
|
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
|
+
| {
|
|
244
275
|
kind: 'worker_report';
|
|
245
276
|
outcome: WorkerReportOutcome;
|
|
246
|
-
summary
|
|
277
|
+
summary?: SummaryRef;
|
|
247
278
|
hasHandoffNotes: boolean;
|
|
248
279
|
branchState?: WorkerBranchState;
|
|
249
280
|
touchedFileCount?: number;
|
|
@@ -334,7 +365,7 @@ export declare const isEvidenceSourceId: (value: unknown) => value is "fsm_edge"
|
|
|
334
365
|
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";
|
|
335
366
|
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";
|
|
336
367
|
export declare const isNotifyKind: (value: unknown) => value is "stopped" | "failed" | "no_progress" | "completed" | "cancelled" | "approval" | "choice" | "approval_resolved" | "candidate" | "progress" | "late_completion" | "mesh_event";
|
|
337
|
-
export declare const isHoldReason: (value: unknown) => value is "await_delivery" | "await_consume" | "await_turn" | "liveness" | "hard_ceiling" | "live_pending" | "transcript_quiet" | "weak_candidate" | "suspension_before_consumed" | "await_report";
|
|
368
|
+
export declare const isHoldReason: (value: unknown) => value is "await_delivery" | "await_consume" | "await_turn" | "liveness" | "hard_ceiling" | "live_pending" | "transcript_quiet" | "weak_candidate" | "suspension_before_consumed" | "await_report" | "await_end";
|
|
338
369
|
export declare const isTurnOutcome: (value: unknown) => value is "failed" | "completed" | "cancelled";
|
|
339
370
|
export declare const isCommitStrength: (value: unknown) => value is "operator" | "genuine" | "weak" | "tool_report";
|
|
340
371
|
export declare function isEvidenceIdentifier(value: unknown): value is string;
|
package/package.json
CHANGED
package/src/turn-evidence.ts
CHANGED
|
@@ -59,6 +59,22 @@ export type DeliveryVia = typeof DELIVERY_VIAS[number]
|
|
|
59
59
|
export const DISPATCH_FAILURE_REASONS = ['worker_absent', 'transport_error', 'spawn_failed', 'rejected_by_worker', 'timeout'] as const
|
|
60
60
|
export type DispatchFailureReason = typeof DISPATCH_FAILURE_REASONS[number]
|
|
61
61
|
|
|
62
|
+
/**
|
|
63
|
+
* Normalize a worker's own refusal code (e.g. `session_busy_with_task`,
|
|
64
|
+
* `mesh_sender_not_on_roster`, `provider_quota_exhausted`) into the shape
|
|
65
|
+
* `dispatch_failed.refusalCode` accepts: lowercase ascii + underscore, capped
|
|
66
|
+
* at 64 chars. Returns undefined for anything that yields no usable token, so
|
|
67
|
+
* a malformed/foreign code degrades to "no refusalCode" rather than smuggling
|
|
68
|
+
* arbitrary text through what must stay a closed-enum-like identifier slot
|
|
69
|
+
* (see the field's doc comment — this evidence replicates cross-machine).
|
|
70
|
+
*/
|
|
71
|
+
export function sanitizeRefusalCode(value: unknown): string | undefined {
|
|
72
|
+
if (typeof value !== 'string') return undefined
|
|
73
|
+
const normalized = value.trim().toLowerCase().replace(/[^a-z_]/g, '_').replace(/_+/g, '_').replace(/^_+|_+$/g, '')
|
|
74
|
+
if (!normalized) return undefined
|
|
75
|
+
return normalized.slice(0, 64)
|
|
76
|
+
}
|
|
77
|
+
|
|
62
78
|
export const CONSUME_PROFILES = ['default', 'native_source'] as const
|
|
63
79
|
export type ConsumeProfile = typeof CONSUME_PROFILES[number]
|
|
64
80
|
|
|
@@ -127,6 +143,12 @@ export const HOLD_REASONS = [
|
|
|
127
143
|
// only opens this hold (R9r) — a report commits (R17), a new busy edge cancels
|
|
128
144
|
// it as a false idle (R12r), expiry commits weak (R13r).
|
|
129
145
|
'await_report',
|
|
146
|
+
// A worker report recorded while the session is still generating (R17g):
|
|
147
|
+
// the report is the verdict, the idle edge is only awaited as corroboration
|
|
148
|
+
// — a turn_end commits the report (R9t), expiry commits it anyway (R13t) so
|
|
149
|
+
// a session whose FSM never shows the idle edge again does not wait for
|
|
150
|
+
// liveness / hard_ceiling.
|
|
151
|
+
'await_end',
|
|
130
152
|
] as const
|
|
131
153
|
export type HoldReason = typeof HOLD_REASONS[number]
|
|
132
154
|
|
|
@@ -208,7 +230,20 @@ export type TurnEvidenceBody =
|
|
|
208
230
|
coordinator?: EvidenceCoordinatorIdentity }
|
|
209
231
|
| { kind: 'delivered'; messageId: string; outcome: DeliveryOutcome; via: DeliveryVia }
|
|
210
232
|
| { kind: 'delivery_refused'; messageId: string; reason: SendRefusal }
|
|
211
|
-
|
|
233
|
+
/**
|
|
234
|
+
* `refusalCode` (wiring-unification live-gap fix, 2026-09-25): the worker's own
|
|
235
|
+
* refusal code for an application-level `{success:false}` answer (e.g.
|
|
236
|
+
* `session_busy_with_task`, `mesh_sender_not_on_roster`,
|
|
237
|
+
* `mesh_node_bootstrap_pending`, `provider_quota_exhausted`) — optional and
|
|
238
|
+
* ONLY ever populated for `reason: 'rejected_by_worker'`. Deliberately an `id`
|
|
239
|
+
* (short enum-like token), never free text: this evidence replicates across
|
|
240
|
+
* machines over `mesh.<id>.events` (CONTENT-FREE BY CONSTRUCTION above), so a
|
|
241
|
+
* human-readable detail string must NOT travel here — it stays local (owner
|
|
242
|
+
* WARN log, MCP tool JSON response). Producers sanitize to `[a-z_]{1,64}`
|
|
243
|
+
* before emitting so a stray free-text code can never smuggle prose through
|
|
244
|
+
* this slot.
|
|
245
|
+
*/
|
|
246
|
+
| { kind: 'dispatch_failed'; workerAbsent: boolean; reason: DispatchFailureReason; refusalCode?: string }
|
|
212
247
|
| { kind: 'duplicate_dispatch_refusal'; holderSessionId: string; holderAttemptId?: string }
|
|
213
248
|
| { kind: 'session_rebound'; toSessionId: string; reason: SessionReboundReason }
|
|
214
249
|
// ── worker turn lifecycle ──
|
|
@@ -232,7 +267,12 @@ export type TurnEvidenceBody =
|
|
|
232
267
|
| { kind: 'process_exit'; exitCode: number | null; providerFailure?: ProviderFailure }
|
|
233
268
|
| { kind: 'session_error'; reason: SessionErrorReason }
|
|
234
269
|
// ── worker MCP (F2) ──
|
|
235
|
-
|
|
270
|
+
/**
|
|
271
|
+
* `summary` is the handoff-topic pointer when the report's text was published;
|
|
272
|
+
* a report the owner daemon accepted itself carries its text in the evidence
|
|
273
|
+
* row's local envelope instead (never published), so the pointer is optional.
|
|
274
|
+
*/
|
|
275
|
+
| { kind: 'worker_report'; outcome: WorkerReportOutcome; summary?: SummaryRef; hasHandoffNotes: boolean
|
|
236
276
|
branchState?: WorkerBranchState; touchedFileCount?: number }
|
|
237
277
|
| { kind: 'worker_progress'; note?: SummaryRef }
|
|
238
278
|
// ── coordinator / operator ──
|
|
@@ -298,7 +338,7 @@ export const TURN_EVIDENCE_FIELD_SPECS: TurnEvidenceFieldSpecs = {
|
|
|
298
338
|
},
|
|
299
339
|
delivered: { messageId: id, outcome: en(DELIVERY_OUTCOMES), via: en(DELIVERY_VIAS) },
|
|
300
340
|
delivery_refused: { messageId: id, reason: en(SEND_REFUSAL_REASONS) },
|
|
301
|
-
dispatch_failed: { workerAbsent: bool, reason: en(DISPATCH_FAILURE_REASONS) },
|
|
341
|
+
dispatch_failed: { workerAbsent: bool, reason: en(DISPATCH_FAILURE_REASONS), refusalCode: idOpt },
|
|
302
342
|
duplicate_dispatch_refusal: { holderSessionId: id, holderAttemptId: idOpt },
|
|
303
343
|
session_rebound: { toSessionId: id, reason: en(SESSION_REBOUND_REASONS) },
|
|
304
344
|
turn_started: { retro: bool },
|
|
@@ -320,7 +360,7 @@ export const TURN_EVIDENCE_FIELD_SPECS: TurnEvidenceFieldSpecs = {
|
|
|
320
360
|
process_exit: { exitCode: { t: 'int', nullable: true }, providerFailure: enOpt(PROVIDER_FAILURES) },
|
|
321
361
|
session_error: { reason: en(SESSION_ERROR_REASONS) },
|
|
322
362
|
worker_report: {
|
|
323
|
-
outcome: en(WORKER_REPORT_OUTCOMES), summary: { t: 'summary_ref' }, hasHandoffNotes: bool,
|
|
363
|
+
outcome: en(WORKER_REPORT_OUTCOMES), summary: { t: 'summary_ref', optional: true }, hasHandoffNotes: bool,
|
|
324
364
|
branchState: enOpt(WORKER_BRANCH_STATES), touchedFileCount: intOpt,
|
|
325
365
|
},
|
|
326
366
|
worker_progress: { note: { t: 'summary_ref', optional: true } },
|