@obversa/api 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +49 -0
  3. package/dist/accepted-result-support.d.ts +1 -0
  4. package/dist/accepted-result-support.js +5 -0
  5. package/dist/accepted-result-support.js.map +1 -0
  6. package/dist/action-decision.d.ts +15 -0
  7. package/dist/approval-support.d.ts +1 -0
  8. package/dist/approval-support.js +5 -0
  9. package/dist/approval-support.js.map +1 -0
  10. package/dist/artifacts/conformance.d.ts +20 -0
  11. package/dist/artifacts/store.d.ts +30 -0
  12. package/dist/budget.d.ts +36 -0
  13. package/dist/callback/approval.d.ts +80 -0
  14. package/dist/callback/client-contract.d.ts +81 -0
  15. package/dist/callback/gate.d.ts +49 -0
  16. package/dist/callback/stored-client.d.ts +22 -0
  17. package/dist/chunk-6NA4RDQ4.js +81 -0
  18. package/dist/chunk-6NA4RDQ4.js.map +1 -0
  19. package/dist/chunk-6NAMCSPJ.js +331 -0
  20. package/dist/chunk-6NAMCSPJ.js.map +1 -0
  21. package/dist/chunk-6ZP73HZN.js +293 -0
  22. package/dist/chunk-6ZP73HZN.js.map +1 -0
  23. package/dist/chunk-AJ353QD5.js +157 -0
  24. package/dist/chunk-AJ353QD5.js.map +1 -0
  25. package/dist/chunk-VWZKI7AG.js +552 -0
  26. package/dist/chunk-VWZKI7AG.js.map +1 -0
  27. package/dist/chunk-WGLWWKF3.js +135 -0
  28. package/dist/chunk-WGLWWKF3.js.map +1 -0
  29. package/dist/contracts.d.ts +122 -0
  30. package/dist/engine-conformance.d.ts +80 -0
  31. package/dist/environment.d.ts +53 -0
  32. package/dist/error.d.ts +36 -0
  33. package/dist/events/conformance.d.ts +20 -0
  34. package/dist/events/envelope.d.ts +26 -0
  35. package/dist/events/store.d.ts +15 -0
  36. package/dist/graph-commands.d.ts +23 -0
  37. package/dist/graph-contract.d.ts +48 -0
  38. package/dist/graph-executor.d.ts +61 -0
  39. package/dist/graph-kernel.d.ts +2 -0
  40. package/dist/graph-plan.d.ts +140 -0
  41. package/dist/graph-type.d.ts +45 -0
  42. package/dist/index.d.ts +33 -0
  43. package/dist/index.js +806 -0
  44. package/dist/index.js.map +1 -0
  45. package/dist/json.d.ts +14 -0
  46. package/dist/memory-conformance.d.ts +17 -0
  47. package/dist/memory-types.d.ts +127 -0
  48. package/dist/model-identity.d.ts +28 -0
  49. package/dist/node-data-context.d.ts +11 -0
  50. package/dist/preflight-result.d.ts +17 -0
  51. package/dist/proof/acceptance.d.ts +60 -0
  52. package/dist/proof/artifact.d.ts +2 -0
  53. package/dist/proof/cache.d.ts +46 -0
  54. package/dist/reasoning-record-contract.d.ts +52 -0
  55. package/dist/result-contract.d.ts +16 -0
  56. package/dist/result.d.ts +30 -0
  57. package/dist/run-definition-support.d.ts +1 -0
  58. package/dist/run-definition-support.js +5 -0
  59. package/dist/run-definition-support.js.map +1 -0
  60. package/dist/run-definition.d.ts +73 -0
  61. package/dist/storage/error.d.ts +7 -0
  62. package/dist/storage/id.d.ts +2 -0
  63. package/dist/testing.d.ts +5 -0
  64. package/dist/testing.js +1745 -0
  65. package/dist/testing.js.map +1 -0
  66. package/dist/workspace/conformance.d.ts +30 -0
  67. package/dist/workspace/policy.d.ts +6 -0
  68. package/dist/workspace/provider.d.ts +132 -0
  69. package/package.json +68 -0
