@smartmemory/stratum 0.3.4 → 0.4.1

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 (73) hide show
  1. package/dist/cli/guard.js +63 -6
  2. package/dist/cli/guard.js.map +1 -1
  3. package/dist/cli/learn.js +226 -0
  4. package/dist/cli/learn.js.map +1 -0
  5. package/dist/cli/stratum.js +3 -1
  6. package/dist/cli/stratum.js.map +1 -1
  7. package/dist/connectors/background.js +53 -9
  8. package/dist/connectors/background.js.map +1 -1
  9. package/dist/connectors/base.js +16 -0
  10. package/dist/connectors/base.js.map +1 -1
  11. package/dist/connectors/cancellation.js +119 -0
  12. package/dist/connectors/cancellation.js.map +1 -0
  13. package/dist/connectors/claude-bg-worker.js +9 -1
  14. package/dist/connectors/claude-bg-worker.js.map +1 -1
  15. package/dist/connectors/claude.js +179 -86
  16. package/dist/connectors/claude.js.map +1 -1
  17. package/dist/connectors/codex.js +219 -62
  18. package/dist/connectors/codex.js.map +1 -1
  19. package/dist/connectors/runner.js +44 -3
  20. package/dist/connectors/runner.js.map +1 -1
  21. package/dist/contracts/events.json +34 -1
  22. package/dist/contracts/guard-signers.allowed +36 -0
  23. package/dist/contracts/mcp-surface.json +1085 -104
  24. package/dist/engine/checkpoint.js +8 -1
  25. package/dist/engine/checkpoint.js.map +1 -1
  26. package/dist/engine/engine.js +403 -42
  27. package/dist/engine/engine.js.map +1 -1
  28. package/dist/engine/ledger.js +12 -0
  29. package/dist/engine/ledger.js.map +1 -1
  30. package/dist/engine/receipts.js +91 -0
  31. package/dist/engine/receipts.js.map +1 -0
  32. package/dist/engine/state.js +51 -1
  33. package/dist/engine/state.js.map +1 -1
  34. package/dist/guard/authorization.js +71 -0
  35. package/dist/guard/authorization.js.map +1 -0
  36. package/dist/guard/descriptors.js +248 -0
  37. package/dist/guard/descriptors.js.map +1 -0
  38. package/dist/guard/errors.js +12 -0
  39. package/dist/guard/errors.js.map +1 -1
  40. package/dist/guard/evidence.js +24 -3
  41. package/dist/guard/evidence.js.map +1 -1
  42. package/dist/guard/sshsig.js +264 -0
  43. package/dist/guard/sshsig.js.map +1 -0
  44. package/dist/guard/store.js +13 -0
  45. package/dist/guard/store.js.map +1 -1
  46. package/dist/guard/transition.js +484 -33
  47. package/dist/guard/transition.js.map +1 -1
  48. package/dist/guard/trust.js +78 -0
  49. package/dist/guard/trust.js.map +1 -0
  50. package/dist/judge/judged.js +1 -1
  51. package/dist/judge/pricing.js +1 -0
  52. package/dist/judge/pricing.js.map +1 -1
  53. package/dist/learn/apply.js +600 -0
  54. package/dist/learn/apply.js.map +1 -0
  55. package/dist/learn/candidate.js +186 -0
  56. package/dist/learn/candidate.js.map +1 -0
  57. package/dist/learn/classify.js +181 -0
  58. package/dist/learn/classify.js.map +1 -0
  59. package/dist/learn/harvest.js +138 -0
  60. package/dist/learn/harvest.js.map +1 -0
  61. package/dist/learn/smartmemory_egress.js +330 -0
  62. package/dist/learn/smartmemory_egress.js.map +1 -0
  63. package/dist/mcp/server.js +150 -22
  64. package/dist/mcp/server.js.map +1 -1
  65. package/dist/policy/bundle.js +195 -0
  66. package/dist/policy/bundle.js.map +1 -0
  67. package/dist/policy/events.js +51 -0
  68. package/dist/policy/events.js.map +1 -0
  69. package/dist/policy/smartmemory_client.js +332 -0
  70. package/dist/policy/smartmemory_client.js.map +1 -0
  71. package/dist/policy/types.js +2 -0
  72. package/dist/policy/types.js.map +1 -0
  73. package/package.json +3 -2
