@deepstrike/wasm 0.2.38 → 0.2.40

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.
Files changed (48) hide show
  1. package/README.md +14 -13
  2. package/dist/harness/index.d.ts +127 -61
  3. package/dist/harness/index.js +212 -83
  4. package/dist/index.d.ts +9 -6
  5. package/dist/index.js +4 -2
  6. package/dist/memory/extraction.d.ts +4 -0
  7. package/dist/memory/extraction.js +48 -0
  8. package/dist/memory/in-memory-store.d.ts +19 -9
  9. package/dist/memory/in-memory-store.js +68 -23
  10. package/dist/memory/index.d.ts +52 -24
  11. package/dist/memory/ranking.d.ts +33 -0
  12. package/dist/memory/ranking.js +77 -0
  13. package/dist/memory/retention.d.ts +17 -0
  14. package/dist/memory/retention.js +54 -0
  15. package/dist/providers/base.d.ts +5 -0
  16. package/dist/providers/base.js +32 -0
  17. package/dist/runtime/context-policy.d.ts +35 -0
  18. package/dist/runtime/context-policy.js +66 -0
  19. package/dist/runtime/eval.d.ts +2 -0
  20. package/dist/runtime/execution-plane.d.ts +2 -1
  21. package/dist/runtime/execution-plane.js +3 -3
  22. package/dist/runtime/facade.js +2 -1
  23. package/dist/runtime/index.d.ts +11 -4
  24. package/dist/runtime/index.js +5 -1
  25. package/dist/runtime/kernel-event-log.js +46 -13
  26. package/dist/runtime/kernel-rebuild.d.ts +8 -0
  27. package/dist/runtime/kernel-rebuild.js +65 -0
  28. package/dist/runtime/kernel-step.d.ts +139 -7
  29. package/dist/runtime/kernel-step.js +110 -10
  30. package/dist/runtime/kernel-transaction-log.d.ts +61 -0
  31. package/dist/runtime/kernel-transaction-log.js +140 -0
  32. package/dist/runtime/os-profile.d.ts +9 -10
  33. package/dist/runtime/os-profile.js +14 -10
  34. package/dist/runtime/os-snapshot.d.ts +19 -0
  35. package/dist/runtime/os-snapshot.js +16 -3
  36. package/dist/runtime/runner.d.ts +73 -41
  37. package/dist/runtime/runner.js +562 -290
  38. package/dist/runtime/session-log.d.ts +55 -10
  39. package/dist/runtime/session-log.js +60 -3
  40. package/dist/runtime/session-repair.d.ts +11 -7
  41. package/dist/runtime/session-repair.js +11 -8
  42. package/dist/runtime/sub-agent-orchestrator.js +1 -1
  43. package/dist/runtime/types/agent.d.ts +31 -0
  44. package/dist/runtime/types/agent.js +35 -0
  45. package/dist/signals/index.d.ts +21 -1
  46. package/dist/signals/index.js +1 -0
  47. package/dist/types.d.ts +7 -2
  48. package/package.json +2 -2
@@ -1,5 +1,11 @@
1
1
  import type { ProviderReplay, ToolCall, ToolErrorKind } from "../types.js";
2
+ import type { MemoryRecall, MemoryScope } from "../memory/index.js";
2
3
  import type { KernelPrimitive } from "./kernel-event-log.js";
