@deepstrike/sdk 0.2.39 → 0.2.41

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 (102) hide show
  1. package/README.md +64 -34
  2. package/dist/collaboration/contract.d.ts +2 -2
  3. package/dist/collaboration/contract.js +2 -2
  4. package/dist/collaboration/handoff.d.ts +2 -14
  5. package/dist/collaboration/handoff.js +1 -17
  6. package/dist/collaboration/harness.d.ts +16 -47
  7. package/dist/collaboration/harness.js +57 -158
  8. package/dist/collaboration/index.d.ts +2 -2
  9. package/dist/collaboration/index.js +1 -2
  10. package/dist/collaboration/modes/creator-verifier.js +42 -6
  11. package/dist/collaboration/pool.d.ts +8 -0
  12. package/dist/collaboration/pool.js +56 -3
  13. package/dist/harness/harness.d.ts +97 -97
  14. package/dist/harness/harness.js +190 -144
  15. package/dist/harness/judge.d.ts +3 -2
  16. package/dist/harness/judge.js +7 -3
  17. package/dist/harness/public.d.ts +5 -3
  18. package/dist/harness/public.js +3 -2
  19. package/dist/index.d.ts +22 -7
  20. package/dist/index.js +8 -1
  21. package/dist/kernel.d.ts +12 -39
  22. package/dist/memory/agent.d.ts +8 -41
  23. package/dist/memory/agent.js +34 -117
  24. package/dist/memory/extraction.d.ts +4 -0
  25. package/dist/memory/extraction.js +79 -0
  26. package/dist/memory/in-memory-store.d.ts +28 -15
  27. package/dist/memory/in-memory-store.js +74 -25
  28. package/dist/memory/protocols.d.ts +56 -56
  29. package/dist/memory/protocols.js +1 -0
  30. package/dist/memory/public.d.ts +6 -1
  31. package/dist/memory/public.js +3 -0
  32. package/dist/memory/ranking.d.ts +32 -0
  33. package/dist/memory/ranking.js +77 -0
  34. package/dist/memory/retention.d.ts +17 -0
  35. package/dist/memory/retention.js +54 -0
  36. package/dist/os/public.d.ts +5 -4
  37. package/dist/os/public.js +2 -1
  38. package/dist/providers/base.d.ts +8 -0
  39. package/dist/providers/base.js +0 -0
  40. package/dist/providers/gemini.js +12 -0
  41. package/dist/providers/ollama.js +3 -1
  42. package/dist/providers/openai-responses.js +9 -2
  43. package/dist/providers/profiles.d.ts +5 -3
  44. package/dist/providers/profiles.js +3 -3
  45. package/dist/runtime/context-policy.d.ts +35 -0
  46. package/dist/runtime/context-policy.js +66 -0
  47. package/dist/runtime/eval.d.ts +6 -2
  48. package/dist/runtime/eval.js +2 -2
  49. package/dist/runtime/event-stream.d.ts +9 -0
  50. package/dist/runtime/event-stream.js +25 -11
  51. package/dist/runtime/execution-plane.d.ts +5 -1
  52. package/dist/runtime/execution-plane.js +9 -3
  53. package/dist/runtime/facade.js +2 -1
  54. package/dist/runtime/kernel-event-log.d.ts +0 -2
  55. package/dist/runtime/kernel-event-log.js +61 -13
  56. package/dist/runtime/kernel-primitives-dashboard.js +1 -1
  57. package/dist/runtime/kernel-rebuild.d.ts +13 -0
  58. package/dist/runtime/kernel-rebuild.js +75 -0
  59. package/dist/runtime/kernel-step.d.ts +157 -8
  60. package/dist/runtime/kernel-step.js +220 -7
  61. package/dist/runtime/kernel-transaction-log.d.ts +61 -0
  62. package/dist/runtime/kernel-transaction-log.js +149 -0
  63. package/dist/runtime/large-result-spool.d.ts +3 -1
  64. package/dist/runtime/large-result-spool.js +24 -5
  65. package/dist/runtime/loop-driver.d.ts +1 -1
  66. package/dist/runtime/loop-driver.js +2 -7
  67. package/dist/runtime/mcp-proxy-plane.d.ts +1 -0
  68. package/dist/runtime/mcp-proxy-plane.js +23 -6
  69. package/dist/runtime/os-profile.d.ts +9 -10
  70. package/dist/runtime/os-profile.js +14 -10
  71. package/dist/runtime/os-snapshot.d.ts +19 -0
  72. package/dist/runtime/os-snapshot.js +33 -3
  73. package/dist/runtime/process-sandbox-plane.js +16 -11
  74. package/dist/runtime/reaction-checkpoint.d.ts +51 -0
  75. package/dist/runtime/reaction-checkpoint.js +83 -0
  76. package/dist/runtime/reactive-session.d.ts +9 -3
  77. package/dist/runtime/reactive-session.js +44 -14
  78. package/dist/runtime/reliability.d.ts +48 -0
  79. package/dist/runtime/reliability.js +86 -0
  80. package/dist/runtime/remote-vpc-plane.js +4 -3
  81. package/dist/runtime/run-group.d.ts +38 -35
  82. package/dist/runtime/run-group.js +97 -54
  83. package/dist/runtime/runner.d.ts +117 -78
  84. package/dist/runtime/runner.js +1516 -1197
  85. package/dist/runtime/session-log.d.ts +71 -12
  86. package/dist/runtime/session-log.js +192 -32
  87. package/dist/runtime/session-repair.d.ts +11 -7
  88. package/dist/runtime/session-repair.js +11 -8
  89. package/dist/runtime/sub-agent-orchestrator.d.ts +6 -2
  90. package/dist/runtime/sub-agent-orchestrator.js +45 -18
  91. package/dist/signals/gateway.d.ts +23 -10
  92. package/dist/signals/gateway.js +81 -17
  93. package/dist/signals/scheduled.js +0 -1
  94. package/dist/signals/types.d.ts +21 -13
  95. package/dist/skills/loader.js +12 -2
  96. package/dist/tools/index.d.ts +2 -0
  97. package/dist/types/agent.d.ts +40 -1
  98. package/dist/types/agent.js +61 -1
  99. package/dist/types.d.ts +6 -1
  100. package/dist/workflow/public.d.ts +2 -3
  101. package/dist/workflow/public.js +0 -1
  102. package/package.json +2 -2