@@ -0,0 +1,330 @@
1
+ const MIN_BACKOFF_MS = 1_000;
2
+ const MAX_BACKOFF_MS = 5 * 60_000;
3
+ const REQUEST_TIMEOUT_MS = 5_000;
4
+ const DEAD_STATUSES = new Set([400, 401, 403, 404, 422]);
5
+ const MEMORY_TYPES = [
6
+ "stratum_usage_debit",
7
+ "stratum_step_reset",
8
+ "stratum_checkpoint_reverted",
9
+ ];
10
+ export class LearnEgress {
11
+ url;
12
+ apiKey;
13
+ workspaceId;
14
+ optedIn;
15
+ fetchImpl;
16
+ now;
17
+ random;
18
+ warn;
19
+ setTimeoutImpl;
20
+ clearTimeoutImpl;
21
+ store;
22
+ withReceiptUpdate;
23
+ drains = new Map();
24
+ backoffs = new Map();
25
+ workspaceWarningIssued = false;
26
+ constructor(options) {
27
+ const env = options.env ?? process.env;
28
+ const url = env.SMARTMEMORY_API_URL?.replace(/\/+$/, "");
29
+ this.url = url ? url : undefined;
30
+ this.apiKey = env.SMARTMEMORY_API_KEY || undefined;
31
+ this.workspaceId = env.SMARTMEMORY_WORKSPACE_ID || undefined;
32
+ this.optedIn = env.STRATUM_LEARN_EGRESS === "1";
33
+ this.fetchImpl = options.fetchImpl ?? globalThis.fetch;
34
+ this.now = options.now ?? Date.now;
35
+ this.random = options.random ?? Math.random;
36
+ this.warn = options.warn ?? ((warning) => console.warn(warning));
37
+ this.setTimeoutImpl = options.setTimeoutImpl ?? setTimeout;
38
+ this.clearTimeoutImpl = options.clearTimeoutImpl ?? clearTimeout;
39
+ this.store = options.store;
40
+ this.withReceiptUpdate = options.withReceiptUpdate;
41
+ }
42
+ enabled() {
43
+ if (!this.optedIn || this.url === undefined || this.apiKey === undefined)
44
+ return false;
45
+ if (this.workspaceId !== undefined)
46
+ return true;
47
+ if (!this.workspaceWarningIssued) {
48
+ this.workspaceWarningIssued = true;
49
+ this.warn("SmartMemory receipt egress is disabled: SMARTMEMORY_WORKSPACE_ID is required");
50
+ }
51
+ return false;
52
+ }
53
+ async drainRun(runId) {
54
+ if (!this.enabled())
55
+ return;
56
+ let state = this.drains.get(runId);
57
+ if (state === undefined) {
58
+ state = { dirty: false, inFlight: undefined };
59
+ this.drains.set(runId, state);
60
+ }
61
+ state.dirty = true;
62
+ if (state.inFlight === undefined)
63
+ this.startDrain(runId, state);
64
+ await state.inFlight;
65
+ }
66
+ async drainAll() {
67
+ if (!this.enabled())
68
+ return;
69
+ try {
70
+ await Promise.all((await this.store.list()).map((runId) => this.drainRun(runId)));
71
+ }
72
+ catch (error) {
73
+ this.warn(`SmartMemory egress reconciliation failed: ${message(error)}`);
74
+ }
75
+ }
76
+ async close() {
77
+ for (;;) {
78
+ const inFlight = [...this.drains.values()].flatMap((state) => state.inFlight ? [state.inFlight] : []);
79
+ if (inFlight.length === 0)
80
+ return;
81
+ await Promise.all(inFlight);
82
+ }
83
+ }
84
+ async verifyRun(runId) {
85
+ if (!this.enabled()) {
86
+ throw new Error("SmartMemory egress is disabled: STRATUM_LEARN_EGRESS=1 and SMARTMEMORY_API_URL/API_KEY/WORKSPACE_ID are required");
87
+ }
88
+ const run = await this.store.load(runId);
89
+ const local = run.receipts ?? [];
90
+ let missingCount = 0;
91
+ let duplicateCount = 0;
92
+ let wrongTypeCount = 0;
93
+ for (const receipt of local) {
94
+ const receiptId = `${runId}:${receipt.seq}`;
95
+ const expectedType = memoryTypeFor(receipt);
96
+ const expectedHits = await this.exactHits(receiptId, expectedType);
97
+ if (expectedHits.length > 0) {
98
+ duplicateCount += expectedHits.length - 1;
99
+ continue;
100
+ }
101
+ missingCount += 1;
102
+ for (const otherType of MEMORY_TYPES) {
103
+ if (otherType === expectedType)
104
+ continue;
105
+ wrongTypeCount += (await this.exactHits(receiptId, otherType)).length;
106
+ }
107
+ }
108
+ return {
109
+ runId,
110
+ receiptCount: local.length,
111
+ missingCount,
112
+ duplicateCount,
113
+ wrongTypeCount,
114
+ deadCount: local.filter((receipt) => receipt.egress === "dead").length,
115
+ };
116
+ }
117
+ async retryDead(runId) {
118
+ let retried = 0;
119
+ try {
120
+ retried = await this.withReceiptUpdate(runId, (run) => {
121
+ let changed = 0;
122
+ for (const receipt of run.receipts ?? []) {
123
+ if (receipt.egress !== "dead")
124
+ continue;
125
+ receipt.egress = "pending";
126
+ delete receipt.egressStatus;
127
+ changed += 1;
128
+ }
129
+ return changed;
130
+ });
131
+ await this.drainRun(runId);
132
+ }
133
+ catch (error) {
134
+ this.warn(`SmartMemory egress could not retry dead receipts for run ${runId}: ${message(error)}`);
135
+ }
136
+ return retried;
137
+ }
138
+ startDrain(runId, state) {
139
+ const inFlight = this.drainLoop(runId, state)
140
+ .catch((error) => {
141
+ this.warn(`SmartMemory egress could not drain run ${runId}: ${message(error)}`);
142
+ })
143
+ .finally(() => {
144
+ state.inFlight = undefined;
145
+ if (state.dirty)
146
+ this.startDrain(runId, state);
147
+ else if (this.drains.get(runId) === state)
148
+ this.drains.delete(runId);
149
+ });
150
+ state.inFlight = inFlight;
151
+ }
152
+ async drainLoop(runId, state) {
153
+ while (state.dirty) {
154
+ state.dirty = false;
155
+ await this.drainOnce(runId);
156
+ }
157
+ }
158
+ async drainOnce(runId) {
159
+ const backoff = this.backoffs.get(runId);
160
+ if (backoff !== undefined && this.now() < backoff.nextAttemptAt)
161
+ return;
162
+ const snapshot = await this.withReceiptUpdate(runId, (run) => ({
163
+ id: run.id,
164
+ flowName: run.flowName,
165
+ ...(run.workspaceRoot !== undefined ? { workspaceRoot: run.workspaceRoot } : {}),
166
+ ...(run.revisionDigest !== undefined ? { revisionDigest: run.revisionDigest } : {}),
167
+ pending: (run.receipts ?? [])
168
+ .filter((receipt) => receipt.egress === "pending")
169
+ .sort((left, right) => left.seq - right.seq)
170
+ .map((receipt) => structuredClone(receipt)),
171
+ }));
172
+ if (snapshot.pending.length === 0)
173
+ return;
174
+ const transitions = [];
175
+ for (const receipt of snapshot.pending) {
176
+ let response;
177
+ let failure;
178
+ try {
179
+ response = await this.add(snapshot, receipt);
180
+ }
181
+ catch (error) {
182
+ failure = error;
183
+ }
184
+ if (response?.ok) {
185
+ transitions.push({ seq: receipt.seq, egress: "sent" });
186
+ this.resetBackoff(runId);
187
+ continue;
188
+ }
189
+ if (response !== undefined && DEAD_STATUSES.has(response.status)) {
190
+ transitions.push({ seq: receipt.seq, egress: "dead", status: response.status });
191
+ this.warn(`SmartMemory egress dead-lettered ${snapshot.id}:${receipt.seq}: HTTP ${response.status}`);
192
+ continue;
193
+ }
194
+ this.recordFailure(runId);
195
+ const detail = response === undefined ? message(failure) : `HTTP ${response.status}`;
196
+ this.warn(`SmartMemory egress stopped at ${snapshot.id}:${receipt.seq}: ${detail}`);
197
+ break;
198
+ }
199
+ if (transitions.length === 0)
200
+ return;
201
+ await this.withReceiptUpdate(runId, (run) => {
202
+ const bySequence = new Map((run.receipts ?? []).map((receipt) => [receipt.seq, receipt]));
203
+ for (const transition of transitions) {
204
+ const receipt = bySequence.get(transition.seq);
205
+ if (receipt === undefined || receipt.egress !== "pending")
206
+ continue;
207
+ receipt.egress = transition.egress;
208
+ if (transition.status === undefined)
209
+ delete receipt.egressStatus;
210
+ else
211
+ receipt.egressStatus = transition.status;
212
+ }
213
+ });
214
+ }
215
+ async add(run, receipt) {
216
+ return this.request(`${this.url}/memory/add`, {
217
+ content: summary(run, receipt),
218
+ memory_type: memoryTypeFor(receipt),
219
+ metadata: {
220
+ ...receipt,
221
+ ...(receipt.detail !== undefined ? { detail: receipt.detail } : {}),
222
+ run_id: run.id,
223
+ workspace_root: run.workspaceRoot ?? null,
224
+ flow_name: run.flowName,
225
+ spec_digest: run.revisionDigest ?? null,
226
+ event_ordinal: receipt.seq,
227
+ receipt_id: `${run.id}:${receipt.seq}`,
228
+ origin: "cli:stratum",
229
+ },
230
+ use_pipeline: false,
231
+ });
232
+ }
233
+ async exactHits(receiptId, memoryType) {
234
+ const response = await this.request(`${this.url}/memory/search`, {
235
+ query: receiptId,
236
+ memory_type: memoryType,
237
+ top_k: 20,
238
+ });
239
+ if (!response.ok)
240
+ throw new Error(`SmartMemory verify failed for ${memoryType}: HTTP ${response.status}`);
241
+ const payload = await response.json();
242
+ if (!Array.isArray(payload.results))
243
+ throw new Error(`SmartMemory verify returned no results array for ${memoryType}`);
244
+ return payload.results.filter((result) => resultReceiptId(result) === receiptId && resultMemoryType(result) === memoryType);
245
+ }
246
+ async request(url, body) {
247
+ const controller = new AbortController();
248
+ const timeout = this.setTimeoutImpl(() => controller.abort(), REQUEST_TIMEOUT_MS);
249
+ try {
250
+ return await this.fetchImpl(url, {
251
+ method: "POST",
252
+ headers: {
253
+ Authorization: `Bearer ${this.apiKey}`,
254
+ "X-Workspace-Id": this.workspaceId,
255
+ "Content-Type": "application/json",
256
+ },
257
+ body: JSON.stringify(body),
258
+ signal: controller.signal,
259
+ });
260
+ }
261
+ finally {
262
+ this.clearTimeoutImpl(timeout);
263
+ }
264
+ }
265
+ recordFailure(runId) {
266
+ const current = this.backoffs.get(runId) ?? { consecutiveFailures: 0, nextAttemptAt: 0 };
267
+ current.consecutiveFailures += 1;
268
+ const exponent = Math.min(current.consecutiveFailures - 1, 20);
269
+ const base = Math.min(MAX_BACKOFF_MS, MIN_BACKOFF_MS * (2 ** exponent));
270
+ const jittered = Math.min(MAX_BACKOFF_MS, base + (base * 0.2 * this.random()));
271
+ current.nextAttemptAt = this.now() + jittered;
272
+ this.backoffs.set(runId, current);
273
+ }
274
+ resetBackoff(runId) {
275
+ this.backoffs.delete(runId);
276
+ }
277
+ }
278
+ function memoryTypeFor(receipt) {
279
+ if (receipt.source === "engine" && receipt.dispatchId.startsWith("engine:step_reset:"))
280
+ return "stratum_step_reset";
281
+ if (receipt.source === "engine" && receipt.dispatchId.startsWith("engine:checkpoint_reverted:"))
282
+ return "stratum_checkpoint_reverted";
283
+ return "stratum_usage_debit";
284
+ }
285
+ function summary(run, receipt) {
286
+ const tokens = receipt.amount.tokens ?? 0;
287
+ const milliseconds = receipt.amount.ms ?? receipt.telemetry.durationMs;
288
+ return `${run.flowName}/${receipt.stepId ?? "run"} ${receipt.source} (${receipt.telemetry.model}): ${tokens} tokens, ${milliseconds} ms`;
289
+ }
290
+ function resultReceiptId(result) {
291
+ return resultField(result, (value) => {
292
+ if (typeof value.receipt_id === "string")
293
+ return value.receipt_id;
294
+ if (typeof value.metadata !== "object" || value.metadata === null || Array.isArray(value.metadata))
295
+ return undefined;
296
+ const receiptId = value.metadata.receipt_id;
297
+ return typeof receiptId === "string" ? receiptId : undefined;
298
+ });
299
+ }
300
+ function resultMemoryType(result) {
301
+ return resultField(result, (value) => {
302
+ if (typeof value.memory_type === "string")
303
+ return value.memory_type;
304
+ if (typeof value.metadata !== "object" || value.metadata === null || Array.isArray(value.metadata))
305
+ return undefined;
306
+ const memoryType = value.metadata.memory_type;
307
+ return typeof memoryType === "string" ? memoryType : undefined;
308
+ });
309
+ }
310
+ function resultField(result, read) {
311
+ if (typeof result !== "object" || result === null || Array.isArray(result))
312
+ return undefined;
313
+ const row = result;
314
+ const direct = read(row);
315
+ if (direct !== undefined)
316
+ return direct;
317
+ for (const key of ["item", "context"]) {
318
+ const nested = row[key];
319
+ if (typeof nested !== "object" || nested === null || Array.isArray(nested))
320
+ continue;
321
+ const found = read(nested);
322
+ if (found !== undefined)
323
+ return found;
324
+ }
325
+ return undefined;
326
+ }
327
+ function message(error) {
328
+ return error instanceof Error ? error.message : String(error);
329
+ }
330
+ //# sourceMappingURL=smartmemory_egress.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"smartmemory_egress.js","sourceRoot":"","sources":["../../src/learn/smartmemory_egress.ts"],"names":[],"mappings":"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"}
@@ -1,11 +1,11 @@
1
+ import { linkAbort, teardownDeadline } from "../connectors/cancellation.js";
1
2
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
2
3
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
4
  import { CallToolRequestSchema, ErrorCode, ListToolsRequestSchema, McpError } from "@modelcontextprotocol/sdk/types.js";