4
+ import type { DurableAppendReceipt, KernelGenesisReceipt, KernelOperationGenesis, KernelTransaction } from "./kernel-transaction-log.js";
5
+ export interface KernelTransactionEntry {
6
+ log_seq: number;
7
+ transaction: KernelTransaction;
8
+ }
3
9
  export type RollbackReason = {
4
10
  kind: "fatal_tool_error";
5
11
  tool_name: string;
@@ -26,6 +32,7 @@ export type SessionEvent = {
26
32
  criteria: string[];
27
33
  agent_id?: string;
28
34
  system_prompt?: string;
35
+ attachments?: import("../types.js").ContentPart[];
29
36
  } | {
30
37
  kind: "llm_completed";
31
38
  turn: number;
@@ -78,7 +85,6 @@ export type SessionEvent = {
78
85
  action?: "snip_compact" | "micro_compact" | "context_collapse" | "auto_compact";
79
86
  summary?: string;
80
87
  summary_tokens?: number;
81
- archive_ref?: string;
82
88
  preserved_refs?: string[];
83
89
  } | {
84
90
  kind: "page_out";
@@ -87,6 +93,7 @@ export type SessionEvent = {
87
93
  summary?: string;
88
94
  tier_hint?: string;
89
95
  message_count?: number;
96
+ archive_ref?: string;
90
97
  } | {
91
98
  kind: "page_in";
92
99
  turn: number;
@@ -136,15 +143,34 @@ export type SessionEvent = {
136
143
  tool: string;
137
144
  reason: string;
138
145
  } | {
139
- kind: "signal_disposed";
146
+ kind: "signal_delivery_disposed";
140
147
  turn: number;
148
+ operation_id: string;
149
+ delivery_id: string;
150
+ attempt: number;
141
151
  signal_id: string;
142
152
  disposition: string;
143
153
  queue_depth: number;
144
154
  } | {
145
155
  kind: "budget_exceeded";
146
156
  turn: number;
157
+ operation_id: string;
158
+ reservation_id?: string;
147
159
  budget: string;
160
+ } | {
161
+ kind: "budget_usage_reported";
162
+ turn: number;
163
+ operation_id: string;
164
+ reservation_id: string;
165
+ tokens: number;
166
+ subagents: number;
167
+ rounds: number;
168
+ } | {
169
+ kind: "operation_cancelled";
170
+ turn: number;
171
+ operation_id: string;
172
+ reason: "user" | "deadline" | "lease_lost" | "host_shutdown";
173
+ pending_call_ids: string[];
148
174
  } | {
149
175
  kind: "milestone_advanced";
150
176
  turn: number;
@@ -188,33 +214,38 @@ export type SessionEvent = {
188
214
  } | {
189
215
  kind: "memory_written";
190
216
  turn: number;
191
- memory_id: string;
217
+ record_id: string;
218
+ scope: MemoryScope;
192
219
  memory_kind: string;
220
+ name: string;
193
221
  size_bytes: number;
194
222
  } | {
195
223
  kind: "memory_queried";
196
224
  turn: number;
197
- query_context: string;
225
+ scope: MemoryScope;
226
+ query: string;
198
227
  requested_k: number;
199
228
  requires_async_response: boolean;
200
229
  } | {
201
230
  kind: "memory_validation_failed";
202
231
  turn: number;
203
- memory_id: string;
232
+ record_id: string;
204
233
  error: string;
234
+ } | {
235
+ kind: "memory_retrieval_result";
236
+ hits: MemoryRecall[];
205
237
  } | {
206
238
  kind: "workflow_node_completed";
207
239
  turn: number;
208
240
  agent_id: string;
241
+ status: import("./types/agent.js").WorkflowNodeStatus;
209
242
  termination: string;
210
243
  /** W-1: result-borne control signals, persisted so resume replays control flow faithfully —
211
244
  * a classifier re-prunes its rejected branches, a recorded loop stop is honored. */
212
245
  classify_branch?: string;
213
246
  tournament_winner?: string;
214
247
  loop_continue?: boolean;
215
- /** W-1: the node's final output text — resume re-seeds the driver's outputs map from it so
216
- * post-resume reduce/judge/dependent nodes still see their dependencies' outputs. */
217
- output?: string;
248
+ output?: import("../types.js").Message;
218
249
  } | {
219
250
  kind: "workflow_nodes_submitted";
220
251
  turn: number;
@@ -234,8 +265,7 @@ export type SessionEvent = {
234
265
  } | {
235
266
  kind: "workflow_completed";
236
267
  turn: number;
237
- completed: string[];
238
- failed: string[];
268
+ node_outcomes: import("./types/agent.js").KernelWorkflowNodeOutcome[];
239
269
  total_nodes: number;
240
270
  } | {
241
271
  kind: "run_terminal";
@@ -254,13 +284,28 @@ export interface SessionLog {
254
284
  event: SessionEvent;
255
285
  }>>;
256
286
  latestSeq(sessionId: string): Promise<number>;
287
+ appendKernelGenesis(sessionId: string, genesis: KernelOperationGenesis): Promise<KernelGenesisReceipt>;
288
+ readKernelGenesis(sessionId: string, operationId: string): Promise<KernelOperationGenesis | undefined>;
289
+ compareAndAppendKernelTransaction(sessionId: string, expectedTransactionHead: string, transaction: KernelTransaction): Promise<DurableAppendReceipt>;
290
+ readKernelTransactions(sessionId: string, operationId: string, fromStepSeq?: number): Promise<KernelTransactionEntry[]>;
291
+ kernelTransactionHead(sessionId: string, operationId: string): Promise<string | undefined>;
257
292
  }
258
293
  export declare class InMemorySessionLog implements SessionLog {
259
294
  private store;
295
+ private seqCounters;
296
+ private genesisStore;
297
+ private transactionStore;
298
+ private operationKey;
299
+ private nextSeq;
260
300
  append(sessionId: string, event: SessionEvent): Promise<number>;
261
301
  read(sessionId: string, fromSeq?: number, primitiveFilter?: KernelPrimitive): Promise<Array<{
262
302
  seq: number;
263
303
  event: SessionEvent;
264
304
  }>>;
265
305
  latestSeq(sessionId: string): Promise<number>;
306
+ appendKernelGenesis(sessionId: string, genesis: KernelOperationGenesis): Promise<KernelGenesisReceipt>;
307
+ readKernelGenesis(sessionId: string, operationId: string): Promise<KernelOperationGenesis | undefined>;
308
+ compareAndAppendKernelTransaction(sessionId: string, expectedTransactionHead: string, transaction: KernelTransaction): Promise<DurableAppendReceipt>;
309
+ readKernelTransactions(sessionId: string, operationId: string, fromStepSeq?: number): Promise<KernelTransactionEntry[]>;
310
+ kernelTransactionHead(sessionId: string, operationId: string): Promise<string | undefined>;
266
311
  }
@@ -1,11 +1,23 @@
1
1
  import { primitiveForKind } from "./kernel-event-log.js";
2
+ import { KernelLogConflictError, KernelLogIntegrityError, verifyKernelOperationGenesis, verifyKernelTransaction, verifyKernelTransactionSuccessor, } from "./kernel-transaction-log.js";
2
3
  export class InMemorySessionLog {
3
4
  store = new Map();
5
+ seqCounters = new Map();
6
+ genesisStore = new Map();
7
+ transactionStore = new Map();
8
+ operationKey(sessionId, operationId) {
9
+ return `${sessionId}\u0000${operationId}`;
10
+ }
11
+ nextSeq(sessionId) {
12
+ const seq = this.seqCounters.get(sessionId) ?? 0;
13
+ this.seqCounters.set(sessionId, seq + 1);
14
+ return seq;
15
+ }
4
16
  async append(sessionId, event) {
5
17
  if (!this.store.has(sessionId))
6
18
  this.store.set(sessionId, []);
7
19
  const entries = this.store.get(sessionId);
8
- const seq = entries.length;
20
+ const seq = this.nextSeq(sessionId);
9
21
  entries.push({ seq, event });
10
22
  return seq;
11
23
  }
@@ -20,7 +32,52 @@ export class InMemorySessionLog {
20
32
  });
21
33
  }
22
34
  async latestSeq(sessionId) {
23
- const entries = this.store.get(sessionId);
24
- return entries ? entries.length - 1 : -1;
35
+ return (this.seqCounters.get(sessionId) ?? 0) - 1;
36
+ }
37
+ async appendKernelGenesis(sessionId, genesis) {
38
+ await verifyKernelOperationGenesis(genesis);
39
+ const operationKey = this.operationKey(sessionId, genesis.operation_id);
40
+ const existing = this.genesisStore.get(operationKey);
41
+ if (existing) {
42
+ if (existing.genesis.genesis_digest !== genesis.genesis_digest) {
43
+ throw new KernelLogConflictError("session already has a different kernel operation genesis");
44
+ }
45
+ return { log_seq: existing.log_seq, genesis_digest: genesis.genesis_digest };
46
+ }
47
+ const log_seq = this.nextSeq(sessionId);
48
+ this.genesisStore.set(operationKey, { log_seq, genesis });
49
+ return { log_seq, genesis_digest: genesis.genesis_digest };
50
+ }
51
+ async readKernelGenesis(sessionId, operationId) {
52
+ return this.genesisStore.get(this.operationKey(sessionId, operationId))?.genesis;
53
+ }
54
+ async compareAndAppendKernelTransaction(sessionId, expectedTransactionHead, transaction) {
55
+ await verifyKernelTransaction(transaction);
56
+ const operationKey = this.operationKey(sessionId, transaction.operation_id);
57
+ const genesis = this.genesisStore.get(operationKey)?.genesis;
58
+ if (!genesis)
59
+ throw new KernelLogIntegrityError("kernel transaction requires a durable genesis");
60
+ if (transaction.operation_id !== genesis.operation_id) {
61
+ throw new KernelLogIntegrityError("kernel transaction operation_id does not match genesis");
62
+ }
63
+ const head = await this.kernelTransactionHead(sessionId, transaction.operation_id);
64
+ if (head !== expectedTransactionHead || transaction.previous_transaction_digest !== head) {
65
+ throw new KernelLogConflictError("kernel transaction head changed before compare-and-append");
66
+ }
67
+ const entries = this.transactionStore.get(operationKey) ?? [];
68
+ verifyKernelTransactionSuccessor(entries.at(-1)?.transaction, transaction);
69
+ const log_seq = this.nextSeq(sessionId);
70
+ entries.push({ log_seq, transaction });
71
+ this.transactionStore.set(operationKey, entries);
72
+ return { log_seq, transaction_digest: transaction.transaction_digest };
73
+ }
74
+ async readKernelTransactions(sessionId, operationId, fromStepSeq = 1) {
75
+ return (this.transactionStore.get(this.operationKey(sessionId, operationId)) ?? []).filter(entry => entry.transaction.step_seq >= fromStepSeq);
76
+ }
77
+ async kernelTransactionHead(sessionId, operationId) {
78
+ const operationKey = this.operationKey(sessionId, operationId);
79
+ const entries = this.transactionStore.get(operationKey) ?? [];
80
+ return entries.at(-1)?.transaction.transaction_digest
81
+ ?? this.genesisStore.get(operationKey)?.genesis.genesis_digest;
25
82
  }
26
83
  }
@@ -1,5 +1,6 @@
1
- import type { ProviderReplay, ToolCall } from "../types.js";
1
+ import type { Message, ProviderReplay, ToolCall } from "../types.js";
2
2
  import type { SessionEvent } from "./session-log.js";
3
+ import type { WorkflowNodeStatus } from "./types/agent.js";
3
4
  export { REPLAY_CONTENT_MAX_BYTES as RECOVERY_CONTENT_MAX_BYTES } from "./replay-sanitize.js";
4
5
  /**
5
6
  * Normalize a persisted llm_completed event for recovery. Content is sanitized
@@ -41,33 +42,36 @@ export declare function buildRunTerminalEvent(input: {
41
42
  export declare function buildWorkflowNodeCompletedEvent(input: {
42
43
  turn: number;
43
44
  agentId: string;
45
+ status: WorkflowNodeStatus;
44
46
  termination: string;
45
47
  classifyBranch?: string;
46
48
  tournamentWinner?: string;
47
49
  loopContinue?: boolean;
48
- output?: string;
50
+ output?: Message;
49
51
  }): Extract<SessionEvent, {
50
52
  kind: "workflow_node_completed";
51
53
  }>;
52
54
  /** One recovered node completion: the agent id plus its persisted control signals and output. */
53
- export interface RecoveredNodeCompletion {
55
+ export interface RecoveredNodeOutcome {
54
56
  agentId: string;
57
+ status: WorkflowNodeStatus;
58
+ termination: string;
55
59
  classifyBranch?: string;
56
60
  tournamentWinner?: string;
57
61
  loopContinue?: boolean;
58
- output?: string;
62
+ output?: Message;
59
63
  }
60
64
  /**
61
65
  * Recover completed workflow node records from a session event stream. Scans for
62
66
  * workflow_node_completed events with termination "completed" and returns them WITH their
63
67
  * result-borne control signals (W-1) — resumeWorkflow lowers these to the kernel's
64
- * `resumed_results` so a classifier re-prunes and a loop stop is honored, and re-seeds the
68
+ * `resumed_outcomes` so a classifier re-prunes and a loop stop is honored, and re-seeds the
65
69
  * driver's outputs map from the persisted output text.
66
70
  */
67
- export declare function recoverCompletedWorkflowNodes(events: Array<{
71
+ export declare function recoverWorkflowNodeOutcomes(events: Array<{
68
72
  seq: number;
69
73
  event: SessionEvent;
70
- }>): RecoveredNodeCompletion[];
74
+ }>): RecoveredNodeOutcome[];
71
75
  /** R3-1: build workflow_nodes_submitted for persistence after a runtime submission, so resume can
72
76
  * re-apply it. `nodes` is the kernel-shape (snake_case) submitted node array. */
73
77
  export declare function buildWorkflowNodesSubmittedEvent(input: {
@@ -55,6 +55,7 @@ export function buildWorkflowNodeCompletedEvent(input) {
55
55
  kind: "workflow_node_completed",
56
56
  turn: input.turn,
57
57
  agent_id: input.agentId,
58
+ status: input.status,
58
59
  termination: input.termination,
59
60
  ...(input.classifyBranch !== undefined ? { classify_branch: input.classifyBranch } : {}),
60
61
  ...(input.tournamentWinner !== undefined ? { tournament_winner: input.tournamentWinner } : {}),
@@ -66,15 +67,17 @@ export function buildWorkflowNodeCompletedEvent(input) {
66
67
  * Recover completed workflow node records from a session event stream. Scans for
67
68
  * workflow_node_completed events with termination "completed" and returns them WITH their
68
69
  * result-borne control signals (W-1) — resumeWorkflow lowers these to the kernel's
69
- * `resumed_results` so a classifier re-prunes and a loop stop is honored, and re-seeds the
70
+ * `resumed_outcomes` so a classifier re-prunes and a loop stop is honored, and re-seeds the
70
71
  * driver's outputs map from the persisted output text.
71
72
  */
72
- export function recoverCompletedWorkflowNodes(events) {
73
+ export function recoverWorkflowNodeOutcomes(events) {
73
74
  const completed = [];
74
75
  for (const { event } of events) {
75
- if (event.kind === "workflow_node_completed" && event.termination === "completed") {
76
+ if (event.kind === "workflow_node_completed") {
76
77
  completed.push({
77
78
  agentId: event.agent_id,
79
+ status: event.status,
80
+ termination: event.termination,
78
81
  ...(event.classify_branch !== undefined ? { classifyBranch: event.classify_branch } : {}),
79
82
  ...(event.tournament_winner !== undefined ? { tournamentWinner: event.tournament_winner } : {}),
80
83
  ...(event.loop_continue !== undefined ? { loopContinue: event.loop_continue } : {}),
@@ -106,11 +109,11 @@ export function recoverSubmittedWorkflowNodes(events) {
106
109
  if (event.kind === "workflow_nodes_submitted") {
107
110
  submissions.push(event.nodes);
108
111
  submitters.push(event.submitter_agent_id);
109
- // Absent on legacy logs → order-only replay (bases array stays parallel-short only
110
- // if ALL records carry it; a mixed log degrades to order-only for safety).
111
- if (event.base_index !== undefined)
112
- bases.push(event.base_index);
112
+ if (event.base_index === undefined) {
113
+ throw new Error("workflow_nodes_submitted is missing required base_index");
114
+ }
115
+ bases.push(event.base_index);
113
116
  }
114
117
  }
115
- return { submissions, bases: bases.length === submissions.length ? bases : [], submitters };
118
+ return { submissions, bases, submitters };
116
119
  }
@@ -157,7 +157,7 @@ export async function spawnStandalone(parentOpts, parentSessionId, spec, orchest
157
157
  const runtime = new kernel.KernelRuntime({
158
158
  maxTokens: parentOpts.maxTokens,
159
159
  maxTurns: parentOpts.maxTurns ?? 25,
160
- timeoutMs: parentOpts.timeoutMs !== undefined ? BigInt(parentOpts.timeoutMs) : undefined,
160
+ timeoutMs: parentOpts.timeoutMs,
161
161
  });
162
162
  const pending = [];
163
163
  kernelApply(runtime, pending, { kind: "start_run", task: { goal: "coordinator", criteria: [] } });
@@ -126,6 +126,9 @@ export type WorkflowTaskSpec = {
126
126
  } | string;
127
127
  /** One node in a declarative workflow DAG (camelCase host shape). */
128
128
  export type NodeTrust = "trusted" | "quarantined";
129
+ export type WorkflowDependencyPolicy = "all_success" | "accept_partial" | "all_terminal" | "optional";
130
+ export type WorkflowNodeStatus = "completed" | "completed_partial" | "failed" | "skipped_upstream_failed";
131
+ export declare function workflowNodeStatusFromTermination(termination: TerminationReason | string): WorkflowNodeStatus;
129
132
  export interface WorkflowNodeSpec {
130
133
  task: WorkflowTaskSpec;
131
134
  role: KernelAgentRole;
@@ -165,11 +168,39 @@ export interface WorkflowNodeSpec {
165
168
  maxWallMs?: number;
166
169
  /** Indices of nodes this node depends on. */
167
170
  dependsOn?: number[];
171
+ /** How dependency terminal states gate this node. Defaults to `all_success`. */
172
+ depPolicy?: WorkflowDependencyPolicy;
168
173
  }
169
174
  /** A declarative workflow DAG the kernel runs node-by-node, gating each spawn. */
170
175
  export interface WorkflowSpec {
171
176
  nodes: WorkflowNodeSpec[];
172
177
  }
178
+ export interface KernelWorkflowNodeOutcome {
179
+ node_id: string;
180
+ status: WorkflowNodeStatus;
181
+ termination?: TerminationReason;
182
+ output?: {
183
+ role: Message["role"];
184
+ content: string;
185
+ tool_calls?: Array<{
186
+ id: string;
187
+ name: string;
188
+ arguments?: Record<string, unknown>;
189
+ }>;
190
+ token_count?: number;
191
+ };
192
+ }
193
+ export interface WorkflowNodeOutcome {
194
+ nodeId: string;
195
+ status: WorkflowNodeStatus;
196
+ termination?: TerminationReason;
197
+ output?: Message;
198
+ }
199
+ export interface WorkflowOutcome {
200
+ nodeOutcomes: WorkflowNodeOutcome[];
201
+ outputs: Record<string, string>;
202
+ }
203
+ export declare function workflowNodeOutcomeFromKernel(raw: KernelWorkflowNodeOutcome): WorkflowNodeOutcome;
173
204
  /** Per-node spawn descriptor carried in the `workflow_batch_spawned` observation. */
174
205
  export interface WorkflowSpawnInfo {
175
206
  agent_id: string;
@@ -121,6 +121,35 @@ export function milestoneCheckPass(phaseId) {
121
121
  export function milestoneCheckFail(phaseId, reason) {
122
122
  return { phaseId, passed: false, reason };
123
123
  }
124
+ export function workflowNodeStatusFromTermination(termination) {
125
+ if (termination === "completed")
126
+ return "completed";
127
+ if (termination === "error" || termination === "user_abort")
128
+ return "failed";
129
+ return "completed_partial";
130
+ }
131
+ export function workflowNodeOutcomeFromKernel(raw) {
132
+ const output = raw.output;
133
+ return {
134
+ nodeId: raw.node_id,
135
+ status: raw.status,
136
+ ...(raw.termination ? { termination: raw.termination } : {}),
137
+ ...(output
138
+ ? {
139
+ output: {
140
+ role: output.role,
141
+ content: output.content,
142
+ toolCalls: (output.tool_calls ?? []).map(call => ({
143
+ id: call.id,
144
+ name: call.name,
145
+ arguments: JSON.stringify(call.arguments ?? {}),
146
+ })),
147
+ ...(output.token_count != null ? { tokenCount: output.token_count } : {}),
148
+ },
149
+ }
150
+ : {}),
151
+ };
152
+ }
124
153
  /** G4: a concise budget note appended to a coordinator node's goal. "" when nothing is bounded. */
125
154
  export function workflowBudgetNote(budget) {
126
155
  if (!budget)
@@ -188,6 +217,7 @@ export function workflowNodeSpecToKernel(n) {
188
217
  ...(n.maxTurns != null ? { max_turns: n.maxTurns } : {}),
189
218
  ...(n.maxWallMs != null ? { max_wall_ms: n.maxWallMs } : {}),
190
219
  ...(n.dependsOn && n.dependsOn.length ? { depends_on: n.dependsOn } : {}),
220
+ dep_policy: n.depPolicy ?? "all_success",
191
221
  };
192
222
  }
193
223
  export function workflowSpecToKernel(spec) {
@@ -274,6 +304,11 @@ const workflowNodesArraySchema = {
274
304
  },
275
305
  tokenBudget: { type: "integer", description: "Cap this node's child run at this many cumulative tokens." },
276
306
  dependsOn: { type: "array", items: { type: "integer" } },
307
+ depPolicy: {
308
+ type: "string",
309
+ enum: ["all_success", "accept_partial", "all_terminal", "optional"],
310
+ description: "How dependency terminal states gate this node; defaults to all_success.",
311
+ },
277
312
  },
278
313
  required: ["task", "role"],
279
314
  },
@@ -4,9 +4,29 @@ export interface RuntimeSignal {
4
4
  urgency: "low" | "normal" | "high" | "critical";
5
5
  payload: Record<string, unknown>;
6
6
  dedupeKey?: string;
7
+ /** Target a specific session loop. Omitted means a shared signal. */
8
+ recipient?: string;
9
+ /** Absolute journal-clock deadline for optional urgency escalation. */
10
+ deadlineMs?: number;
11
+ /** Merge with an unconsumed queued signal carrying the same key. */
12
+ coalesceKey?: string;
13
+ /** Number of host signals deterministically represented by this signal. */
14
+ coalescedCount?: number;
7
15
  }
8
16
  export interface SignalSource {
9
- nextSignal(): Promise<RuntimeSignal | null>;
17
+ claimSignal(): Promise<SignalClaim | null>;
18
+ ackSignal(receipt: SignalDeliveryReceipt): Promise<boolean>;
19
+ nackSignal(receipt: SignalDeliveryReceipt): Promise<boolean>;
20
+ }
21
+ export interface SignalDeliveryReceipt {
22
+ deliveryId: string;
23
+ leaseToken: string;
24
+ }
25
+ export interface SignalClaim extends SignalDeliveryReceipt {
26
+ signalId: string;
27
+ deliveryAttempt: number;
28
+ signal: RuntimeSignal;
29
+ leaseExpiresAtMs: number;
10
30
  }
11
31
  export declare class ScheduledPrompt {
12
32
  readonly goal: string;
@@ -15,6 +15,7 @@ export class ScheduledPrompt {
15
15
  signalType: "job",
16
16
  urgency: "normal",
17
17
  payload: { goal: this.goal, criteria: this.criteria, runAtMs: this.runAtMs, ...this.metadata },
18
+ coalescedCount: 1,
18
19
  dedupeKey: `scheduled-${this.runAtMs}`,
19
20
  };
20
21
  }
package/dist/types.d.ts CHANGED
@@ -54,6 +54,12 @@ export interface RenderedContext {
54
54
  /** Message count of the frozen history prefix (compaction boundary). When set,
55
55
  * Anthropic pins a deep cache breakpoint here instead of the rolling pair. */
56
56
  frozenPrefixLen?: number;
57
+ budgetOverflow?: ContextBudgetOverflow;
58
+ }
59
+ export interface ContextBudgetOverflow {
60
+ kind: "fixed_context" | "protected_tail";
61
+ requiredTokens: number;
62
+ maxTokens: number;
57
63
  }
58
64
  export interface StreamEvent {
59
65
  type: string;
@@ -104,8 +110,7 @@ export interface DoneEvent extends StreamEvent {
104
110
  type: "done";
105
111
  iterations: number;
106
112
  totalTokens: number;
107
- status: string;
108
- dreamResult?: import("./memory/index.js").DreamResult; /** ③ loop-agent: the kernel-adjudicated after-round decision (absent on non-loop runs). */
113
+ status: string; /** ③ loop-agent: the kernel-adjudicated after-round decision (absent on non-loop runs). */
109
114
  paceDecision?: import("./runtime/kernel-step.js").PaceDecision;
110
115
  }
111
116
  export interface ErrorEvent extends StreamEvent {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deepstrike/wasm",
3
- "version": "0.2.38",
3
+ "version": "0.2.40",
4
4
  "description": "DeepStrike WASM SDK — browser, Cloudflare Workers, Deno Deploy",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -15,7 +15,7 @@
15
15
  "test": "node --experimental-vm-modules node_modules/.bin/jest"
16
16
  },
17
17
  "dependencies": {
18
- "@deepstrike/wasm-kernel": "0.2.38"
18
+ "@deepstrike/wasm-kernel": "0.2.40"
19
19
  },
20
20
  "devDependencies": {
21
21
  "@types/jest": "^30.0.0",