package/README.md CHANGED
@@ -88,13 +88,13 @@ The root export is the **intent layer** — what you reach for to run an agent,
88
88
 
89
89
  | Import | Contains |
90
90
  |--------|----------|
91
- | `@deepstrike/sdk` | `runAgent` · `runFanout` · `RuntimeRunner` · `tool` · `LocalExecutionPlane` · `InMemorySessionLog`/`FileSessionLog` · `AnthropicProvider`/`OpenAIProvider`/`OpenAIResponsesProvider` · `createProvider` · `Governance` · `AgentPool` · core types |
91
+ | `@deepstrike/sdk` | `runAgent` · `runFanout` · `RuntimeRunner` · `tool` · `LocalExecutionPlane` · `InMemorySessionLog`/`FileSessionLog` · `AnthropicProvider`/`OpenAIProvider`/`OpenAIResponsesProvider` · `createProvider` · `Governance` · `AgentPool` · `operationAbortSignal` · core types |
92
92
  | `@deepstrike/sdk/providers` | backend factories (`deepseek`, `kimi`, `qwen`, `glm`, `minimax`, `gemini`, `ollama`), profiles, `CircuitBreaker` |
93
93
  | `@deepstrike/sdk/workflow` | `SubAgentOrchestrator`, `spawnStandalone`, reducers, contracts, handoff/modes, agent + spec types |
94
94
  | `@deepstrike/sdk/planes` | `WorktreeExecutionPlane`, `ProcessSandboxPlane`, `McpProxyPlane`, `RemoteVpcPlane`, archive/credential stores |
95
- | `@deepstrike/sdk/memory` | `DreamStore`, `WorkingMemory`, `InMemoryDreamStore`, `KnowledgeSource` |
96
- | `@deepstrike/sdk/harness` | `SinglePassHarness`, `EvalLoopHarness`, `HarnessLoop`, `judge` |
97
- | `@deepstrike/sdk/os` | profiles, `KernelPrimitivesDashboard`, signals, `PermissionManager`, replay-testing utilities |
95
+ | `@deepstrike/sdk/memory` | `DreamStore`, `WorkingMemory`, `InMemoryDreamStore`, `rankMemories`, `extractSessionMemories`, `KnowledgeSource` |
96
+ | `@deepstrike/sdk/harness` | `AttemptLoop`, body/judge/carry policies, `judge` |
97
+ | `@deepstrike/sdk/os` | profiles, `KernelPrimitivesDashboard`, `primitiveForKind` / `KernelPrimitive`, signals, `PermissionManager`, replay-testing utilities |
98
98
 
99
99
  > **Migration from 0.2.x:** the kernel-lowering converters (`*ToKernel`), low-level prompt/eval builders, and the `OpenAIChatProvider` alias are no longer exported from root; backend providers, planes, memory, harness, and OS utilities moved to the subpaths above. See [`MIGRATION-v0.2.300.md`](./MIGRATION-v0.2.300.md).
100
100
 
@@ -190,7 +190,7 @@ Tool calls, spawns, compression, and signals pass through one kernel gate with a
190
190
  Oversized tool results (> 50 KB) stay in context as a preview plus a `.spool/` reference — the model reads the full payload on demand via ordinary file tools. When pressure triggers semantic eviction, the SDK summarizes archived content into `DreamStore`. Long tasks survive token pressure instead of failing mid-run.
191
191
 
192
192
  **Safety and governance by default (OS native profile)**
193
- Every run loads declarative `governancePolicy` (deny / ask_user / rate-limit / param rules) and in-kernel signal routing (`attentionPolicy`, default queue 64). Dangerous tools, external interrupts, and approval flows are policy — not ad-hoc `if` checks in your handlers.
193
+ Every run loads declarative `governancePolicy` (deny / ask_user / rate-limit / param rules) and in-kernel signal routing (`signalPolicy`, default queue 64). Dangerous tools, external interrupts, and approval flows are policy — not ad-hoc `if` checks in your handlers.
194
194
 
