@deepstrike/sdk 0.2.71 → 0.2.72

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 (77) hide show
  1. package/README.md +27 -3
  2. package/dist/advanced/public.d.ts +4 -0
  3. package/dist/advanced/public.js +2 -0
  4. package/dist/agent-facade.d.ts +19 -6
  5. package/dist/agent-facade.js +118 -20
  6. package/dist/agent-ir.d.ts +11 -5
  7. package/dist/agent-ir.js +42 -26
  8. package/dist/canonical-prefix-allowlist.d.ts +6 -0
  9. package/dist/canonical-prefix-allowlist.js +30 -0
  10. package/dist/evals/public.d.ts +50 -0
  11. package/dist/evals/public.js +25 -0
  12. package/dist/guardrail.d.ts +4 -1
  13. package/dist/handoff-target.d.ts +2 -0
  14. package/dist/handoff-target.js +7 -1
  15. package/dist/index.d.ts +10 -16
  16. package/dist/index.js +5 -7
  17. package/dist/kernel.d.ts +2 -2
  18. package/dist/knowledge/public.d.ts +2 -0
  19. package/dist/knowledge/public.js +1 -1
  20. package/dist/knowledge/source.d.ts +7 -0
  21. package/dist/knowledge/source.js +20 -1
  22. package/dist/memory/protocols.d.ts +2 -2
  23. package/dist/projection-pairs.d.ts +43 -0
  24. package/dist/projection-pairs.js +9 -0
  25. package/dist/providers/anthropic-adapter.d.ts +2 -2
  26. package/dist/providers/anthropic.d.ts +4 -4
  27. package/dist/providers/base.d.ts +5 -5
  28. package/dist/providers/content-normalization.d.ts +4 -4
  29. package/dist/providers/gemini-adapter.d.ts +2 -2
  30. package/dist/providers/gemini.d.ts +3 -3
  31. package/dist/providers/ollama-adapter.d.ts +2 -2
  32. package/dist/providers/ollama.d.ts +2 -2
  33. package/dist/providers/openai-chat.d.ts +4 -4
  34. package/dist/providers/openai-responses-adapter.d.ts +2 -2
  35. package/dist/providers/openai-responses.d.ts +2 -2
  36. package/dist/providers/openai.d.ts +4 -4
  37. package/dist/providers/protocol-adapter.d.ts +2 -2
  38. package/dist/providers/protocol-capabilities.d.ts +1 -0
  39. package/dist/providers/protocol-capabilities.js +3 -0
  40. package/dist/providers/public.d.ts +4 -2
  41. package/dist/providers/public.js +2 -1
  42. package/dist/providers/replay-validator.d.ts +3 -3
  43. package/dist/runtime/archive.d.ts +7 -7
  44. package/dist/runtime/canonical-kernel-step.d.ts +2 -2
  45. package/dist/runtime/context-manager.d.ts +56 -0
  46. package/dist/runtime/context-manager.js +112 -0
  47. package/dist/runtime/eval.d.ts +2 -2
  48. package/dist/runtime/kernel-step.d.ts +5 -5
  49. package/dist/runtime/provider-replay.d.ts +2 -2
  50. package/dist/runtime/public.d.ts +22 -0
  51. package/dist/runtime/public.js +11 -0
  52. package/dist/runtime/replay-fixture.d.ts +3 -3
  53. package/dist/runtime/replay-fixture.js +1 -1
  54. package/dist/runtime/replay-provider.d.ts +4 -4
  55. package/dist/runtime/replay-provider.js +1 -1
  56. package/dist/runtime/runner.d.ts +17 -5
  57. package/dist/runtime/runner.js +110 -37
  58. package/dist/runtime/session-log.d.ts +1 -1
  59. package/dist/runtime/session-repair.d.ts +2 -2
  60. package/dist/runtime/workflow-control-flow.d.ts +1 -1
  61. package/dist/runtime/workflow-control-flow.js +16 -2
  62. package/dist/runtime-classification.d.ts +161 -0
  63. package/dist/runtime-classification.js +66 -0
  64. package/dist/runtime-language.d.ts +32 -0
  65. package/dist/runtime-language.js +51 -0
  66. package/dist/skill.d.ts +31 -5
  67. package/dist/types/agent.d.ts +17 -4
  68. package/dist/types.d.ts +22 -12
  69. package/dist/workflow/definition.d.ts +19 -0
  70. package/dist/workflow/definition.js +29 -0
  71. package/dist/workflow/public.d.ts +3 -1
  72. package/dist/workflow/public.js +1 -0
  73. package/package.json +16 -2
  74. package/dist/compat/anthropic/mcp.d.ts +0 -15
  75. package/dist/compat/anthropic/mcp.js +0 -10
  76. package/dist/compat/openai/agent.d.ts +0 -34
  77. package/dist/compat/openai/agent.js +0 -24