package/dist/index.js ADDED
@@ -0,0 +1,806 @@
1
+ export { EngineError, EngineIncompleteResultError, LANE_DEAD_FAILURES, assistantResult, classifyEngineFailure, engineSelection, finalResultPart, finalResultText, modelIdentity, reportedUsage, requireFinalResultText, validateAgentResult, validateIncompleteResultEvidence } from './chunk-6ZP73HZN.js';
2
+ import { validateNewDomainEvent, GraphValidationError } from './chunk-VWZKI7AG.js';
3
+ export { GraphValidationError, compileGraphDefinition, validateDomainEventEnvelope, validateDomainEventId, validateNewDomainEvent, validateRunDefinition, validateRunStartRecord, validateRunStoragePolicy, validateRunStorageRecord } from './chunk-VWZKI7AG.js';
4
+ export { acceptedResultMatches, validateAcceptedResultRecord } from './chunk-6NA4RDQ4.js';
5
+ import { validateCallbackRequest } from './chunk-6NAMCSPJ.js';
6
+ export { ApprovalSubjectError, approvalSubjectDigest, assertApprovalPermissionsAdmitted, callbackRequestDigest, createApprovalCallbackGate, createCallbackGate, snapshotApprovalSubject, validateActionDecision, validateApprovalRecord, validateApprovalSubject, validateCallbackRequest, validateCallbackResponse } from './chunk-6NAMCSPJ.js';
7
+ import { validateStorageId } from './chunk-WGLWWKF3.js';
8
+ export { validateArtifactReference, validateArtifactScope, validateNewArtifact, validateStorageId } from './chunk-WGLWWKF3.js';
9
+ import { canonicalJson, cloneFrozenJson, digestJson, JsonValueError, StorageError } from './chunk-AJ353QD5.js';
10
+ export { JsonValueError, StorageError, canonicalJson, cloneFrozenJson, digestJson } from './chunk-AJ353QD5.js';
11
+ import { isDeepStrictEqual } from 'util';
12
+
13
+ // src/contracts.ts
14
+ var SUBAGENT_TOOLS = ["Task", "Agent", "task"];
15
+ var CLAUDE_SUBAGENT_TOOLS = ["Task", "Agent"];
16
+ function assertReadAccess(request) {
17
+ if (request.workspaceMode === "read" && (request.tools?.length ?? 0) === 0) {
18
+ throw new TypeError("read workspace requires at least one declared tool");
19
+ }
20
+ }
21
+ function isEngine(value) {
22
+ return typeof value === "object" && value !== null && typeof value.name === "string" && typeof value.run === "function";
23
+ }
24
+
25
+ // src/memory-types.ts
26
+ var MEMORY_ROOT = "/memories";
27
+
28
+ // src/graph-executor.ts
29
+ var GraphExecutionError = class extends Error {
30
+ code;
31
+ constructor(code, message, options) {
32
+ super(message, options);
33
+ this.name = "GraphExecutionError";
34
+ this.code = code;
35
+ }
36
+ };
37
+ function issue(code, path, message) {
38
+ return { code, path, message };
39
+ }
40
+ function fail(code, path, message) {
41
+ throw new GraphValidationError(`Invalid graph plan: ${message}`, [
42
+ issue(code, path, message)
43
+ ]);
44
+ }
45
+ function record(value, path, label) {
46
+ if (value === null || typeof value !== "object" || Array.isArray(value)) {
47
+ fail("INVALID_SHAPE", path, `${label} must be an object.`);
48
+ }
49
+ return value;
50
+ }
51
+ function list(value, path, label) {
52
+ if (!Array.isArray(value)) {
53
+ fail("INVALID_SHAPE", path, `${label} must be an array.`);
54
+ }
55
+ return value;
56
+ }
57
+ function requireFields(value, fields, path) {
58
+ for (const field of fields) {
59
+ if (!Object.hasOwn(value, field)) {
60
+ fail(
61
+ "MISSING_FIELD",
62
+ `${path}/${field}`,
63
+ `Required field "${field}" is missing.`
64
+ );
65
+ }
66
+ }
67
+ }
68
+ function exactFields(value, fields, path) {
69
+ requireFields(value, fields, path);
70
+ const expected = new Set(fields);
71
+ for (const field of Object.keys(value)) {
72
+ if (!expected.has(field)) {
73
+ fail(
74
+ "UNKNOWN_FIELD",
75
+ `${path}/${field}`,
76
+ `Unknown field "${field}" is not allowed.`
77
+ );
78
+ }
79
+ }
80
+ }
81
+ function json(value, path) {
82
+ try {
83
+ return cloneFrozenJson(value);
84
+ } catch (error) {
85
+ if (!(error instanceof JsonValueError)) throw error;
86
+ fail("INVALID_JSON_VALUE", `${path}${error.path}`, error.message);
87
+ }
88
+ }
89
+ function text(value, path, label) {
90
+ if (typeof value !== "string" || value.trim().length === 0 || /[\u0000-\u001f\u007f]/.test(value)) {
91
+ fail("INVALID_TEXT", path, `${label} must be a non-empty string without control characters.`);
92
+ }
93
+ return value;
94
+ }
95
+ function identifier(value, path, label) {
96
+ if (typeof value !== "string" || value.length === 0 || value !== value.trim() || /[\u0000-\u001f\u007f]/.test(value)) {
97
+ fail(
98
+ "INVALID_ID",
99
+ path,
100
+ `${label} must be a non-empty trimmed string without control characters.`
101
+ );
102
+ }
103
+ return value;
104
+ }
105
+ function positiveVersion(value, path) {
106
+ if (!Number.isSafeInteger(value) || value < 1) {
107
+ fail("INVALID_VERSION", path, "Version must be a positive safe integer.");
108
+ }
109
+ return value;
110
+ }
111
+ function digest(value, path) {
112
+ if (typeof value !== "string" || !/^sha256:[0-9a-f]{64}$/.test(value)) {
113
+ fail("INVALID_DIGEST", path, "Digest must be lowercase sha256 followed by 64 hex characters.");
114
+ }
115
+ return value;
116
+ }
117
+ function unique(values, path, label) {
118
+ const seen = /* @__PURE__ */ new Set();
119
+ for (let index = 0; index < values.length; index += 1) {
120
+ const value = text(values[index], `${path}/${index}`, label);
121
+ if (seen.has(value)) fail("DUPLICATE_ID", `${path}/${index}`, `Duplicate ${label} "${value}".`);
122
+ seen.add(value);
123
+ }
124
+ }
125
+ function target(value, path) {
126
+ const item = record(value, path, "Execution target");
127
+ requireFields(item, ["adapter", "provider", "modelFamily", "model", "tools"], path);
128
+ text(value.adapter, `${path}/adapter`, "adapter");
129
+ text(value.provider, `${path}/provider`, "provider");
130
+ text(value.modelFamily, `${path}/modelFamily`, "modelFamily");
131
+ text(value.model, `${path}/model`, "model");
132
+ unique(list(value.tools, `${path}/tools`, "tools"), `${path}/tools`, "tool");
133
+ }
134
+ function bound(value, path) {
135
+ const item = record(value, path, "Plan bound");
136
+ requireFields(item, ["kind"], path);
137
+ if (value.kind === "known") {
138
+ requireFields(item, ["value"], path);
139
+ if (!Number.isSafeInteger(value.value) || value.value < 0) {
140
+ fail("INVALID_BOUND", `${path}/value`, "A known bound must be a non-negative safe integer.");
141
+ }
142
+ return;
143
+ }
144
+ if (value.kind === "unknown") {
145
+ requireFields(item, ["reason"], path);
146
+ text(value.reason, `${path}/reason`, "unknown-bound reason");
147
+ return;
148
+ }
149
+ fail("INVALID_BOUND", `${path}/kind`, "Bound kind must be known or unknown.");
150
+ }
151
+ function permission(value, path) {
152
+ const item = record(value, path, "Permission");
153
+ requireFields(item, ["name", "scope"], path);
154
+ text(value.name, `${path}/name`, "permission name");
155
+ json(value.scope, `${path}/scope`);
156
+ }
157
+ function packageIdentity(value, path) {
158
+ const item = record(value, path, "Package identity");
159
+ requireFields(item, ["source", "version", "digest"], path);
160
+ text(value.source, `${path}/source`, "package source");
161
+ text(value.version, `${path}/version`, "package version");
162
+ digest(value.digest, `${path}/digest`);
163
+ }
164
+ function strictTarget(value, path) {
165
+ const item = record(value, path, "Execution target");
166
+ exactFields(item, ["adapter", "provider", "modelFamily", "model", "tools"], path);
167
+ target(item, path);
168
+ }
169
+ function strictPermission(value, path) {
170
+ const item = record(value, path, "Permission");
171
+ exactFields(item, ["name", "scope"], path);
172
+ permission(item, path);
173
+ }
174
+ function strictBound(value, path) {
175
+ const item = record(value, path, "Plan bound");
176
+ bound(item, path);
177
+ exactFields(
178
+ item,
179
+ item.kind === "known" ? ["kind", "value"] : ["kind", "reason"],
180
+ path
181
+ );
182
+ }
183
+ function preflightPolicy(value, laneIds) {
184
+ const root = record(value, "/preflight", "Preflight policy");
185
+ exactFields(root, ["timeoutMs", "lanes"], "/preflight");
186
+ if (!Number.isSafeInteger(root.timeoutMs) || root.timeoutMs < 1 || root.timeoutMs > 2147483647) {
187
+ fail("INVALID_BOUND", "/preflight/timeoutMs", "Preflight timeout must be an integer from 1 to 2147483647 milliseconds.");
188
+ }
189
+ const remaining = new Set(laneIds);
190
+ const lanes = list(root.lanes, "/preflight/lanes", "Preflight lanes");
191
+ for (let index = 0; index < lanes.length; index += 1) {
192
+ const path = `/preflight/lanes/${index}`;
193
+ const lane = record(lanes[index], path, "Preflight lane");
194
+ exactFields(lane, ["laneId", "live", "unsupportedStatic"], path);
195
+ const laneId = identifier(lane.laneId, `${path}/laneId`, "lane id");
196
+ if (!remaining.delete(laneId)) {
197
+ fail("INVALID_LANE_RESOLUTION", `${path}/laneId`, "Preflight lane is unknown or duplicated.");
198
+ }
199
+ if (lane.live !== "required" && lane.live !== "skip") {
200
+ fail("INVALID_SHAPE", `${path}/live`, "Preflight live policy must be required or skip.");
201
+ }
202
+ if (lane.unsupportedStatic !== "block" && lane.unsupportedStatic !== "allow") {
203
+ fail("INVALID_SHAPE", `${path}/unsupportedStatic`, "Unsupported static policy must be block or allow.");
204
+ }
205
+ }
206
+ if (remaining.size !== 0) {
207
+ fail("INVALID_LANE_RESOLUTION", "/preflight/lanes", "Every resolved lane needs one preflight policy.");
208
+ }
209
+ return root;
210
+ }
211
+ function validateResolvedPlan(value) {
212
+ const raw = json(value, "");
213
+ const root = record(raw, "", "Resolved plan");
214
+ exactFields(root, [
215
+ "schemaVersion",
216
+ "graph",
217
+ "package",
218
+ "inputContract",
219
+ "outputContract",
220
+ "phases",
221
+ "nodes",
222
+ "edges",
223
+ "policies",
224
+ "executionLanes",
225
+ "permissions",
226
+ "bounds",
227
+ "requirements",
228
+ ...Object.hasOwn(root, "preflight") ? ["preflight"] : []
229
+ ], "");
230
+ const graph = record(root.graph, "/graph", "Graph metadata");
231
+ exactFields(graph, [
232
+ "id",
233
+ "definitionVersion",
234
+ "kind",
235
+ "typeVersion",
236
+ "definitionDigest"
237
+ ], "/graph");
238
+ const packageValue = record(root.package, "/package", "Package identity");
239
+ exactFields(packageValue, ["source", "version", "digest"], "/package");
240
+ const phases = list(root.phases, "/phases", "Phases");
241
+ phases.forEach((phase, index) => {
242
+ const item = record(phase, `/phases/${index}`, "Phase");
243
+ exactFields(item, ["id", "name", "nodeIds"], `/phases/${index}`);
244
+ });
245
+ const nodes = list(root.nodes, "/nodes", "Nodes");
246
+ nodes.forEach((node, index) => {
247
+ const item = record(node, `/nodes/${index}`, "Node description");
248
+ exactFields(item, [
249
+ "id",
250
+ "phaseId",
251
+ "inputContract",
252
+ "outputContract",
253
+ "laneId"
254
+ ], `/nodes/${index}`);
255
+ });
256
+ const edges = list(root.edges, "/edges", "Edges");
257
+ edges.forEach((edge, index) => {
258
+ const item = record(edge, `/edges/${index}`, "Edge description");
259
+ exactFields(item, ["id", "source", "target"], `/edges/${index}`);
260
+ });
261
+ const policies = record(root.policies, "/policies", "Policies");
262
+ exactFields(policies, [
263
+ "retry",
264
+ "stop",
265
+ "concurrency",
266
+ "write",
267
+ "budget",
268
+ "action"
269
+ ], "/policies");
270
+ const lanes = list(root.executionLanes, "/executionLanes", "Execution lanes");
271
+ lanes.forEach((lane, index) => {
272
+ const path = `/executionLanes/${index}`;
273
+ const item = record(lane, path, "Resolved execution lane");
274
+ exactFields(item, [
275
+ "id",
276
+ "requested",
277
+ "knownSubstitutions",
278
+ "effective",
279
+ "fallbacks"
280
+ ], path);
281
+ strictTarget(item.requested, `${path}/requested`);
282
+ list(
283
+ item.knownSubstitutions,
284
+ `${path}/knownSubstitutions`,
285
+ "Known substitutions"
286
+ ).forEach((targetValue, targetIndex) => {
287
+ strictTarget(
288
+ targetValue,
289
+ `${path}/knownSubstitutions/${targetIndex}`
290
+ );
291
+ });
292
+ strictTarget(item.effective, `${path}/effective`);
293
+ list(item.fallbacks, `${path}/fallbacks`, "Fallbacks").forEach((targetValue, targetIndex) => {
294
+ strictTarget(targetValue, `${path}/fallbacks/${targetIndex}`);
295
+ });
296
+ });
297
+ const permissions = record(root.permissions, "/permissions", "Permissions");
298
+ exactFields(permissions, ["requested", "admitted"], "/permissions");
299
+ list(permissions.requested, "/permissions/requested", "Requested permissions").forEach((item, index) => {
300
+ strictPermission(item, `/permissions/requested/${index}`);
301
+ });
302
+ list(permissions.admitted, "/permissions/admitted", "Admitted permissions").forEach((item, index) => {
303
+ strictPermission(item, `/permissions/admitted/${index}`);
304
+ });
305
+ const bounds = record(root.bounds, "/bounds", "Bounds");
306
+ exactFields(bounds, [
307
+ "dispatches",
308
+ "maxConcurrency",
309
+ "maxFanOut"
310
+ ], "/bounds");
311
+ const dispatches = record(
312
+ bounds.dispatches,
313
+ "/bounds/dispatches",
314
+ "Dispatch bounds"
315
+ );
316
+ exactFields(dispatches, ["min", "max"], "/bounds/dispatches");
317
+ strictBound(dispatches.min, "/bounds/dispatches/min");
318
+ strictBound(dispatches.max, "/bounds/dispatches/max");
319
+ strictBound(bounds.maxConcurrency, "/bounds/maxConcurrency");
320
+ strictBound(bounds.maxFanOut, "/bounds/maxFanOut");
321
+ const requirements = record(root.requirements, "/requirements", "Requirements");
322
+ exactFields(requirements, ["memory"], "/requirements");
323
+ const plan = root;
324
+ const description = validateGraphDescription({
325
+ schemaVersion: plan.schemaVersion,
326
+ graph: plan.graph,
327
+ inputContract: plan.inputContract,
328
+ outputContract: plan.outputContract,
329
+ phases: plan.phases,
330
+ nodes: plan.nodes,
331
+ edges: plan.edges,
332
+ policies: plan.policies,
333
+ executionLanes: plan.executionLanes.map((lane) => ({
334
+ id: lane.id,
335
+ requested: lane.requested,
336
+ knownSubstitutions: lane.knownSubstitutions
337
+ })),
338
+ requestedPermissions: plan.permissions.requested,
339
+ bounds: plan.bounds,
340
+ requirements: plan.requirements
341
+ });
342
+ const rebuilt = resolveGraphPlan(description, {
343
+ package: plan.package,
344
+ admission: {
345
+ package: plan.package,
346
+ permissions: plan.permissions.admitted
347
+ },
348
+ executionLanes: plan.executionLanes.map((lane) => ({
349
+ id: lane.id,
350
+ effective: lane.effective,
351
+ fallbacks: lane.fallbacks
352
+ })),
353
+ ...Object.hasOwn(root, "preflight") ? { preflight: plan.preflight } : {}
354
+ }).plan;
355
+ if (!isDeepStrictEqual(plan, rebuilt)) {
356
+ fail(
357
+ "RESOLVED_PLAN_MISMATCH",
358
+ "",
359
+ "Resolved plan does not match its graph description and host resolution."
360
+ );
361
+ }
362
+ return rebuilt;
363
+ }
364
+ function validateGraphDescription(value) {
365
+ const raw = json(value, "");
366
+ const root = record(raw, "", "Graph description");
367
+ requireFields(root, [
368
+ "schemaVersion",
369
+ "graph",
370
+ "inputContract",
371
+ "outputContract",
372
+ "phases",
373
+ "nodes",
374
+ "edges",
375
+ "policies",
376
+ "executionLanes",
377
+ "requestedPermissions",
378
+ "bounds",
379
+ "requirements"
380
+ ], "");
381
+ const graph = record(root.graph, "/graph", "Graph metadata");
382
+ requireFields(graph, [
383
+ "id",
384
+ "definitionVersion",
385
+ "kind",
386
+ "typeVersion",
387
+ "definitionDigest"
388
+ ], "/graph");
389
+ const phaseValues = list(root.phases, "/phases", "Phases");
390
+ const nodeValues = list(root.nodes, "/nodes", "Nodes");
391
+ const edgeValues = list(root.edges, "/edges", "Edges");
392
+ const laneValues = list(root.executionLanes, "/executionLanes", "Execution lanes");
393
+ const permissionValues = list(
394
+ root.requestedPermissions,
395
+ "/requestedPermissions",
396
+ "Requested permissions"
397
+ );
398
+ const policies = record(root.policies, "/policies", "Policies");
399
+ requireFields(policies, [
400
+ "retry",
401
+ "stop",
402
+ "concurrency",
403
+ "write",
404
+ "budget",
405
+ "action"
406
+ ], "/policies");
407
+ const bounds = record(root.bounds, "/bounds", "Bounds");
408
+ requireFields(bounds, [
409
+ "dispatches",
410
+ "maxConcurrency",
411
+ "maxFanOut"
412
+ ], "/bounds");
413
+ const dispatchBounds = record(bounds.dispatches, "/bounds/dispatches", "Dispatch bounds");
414
+ requireFields(dispatchBounds, ["min", "max"], "/bounds/dispatches");
415
+ const requirements = record(root.requirements, "/requirements", "Requirements");
416
+ requireFields(requirements, ["memory"], "/requirements");
417
+ phaseValues.forEach((phase, index) => {
418
+ const item = record(phase, `/phases/${index}`, "Phase");
419
+ requireFields(item, ["id", "name", "nodeIds"], `/phases/${index}`);
420
+ list(item.nodeIds, `/phases/${index}/nodeIds`, "Phase nodeIds");
421
+ });
422
+ nodeValues.forEach((node, index) => {
423
+ const item = record(node, `/nodes/${index}`, "Node description");
424
+ requireFields(item, [
425
+ "id",
426
+ "phaseId",
427
+ "inputContract",
428
+ "outputContract",
429
+ "laneId"
430
+ ], `/nodes/${index}`);
431
+ });
432
+ edgeValues.forEach((edge, index) => {
433
+ const item = record(edge, `/edges/${index}`, "Edge description");
434
+ requireFields(item, ["id", "source", "target"], `/edges/${index}`);
435
+ });
436
+ laneValues.forEach((lane, index) => {
437
+ const item = record(lane, `/executionLanes/${index}`, "Execution lane");
438
+ requireFields(item, [
439
+ "id",
440
+ "requested",
441
+ "knownSubstitutions"
442
+ ], `/executionLanes/${index}`);
443
+ list(
444
+ item.knownSubstitutions,
445
+ `/executionLanes/${index}/knownSubstitutions`,
446
+ "Known substitutions"
447
+ );
448
+ });
449
+ permissionValues.forEach((item, index) => {
450
+ record(item, `/requestedPermissions/${index}`, "Permission");
451
+ });
452
+ const description = root;
453
+ if (description.schemaVersion !== 1) {
454
+ fail("INVALID_SCHEMA_VERSION", "/schemaVersion", "Graph description schemaVersion must be 1.");
455
+ }
456
+ identifier(description.graph.id, "/graph/id", "graph id");
457
+ positiveVersion(description.graph.definitionVersion, "/graph/definitionVersion");
458
+ text(description.graph.kind, "/graph/kind", "graph kind");
459
+ positiveVersion(description.graph.typeVersion, "/graph/typeVersion");
460
+ digest(description.graph.definitionDigest, "/graph/definitionDigest");
461
+ description.phases.forEach((phase, index) => {
462
+ identifier(phase.id, `/phases/${index}/id`, "phase id");
463
+ });
464
+ description.nodes.forEach((node, index) => {
465
+ identifier(node.id, `/nodes/${index}/id`, "node id");
466
+ });
467
+ description.edges.forEach((edge, index) => {
468
+ identifier(edge.id, `/edges/${index}/id`, "edge id");
469
+ });
470
+ description.executionLanes.forEach((lane, index) => {
471
+ identifier(lane.id, `/executionLanes/${index}/id`, "lane id");
472
+ });
473
+ description.phases.forEach((phase, phaseIndex) => {
474
+ phase.nodeIds.forEach((nodeId, nodeIndex) => {
475
+ identifier(nodeId, `/phases/${phaseIndex}/nodeIds/${nodeIndex}`, "node id");
476
+ });
477
+ });
478
+ description.nodes.forEach((node, index) => {
479
+ identifier(node.phaseId, `/nodes/${index}/phaseId`, "phase id");
480
+ if (node.laneId !== null) {
481
+ identifier(node.laneId, `/nodes/${index}/laneId`, "lane id");
482
+ }
483
+ });
484
+ description.edges.forEach((edge, index) => {
485
+ identifier(edge.source, `/edges/${index}/source`, "node id");
486
+ identifier(edge.target, `/edges/${index}/target`, "node id");
487
+ });
488
+ unique(description.phases.map((phase) => phase.id), "/phases", "phase id");
489
+ unique(description.nodes.map((node) => node.id), "/nodes", "node id");
490
+ unique(description.edges.map((edge) => edge.id), "/edges", "edge id");
491
+ unique(description.executionLanes.map((lane) => lane.id), "/executionLanes", "lane id");
492
+ unique(description.requestedPermissions.map((item) => item.name), "/requestedPermissions", "permission name");
493
+ const phaseIds = new Set(description.phases.map((phase) => phase.id));
494
+ const nodeIds = new Set(description.nodes.map((node) => node.id));
495
+ const laneIds = new Set(description.executionLanes.map((lane) => lane.id));
496
+ const assignedNodes = [];
497
+ const assignedPhaseByNode = /* @__PURE__ */ new Map();
498
+ for (let index = 0; index < description.phases.length; index += 1) {
499
+ const phase = description.phases[index];
500
+ text(phase.name, `/phases/${index}/name`, "phase name");
501
+ unique(phase.nodeIds, `/phases/${index}/nodeIds`, "node id");
502
+ for (const nodeId of phase.nodeIds) {
503
+ if (!nodeIds.has(nodeId)) {
504
+ fail("UNKNOWN_NODE", `/phases/${index}/nodeIds`, `Phase refers to unknown node "${nodeId}".`);
505
+ }
506
+ assignedNodes.push(nodeId);
507
+ assignedPhaseByNode.set(nodeId, phase.id);
508
+ }
509
+ }
510
+ if (assignedNodes.length !== nodeIds.size || new Set(assignedNodes).size !== nodeIds.size) {
511
+ fail("INVALID_PHASE_ASSIGNMENT", "/phases", "Every node must appear in exactly one phase.");
512
+ }
513
+ for (let index = 0; index < description.nodes.length; index += 1) {
514
+ const node = description.nodes[index];
515
+ if (!phaseIds.has(node.phaseId)) {
516
+ fail("UNKNOWN_PHASE", `/nodes/${index}/phaseId`, `Node refers to unknown phase "${node.phaseId}".`);
517
+ }
518
+ if (assignedPhaseByNode.get(node.id) !== node.phaseId) {
519
+ fail(
520
+ "INVALID_PHASE_ASSIGNMENT",
521
+ `/nodes/${index}/phaseId`,
522
+ `Node "${node.id}" claims phase "${node.phaseId}" but is listed in phase "${assignedPhaseByNode.get(node.id)}".`
523
+ );
524
+ }
525
+ if (node.laneId !== null && !laneIds.has(node.laneId)) {
526
+ fail("UNKNOWN_LANE", `/nodes/${index}/laneId`, `Node refers to unknown lane "${node.laneId}".`);
527
+ }
528
+ }
529
+ for (let index = 0; index < description.edges.length; index += 1) {
530
+ const edge = description.edges[index];
531
+ if (!nodeIds.has(edge.source) || !nodeIds.has(edge.target)) {
532
+ fail("UNKNOWN_NODE", `/edges/${index}`, "Edge refers to an unknown node.");
533
+ }
534
+ }
535
+ for (let index = 0; index < description.executionLanes.length; index += 1) {
536
+ const lane = description.executionLanes[index];
537
+ target(lane.requested, `/executionLanes/${index}/requested`);
538
+ const substitutions = /* @__PURE__ */ new Set();
539
+ for (let item = 0; item < lane.knownSubstitutions.length; item += 1) {
540
+ const substitution = lane.knownSubstitutions[item];
541
+ target(substitution, `/executionLanes/${index}/knownSubstitutions/${item}`);
542
+ const key = canonicalJson(substitution);
543
+ if (substitutions.has(key)) {
544
+ fail("DUPLICATE_SUBSTITUTION", `/executionLanes/${index}/knownSubstitutions/${item}`, "Execution substitution is duplicated.");
545
+ }
546
+ substitutions.add(key);
547
+ }
548
+ }
549
+ for (let index = 0; index < description.requestedPermissions.length; index += 1) {
550
+ permission(description.requestedPermissions[index], `/requestedPermissions/${index}`);
551
+ }
552
+ bound(description.bounds.dispatches.min, "/bounds/dispatches/min");
553
+ bound(description.bounds.dispatches.max, "/bounds/dispatches/max");
554
+ bound(description.bounds.maxConcurrency, "/bounds/maxConcurrency");
555
+ bound(description.bounds.maxFanOut, "/bounds/maxFanOut");
556
+ const min = description.bounds.dispatches.min;
557
+ const max = description.bounds.dispatches.max;
558
+ if (min.kind === "known" && max.kind === "known" && min.value > max.value) {
559
+ fail("INVALID_BOUND", "/bounds/dispatches", "Minimum dispatches cannot exceed maximum dispatches.");
560
+ }
561
+ if (description.requirements.memory !== "required" && description.requirements.memory !== "unused") {
562
+ fail("INVALID_REQUIREMENT", "/requirements/memory", "Memory must be required or unused.");
563
+ }
564
+ return description;
565
+ }
566
+ function resolveGraphPlan(value, input) {
567
+ const description = validateGraphDescription(value);
568
+ const raw = json(input, "");
569
+ const root = record(raw, "", "Plan resolution");
570
+ requireFields(root, ["package", "admission", "executionLanes"], "");
571
+ const admission = record(root.admission, "/admission", "Package admission");
572
+ requireFields(admission, ["package", "permissions"], "/admission");
573
+ list(admission.permissions, "/admission/permissions", "Admitted permissions").forEach((item, index) => {
574
+ record(item, `/admission/permissions/${index}`, "Permission");
575
+ });
576
+ list(root.executionLanes, "/executionLanes", "Lane resolutions").forEach((item, index) => {
577
+ const lane = record(item, `/executionLanes/${index}`, "Lane resolution");
578
+ requireFields(lane, ["id", "effective"], `/executionLanes/${index}`);
579
+ list(
580
+ lane.fallbacks ?? [],
581
+ `/executionLanes/${index}/fallbacks`,
582
+ "Fallbacks"
583
+ );
584
+ });
585
+ const resolution = root;
586
+ packageIdentity(resolution.package, "/package");
587
+ packageIdentity(resolution.admission.package, "/admission/package");
588
+ if (!isDeepStrictEqual(resolution.package, resolution.admission.package)) {
589
+ fail("PACKAGE_NOT_ADMITTED", "/admission/package", "Host admission does not match the requested package.");
590
+ }
591
+ unique(resolution.executionLanes.map((lane) => lane.id), "/executionLanes", "lane resolution id");
592
+ const resolutions = new Map(resolution.executionLanes.map((lane) => [lane.id, lane]));
593
+ if (resolutions.size !== description.executionLanes.length) {
594
+ fail("INVALID_LANE_RESOLUTION", "/executionLanes", "Every described lane needs exactly one resolution.");
595
+ }
596
+ const resolvedLanes = [];
597
+ for (let index = 0; index < description.executionLanes.length; index += 1) {
598
+ const lane = description.executionLanes[index];
599
+ const resolved = resolutions.get(lane.id);
600
+ if (!resolved) {
601
+ fail("INVALID_LANE_RESOLUTION", "/executionLanes", `Lane "${lane.id}" has no resolution.`);
602
+ }
603
+ target(resolved.effective, `/executionLanes/${index}/effective`);
604
+ const allowed = [lane.requested, ...lane.knownSubstitutions];
605
+ if (!allowed.some((candidate) => isDeepStrictEqual(candidate, resolved.effective))) {
606
+ fail("UNKNOWN_SUBSTITUTION", `/executionLanes/${index}/effective`, `Lane "${lane.id}" uses an undeclared substitution.`);
607
+ }
608
+ const fallbacks = resolved.fallbacks ?? [];
609
+ const fallbackKeys = /* @__PURE__ */ new Set();
610
+ for (let fallbackIndex = 0; fallbackIndex < fallbacks.length; fallbackIndex += 1) {
611
+ const fallback = fallbacks[fallbackIndex];
612
+ const path = `/executionLanes/${index}/fallbacks/${fallbackIndex}`;
613
+ target(fallback, path);
614
+ if (!allowed.some((candidate) => isDeepStrictEqual(candidate, fallback))) {
615
+ fail("UNKNOWN_SUBSTITUTION", path, `Lane "${lane.id}" uses an undeclared fallback.`);
616
+ }
617
+ if (isDeepStrictEqual(fallback, resolved.effective)) {
618
+ fail("DUPLICATE_SUBSTITUTION", path, "A fallback cannot repeat the effective target.");
619
+ }
620
+ const key = canonicalJson(fallback);
621
+ if (fallbackKeys.has(key)) {
622
+ fail("DUPLICATE_SUBSTITUTION", path, "Execution fallback is duplicated.");
623
+ }
624
+ fallbackKeys.add(key);
625
+ }
626
+ resolvedLanes.push({
627
+ ...lane,
628
+ effective: resolved.effective,
629
+ fallbacks
630
+ });
631
+ resolutions.delete(lane.id);
632
+ }
633
+ if (resolutions.size > 0) {
634
+ fail("INVALID_LANE_RESOLUTION", "/executionLanes", "Resolution contains an unknown lane.");
635
+ }
636
+ const preflight = Object.hasOwn(root, "preflight") ? preflightPolicy(root.preflight, resolvedLanes.map((lane) => lane.id)) : void 0;
637
+ const admittedByName = /* @__PURE__ */ new Map();
638
+ for (let index = 0; index < resolution.admission.permissions.length; index += 1) {
639
+ const item = resolution.admission.permissions[index];
640
+ permission(item, `/admission/permissions/${index}`);
641
+ if (admittedByName.has(item.name)) {
642
+ fail("DUPLICATE_PERMISSION", `/admission/permissions/${index}`, `Permission "${item.name}" is duplicated.`);
643
+ }
644
+ admittedByName.set(item.name, item);
645
+ }
646
+ for (let index = 0; index < description.requestedPermissions.length; index += 1) {
647
+ const requested = description.requestedPermissions[index];
648
+ const admitted = admittedByName.get(requested.name);
649
+ if (!admitted || canonicalJson(admitted.scope) !== canonicalJson(requested.scope)) {
650
+ fail("PERMISSION_NOT_ADMITTED", `/requestedPermissions/${index}`, `Permission "${requested.name}" is outside host admission.`);
651
+ }
652
+ }
653
+ const plan = cloneFrozenJson({
654
+ schemaVersion: 1,
655
+ graph: description.graph,
656
+ package: resolution.package,
657
+ inputContract: description.inputContract,
658
+ outputContract: description.outputContract,
659
+ phases: description.phases,
660
+ nodes: description.nodes,
661
+ edges: description.edges,
662
+ policies: description.policies,
663
+ executionLanes: resolvedLanes,
664
+ ...preflight === void 0 ? {} : { preflight },
665
+ permissions: {
666
+ requested: description.requestedPermissions,
667
+ admitted: resolution.admission.permissions
668
+ },
669
+ bounds: description.bounds,
670
+ requirements: description.requirements
671
+ });
672
+ const canonical = canonicalJson(plan);
673
+ return Object.freeze({
674
+ plan,
675
+ canonicalJson: canonical,
676
+ digest: digestJson(plan)
677
+ });
678
+ }
679
+
680
+ // src/events/store.ts
681
+ function fail2(message, path) {
682
+ throw new StorageError("INVALID_STORED_VALUE", message, { path });
683
+ }
684
+ function validateEventStreamRef(value) {
685
+ let safe;
686
+ try {
687
+ safe = cloneFrozenJson(value);
688
+ } catch (error) {
689
+ if (!(error instanceof JsonValueError)) throw error;
690
+ fail2(error.message, error.path);
691
+ }
692
+ if (safe === null || typeof safe !== "object" || Array.isArray(safe)) {
693
+ fail2("Event stream reference must be an object.", "");
694
+ }
695
+ const record2 = safe;
696
+ const fields = Object.keys(record2).sort();
697
+ if (fields.length !== 2 || fields[0] !== "namespace" || fields[1] !== "streamId") {
698
+ fail2(
699
+ "Event stream reference must contain exactly namespace and streamId.",
700
+ ""
701
+ );
702
+ }
703
+ validateStorageId(record2.namespace, "/namespace");
704
+ validateStorageId(record2.streamId, "/streamId");
705
+ return record2;
706
+ }
707
+ function validateStreamRevision(value, path) {
708
+ if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 0) {
709
+ fail2("Stream revision must be a non-negative safe integer.", path);
710
+ }
711
+ return value;
712
+ }
713
+ function validateDomainEventBatch(value) {
714
+ let safe;
715
+ try {
716
+ safe = cloneFrozenJson(value);
717
+ } catch (error) {
718
+ if (!(error instanceof JsonValueError)) throw error;
719
+ fail2(error.message, `/events${error.path}`);
720
+ }
721
+ if (!Array.isArray(safe) || safe.length === 0) {
722
+ fail2("An append batch must contain at least one event.", "/events");
723
+ }
724
+ const events = safe.map((event) => validateNewDomainEvent(event));
725
+ return Object.freeze(events);
726
+ }
727
+ function jsonContains(value, needle) {
728
+ if (typeof value === "string") return value.includes(needle);
729
+ if (value === null || typeof value !== "object") return false;
730
+ if (Array.isArray(value)) {
731
+ return value.some((item) => jsonContains(item, needle));
732
+ }
733
+ return Object.entries(value).some(([key, item]) => key.includes(needle) || jsonContains(item, needle));
734
+ }
735
+ function findKnownSecretInEvents(knownSecrets, serializedBytes, events) {
736
+ return knownSecrets.find((secret) => serializedBytes.includes(secret) || events.some((event) => jsonContains(event, secret)));
737
+ }
738
+
739
+ // src/callback/client-contract.ts
740
+ var CALLBACK_DIGEST = /^[0-9a-f]{64}$/u;
741
+ function callbackObject(value) {
742
+ const stored = cloneFrozenJson(value);
743
+ if (stored === null || typeof stored !== "object" || Array.isArray(stored)) {
744
+ throw new TypeError("a stored callback event must be an object");
745
+ }
746
+ return stored;
747
+ }
748
+ function exactFields2(value, fields) {
749
+ const actual = Object.keys(value).sort();
750
+ const expected = [...fields].sort();
751
+ if (actual.length !== expected.length || actual.some((field, index) => field !== expected[index])) {
752
+ throw new TypeError("a stored callback event has missing or unknown fields");
753
+ }
754
+ }
755
+ function callbackText(value, field) {
756
+ if (typeof value !== "string" || value.length === 0) {
757
+ throw new TypeError(`a stored callback event needs ${field}`);
758
+ }
759
+ return value;
760
+ }
761
+ function validateCallbackEvent(value) {
762
+ const event = callbackObject(value);
763
+ switch (event.kind) {
764
+ case "callback-requested":
765
+ exactFields2(event, ["kind", "request"]);
766
+ validateCallbackRequest(event.request);
767
+ break;
768
+ case "callback-claimed":
769
+ exactFields2(event, ["kind", "requestId", "routerId", "claimToken"]);
770
+ callbackText(event.requestId, "requestId");
771
+ callbackText(event.routerId, "routerId");
772
+ callbackText(event.claimToken, "claimToken");
773
+ break;
774
+ case "callback-released":
775
+ exactFields2(event, ["kind", "requestId", "routerId"]);
776
+ callbackText(event.requestId, "requestId");
777
+ callbackText(event.routerId, "routerId");
778
+ break;
779
+ case "callback-submitted":
780
+ if (typeof event.requestDigest !== "string" || !CALLBACK_DIGEST.test(event.requestDigest)) {
781
+ throw new TypeError("a stored callback submission has an invalid requestDigest");
782
+ }
783
+ exactFields2(event, ["kind", "requestId", "requestDigest", "routerId", "response"]);
784
+ callbackText(event.requestId, "requestId");
785
+ callbackText(event.routerId, "routerId");
786
+ break;
787
+ case "callback-rejected":
788
+ exactFields2(event, ["kind", "requestId", "routerId", "reason"]);
789
+ callbackText(event.requestId, "requestId");
790
+ callbackText(event.routerId, "routerId");
791
+ callbackText(event.reason, "reason");
792
+ break;
793
+ case "callback-superseded":
794
+ exactFields2(event, ["kind", "requestId", "supersededBy"]);
795
+ callbackText(event.requestId, "requestId");
796
+ callbackText(event.supersededBy, "supersededBy");
797
+ break;
798
+ default:
799
+ throw new TypeError("a stored callback event has an unknown kind");
800
+ }
801
+ return event;
802
+ }
803
+
804
+ export { CLAUDE_SUBAGENT_TOOLS, GraphExecutionError, MEMORY_ROOT, SUBAGENT_TOOLS, assertReadAccess, findKnownSecretInEvents, isEngine, resolveGraphPlan, validateCallbackEvent, validateDomainEventBatch, validateEventStreamRef, validateGraphDescription, validateResolvedPlan, validateStreamRevision };
805
+ //# sourceMappingURL=index.js.map
806
+ //# sourceMappingURL=index.js.map