195
195
  **Long-term memory as syscalls (Phase-7)**
196
196
  `writeMemory` and `queryMemory` run outside the main tool loop: kernel validation before `DreamStore.commit`, search → `selectMemories` → `memory_retrieval_result` on query. Failed writes emit `memory_validation_failed` for audit; good memory is durable without polluting history.
@@ -204,7 +204,7 @@ Spool, page-out, signals, processes, budgets, and memory events land in `Session
204
204
  | You need… | Use… |
205
205
  |---|---|
206
206
  | Policy before tools run | `governancePolicy` (default: allow-all native profile) |
207
- | External interrupts | `signalSource` + in-kernel `attentionPolicy` |
207
+ | External interrupts | `signalSource` + in-kernel `signalPolicy` |
208
208
  | Huge tool output | Automatic Layer-1 spool; optional custom `resultSpool` |
209
209
  | Durable recall across runs | `DreamStore` + semantic `page_out` via `dreamSummarizer` |
210
210
  | Programmatic memory I/O | `runner.writeMemory()` / `runner.queryMemory()` |
@@ -336,7 +336,7 @@ Full reference: [docs/concepts/context-slots-compression.md](../docs/concepts/co
336
336
  ```typescript
337
337
  import {
338
338
  DEFAULT_NATIVE_GOVERNANCE_POLICY,
339
- DEFAULT_NATIVE_ATTENTION_POLICY,
339
+ DEFAULT_NATIVE_SIGNAL_POLICY,
340
340
  } from "@deepstrike/sdk"
341
341
 