@@ -11,6 +11,23 @@ import { buildLlmCompletedEvent, buildRunTerminalEvent, buildWorkflowNodeComplet
11
11
  import { KernelPrimitivesDashboard } from "./kernel-primitives-dashboard.js";
12
12
  import { capabilityMarker, capabilitySkill, capabilityTool, capabilityCommandMount, capabilityCommandUnmount, archivePresentationFromObservations, entropySampleFromObservation, messageToKernelMessage, skillMetadataToKernel, taskUpdateToKernel, toolResultToKernel, toolSchemaToKernel, } from "./kernel-step.js";
13
13
  import { CanonicalKernelRejectedError, CanonicalRunnerRuntime, canonicalKernelAction, canonicalKernelApply, canonicalKernelMaybeAction, canonicalStartAgent, canonicalStartWorkflow, } from "./canonical-kernel-step.js";
14
+ function intersectCapabilityFilters(a, b) {
15
+ if (!a && !b)
16
+ return undefined;
17
+ const intersect = (left, right) => {
18
+ if (!left?.length)
19
+ return right?.length ? [...right] : undefined;
20
+ if (!right?.length)
21
+ return [...left];
22
+ return left.filter(value => right.includes(value));
23
+ };
24
+ const allowedKinds = intersect(a?.allowedKinds, b?.allowedKinds);
25
+ const allowedIds = intersect(a?.allowedIds, b?.allowedIds);
26
+ return {
27
+ ...(allowedKinds?.length ? { allowedKinds } : allowedKinds ? { allowedKinds: [] } : {}),
28
+ ...(allowedIds?.length ? { allowedIds } : allowedIds ? { allowedIds: [] } : {}),
29
+ };
30
+ }
14
31
  export function stableSemanticArchiveName(effectId) {
15
32
  const stableEffectId = effectId.replace(/[^a-zA-Z0-9._:-]/g, "_");
16
33
  return `page-out-${stableEffectId || "unknown"}`;
@@ -153,6 +170,8 @@ export class RuntimeRunner {
153
170
  * run — guards against re-pushing a duplicate entry if the model calls `skill(name)` again for
154
171
  * an already-active skill (loading is idempotent; the knowledge push should be too). */
155
172
  knowledgePushedSkills = new Set();
173
+ /** Host mirror of kernel skill lease expiry, used only to clear ContextManager overlays. */
174
+ skillLeaseExpirations = new Map();
156
175
  nextArchiveStart = 0;
157
176
  pendingPageOutArchives = [];
158
177
  activePageOutArchive;
@@ -273,7 +292,7 @@ export class RuntimeRunner {
273
292
  * agent syscall: the host selects records from its store, then the kernel owns the write
274
293
  * of live semantic context. `seenRecordIds` is the prefetch's dedupe horizon.
275
294
  */
276
- async prefetchMemoryIntoKnowledge(runtime, query, agentId, sessionId, seenRecordIds, leftovers) {
295
+ async prefetchMemoryIntoKnowledge(runtime, query, agentId, sessionId, seenRecordIds) {
277
296
  let hits = [];
278
297
  try {
279
298
  hits = await this.retrieveMemoryFromStore(query, query.top_k, agentId);
@@ -287,12 +306,10 @@ export class RuntimeRunner {
287
306
  });
288
307
  }
289
308
  for (const hit of hits) {
290
- await this.commitKernelApply(runtime, leftovers ?? [], {
291
- kind: "add_knowledge_message",
292
- key: `memory:${hit.record.record_id}`,
293
- content: hit.record.content,
294
- tokens: Math.max(1, Math.ceil(hit.record.content.length / 4)),
295
- }, sessionId);
309
+ // Route renewal recalls through the same host context admission path as every other
310
+ // dynamic knowledge entry. This keeps ContextManager budgets and ledger events in sync
311
+ // while preserving the canonical kernel knowledge command underneath.
312
+ await this.pushKnowledge({ role: "system", content: hit.record.content, toolCalls: [] }, Math.max(1, Math.ceil(hit.record.content.length / 4)), { key: `memory:${hit.record.record_id}` });
296
313
  }
297
314
  await this.applyHostMemoryRecallLifecycle(hits, agentId);
298
315
  await this.logMemoryRetrievalResult(sessionId, hits);
@@ -598,10 +615,27 @@ export class RuntimeRunner {
598
615
  async pushKnowledge(message, tokens, opts) {
599
616
  if (!this.activeKernel)
600
617
  return;
618
+ const content = message.content ?? "";
619
+ const itemId = opts?.key ?? `context:${createHash("sha256").update(content).digest("hex").slice(0, 16)}`;
620
+ if (this.opts.contextManager) {
621
+ this.opts.contextManager.upsert({
622
+ id: itemId,
623
+ kind: opts?.key?.startsWith("skill:") ? "skill" : opts?.key?.startsWith("memory:") ? "memory" : "knowledge",
624
+ content,
625
+ scope: opts?.key?.startsWith("skill:") ? "session" : "turn",
626
+ priority: opts?.pinned ? 100 : 50,
627
+ pinned: opts?.pinned,
628
+ source: { type: opts?.key?.split(":", 1)[0] ?? "context", ...(opts?.key ? { id: opts.key } : {}) },
629
+ });
630
+ if (!this.opts.contextManager.select().some(item => item.id === itemId)) {
631
+ this.opts.contextManager.remove(itemId);
632
+ return;
633
+ }
634
+ }
601
635
  await this.commitKernelApply(this.activeKernel, this.pendingObservations, {
602
636
  kind: "add_knowledge_message",
603
- content: message.content ?? "",
604
- tokens: tokens ?? Math.max(1, Math.ceil((message.content?.length ?? 0) / 4)),
637
+ content,
638
+ tokens: tokens ?? Math.max(1, Math.ceil(content.length / 4)),
605
639
  ...(opts?.key !== undefined ? { key: opts.key } : {}),
606
640
  ...(opts?.pinned ? { pinned: true } : {}),
607
641
  });
@@ -609,6 +643,7 @@ export class RuntimeRunner {
609
643
  /** K1: mark a keyed knowledge entry for removal at the next compaction/renewal boundary.
610
644
  * Errs-open: an unknown key is a kernel-side no-op. */
611
645
  async removeKnowledge(key) {
646
+ this.opts.contextManager?.remove(key);
612
647
  if (!this.activeKernel)
613
648
  return;
614
649
  await this.commitKernelApply(this.activeKernel, this.pendingObservations, { kind: "remove_knowledge", key });
@@ -618,11 +653,24 @@ export class RuntimeRunner {
618
653
  * drops at the next compaction/renewal boundary. A later `skill(name)` call re-activates and
619
654
  * re-pins fresh content. Errs-open: not-active is a kernel-side no-op. */
620
655
  async deactivateSkill(name) {
621
- if (!this.activeKernel)
622
- return;
623
- await this.commitKernelApply(this.activeKernel, this.pendingObservations, { kind: "skill_deactivated", name });
656
+ if (this.activeKernel) {
657
+ await this.commitKernelApply(this.activeKernel, this.pendingObservations, { kind: "skill_deactivated", name });
658
+ }
624
659
  // Re-arm the SDK-side push guard so a re-activation re-pins the content.
625
660
  this.knowledgePushedSkills.delete(name);
661
+ this.skillLeaseExpirations.delete(name);
662
+ this.opts.contextManager?.remove(`skill:${name}`);
663
+ }
664
+ expireSkillContext(currentTurn) {
665
+ if (this.opts.skillLeaseTurns === undefined)
666
+ return;
667
+ for (const [name, expiresAtTurn] of this.skillLeaseExpirations) {
668
+ if (currentTurn < expiresAtTurn)
669
+ continue;
670
+ this.skillLeaseExpirations.delete(name);
671
+ this.knowledgePushedSkills.delete(name);
672
+ this.opts.contextManager?.remove(`skill:${name}`);
673
+ }
626
674
  }
627
675
  /**
628
676
  * G3: run one workflow node, enforcing its `output_schema` (if any). Without a schema this is a
@@ -632,7 +680,7 @@ export class RuntimeRunner {
632
680
  * validation reason — a node that cannot meet its declared output contract starves its dependents,
633
681
  * exactly as a denied spawn does.
634
682
  */
635
- async runWorkflowNode(node, parentSessionId, orchestrator, budget, outputs, abortSignal) {
683
+ async runWorkflowNode(node, parentSessionId, orchestrator, budget, outputs, abortSignal, contextPolicies) {
636
684
  // G2: a reduce node runs no LLM — execute the registered pure function over its dependency
637
685
  // outputs and feed the result back as an ordinary completion. Deterministic; no agent burned.
638
686
  if (node.reducer) {
@@ -645,7 +693,11 @@ export class RuntimeRunner {
645
693
  const budgetNote = workflowBudgetNote(budget);
646
694
  // W-N2: a DAG edge carries data — every dependent node sees its dependencies' outputs (the
647
695
  // kernel sends `input_agent_ids` for all dependents; judges/reduce keep their special paths).
648
- const depsNote = dependencyOutputsNote(node.input_agent_ids, outputs);
696
+ const policy = contextPolicies?.get(node.agent_id) ?? contextPolicies?.get(node.agent_id.replace(/-i\d+$/, ""));
697
+ const include = policy?.include ?? ["dependency_outputs"];
698
+ const depsNote = include.includes("dependency_outputs")
699
+ ? dependencyOutputsNote(node.input_agent_ids, outputs, policy?.maxTokens !== undefined ? Math.max(256, policy.maxTokens * 4) : 8_000, policy?.dependencyMode ?? "full")
700
+ : "";
649
701
  const withBudget = (goal) => [goal, depsNote, budgetNote].filter(Boolean).join("\n\n");
650
702
  const mkCtx = (goal) => ({
651
703
  parentOpts: this.opts,
@@ -806,7 +858,7 @@ export class RuntimeRunner {
806
858
  };
807
859
  }
808
860
  const observations = this.pendingObservations.slice(observationStart);
809
- const outcome = await this.driveWorkflow(initialAction, observations, parentSessionId, runtime, new Map());
861
+ const outcome = await this.driveWorkflow(initialAction, observations, parentSessionId, runtime, new Map(), new Map(spec.nodes.flatMap((node, index) => node.context ? [[`wf-node${index}`, node.context]] : [])));
810
862
  if (bootstrapped) {
811
863
  let terminal = runtime.resumeAction();
812
864
  if (!terminal)
@@ -861,6 +913,8 @@ export class RuntimeRunner {
861
913
  this.pendingObservations = [];
862
914
  this.pendingPageOutArchives = [];
863
915
  this.activePageOutArchive = undefined;
916
+ this.knowledgePushedSkills.clear();
917
+ this.skillLeaseExpirations.clear();
864
918
  this.currentSessionId = sessionId;
865
919
  const runtime = this.createCanonicalRuntime(runId, sessionId);
866
920
  this.activeKernel = runtime;
@@ -965,7 +1019,7 @@ export class RuntimeRunner {
965
1019
  * Drive a canonical root or provider-authored workflow from kernel effects only: run each
966
1020
  * emitted batch, resolve its launch/completion/preemption effects, and stop at the kernel terminal.
967
1021
  */
968
- async driveWorkflow(initialAction, initial, parentSessionId, runtime, seedOutputs) {
1022
+ async driveWorkflow(initialAction, initial, parentSessionId, runtime, seedOutputs, contextPolicies) {
969
1023
  let observations = initial;
970
1024
  const orchestrator = this.opts.subAgentOrchestrator ?? defaultSubAgentOrchestrator;
971
1025
  const findDone = (obs) => obs.find(o => o.kind === "workflow_completed");
@@ -1027,7 +1081,7 @@ export class RuntimeRunner {
1027
1081
  const controllers = new Map(nodes.map(n => [n.agent_id, new AbortController()]));
1028
1082
  const batchState = { settled: false };
1029
1083
  const monitor = this.monitorWorkflowPreemption(runtime, controllers, batchState);
1030
- const results = await Promise.all(nodes.map(node => this.runWorkflowNode(node, parentSessionId, orchestrator, roundBudget, outputs, controllers.get(node.agent_id)?.signal)));
1084
+ const results = await Promise.all(nodes.map(node => this.runWorkflowNode(node, parentSessionId, orchestrator, roundBudget, outputs, controllers.get(node.agent_id)?.signal, contextPolicies)));
1031
1085
  batchState.settled = true;
1032
1086
  const preempted = await monitor;
1033
1087
  if (preempted !== null) {
@@ -1352,6 +1406,8 @@ export class RuntimeRunner {
1352
1406
  this.pendingObservations = [];
1353
1407
  this.pendingPageOutArchives = [];
1354
1408
  this.activePageOutArchive = undefined;
1409
+ this.knowledgePushedSkills.clear();
1410
+ this.skillLeaseExpirations.clear();
1355
1411
  this.currentSessionId = sessionId;
1356
1412
  this.activeProviderInvocationId = undefined;
1357
1413
  this.providerRetryPending = false;
@@ -1413,17 +1469,23 @@ export class RuntimeRunner {
1413
1469
  });
1414
1470
  }
1415
1471
  if (this.opts.initialMemory) {
1416
- for (const mem of this.opts.initialMemory) {
1417
- await this.commitKernelApply(runtime, this.pendingObservations, {
1418
- kind: "add_knowledge_message",
1419
- content: mem,
1420
- tokens: Math.max(1, Math.ceil(mem.length / 4)),
1421
- });
1472
+ for (const [index, mem] of this.opts.initialMemory.entries()) {
1473
+ await this.pushKnowledge({ role: "system", content: mem, toolCalls: [] }, undefined, { key: `initial:${index}`, pinned: true });
1422
1474
  }
1423
1475
  }
1424
- if (this.opts.skillDir) {
1476
+ if (this.opts.skillDir || this.opts.skillCatalog?.length) {
1425
1477
  const { scanSkillDir } = await import("../skills/loader.js");
1426
- const metas = await scanSkillDir(this.opts.skillDir);
1478
+ const metas = [
1479
+ ...(this.opts.skillDir ? await scanSkillDir(this.opts.skillDir) : []),
1480
+ ...(this.opts.skillCatalog ?? []).map(skill => ({
1481
+ name: skill.name,
1482
+ description: skill.description ?? "",
1483
+ ...(skill.metadata?.whenToUse ? { whenToUse: String(skill.metadata.whenToUse) } : {}),
1484
+ ...(skill.metadata?.effort !== undefined ? { effort: Number(skill.metadata.effort) } : {}),
1485
+ ...(skill.metadata?.estimatedTokens !== undefined ? { estimatedTokens: Number(skill.metadata.estimatedTokens) } : {}),
1486
+ ...(skill.tools?.length ? { allowedTools: skill.tools.map(tool => typeof tool === "string" ? tool : tool.name) } : {}),
1487
+ })),
1488
+ ];
1427
1489
  // S2 host-layer skill allowlist: keep only scanned skills named in `skillFilter` before feeding
1428
1490
  // the catalog. Absent ⇒ feed all (identical to the pre-feature message); empty ⇒ feed none. The
1429
1491
  // `set_available_skills` message is ALWAYS sent when a skillDir exists (shape preserved) — only
@@ -1505,9 +1567,16 @@ export class RuntimeRunner {
1505
1567
  role: "custom",
1506
1568
  goal,
1507
1569
  };
1508
- let spec = hasProfile
1509
- ? { ...baseSpec, capabilityFilter: { ...baseSpec.capabilityFilter, allowedIds: allowedToolIds } }
1570
+ const filtered = intersectCapabilityFilters(baseSpec.capabilityFilter, this.opts.capabilityFilter);
1571
+ let spec = filtered
1572
+ ? { ...baseSpec, capabilityFilter: filtered }
1510
1573
  : baseSpec;
1574
+ if (hasProfile) {
1575
+ spec = {
1576
+ ...spec,
1577
+ capabilityFilter: intersectCapabilityFilters(spec.capabilityFilter, { allowedIds: allowedToolIds }),
1578
+ };
1579
+ }
1511
1580
  spec = { ...spec, exposureBaseline: baselineToolIds };
1512
1581
  if (hasMilestoneContract && !spec.verificationContractId) {
1513
1582
  spec = { ...spec, verificationContractId: "node-default" };
@@ -1569,6 +1638,7 @@ export class RuntimeRunner {
1569
1638
  while (!runtime.isTerminal()) {
1570
1639
  nextCompressedArchiveStart = await this.appendObservations(sessionId, runtime, nextCompressedArchiveStart, taskScope);
1571
1640
  this.nextArchiveStart = nextCompressedArchiveStart;
1641
+ this.expireSkillContext(runtime.turn());
1572
1642
  if (this.interrupted) {
1573
1643
  action = await this.commitKernelAction(runtime, this.pendingObservations, {
1574
1644
  kind: "cancel_operation",
@@ -1921,7 +1991,7 @@ export class RuntimeRunner {
1921
1991
  ...(turnOutputTokens > 0 ? { observed_output_tokens: settlement?.observed_output_tokens ?? turnOutputTokens } : {}),
1922
1992
  ...(turnStopReason ? { stop_reason: turnStopReason } : {}),
1923
1993
  };
1924
- if (this.opts.skillDir) {
1994
+ if (this.opts.skillDir || this.opts.skillCatalog?.length) {
1925
1995
  const skillCalls = finalToolCalls.filter(call => call.name === "skill");
1926
1996
  if (skillCalls.length > 0) {
1927
1997
  const { readSkillFile } = await import("../skills/loader.js");
@@ -1932,16 +2002,16 @@ export class RuntimeRunner {
1932
2002
  continue;
1933
2003
  if (this.opts.skillFilter && !this.opts.skillFilter.includes(name))
1934
2004
  continue;
1935
- const content = await readSkillFile(this.opts.skillDir, name);
2005
+ const inline = this.opts.skillCatalog?.find(skill => skill.name === name);
2006
+ const content = inline?.instructions
2007
+ ?? (this.opts.skillDir ? await readSkillFile(this.opts.skillDir, name) : null);
1936
2008
  if (!content)
1937
2009
  continue;
1938
- await this.commitKernelApply(runtime, this.pendingObservations, {
1939
- kind: "add_knowledge_message",
1940
- key: `skill:${name}`,
1941
- content,
1942
- tokens: Math.max(1, Math.ceil(content.length / 4)),
1943
- pinned: true,
1944
- });
2010
+ const knowledge = inline?.knowledge
2011
+ ?.map(entry => typeof entry === "string" ? entry : entry.content)
2012
+ .filter((entry) => Boolean(entry)) ?? [];
2013
+ const fullContent = [content, ...knowledge].join("\n\n");
2014
+ await this.pushKnowledge({ role: "system", content: fullContent, toolCalls: [] }, Math.max(1, Math.ceil(fullContent.length / 4)), { key: `skill:${name}`, pinned: true });
1945
2015
  }
1946
2016
  catch {
1947
2017
  // A missing or malformed skill stays a model-visible syscall rejection.
@@ -2372,6 +2442,9 @@ export class RuntimeRunner {
2372
2442
  if (this.opts.skillLeaseTurns !== undefined || !this.knowledgePushedSkills.has(name)) {
2373
2443
  this.knowledgePushedSkills.add(name);
2374
2444
  await this.pushKnowledge({ role: "system", content: res.output, toolCalls: [] }, undefined, { key: `skill:${name}` });
2445
+ if (this.opts.skillLeaseTurns !== undefined) {
2446
+ this.skillLeaseExpirations.set(name, runtime.turn() + this.opts.skillLeaseTurns);
2447
+ }
2375
2448
  }
2376
2449
  }
2377
2450
  catch { /* malformed skill args — skip the knowledge pin */ }
@@ -2614,7 +2687,7 @@ export class RuntimeRunner {
2614
2687
  for (const q of queries ?? []) {
2615
2688
  if (!q.query.trim())
2616
2689
  continue;
2617
- const { action } = await this.prefetchMemoryIntoKnowledge(runtime, q, this.opts.agentId, this.durableSessionId(this.currentSessionId), seenRecordIds, this.pendingObservations);
2690
+ const { action } = await this.prefetchMemoryIntoKnowledge(runtime, q, this.opts.agentId, this.durableSessionId(this.currentSessionId), seenRecordIds);
2618
2691
  resumed = action ?? resumed;
2619
2692
  }
2620
2693
  // Every seed command leaves the pending provider action authoritative; use the last view.
@@ -279,7 +279,7 @@ export type SessionEvent = {
279
279
  classify_branch?: string;
280
280
  tournament_winner?: string;
281
281
  loop_continue?: boolean;
282
- output?: import("../types.js").ProviderMessage;
282
+ output?: import("../types.js").ModelMessage;
283
283
  } | {
284
284
  kind: "workflow_nodes_submitted";
285
285
  turn: number;
@@ -1,4 +1,4 @@
1
- import type { ProviderMessage, ProviderWireEvidence, ToolCall } from "../types.js";
1
+ import type { ModelMessage, ProviderWireEvidence, ToolCall } from "../types.js";
2
2
  import type { SessionEvent } from "./session-log.js";
3
3
  import type { WorkflowNodeStatus } from "../types/agent.js";
4
4
  export { REPLAY_CONTENT_MAX_BYTES as RECOVERY_CONTENT_MAX_BYTES } from "./replay-sanitize.js";
@@ -57,7 +57,7 @@ export declare function buildWorkflowNodeCompletedEvent(input: {
57
57
  classifyBranch?: string;
58
58
  tournamentWinner?: string;
59
59
  loopContinue?: boolean;
60
- output?: ProviderMessage;
60
+ output?: ModelMessage;
61
61
  }): Extract<SessionEvent, {
62
62
  kind: "workflow_node_completed";
63
63
  }>;
@@ -7,7 +7,7 @@ export declare function loopInstruction(maxIters: number, iteration?: number): s
7
7
  * just ordering (fan-out→synthesize was an uninformed synthesis without this). Each dependency's
8
8
  * output is clipped so a chain of large nodes can't blow the child's context; empty/unknown
9
9
  * outputs are skipped. Returns "" when the node has no dependencies. */
10
- export declare function dependencyOutputsNote(inputAgentIds: string[] | undefined, outputs: Map<string, string> | undefined, maxPerDep?: number): string;
10
+ export declare function dependencyOutputsNote(inputAgentIds: string[] | undefined, outputs: Map<string, string> | undefined, maxPerDep?: number, mode?: "full" | "summary" | "reference"): string;
11
11
  /** Instruction appended to a classify node's goal: pick exactly one of the kernel's branch labels. */
12
12
  export declare function classifyInstruction(labels: string[]): string;
13
13
  /** Build a tournament judge's goal: the controller's criterion + the two candidates to compare. */
@@ -20,20 +20,34 @@ export function loopInstruction(maxIters, iteration = 0) {
20
20
  * just ordering (fan-out→synthesize was an uninformed synthesis without this). Each dependency's
21
21
  * output is clipped so a chain of large nodes can't blow the child's context; empty/unknown
22
22
  * outputs are skipped. Returns "" when the node has no dependencies. */
23
- export function dependencyOutputsNote(inputAgentIds, outputs, maxPerDep = 8_000) {
23
+ export function dependencyOutputsNote(inputAgentIds, outputs, maxPerDep = 8_000, mode = "full") {
24
24
  if (!inputAgentIds?.length || !outputs)
25
25
  return "";
26
+ if (mode === "reference") {
27
+ return inputAgentIds.some(id => outputs.has(id))
28
+ ? `[dependency references]\n${inputAgentIds.filter(id => outputs.has(id)).join(", ")}`
29
+ : "";
30
+ }
26
31
  const blocks = inputAgentIds
27
32
  .map(id => {
28
33
  const out = outputs.get(id) ?? "";
29
34
  if (!out)
30
35
  return "";
31
- const clipped = out.length > maxPerDep ? `${out.slice(0, maxPerDep)}\n…[truncated]` : out;
36
+ const clipped = mode === "summary"
37
+ ? summarizeDependency(out, maxPerDep)
38
+ : out.length > maxPerDep ? `${out.slice(0, maxPerDep)}\n…[truncated]` : out;
32
39
  return `[dependency ${id} output]\n${clipped}`;
33
40
  })
34
41
  .filter(Boolean);
35
42
  return blocks.join("\n\n");
36
43
  }
44
+ function summarizeDependency(value, maxChars) {
45
+ if (value.length <= maxChars)
46
+ return value;
47
+ const head = Math.max(1, Math.floor(maxChars * 0.7));
48
+ const tail = Math.max(1, maxChars - head);
49
+ return `${value.slice(0, head)}\n…[summary truncated]…\n${value.slice(-tail)}`;
50
+ }
37
51
  /** Instruction appended to a classify node's goal: pick exactly one of the kernel's branch labels. */
38
52
  export function classifyInstruction(labels) {
39
53
  return (`Classify the input and choose EXACTLY ONE label from: ${labels.map(l => JSON.stringify(l)).join(", ")}. ` +
@@ -0,0 +1,161 @@
1
+ /** SPC-028-02: cross-layer object classification registry. */
2
+ export type RuntimeDomain = "public" | "host" | "kernel" | "provider";
3
+ export type RuntimeAuthority = "public-agent" | "host-runtime" | "kernel" | "none";
4
+ export type RuntimeRepresentation = "semantic" | "projection" | "measurement" | "evidence" | "wire" | "state-truth" | "snapshot";
5
+ export type RuntimeDurability = "durable" | "ephemeral" | "rebuildable" | "append-only";
6
+ export interface RuntimeObjectClassification {
7
+ domain: RuntimeDomain;
8
+ authority: RuntimeAuthority;
9
+ representation: RuntimeRepresentation;
10
+ durability: RuntimeDurability;
11
+ identity: string;
12
+ causation: string;
13
+ replay: string;
14
+ }
15
+ export declare const RUNTIME_OBJECT_CLASSIFICATIONS: {
16
+ readonly AgentDefinition: {
17
+ readonly domain: "public";
18
+ readonly authority: "public-agent";
19
+ readonly representation: "semantic";
20
+ readonly durability: "rebuildable";
21
+ readonly identity: "agent name or host-assigned agent identity";
22
+ readonly causation: "agent declaration";
23
+ readonly replay: "input to AgentSpec projection";
24
+ };
25
+ readonly AgentSpec: {
26
+ readonly domain: "host";
27
+ readonly authority: "host-runtime";
28
+ readonly representation: "semantic";
29
+ readonly durability: "rebuildable";
30
+ readonly identity: "agent identity";
31
+ readonly causation: "AgentDefinition plus host bindings";
32
+ readonly replay: "re-derived from public definition and runtime bindings";
33
+ };
34
+ readonly StoredMessageState: {
35
+ readonly domain: "host";
36
+ readonly authority: "host-runtime";
37
+ readonly representation: "state-truth";
38
+ readonly durability: "durable";
39
+ readonly identity: "message identity";
40
+ readonly causation: "accepted session or run input";
41
+ readonly replay: "replayed from durable message history";
42
+ };
43
+ readonly ModelMessage: {
44
+ readonly domain: "host";
45
+ readonly authority: "host-runtime";
46
+ readonly representation: "semantic";
47
+ readonly durability: "rebuildable";
48
+ readonly identity: "message identity";
49
+ readonly causation: "stored or runtime message projection";
50
+ readonly replay: "re-rendered from message state";
51
+ };
52
+ readonly ProviderRequestPlan: {
53
+ readonly domain: "host";
54
+ readonly authority: "none";
55
+ readonly representation: "projection";
56
+ readonly durability: "rebuildable";
57
+ readonly identity: "request fingerprint";
58
+ readonly causation: "ContextCandidate plus ResolvedProviderRoute";
59
+ readonly replay: "re-rendered and re-encoded from inputs";
60
+ };
61
+ readonly PromptMeasurement: {
62
+ readonly domain: "host";
63
+ readonly authority: "host-runtime";
64
+ readonly representation: "measurement";
65
+ readonly durability: "durable";
66
+ readonly identity: "request fingerprint";
67
+ readonly causation: "prepared provider request";
68
+ readonly replay: "reused only on exact fingerprint match";
69
+ };
70
+ readonly ProviderUsage: {
71
+ readonly domain: "provider";
72
+ readonly authority: "host-runtime";
73
+ readonly representation: "measurement";
74
+ readonly durability: "durable";
75
+ readonly identity: "provider attempt identity";
76
+ readonly causation: "decoded provider response";
77
+ readonly replay: "retained as response evidence";
78
+ };
79
+ readonly ResolvedProviderRoute: {
80
+ readonly domain: "provider";
81
+ readonly authority: "host-runtime";
82
+ readonly representation: "projection";
83
+ readonly durability: "durable";
84
+ readonly identity: "route identity";
85
+ readonly causation: "model resolution";
86
+ readonly replay: "frozen on ProviderAttempt";
87
+ };
88
+ readonly ProviderAttempt: {
89
+ readonly domain: "host";
90
+ readonly authority: "host-runtime";
91
+ readonly representation: "evidence";
92
+ readonly durability: "append-only";
93
+ readonly identity: "effect identity plus attempt sequence";
94
+ readonly causation: "CallProvider effect";
95
+ readonly replay: "evidence for one physical execution";
96
+ };
97
+ readonly KernelInput: {
98
+ readonly domain: "kernel";
99
+ readonly authority: "kernel";
100
+ readonly representation: "wire";
101
+ readonly durability: "append-only";
102
+ readonly identity: "input identity";
103
+ readonly causation: "host submission";
104
+ readonly replay: "durable input sequence";
105
+ };
106
+ readonly KernelEffect: {
107
+ readonly domain: "kernel";
108
+ readonly authority: "kernel";
109
+ readonly representation: "wire";
110
+ readonly durability: "append-only";
111
+ readonly identity: "effect identity";
112
+ readonly causation: "kernel decision";
113
+ readonly replay: "journal decision chain";
114
+ };
115
+ readonly BudgetLedger: {
116
+ readonly domain: "kernel";
117
+ readonly authority: "kernel";
118
+ readonly representation: "state-truth";
119
+ readonly durability: "durable";
120
+ readonly identity: "operation or group budget identity";
121
+ readonly causation: "accepted kernel facts";
122
+ readonly replay: "folded from journal facts";
123
+ };
124
+ readonly Journal: {
125
+ readonly domain: "kernel";
126
+ readonly authority: "kernel";
127
+ readonly representation: "state-truth";
128
+ readonly durability: "append-only";
129
+ readonly identity: "journal sequence and digest";
130
+ readonly causation: "kernel inputs and facts";
131
+ readonly replay: "source of durable state truth";
132
+ };
133
+ readonly Checkpoint: {
134
+ readonly domain: "kernel";
135
+ readonly authority: "kernel";
136
+ readonly representation: "snapshot";
137
+ readonly durability: "durable";
138
+ readonly identity: "checkpoint identity and journal head";
139
+ readonly causation: "checkpoint boundary";
140
+ readonly replay: "restore seed verified against journal";
141
+ };
142
+ readonly SessionLog: {
143
+ readonly domain: "host";
144
+ readonly authority: "none";
145
+ readonly representation: "evidence";
146
+ readonly durability: "append-only";
147
+ readonly identity: "session identity and event sequence";
148
+ readonly causation: "host observations";
149
+ readonly replay: "evidence only; never recovery authority";
150
+ };
151
+ readonly EvaluationRun: {
152
+ readonly domain: "host";
153
+ readonly authority: "host-runtime";
154
+ readonly representation: "semantic";
155
+ readonly durability: "durable";
156
+ readonly identity: "evaluation run identity";
157
+ readonly causation: "public Eval request";
158
+ readonly replay: "replayed from dataset and captured evidence";
159
+ };
160
+ };
161
+ export type RuntimeObjectName = keyof typeof RUNTIME_OBJECT_CLASSIFICATIONS;
@@ -0,0 +1,66 @@
1
+ export const RUNTIME_OBJECT_CLASSIFICATIONS = {
2
+ AgentDefinition: {
3
+ domain: "public", authority: "public-agent", representation: "semantic", durability: "rebuildable",
4
+ identity: "agent name or host-assigned agent identity", causation: "agent declaration", replay: "input to AgentSpec projection",
5
+ },
6
+ AgentSpec: {
7
+ domain: "host", authority: "host-runtime", representation: "semantic", durability: "rebuildable",
8
+ identity: "agent identity", causation: "AgentDefinition plus host bindings", replay: "re-derived from public definition and runtime bindings",
9
+ },
10
+ StoredMessageState: {
11
+ domain: "host", authority: "host-runtime", representation: "state-truth", durability: "durable",
12
+ identity: "message identity", causation: "accepted session or run input", replay: "replayed from durable message history",
13
+ },
14
+ ModelMessage: {
15
+ domain: "host", authority: "host-runtime", representation: "semantic", durability: "rebuildable",
16
+ identity: "message identity", causation: "stored or runtime message projection", replay: "re-rendered from message state",
17
+ },
18
+ ProviderRequestPlan: {
19
+ domain: "host", authority: "none", representation: "projection", durability: "rebuildable",
20
+ identity: "request fingerprint", causation: "ContextCandidate plus ResolvedProviderRoute", replay: "re-rendered and re-encoded from inputs",
21
+ },
22
+ PromptMeasurement: {
23
+ domain: "host", authority: "host-runtime", representation: "measurement", durability: "durable",
24
+ identity: "request fingerprint", causation: "prepared provider request", replay: "reused only on exact fingerprint match",
25
+ },
26
+ ProviderUsage: {
27
+ domain: "provider", authority: "host-runtime", representation: "measurement", durability: "durable",
28
+ identity: "provider attempt identity", causation: "decoded provider response", replay: "retained as response evidence",
29
+ },
30
+ ResolvedProviderRoute: {
31
+ domain: "provider", authority: "host-runtime", representation: "projection", durability: "durable",
32
+ identity: "route identity", causation: "model resolution", replay: "frozen on ProviderAttempt",
33
+ },
34
+ ProviderAttempt: {
35
+ domain: "host", authority: "host-runtime", representation: "evidence", durability: "append-only",
36
+ identity: "effect identity plus attempt sequence", causation: "CallProvider effect", replay: "evidence for one physical execution",
37
+ },
38
+ KernelInput: {
39
+ domain: "kernel", authority: "kernel", representation: "wire", durability: "append-only",
40
+ identity: "input identity", causation: "host submission", replay: "durable input sequence",
41
+ },
42
+ KernelEffect: {
43
+ domain: "kernel", authority: "kernel", representation: "wire", durability: "append-only",
44
+ identity: "effect identity", causation: "kernel decision", replay: "journal decision chain",
45
+ },
46
+ BudgetLedger: {
47
+ domain: "kernel", authority: "kernel", representation: "state-truth", durability: "durable",
48
+ identity: "operation or group budget identity", causation: "accepted kernel facts", replay: "folded from journal facts",
49
+ },
50
+ Journal: {
51
+ domain: "kernel", authority: "kernel", representation: "state-truth", durability: "append-only",
52
+ identity: "journal sequence and digest", causation: "kernel inputs and facts", replay: "source of durable state truth",
53
+ },
54
+ Checkpoint: {
55
+ domain: "kernel", authority: "kernel", representation: "snapshot", durability: "durable",
56
+ identity: "checkpoint identity and journal head", causation: "checkpoint boundary", replay: "restore seed verified against journal",
57
+ },
58
+ SessionLog: {
59
+ domain: "host", authority: "none", representation: "evidence", durability: "append-only",
60
+ identity: "session identity and event sequence", causation: "host observations", replay: "evidence only; never recovery authority",
61
+ },
62
+ EvaluationRun: {
63
+ domain: "host", authority: "host-runtime", representation: "semantic", durability: "durable",
64
+ identity: "evaluation run identity", causation: "public Eval request", replay: "replayed from dataset and captured evidence",
65
+ },
66
+ };
@@ -0,0 +1,32 @@
1
+ /**
2
+ * SPC-028-01: the normative vocabulary for the four runtime language layers.
3
+ *
4
+ * Terms are names, not a second semantic authority. The registry is consumed by
5
+ * conformance tests and documentation tooling so each term has one primary layer.
6
+ */
7
+ export declare const RUNTIME_VOCABULARY: {
8
+ readonly version: "0.2.72";
9
+ readonly public: readonly ["Agent", "Model", "Run", "Session", "Tool", "Skill", "Memory", "Knowledge", "MCPServer", "Handoff", "Workflow", "Guardrail", "Eval", "Dataset", "Evaluator", "Output", "Usage"];
10
+ readonly host: readonly ["AgentSpec", "Context", "ContextPlan", "Capability", "ModelRoute", "Invocation", "ProviderAttempt", "Measurement", "Evidence", "Artifact", "Evaluation", "Promotion", "ExecutionPlane"];
11
+ readonly kernel: readonly ["Operation", "Intent", "Decision", "Effect", "Fact", "Settlement", "Task", "Capability", "Budget", "Journal", "Checkpoint", "StateTransition"];
12
+ readonly provider: readonly ["Model", "Provider", "Endpoint", "Protocol", "Route", "Adapter", "Request", "Response", "Usage", "ReplayEvidence"];
13
+ readonly primaryDomain: {
14
+ readonly Model: "public";
15
+ readonly Usage: "public";
16
+ readonly Capability: "host";
17
+ readonly Route: "host";
18
+ };
19
+ readonly verbs: {
20
+ readonly resolve: "select or answer a runtime object at a boundary";
21
+ readonly render: "project semantic state into model-facing input";
22
+ readonly encode: "map semantic input into a wire request";
23
+ readonly execute: "perform one physical provider or external call";
24
+ readonly decode: "extract semantic output and retained wire evidence";
25
+ readonly normalize: "map vendor data into the controlled runtime vocabulary";
26
+ readonly settle: "apply accounting policy to an observed measurement";
27
+ };
28
+ };
29
+ export type RuntimeLanguage = typeof RUNTIME_VOCABULARY;
30
+ export type RuntimeLanguageDomain = "public" | "host" | "kernel" | "provider";
31
+ /** Returns all layer terms while preserving the registry's primary-domain order. */
32
+ export declare function runtimeVocabularyTerms(): readonly string[];