4
- import { randomUUID } from "node:crypto";
5
5
  import { readFileSync } from "node:fs";
6
6
  import { stat } from "node:fs/promises";
7
7
  import { cancelBackgroundRun, pollBackgroundRun, runAgent } from "../connectors/index.js";
8
- import { CheckpointOperationError, SpecValidationError, StratumEngine } from "../engine/engine.js";
8
+ import { CheckpointOperationError, InputValidationError, SpecValidationError, StratumEngine } from "../engine/engine.js";
9
9
  import { createEvaluator } from "../eval/expr.js";
10
10
  import { createEvaluateRunner } from "../engine/evaluate.js";
11
11
  import { validateSpec } from "../ir/validate.js";
@@ -53,14 +53,65 @@ function defaultEngine() {
53
53
  evaluateRunner: createEvaluateRunner(),
54
54
  });
55
55
  }
56
+ /** Every structured MCP error goes through the registry: an envelope the
57
+ * contract does not declare (or whose payload drifts from the declaration)
58
+ * fails here rather than reaching a client as an undeclared shape. */
59
+ async function registryError(envelope, errorCode, message, data) {
60
+ const declaration = (await mcpSurface()).errors[envelope];
61
+ if (!declaration)
62
+ throw new Error(`MCP error registry is missing ${envelope}`);
63
+ assertShape(data, declaration.data, `errors.${envelope}.data`);
64
+ return new McpError(errorCode, message, data);
65
+ }
66
+ /** Rejects a request field before the contract check can run — the cancellation
67
+ * bookkeeping below must be in place before any awaited contract I/O, so these
68
+ * few fields are validated by hand and reported in the declared shape. */
69
+ function inputValidationError(path, message) {
70
+ return registryError("input_validation_failed", ErrorCode.InvalidParams, message, {
71
+ code: "input_validation_failed",
72
+ errors: [{ code: "input_validation_failed", path, message }],
73
+ });
74
+ }
56
75
  export function createToolDispatcher(dependencies = {}) {
57
76
  const engine = dependencies.engine ?? defaultEngine();
58
77
  const agentRun = dependencies.runAgent ?? runAgent;
59
78
  const agentPoll = dependencies.pollBackgroundRun ?? pollBackgroundRun;
60
79
  const agentCancel = dependencies.cancelBackgroundRun ?? cancelBackgroundRun;
80
+ // Register before contract I/O: an immediate cancellation cannot overtake startup.
81
+ // UUIDs cannot collide with durable background IDs.
82
+ const foreground = new Map();
83
+ const completed = new Map();
61
84
  return {
62
85
  async call(tool, request, context = {}) {
86
+ // This request has one required string field. Check that exact shape before
87
+ // acting synchronously, otherwise contract loading can let startup overtake
88
+ // an already-received cancellation. Full contract validation still follows.
89
+ if (tool === "stratum_cancel_agent_run" && typeof request.runId === "string"
90
+ && Object.keys(request).length === 1) {
91
+ foreground.get(request.runId)?.controller.abort(new Error("Foreground agent run cancelled"));
92
+ }
93
+ let cancellationId;
94
+ let controller;
95
+ let settle;
96
+ let unlink;
97
+ let succeeded = false;
98
+ let teardownFailure;
63
99
  try {
100
+ if (tool === "stratum_agent_run" && request.cancellationId !== undefined) {
101
+ if (typeof request.cancellationId !== "string"
102
+ || !/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(request.cancellationId)) {
103
+ throw await inputValidationError("cancellationId", "cancellationId must be a UUID");
104
+ }
105
+ cancellationId = request.cancellationId;
106
+ if (request.background === true)
107
+ throw await inputValidationError("background", "cancellationId is only supported for foreground runs");
108
+ if (foreground.has(cancellationId) || completed.has(cancellationId))
109
+ throw await inputValidationError("cancellationId", "cancellationId has already been used");
110
+ controller = new AbortController();
111
+ const settled = new Promise((resolve) => { settle = resolve; });
112
+ foreground.set(cancellationId, { controller, settled });
113
+ unlink = linkAbort(context.signal, controller);
114
+ }
64
115
  await assertToolRequest(tool, request);
65
116
  let response;
66
117
  switch (tool) {
@@ -91,12 +142,21 @@ export function createToolDispatcher(dependencies = {}) {
91
142
  response = validation.ok ? { status: "valid" } : { status: "invalid", errors: validation.errors };
92
143
  break;
93
144
  }
94
- case "stratum_plan":
95
- response = await engine.plan(request.spec, request.input, option(request, "workspaceRoot"));
145
+ case "stratum_plan": {
146
+ const policyStepSelector = optionalString(request, "policy_step_selector");
147
+ response = await engine.plan(request.spec, request.input, {
148
+ ...option(request, "workspaceRoot"),
149
+ ...(request.policy_bundle !== undefined ? { policyBundle: record(request, "policy_bundle") } : {}),
150
+ ...(policyStepSelector !== undefined ? { policyStepSelector } : {}),
151
+ });
96
152
  break;
153
+ }
97
154
  case "stratum_step_done":
98
155
  response = await engine.stepDone(string(request, "runId"), string(request, "stepId"), record(request, "result"), string(request, "dispatchToken"));
99
156
  break;
157
+ case "stratum_usage_report":
158
+ response = await engine.usageReport(string(request, "runId"), record(request, "receipt"));
159
+ break;
100
160
  case "stratum_commit":
101
161
  response = { ...await engine.commit(string(request, "flow_id"), string(request, "label")) };
102
162
  break;
@@ -110,7 +170,7 @@ export function createToolDispatcher(dependencies = {}) {
110
170
  response = auditResponse(await engine.audit(string(request, "runId")));
111
171
  break;
112
172
  case "stratum_gate_resolve":
113
- response = await engine.gateResolve(string(request, "runId"), string(request, "stepId"), string(request, "decision"), string(request, "gateToken"));
173
+ response = await engine.gateResolve(string(request, "runId"), string(request, "stepId"), string(request, "decision"), string(request, "gateToken"), optionalString(request, "user_id"));
114
174
  break;
115
175
  case "stratum_flow_poll":
116
176
  response = flowPollResponse(await engine.flowPoll(string(request, "runId"), optionalNumber(request, "cursor")));
@@ -138,6 +198,7 @@ export function createToolDispatcher(dependencies = {}) {
138
198
  : undefined;
139
199
  const executed = await agentRun({
140
200
  agent: string(request, "agent"),
201
+ ...(cancellationId !== undefined ? { ownProcessGroup: true } : {}),
141
202
  prompt: string(request, "prompt"),
142
203
  cwd: string(request, "cwd"),
143
204
  // Presence-based forwarding, NOT truthiness: sandboxMode:"" must reach
@@ -150,37 +211,73 @@ export function createToolDispatcher(dependencies = {}) {
150
211
  ...(allowedTools !== undefined ? { allowedTools } : {}),
151
212
  ...(disallowedTools !== undefined ? { disallowedTools } : {}),
152
213
  ...(context.onAgentEvent !== undefined ? { onEvent: context.onAgentEvent } : {}),
214
+ ...((controller?.signal ?? context.signal) !== undefined ? { signal: (controller?.signal ?? context.signal) } : {}),
215
+ ...(request.thinking !== undefined ? { thinking: record(request, "thinking") } : {}),
216
+ ...(request.effort !== undefined ? { effort: string(request, "effort") } : {}),
153
217
  });
218
+ unlink?.(); // Provider finished; a late disconnect cannot cancel a completed run.
219
+ succeeded = true;
154
220
  response = "status" in executed ? { ...executed } : { status: "complete", ...executed };
155
221
  break;
156
222
  }
157
223
  case "stratum_agent_poll":
158
224
  response = await agentPoll(string(request, "runId"));
159
225
  break;
160
- case "stratum_cancel_agent_run":
161
- response = await agentCancel(string(request, "runId"));
226
+ case "stratum_cancel_agent_run": {
227
+ const runId = string(request, "runId");
228
+ const running = foreground.get(runId);
229
+ if (running) {
230
+ running.controller.abort(new Error("Foreground agent run cancelled"));
231
+ // Acknowledge only after the connector has finished teardown.
232
+ await teardownDeadline(running.settled, dependencies.cancellationTimeoutMs ?? Number(process.env.STRATUM_CANCEL_TIMEOUT_MS ?? 15000), "Foreground connector teardown did not settle");
233
+ const outcome = completed.get(runId);
234
+ if (outcome instanceof Error)
235
+ throw outcome;
236
+ response = { status: "cancelled", runId };
237
+ }
238
+ else if (completed.has(runId)) {
239
+ const outcome = completed.get(runId);
240
+ if (outcome instanceof Error)
241
+ throw outcome;
242
+ response = { status: outcome, runId };
243
+ }
244
+ else
245
+ response = await agentCancel(runId);
162
246
  break;
247
+ }
163
248
  case "stratum_guard_register": {
164
249
  const { registerGuard } = await import("../guard/transition.js");
165
- response = await registerGuard(string(request, "resource_id"), record(request, "graph"), record(request, "edge_predicates"), string(request, "initial"), optionalArray(request, "terminal"), optionalRecord(request, "stakes"), optionalString(request, "workspace_root") ?? null);
250
+ response = await registerGuard(string(request, "resource_id"), record(request, "graph"), record(request, "edge_predicates"), string(request, "initial"), optionalArray(request, "terminal"), optionalRecord(request, "stakes"), optionalString(request, "workspace_root") ?? null, request.policy_bundle !== undefined ? record(request, "policy_bundle") : undefined);
166
251
  break;
167
252
  }
168
253
  case "stratum_guard_transition": {
169
254
  const { guardTransition } = await import("../guard/transition.js");
255
+ const runId = optionalString(request, "run_id");
170
256
  response = await guardTransition(string(request, "resource_id"), string(request, "from_state"), string(request, "to_state"), {
171
257
  artifacts: record(request, "artifacts"), modifiedFiles: optionalArray(request, "modified_files"), idempotencyKey: optionalString(request, "idempotency_key") ?? null, resolvedBy: optionalString(request, "resolved_by") ?? "agent",
258
+ ...(runId !== undefined ? { runId } : {}),
172
259
  ...(dependencies.guardJudge !== undefined ? { judge: dependencies.guardJudge } : {}),
173
260
  });
174
261
  break;
175
262
  }
176
263
  case "stratum_guard_override": {
177
264
  const { guardOverride } = await import("../guard/transition.js");
178
- response = await guardOverride(string(request, "resource_id"), string(request, "from_state"), string(request, "to_state"), string(request, "override_token"), string(request, "rationale"), optionalString(request, "resolved_by") ?? "human");
265
+ response = await guardOverride(string(request, "resource_id"), string(request, "from_state"), string(request, "to_state"), string(request, "authorization"), string(request, "rationale"), optionalString(request, "resolved_by") ?? "human", optionalString(request, "user_id"), optionalString(request, "run_id"));
179
266
  break;
180
267
  }
181
268
  case "stratum_guard_migrate": {
182
269
  const { guardMigrate } = await import("../guard/transition.js");
183
- response = await guardMigrate(string(request, "resource_id"), record(request, "new_graph"), record(request, "new_edge_predicates"), string(request, "override_token"), string(request, "rationale"), optionalArray(request, "new_terminal"), optionalRecord(request, "new_stakes"));
270
+ response = await guardMigrate(string(request, "resource_id"), record(request, "new_graph"), record(request, "new_edge_predicates"), string(request, "authorization"), string(request, "rationale"), optionalArray(request, "new_terminal"), optionalRecord(request, "new_stakes"));
271
+ break;
272
+ }
273
+ case "stratum_guard_upgrade": {
274
+ const { guardUpgrade } = await import("../guard/transition.js");
275
+ response = await guardUpgrade(string(request, "resource_id"), record(request, "new_graph"), record(request, "new_edge_predicates"), string(request, "rationale"), optionalArray(request, "new_terminal"), optionalRecord(request, "new_stakes"));
276
+ break;
277
+ }
278
+ case "stratum_guard_apply_upgrade": {
279
+ const { guardApplyUpgrade } = await import("../guard/transition.js");
280
+ response = await guardApplyUpgrade(string(request, "resource_id"), string(request, "descriptor_id"));
184
281
  break;
185
282
  }
186
283
  case "stratum_guard_history": {
@@ -194,31 +291,53 @@ export function createToolDispatcher(dependencies = {}) {
194
291
  await assertEvent(event);
195
292
  }
196
293
  await assertToolResponse(tool, response);
294
+ succeeded = true;
197
295
  return response;
198
296
  }
199
297
  catch (error) {
298
+ if (error instanceof Error && "code" in error
299
+ && ["CANCELLATION_TEARDOWN_TIMEOUT", "CANCELLATION_UNCONFIRMED"].includes(String(error.code))) {
300
+ teardownFailure = error;
301
+ }
200
302
  if (error instanceof SpecValidationError) {
201
303
  const code = tool === "stratum_flow_run_bg"
202
304
  && error.errors.some((entry) => entry.code === "consumer_dispatch_bg_unsupported")
203
- ? "consumer_dispatch_bg_unsupported" : "spec_validation_failed";
204
- const data = { code, errors: error.errors };
205
- const declaration = (await mcpSurface()).errors[code];
206
- if (!declaration)
207
- throw new Error(`MCP error registry is missing ${code}`);
208
- assertShape(data, declaration.data, `errors.${code}.data`);
209
- throw new McpError(ErrorCode.InvalidParams, error.message, data);
305
+ ? "consumer_dispatch_bg_unsupported" : error instanceof InputValidationError ? "input_validation_failed" : "spec_validation_failed";
306
+ throw await registryError(code, ErrorCode.InvalidParams, error.message, { code, errors: error.errors });
210
307
  }
211
308
  if ((tool === "stratum_commit" || tool === "stratum_revert") && error instanceof CheckpointOperationError) {
212
309
  const response = checkpointErrorEnvelope(error);
213
310
  await assertToolResponse(tool, response);
214
311
  return response;
215
312
  }
313
+ if (tool === "stratum_agent_run" || tool === "stratum_cancel_agent_run") {
314
+ // An McpError already carries a declared code and payload — rewrapping it
315
+ // as agent_run_failed would replace a precise contract error (a rejected
316
+ // request field, an undeclared response) with a generic provider failure.
317
+ if (error instanceof McpError)
318
+ throw error;
319
+ const failure = error;
320
+ // The envelope is always agent_run_failed; `code` names the specific
321
+ // connector failure (CANCELLATION_TEARDOWN_TIMEOUT and friends) when it has one.
322
+ const data = { code: failure.code ?? "agent_run_failed", ...Object.fromEntries(["usage", "split", "usdSource", "stderr", "telemetry"].filter(key => key in Object(failure)).map(key => [key, failure[key]])) };
323
+ throw await registryError("agent_run_failed", ErrorCode.InternalError, failure.message ?? String(error), data);
324
+ }
216
325
  if (!tool.startsWith("stratum_guard_"))
217
326
  throw error;
218
327
  const response = guardErrorEnvelope(error);
219
328
  await assertToolResponse(tool, response);
220
329
  return response;
221
330
  }
331
+ finally {
332
+ unlink?.();
333
+ if (cancellationId !== undefined && controller) {
334
+ completed.set(cancellationId, teardownFailure ?? (succeeded ? "already_complete" : controller.signal.aborted ? "cancelled" : "already_error"));
335
+ foreground.delete(cancellationId);
336
+ if (completed.size > 1024)
337
+ completed.delete(completed.keys().next().value);
338
+ settle?.();
339
+ }
340
+ }
222
341
  },
223
342
  };
224
343
  }
@@ -257,20 +376,29 @@ export async function createMcpServer(dependencies = {}) {
257
376
  heartbeat.unref?.();
258
377
  }
259
378
  try {
260
- let context;
379
+ let context = { signal: extra.signal };
261
380
  if (request.params.name === "stratum_agent_run" && progressToken !== undefined) {
262
- const flowId = randomUUID();
381
+ // No flow_id: an agent run has no flow, and a server-invented UUID cannot
382
+ // match any consumer's correlation id — compose dropped EVERY agent event
383
+ // as "misrouted" while it was stamped (2026-08-30 census). Progress
384
+ // notifications are already scoped to this call by progressToken; the
385
+ // consumer stamps its own correlation id on an absent flow_id.
263
386
  let eventSeq = 0;
264
387
  context = {
388
+ signal: extra.signal,
265
389
  onAgentEvent: async (event) => {
266
390
  const message = JSON.stringify({
267
- schema_version: "0.2.7",
268
- flow_id: flowId,
391
+ // 0.2.8: flow_id is OPTIONAL on `_agent_run` envelopes (call-local).
392
+ schema_version: "0.2.8",
269
393
  step_id: "_agent_run",
270
394
  seq: eventSeq,
271
395
  ts: new Date().toISOString(),
272
396
  kind: event.kind,
273
- metadata: event.metadata,
397
+ // Agent connector events are call-local; stamp the same step
398
+ // identity in usage metadata required by the BuildStreamEvent contract.
399
+ metadata: event.kind === "step_usage"
400
+ ? { ...event.metadata, stepId: "_agent_run" }
401
+ : event.metadata,
274
402
  reply_required: false,
275
403
  });
276
404
  eventSeq += 1;