342
342
  const runner = new RuntimeRunner({
@@ -348,7 +348,13 @@ const runner = new RuntimeRunner({
348
348
  maxTokens: 128_000,
349
349
  maxTurns: 25,
350
350
  timeoutMs: 60_000,
351
- schedulerBudget: { maxWallMs: 300_000 },
351
+ schedulerPolicy: {
352
+ version: 1,
353
+ criticalPathWeight: 1_000_000,
354
+ fanoutWeight: 10_000,
355
+ ageWeight: 1_000,
356
+ tokenCostWeight: 1,
357
+ },
352
358
 
353
359
  // Resource quotas (M2) — enforced at the kernel syscall trap. Opt-in; omit for unbounded.
354
360
  resourceQuota: {
@@ -369,7 +375,12 @@ const runner = new RuntimeRunner({
369
375
 
370
376
  // Agent OS native profile (defaults shown)
371
377
  governancePolicy: DEFAULT_NATIVE_GOVERNANCE_POLICY,
372
- attentionPolicy: DEFAULT_NATIVE_ATTENTION_POLICY, // SignalRouter queue size 64
378
+ signalPolicy: DEFAULT_NATIVE_SIGNAL_POLICY, // SignalRouter queue size 64
379
+ promptBudget: {
380
+ promptOverheadTokens: 20,
381
+ outputReserveTokens: 4096,
382
+ safetyMarginTokens: 256,
383
+ },
373
384
 
374
385
  // Host I/O
375
386
  extensions: { temperature: 0.1 },
@@ -404,7 +415,8 @@ const runner = new RuntimeRunner({
404
415
  | Option | Purpose |
405
416
  |--------|---------|
406
417
  | `governancePolicy` | Declarative deny / ask_user / rate-limit / param rules loaded into the kernel before `start_run` |
407
- | `attentionPolicy` | In-kernel signal router queue size (default 64) |
418
+ | `signalPolicy` | Versioned in-kernel signal queue/TTL policy (default queue 64) |
419
+ | `promptBudget` | Provider-envelope overhead, output reserve, and safety margin deducted from the context window |
408
420
  | `resourceQuota` | M2 declarative limits — `maxConcurrentSubagents` / `maxSpawnDepth` / `memoryWritesPerWindow` — enforced at the kernel syscall trap (`set_resource_quota`); over-quota spawns roll back, over-rate writes surface as `memory_validation_failed` |
409
421
  | `memoryPolicy` | Long-term memory config sent as `set_memory_policy` and **kernel-enforced**: `validationEnabled: false` admits writes without validation, `maxContentBytes` / `maxNameLength` override validation limits, `retrievalTopK` caps `query_memory` breadth; `memoryPath` / `staleWarningDays` are SDK-consumed (requires `dreamStore` + `agentId` to enable memory) |
410
422
  | `onPermissionRequest` | Resolves `tool_gated` + `suspended` → kernel `resume` with approved/denied call IDs |
@@ -528,7 +540,7 @@ const runner = new RuntimeRunner({
528
540
  `WorkingMemory` is an SDK helper — not the kernel working partition. Kernel task state lives in `task_state` and renders into Slot 3 (`turns[0]`).
529
541
 
530
542
  ```typescript
531
- import { WorkingMemory } from "@deepstrike/sdk"
543
+ import { WorkingMemory } from "@deepstrike/sdk/memory"
532
544
  const mem = new WorkingMemory()
533
545
  mem.set("step", 1)
534
546
  mem.get("step") // 1
@@ -538,13 +550,13 @@ mem.clear()
538
550
  ### DreamStore (long-term memory)
539
551
 
540
552
  ```typescript
541
- import type { DreamStore } from "@deepstrike/sdk"
553
+ import type { DreamStore } from "@deepstrike/sdk/memory"
542
554
 
543
555
  class MyStore implements DreamStore {
544
556
  async loadSessions(agentId) { ... }
545
557
  async loadMemories(agentId) { ... }
546
558
  async commit(agentId, result, existing) { ... }
547
- async search(agentId, query, topK) { ... }
559
+ async search(agentId, query) { ... } // Promise<MemoryRecall[]>
548
560
  }
549
561
 
550
562
  const runner = new RuntimeRunner({
@@ -577,21 +589,26 @@ Kernel-validated long-term memory I/O outside the main tool loop:
577
589
 
578
590
  ```typescript
579
591
  await runner.writeMemory({
580
- metadata: {
581
- name: "prefers-small-tests",
582
- description: "User prefers focused unit tests",
583
- kind: "feedback",
584
- created_at: Date.now(),
585
- updated_at: Date.now(),
586
- },
592
+ record_id: crypto.randomUUID(),
593
+ scope: { tenant_id: "acme", namespace: "assistant" },
594
+ name: "prefers-small-tests",
595
+ kind: "feedback",
587
596
  content: "User prefers focused unit tests for SDK behavior.",
597
+ description: "Testing preference",
598
+ provenance: { author: "host", trust: "user_asserted", evidence_refs: [] },
599
+ created_at: Date.now(),
600
+ updated_at: Date.now(),
601
+ recall_count: 0,
602
+ confidence: 1,
603
+ links: [],
604
+ pinned: false,
588
605
  }, { sessionId: "my-session" })
589
606
 
590
607
  const hits = await runner.queryMemory({
591
- current_context: "Need testing preferences",
592
- active_tools: [],
593
- already_surfaced: [],
608
+ scope: { tenant_id: "acme", namespace: "assistant" },
609
+ query: "Need testing preferences",
594
610
  top_k: 5,
611
+ kinds: ["feedback"],
595
612
  }, { sessionId: "my-session" })
596
613
  ```
597
614
 
@@ -676,14 +693,14 @@ const runner = new RuntimeRunner({
676
693
  executionPlane: plane,
677
694
  sessionLog,
678
695
  signalSource: gw,
679
- attentionPolicy: { maxQueueSize: 64 },
696
+ signalPolicy: { queueMax: 64, ttlMs: 60_000 },
680
697
  })
681
698
 
682
699
  runner.interrupt() // cooperative abort → kernel timeout path
683
700
  gw.destroy()
684
701
  ```
685
702
 
686
- Each routed signal produces a `signal_disposed` session event (`category: "ipc"`).
703
+ Each routed signal produces a correlated `signal_delivery_disposed` session event (`category: "ipc"`).
687
704
 
688
705
  ---
689
706
 
@@ -709,15 +726,25 @@ Requires an active parent run (`run()` / `wake()` in progress). The kernel emits
709
726
  ## Harness (evaluation framework)
710
727
 
711
728
  ```typescript
712
- import { SinglePassHarness, EvalLoopHarness, HarnessLoop } from "@deepstrike/sdk"
713
-
714
- const outcome = await new SinglePassHarness(runner).run({ goal: "Say hello" })
715
-
716
- const harness = new EvalLoopHarness(runner, {
717
- async evaluate(_req, out) { return out.result.includes("hello") },
718
- }, 3)
719
-
720
- const loop = new HarnessLoop(runner, evalProvider, { maxAttempts: 3, skillDir: "./skills" })
729
+ import {
730
+ AttemptLoop,
731
+ RuntimeAttemptBody,
732
+ LlmEvalJudge,
733
+ freshWithFeedback,
734
+ } from "@deepstrike/sdk/harness"
735
+
736
+ const loop = new AttemptLoop({
737
+ body: new RuntimeAttemptBody(runner),
738
+ judge: new LlmEvalJudge(evalProvider, false),
739
+ stop: { maxAttempts: 3 },
740
+ // carry defaults to continueSession: stable session + journaled feedback signal.
741
+ // Use `carry: freshWithFeedback` only when attempts must be isolated.
742
+ })
743
+ const outcome = await loop.run({
744
+ sessionId: "task-42",
745
+ goal: "Say hello",
746
+ criteria: [{ text: "result greets the user", required: true }],
747
+ })
721
748
 
722
749
  const runnerWithHarness = new RuntimeRunner({
723
750
  provider,
@@ -727,6 +754,9 @@ const runnerWithHarness = new RuntimeRunner({
727
754
  })
728
755
  ```
729
756
 
757
+ `AttemptOutcome` keeps run health (`runStatus`) separate from evaluation (`verdict`) and reports a
758
+ terminal `outcome`: `passed`, `failed_judge`, `exhausted`, or `run_error`.
759
+
730
760
  ---
731
761
 
732
762
  ## Stream events
@@ -48,8 +48,8 @@ export declare class ContractBuilder {
48
48
  }
49
49
  /**
50
50
  * Render the contract as a markdown block for injection into a system prompt.
51
- * Used by ContractDrivenHarness to inject into the executor's system partition.
51
+ * Used by CreatorVerifierBody to inject into the executor's system partition.
52
52
  */
53
53
  export declare function formatContractForSystemPrompt(contract: VerificationContract): string;
54
- /** Derive a flat string[] of criterion texts for the existing HarnessLoop criteria API. */
54
+ /** Derive a flat string[] of criterion texts for RuntimeRunner criteria input. */
55
55
  export declare function contractToCriteriaStrings(contract: VerificationContract): string[];
@@ -35,7 +35,7 @@ export class ContractBuilder {
35
35
  }
36
36
  /**
37
37
  * Render the contract as a markdown block for injection into a system prompt.
38
- * Used by ContractDrivenHarness to inject into the executor's system partition.
38
+ * Used by CreatorVerifierBody to inject into the executor's system partition.
39
39
  */
40
40
  export function formatContractForSystemPrompt(contract) {
41
41
  const lines = [
@@ -59,7 +59,7 @@ export function formatContractForSystemPrompt(contract) {
59
59
  }
60
60
  return lines.join("\n");
61
61
  }
62
- /** Derive a flat string[] of criterion texts for the existing HarnessLoop criteria API. */
62
+ /** Derive a flat string[] of criterion texts for RuntimeRunner criteria input. */
63
63
  export function contractToCriteriaStrings(contract) {
64
64
  return contract.acceptance.map(c => c.text);
65
65
  }
@@ -1,12 +1,10 @@
1
1
  import type { ContractCheckResult, VerificationContract } from "./contract.js";
2
- import type { DreamResult } from "../memory/protocols.js";
3
2
  /**
4
3
  * HandoffArtifact — the single exchange token between sprints and agent instances.
5
4
  *
6
5
  * All handoff paths converge here:
7
- * - ContractDrivenHarness completion → HandoffBus.fromContractOutcome()
6
+ * - CreatorVerifier AttemptLoop completion → HandoffBus.fromContractOutcome()
8
7
  * - Sub-agent completion → HandoffBus.fromSubAgentResult()
9
- * - Dream consolidation → HandoffBus.fromDream()
10
8
  * - Context renewal (kernel) → carried in kernel's HandoffArtifact type
11
9
  *
12
10
  * The invariant: a HandoffArtifact tells the next agent not only *what was done*
@@ -41,7 +39,7 @@ export interface ContractOutcomeInput {
41
39
  */
42
40
  export declare class HandoffBus {
43
41
  /**
44
- * Build a HandoffArtifact from a ContractDrivenHarness outcome.
42
+ * Build a HandoffArtifact from a creator-verifier AttemptLoop outcome.
45
43
  * The artifact field is used as the progress summary.
46
44
  */
47
45
  static fromContractOutcome(input: ContractOutcomeInput): HandoffArtifact;
@@ -54,16 +52,6 @@ export declare class HandoffBus {
54
52
  finalMessage: string;
55
53
  sprint?: number;
56
54
  }): HandoffArtifact;
57
- /**
58
- * Build a HandoffArtifact from a dream consolidation result.
59
- * Used when the idle pipeline produces new memories that should be
60
- * carried into the next sprint's context.
61
- */
62
- static fromDream(opts: {
63
- goal: string;
64
- dreamResult: DreamResult;
65
- sprint?: number;
66
- }): HandoffArtifact;
67
55
  /**
68
56
  * Render the artifact as a compact injection string for the next agent's
69
57
  * working partition (not system — this is a handoff note, not a permanent rule).
@@ -7,7 +7,7 @@
7
7
  */
8
8
  export class HandoffBus {
9
9
  /**
10
- * Build a HandoffArtifact from a ContractDrivenHarness outcome.
10
+ * Build a HandoffArtifact from a creator-verifier AttemptLoop outcome.
11
11
  * The artifact field is used as the progress summary.
12
12
  */
13
13
  static fromContractOutcome(input) {
@@ -46,22 +46,6 @@ export class HandoffBus {
46
46
  blockedOn: [],
47
47
  };
48
48
  }
49
- /**
50
- * Build a HandoffArtifact from a dream consolidation result.
51
- * Used when the idle pipeline produces new memories that should be
52
- * carried into the next sprint's context.
53
- */
54
- static fromDream(opts) {
55
- return {
56
- goal: opts.goal,
57
- sprint: opts.sprint ?? 1,
58
- progressSummary: `Memory consolidated: ${opts.dreamResult.entriesAdded} added, ${opts.dreamResult.entriesRemoved} removed.`,
59
- openTasks: [],
60
- contractStatus: [],
61
- driftRate24h: 0,
62
- blockedOn: [],
63
- };
64
- }
65
49
  /**
66
50
  * Render the artifact as a compact injection string for the next agent's
67
51
  * working partition (not system — this is a handoff note, not a permanent rule).
@@ -1,11 +1,8 @@
1
- import type { AgentPool, CoordinatorConfig } from "./pool.js";
2
- import type { VerificationContract, ContractCheckResult } from "./contract.js";
1
+ import type { AttemptBody, AttemptBodyContext, AttemptBodyEvent } from "../harness/harness.js";
2
+ import type { AttemptJudge, JudgeContext, JudgeResult } from "../harness/judge.js";
3
+ import type { ContractCheckResult, VerificationContract } from "./contract.js";
3
4
  import type { HandoffArtifact } from "./handoff.js";
4
- export interface Violation {
5
- criterionId: string;
6
- text: string;
7
- detail: string;
8
- }
5
+ import type { AgentPool } from "./pool.js";
9
6
  export interface ContractOutcome {
10
7
  success: boolean;
11
8
  artifact: string;
@@ -14,45 +11,17 @@ export interface ContractOutcome {
14
11
  totalTokensConsumed: number;
15
12
  handoff: HandoffArtifact;
16
13
  }
17
- export interface ContractHarnessOptions {
18
- maxAttempts?: number;
19
- onViolation?: (violations: Violation[]) => void;
20
- /** When set with pool.configureCoordinator(), enables kernel spawn path. */
21
- coordinator?: CoordinatorConfig;
14
+ /** The creator-verifier body owns execution only; verification is an AttemptJudge. */
15
+ export declare class CreatorVerifierBody implements AttemptBody {
16
+ private readonly pool;
17
+ private readonly contract;
18
+ constructor(pool: AgentPool, contract: VerificationContract);
19
+ run(context: AttemptBodyContext): AsyncIterable<AttemptBodyEvent>;
22
20
  }
23
- /**
24
- * ContractDrivenHarness the core multi-agent execution primitive.
25
- *
26
- * Differs from HarnessLoop in three ways:
27
- * 1. Executor and verifier are **separate Agent instances** — no shared history.
28
- * 2. Verifier receives only the artifact + contract, not the implementation transcript.
29
- * 3. Feedback returned to the executor is a structured list of Violations,
30
- * not a free-text LLM summary.
31
- *
32
- * Protocol per attempt:
33
- * executor.run(goal, contract) → artifact
34
- * verifier.runIsolated(artifact, contract) → audit text
35
- * parse audit text → ContractCheckResult[]
36
- * all required criteria pass → Done
37
- * violations remain → inject only violation list into next executor goal
38
- * maxAttempts exceeded → produce HandoffArtifact with blocked_on
39
- */
40
- export declare class ContractDrivenHarness {
41
- private pool;
42
- private contract;
43
- private maxAttempts;
44
- private onViolation?;
45
- constructor(pool: AgentPool, contract: VerificationContract, options?: ContractHarnessOptions);
46
- stream(): AsyncIterable<ContractOutcome>;
47
- run(): Promise<ContractOutcome>;
48
- private _findViolations;
49
- private _formatViolationsForFeedback;
50
- /**
51
- * Parse the verifier's free-text audit into structured ContractCheckResult[].
52
- *
53
- * The verifier is prompted to produce a structured PASS/FAIL per criterion.
54
- * This parser handles the common patterns; callers can subclass and override
55
- * for stricter parsing.
56
- */
57
- private _parseAuditText;
21
+ /** Structured verifier output only. Free-text PASS/FAIL inference is intentionally unsupported. */
22
+ export declare class StructuredContractJudge implements AttemptJudge {
23
+ private readonly pool;
24
+ private readonly contract;
25
+ constructor(pool: AgentPool, contract: VerificationContract);
26
+ judge(context: JudgeContext): Promise<JudgeResult>;
58
27
  }
@@ -1,169 +1,68 @@
1
- import { collectText } from "../runtime/runner.js";
2
- import { formatContractForSystemPrompt, contractToCriteriaStrings } from "./contract.js";
3
- import { HandoffBus } from "./handoff.js";
4
- /**
5
- * ContractDrivenHarness — the core multi-agent execution primitive.
6
- *
7
- * Differs from HarnessLoop in three ways:
8
- * 1. Executor and verifier are **separate Agent instances** — no shared history.
9
- * 2. Verifier receives only the artifact + contract, not the implementation transcript.
10
- * 3. Feedback returned to the executor is a structured list of Violations,
11
- * not a free-text LLM summary.
12
- *
13
- * Protocol per attempt:
14
- * executor.run(goal, contract) → artifact
15
- * verifier.runIsolated(artifact, contract) → audit text
16
- * parse audit text → ContractCheckResult[]
17
- * all required criteria pass → Done
18
- * violations remain → inject only violation list into next executor goal
19
- * maxAttempts exceeded → produce HandoffArtifact with blocked_on
20
- */
21
- export class ContractDrivenHarness {
1
+ import { parseVerdict } from "../runtime/eval.js";
2
+ import { formatContractForSystemPrompt } from "./contract.js";
3
+ /** The creator-verifier body owns execution only; verification is an AttemptJudge. */
4
+ export class CreatorVerifierBody {
22
5
  pool;
23
6
  contract;
24
- maxAttempts;
25
- onViolation;
26
- constructor(pool, contract, options = {}) {
7
+ constructor(pool, contract) {
27
8
  this.pool = pool;
28
9
  this.contract = contract;
29
- this.maxAttempts = options.maxAttempts ?? 3;
30
- this.onViolation = options.onViolation;
31
- if (options.coordinator) {
32
- this.pool.configureCoordinator(options.coordinator.opts, options.coordinator.sessionId);
33
- }
34
- }
35
- async *stream() {
36
- yield await this.run();
37
10
  }
38
- async run() {
39
- let artifact = "";
40
- let checkResults = [];
41
- let attemptsUsed = 0;
42
- let currentGoal = this.contract.goal;
43
- for (let attempt = 1; attempt <= this.maxAttempts; attempt++) {
44
- attemptsUsed = attempt;
45
- // ── Phase 1: Executor ──────────────────────────────────────────────────
46
- // Executor sees: contract block + goal. No verifier history.
47
- const contractBlock = formatContractForSystemPrompt(this.contract);
48
- const violationNote = attempt > 1
49
- ? `\n\n[Previous attempt failed. Violations to fix:\n${this._formatViolationsForFeedback(checkResults)}]`
50
- : "";
51
- const executorGoal = `${contractBlock}\n\n---\n\n${currentGoal}${violationNote}`;
52
- if (this.pool.usesSpawnPath()) {
53
- const execResult = await this.pool.spawn("executor", executorGoal, {
54
- verificationContractId: this.contract.id,
55
- });
56
- artifact = execResult.result.finalMessage?.content ?? "";
57
- }
58
- else {
59
- artifact = await collectText(this.pool.get("executor").run({
60
- sessionId: crypto.randomUUID(),
61
- goal: executorGoal,
62
- criteria: contractToCriteriaStrings(this.contract),
63
- }));
64
- }
65
- // ── Phase 2: Verifier ──────────────────────────────────────────────────
66
- // Verifier sees: artifact + contract only. No executor history.
67
- const auditText = await this.pool.verify({ contract: this.contract, artifact });
68
- // ── Phase 3: Parse audit → ContractCheckResult[] ──────────────────────
69
- checkResults = this._parseAuditText(auditText);
70
- const violations = this._findViolations(checkResults);
71
- if (violations.length === 0) {
72
- // All required criteria passed
73
- return {
74
- success: true,
75
- artifact,
76
- checkResults,
77
- attemptsUsed,
78
- totalTokensConsumed: 0,
79
- handoff: HandoffBus.fromContractOutcome({
80
- contract: this.contract,
81
- checkResults,
82
- artifact,
83
- success: true,
84
- }),
85
- };
86
- }
87
- this.onViolation?.(violations);
88
- }
89
- // Max attempts exhausted
90
- const blockedOn = this._findViolations(checkResults).map(v => `[${v.criterionId}] ${v.text}: ${v.detail}`);
91
- return {
92
- success: false,
93
- artifact,
94
- checkResults,
95
- attemptsUsed,
96
- totalTokensConsumed: 0,
97
- handoff: HandoffBus.fromContractOutcome({
98
- contract: this.contract,
99
- checkResults,
100
- artifact,
101
- success: false,
102
- blockedOn,
103
- }),
11
+ async *run(context) {
12
+ const contractBlock = formatContractForSystemPrompt(this.contract);
13
+ const result = await this.pool.execute("executor", {
14
+ sessionId: context.sessionId,
15
+ goal: `${contractBlock}\n\n---\n\n${context.goal}`,
16
+ ...(context.contextInput ? { contextInput: context.contextInput } : {}),
17
+ verificationContractId: this.contract.id,
18
+ });
19
+ const artifact = result.result.finalMessage?.content ?? "";
20
+ if (artifact)
21
+ yield { type: "token", text: artifact };
22
+ yield {
23
+ type: "body_done",
24
+ runStatus: String(result.result.termination),
25
+ result: artifact,
26
+ turns: result.result.turnsUsed,
27
+ totalTokens: result.result.totalTokensUsed,
28
+ ...(result.submittedNodes?.length ? { submittedNodes: result.submittedNodes } : {}),
104
29
  };
105
30
  }
106
- _findViolations(results) {
107
- const violations = [];
108
- for (const result of results) {
109
- if (!result.passed) {
110
- const criterion = this.contract.acceptance.find(c => c.id === result.criterionId);
111
- if (criterion?.required) {
112
- violations.push({
113
- criterionId: result.criterionId,
114
- text: criterion.text,
115
- detail: result.evidence ?? "no evidence provided",
116
- });
117
- }
118
- }
119
- }
120
- return violations;
121
- }
122
- _formatViolationsForFeedback(results) {
123
- return this._findViolations(results)
124
- .map(v => `- [${v.criterionId}] ${v.text}: ${v.detail}`)
125
- .join("\n");
31
+ }
32
+ /** Structured verifier output only. Free-text PASS/FAIL inference is intentionally unsupported. */
33
+ export class StructuredContractJudge {
34
+ pool;
35
+ contract;
36
+ constructor(pool, contract) {
37
+ this.pool = pool;
38
+ this.contract = contract;
126
39
  }
127
- /**
128
- * Parse the verifier's free-text audit into structured ContractCheckResult[].
129
- *
130
- * The verifier is prompted to produce a structured PASS/FAIL per criterion.
131
- * This parser handles the common patterns; callers can subclass and override
132
- * for stricter parsing.
133
- */
134
- _parseAuditText(auditText) {
135
- const results = [];
136
- const lower = auditText.toLowerCase();
137
- for (const criterion of this.contract.acceptance) {
138
- // Look for explicit "id: PASS" or "id: FAIL" patterns from the verifier prompt
139
- const idPattern = new RegExp(`\\b${criterion.id.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\\b[^\\n]*?(pass|fail)`, "i");
140
- const match = auditText.match(idPattern);
141
- if (match) {
142
- const passed = match[1].toLowerCase() === "pass";
143
- // Extract the line as evidence
144
- const lineStart = auditText.lastIndexOf("\n", match.index ?? 0) + 1;
145
- const lineEnd = auditText.indexOf("\n", match.index ?? 0);
146
- const evidence = auditText.slice(lineStart, lineEnd > 0 ? lineEnd : undefined).trim();
147
- results.push({ criterionId: criterion.id, passed, evidence });
148
- }
149
- else {
150
- // Fallback: search for criterion text near PASS/FAIL keywords
151
- const textIdx = lower.indexOf(criterion.text.toLowerCase().slice(0, 30));
152
- if (textIdx !== -1) {
153
- const window = lower.slice(textIdx, textIdx + 200);
154
- const passed = window.includes("pass") && !window.includes("fail");
155
- results.push({ criterionId: criterion.id, passed, evidence: "inferred from context" });
156
- }
157
- else {
158
- // No mention found — conservative: treat as failed
159
- results.push({
160
- criterionId: criterion.id,
161
- passed: false,
162
- evidence: "criterion not mentioned in audit",
163
- });
164
- }
165
- }
40
+ async judge(context) {
41
+ const auditText = await this.pool.verify({ contract: this.contract, artifact: context.result });
42
+ const wire = JSON.parse(auditText);
43
+ if (typeof wire !== "object" || wire === null || Array.isArray(wire)) {
44
+ throw new Error("structured verifier output must be a JSON object");
166
45
  }
167
- return results;
46
+ const parsed = parseVerdict(auditText);
47
+ const details = this.contract.acceptance.map(criterion => {
48
+ const detail = parsed.details.find(candidate => candidate.criterion === criterion.id || candidate.criterion === criterion.text);
49
+ return detail
50
+ ? { ...detail, criterion: criterion.id }
51
+ : {
52
+ criterion: criterion.id,
53
+ passed: false,
54
+ score: 0,
55
+ feedback: "criterion missing from structured verifier output",
56
+ };
57
+ });
58
+ const requiredPassed = this.contract.acceptance.every((criterion, index) => !criterion.required || details[index].passed);
59
+ return {
60
+ verdict: {
61
+ passed: parsed.passed && requiredPassed,
62
+ overallScore: parsed.overallScore,
63
+ feedback: parsed.feedback,
64
+ details,
65
+ },
66
+ };
168
67
  }
169
68
  }
@@ -2,8 +2,8 @@ export type { AcceptanceCriterion, VerificationContract, ContractCheckResult, }
2
2
  export { ContractBuilder, formatContractForSystemPrompt, contractToCriteriaStrings, } from "./contract.js";
3
3
  export { AgentPool } from "./pool.js";
4
4
  export type { AgentRole, IsolatedVerifierContext } from "./pool.js";
5
- export { ContractDrivenHarness } from "./harness.js";
6
- export type { ContractOutcome, ContractHarnessOptions, Violation, } from "./harness.js";
5
+ export { CreatorVerifierBody, StructuredContractJudge } from "./harness.js";
6
+ export type { ContractOutcome } from "./harness.js";
7
7
  export { HandoffBus } from "./handoff.js";
8
8
  export type { HandoffArtifact, ContractOutcomeInput } from "./handoff.js";
9
9
  export { CreatorVerifierMode, OrchestrationMode } from "./modes/creator-verifier.js";
@@ -1,8 +1,7 @@
1
1
  export { ContractBuilder, formatContractForSystemPrompt, contractToCriteriaStrings, } from "./contract.js";
2
2
  // AgentPool
3
3
  export { AgentPool } from "./pool.js";
4
- // ContractDrivenHarness
5
- export { ContractDrivenHarness } from "./harness.js";
4
+ export { CreatorVerifierBody, StructuredContractJudge } from "./harness.js";
6
5
  // HandoffBus
7
6
  export { HandoffBus } from "./handoff.js";
8
7
  // Collaboration modes