@tangle-network/agent-runtime 0.60.0 → 0.61.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 (53) hide show
  1. package/dist/agent.d.ts +1 -1
  2. package/dist/agent.js +1 -2
  3. package/dist/agent.js.map +1 -1
  4. package/dist/analyst-loop.d.ts +1 -1
  5. package/dist/{chunk-IN7WHMGZ.js → chunk-5V343QPB.js} +47 -7
  6. package/dist/chunk-5V343QPB.js.map +1 -0
  7. package/dist/chunk-7IXF3VUJ.js +59 -0
  8. package/dist/chunk-7IXF3VUJ.js.map +1 -0
  9. package/dist/{chunk-ZWGEA722.js → chunk-AU5MCNHO.js} +2 -2
  10. package/dist/chunk-IBRJTG7O.js +475 -0
  11. package/dist/chunk-IBRJTG7O.js.map +1 -0
  12. package/dist/{chunk-MMDIORZY.js → chunk-Q5R33I7Y.js} +4 -23
  13. package/dist/chunk-Q5R33I7Y.js.map +1 -0
  14. package/dist/{chunk-45D64J7B.js → chunk-VCOT7XEQ.js} +190 -99
  15. package/dist/chunk-VCOT7XEQ.js.map +1 -0
  16. package/dist/coder-DD5J5Onk.d.ts +52 -0
  17. package/dist/coordination-k29badiX.d.ts +381 -0
  18. package/dist/{delegates-C94qchkz.d.ts → delegates-CWMv_rKL.d.ts} +649 -21
  19. package/dist/index.d.ts +9 -6
  20. package/dist/index.js +9 -9
  21. package/dist/intelligence.d.ts +1 -1
  22. package/dist/{loop-runner-bin-Noz7P-mS.d.ts → loop-runner-bin-Bqt0hiNY.d.ts} +46 -12
  23. package/dist/loop-runner-bin.d.ts +7 -4
  24. package/dist/loop-runner-bin.js +4 -4
  25. package/dist/loops.d.ts +7 -6
  26. package/dist/loops.js +17 -6
  27. package/dist/mcp/bin.js +10 -10
  28. package/dist/mcp/bin.js.map +1 -1
  29. package/dist/mcp/index.d.ts +12 -12
  30. package/dist/mcp/index.js +7 -7
  31. package/dist/{openai-tools-d4GKwgya.d.ts → openai-tools-CA2N3-Ak.d.ts} +1 -1
  32. package/dist/profiles.d.ts +7 -9
  33. package/dist/profiles.js +5 -7
  34. package/dist/profiles.js.map +1 -1
  35. package/dist/{run-loop-CcqfR_gy.d.ts → run-loop-D3PwlG7J.d.ts} +1 -1
  36. package/dist/runtime.d.ts +30 -1046
  37. package/dist/runtime.js +17 -6
  38. package/dist/{types-CUzjRFZ3.d.ts → types-Crxftafi.d.ts} +2 -2
  39. package/dist/workflow.d.ts +2 -2
  40. package/dist/workflow.js +1 -2
  41. package/dist/workflow.js.map +1 -1
  42. package/dist/worktree-fanout-CBULEoVe.d.ts +1098 -0
  43. package/package.json +1 -1
  44. package/dist/chunk-45D64J7B.js.map +0 -1
  45. package/dist/chunk-4FEUFYOY.js +0 -282
  46. package/dist/chunk-4FEUFYOY.js.map +0 -1
  47. package/dist/chunk-7QYOXFCD.js +0 -293
  48. package/dist/chunk-7QYOXFCD.js.map +0 -1
  49. package/dist/chunk-IN7WHMGZ.js.map +0 -1
  50. package/dist/chunk-MMDIORZY.js.map +0 -1
  51. package/dist/coder-CybltHEm.d.ts +0 -163
  52. package/dist/coordination-Biw19JzN.d.ts +0 -944
  53. /package/dist/{chunk-ZWGEA722.js.map → chunk-AU5MCNHO.js.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/mcp/in-process-executor.ts","../src/mcp/bin-helpers.ts","../src/mcp/trace-propagation.ts"],"sourcesContent":["/**\n * @experimental\n *\n * In-process delegation executor — when `agent-runtime-mcp` runs inside a sandbox whose image\n * carries the local coding-harness CLIs (claude / codex / opencode), delegations spawn the harness\n * AS A SUBPROCESS against a git worktree on the SAME filesystem instead of provisioning a sibling\n * sandbox. Zero provisioning latency; worker diffs land in-place; multi-harness fanout = N parallel\n * subprocesses in N parallel worktrees (round-robin `harnesses`).\n *\n * This is a THIN adapter over `runWorktreeHarness` (`./worktree-harness`) — the SAME core the\n * `Scope` leaf `createWorktreeCliExecutor` uses. It only adapts the core to the `SandboxClient`\n * port: `create()` reads the authored profile from `CreateSandboxOptions.backend.profile`, and\n * `streamPrompt` runs the core then emits its raw `WorktreeHarnessResult` (the content-addressed\n * patch artifact) on the `result` event. The sandbox-session decode layer\n * (`./detached-coder`) projects that artifact onto `CoderOutput`; the generic `Scope` path settles\n * the artifact directly. The §1.5 payload (systemPrompt + model) reaches the harness inside the core.\n */\n\nimport { randomUUID } from 'node:crypto'\nimport type {\n AgentProfile,\n CreateSandboxOptions,\n SandboxEvent,\n SandboxInstance,\n} from '@tangle-network/sandbox'\nimport type { LoopSandboxPlacement, SandboxClient } from '../runtime'\nimport type { DelegationExecutor } from './executor'\nimport type { LocalHarness } from './local-harness'\nimport type { GitRunner, WorktreeHandle } from './worktree'\nimport { runWorktreeHarness } from './worktree-harness'\n\n/** @experimental */\nexport interface InProcessExecutorOptions {\n /** Absolute path to the git repo (the workspace). Worktrees go under `<repoRoot>/.agent-worktrees/`. */\n repoRoot: string\n /** Harnesses to round-robin across `create()` calls. One entry = no fanout. Default `['claude']`. */\n harnesses?: ReadonlyArray<LocalHarness>\n /** Optional per-delegation test command run in the worktree after the harness exits. */\n testCmd?: string\n /** Optional per-delegation typecheck command. Same shape as `testCmd`. */\n typecheckCmd?: string\n /** Wall-clock cap per harness subprocess (ms). Default 5min. */\n harnessTimeoutMs?: number\n /** Wall-clock cap per test/typecheck subprocess (ms). Default 2min. */\n postCheckTimeoutMs?: number\n /** Test seam — override the git runner used by the worktree helpers. */\n runGit?: GitRunner\n /** Test seam — override the harness runner (defaults to the real CLI via `runLocalHarness`). */\n runHarness?: typeof import('./local-harness').runLocalHarness\n /** Test seam — override the post-check runner (defaults to a `sh -c` spawn). A throw is folded\n * into a non-fatal `{exitCode:-1}` so a broken check command fails the signal, not the run. */\n runPostCheck?: (\n cmd: string,\n cwd: string,\n signal?: AbortSignal,\n ) => Promise<{ exitCode: number; stdout: string; stderr: string }>\n}\n\n/** @experimental */\nexport interface InProcessExecutorDescribePlacement extends LoopSandboxPlacement {\n /** Worktree path in the parent sandbox's filesystem (set so traces correlate to on-disk artifacts). */\n worktreePath?: string\n /** Which harness handled this delegation. */\n harness?: LocalHarness\n}\n\ninterface VirtualSandbox extends SandboxInstance {\n __inProcess: {\n runId: string\n harness: LocalHarness\n worktree?: WorktreeHandle\n }\n}\n\nconst DEFAULT_HARNESS_TIMEOUT_MS = 5 * 60 * 1000\nconst DEFAULT_POSTCHECK_TIMEOUT_MS = 2 * 60 * 1000\n\n/**\n * Build an in-process executor. Returns a {@link DelegationExecutor} whose `client.create()`\n * returns a minimal virtual `SandboxInstance`; the kernel calls `streamPrompt(msg)` on it, which\n * runs the shared worktree-harness core and emits one `result` event whose `data.result` is the\n * raw `WorktreeHarnessResult` (the content-addressed patch artifact). The authored profile\n * (`backend.profile`) threads its systemPrompt + model into the harness via the core.\n *\n * @experimental\n */\nexport function createInProcessExecutor(options: InProcessExecutorOptions): DelegationExecutor {\n const harnesses =\n options.harnesses && options.harnesses.length > 0\n ? [...options.harnesses]\n : (['claude'] as const)\n const runPostCheck = options.runPostCheck ?? defaultRunPostCheck\n // The core speaks one `runCommand` seam ({exitCode, output}); adapt the post-check seam\n // ({exitCode, stdout, stderr}) onto it, folding a throw into a non-fatal failure signal so a\n // broken check command fails the signal rather than aborting the whole delegation.\n const runCommand = async ({\n command,\n cwd,\n signal,\n }: {\n command: string\n cwd: string\n timeoutMs: number\n signal?: AbortSignal\n }): Promise<{ exitCode: number | null; output: string }> => {\n try {\n const r = await runPostCheck(command, cwd, signal)\n return { exitCode: r.exitCode, output: r.stderr || r.stdout }\n } catch (err) {\n return { exitCode: -1, output: err instanceof Error ? err.message : String(err) }\n }\n }\n\n let callIndex = 0\n\n const client: SandboxClient = {\n async create(opts?: CreateSandboxOptions): Promise<SandboxInstance> {\n const runId = randomUUID()\n const harness = harnesses[callIndex % harnesses.length] as LocalHarness\n callIndex += 1\n // §1.5: the authored profile rides in `backend.profile` (set by `buildBackendOptions`).\n // Without one (a direct test `create()`), fall back to a name-only profile → the harness\n // sees the task prompt with no system prepend, the pre-fix behavior.\n const profile =\n ((opts?.backend as { profile?: AgentProfile } | undefined)?.profile as\n | AgentProfile\n | undefined) ?? ({ name: `in-process-${harness}` } as AgentProfile)\n\n const virtual: VirtualSandbox = {\n id: `in-process-${runId}`,\n __inProcess: { runId, harness },\n async *streamPrompt(\n this: VirtualSandbox,\n message: string | unknown[],\n promptOpts?: { signal?: AbortSignal },\n ): AsyncGenerator<SandboxEvent> {\n const taskPrompt =\n typeof message === 'string'\n ? message\n : message\n .map((p) =>\n typeof p === 'object' && p && 'text' in p\n ? String((p as { text: unknown }).text)\n : '',\n )\n .join('\\n')\n\n // The shared worktree-harness core: worktree → profile-aware harness → diff → checks.\n // A throw cleans up inside the core; on success we own the teardown (the finally).\n const run = await runWorktreeHarness({\n repoRoot: options.repoRoot,\n profile,\n harness,\n taskPrompt,\n runId,\n harnessTimeoutMs: options.harnessTimeoutMs ?? DEFAULT_HARNESS_TIMEOUT_MS,\n checkTimeoutMs: options.postCheckTimeoutMs ?? DEFAULT_POSTCHECK_TIMEOUT_MS,\n ...(options.testCmd !== undefined ? { testCmd: options.testCmd } : {}),\n ...(options.typecheckCmd !== undefined ? { typecheckCmd: options.typecheckCmd } : {}),\n ...(options.runGit ? { runGit: options.runGit } : {}),\n ...(options.runHarness ? { runHarness: options.runHarness } : {}),\n runCommand,\n ...(promptOpts?.signal ? { signal: promptOpts.signal } : {}),\n })\n this.__inProcess.worktree = run.worktree\n\n try {\n yield {\n type: 'in_process.harness.started',\n data: { runId, harness, worktreePath: run.worktree.path, command: harness },\n }\n const h = run.result.harness\n yield {\n type: 'in_process.harness.ended',\n data: {\n runId,\n exitCode: h.exitCode,\n durationMs: h.durationMs,\n killedBySignal: h.killedBySignal,\n timedOut: h.timedOut,\n stdoutBytes: h.stdout.length,\n stderrBytes: h.stderr.length,\n },\n }\n yield {\n type: 'result',\n data: {\n result: run.result,\n source: 'in-process-executor',\n harness,\n runId,\n },\n }\n } finally {\n await run.cleanup()\n }\n },\n } as unknown as VirtualSandbox\n\n return virtual\n },\n describePlacement(box: SandboxInstance): InProcessExecutorDescribePlacement {\n const sandboxId = (box as unknown as { id?: string }).id\n const meta = (box as VirtualSandbox).__inProcess\n return {\n kind: 'sibling',\n sandboxId,\n worktreePath: meta?.worktree?.path,\n harness: meta?.harness,\n }\n },\n }\n\n return {\n client,\n placement: 'in-process',\n describe(): string {\n return `in-process (repoRoot=${options.repoRoot}, harnesses=[${harnesses.join(',')}]${\n options.testCmd ? `, testCmd=\"${options.testCmd}\"` : ''\n }${options.typecheckCmd ? `, typecheckCmd=\"${options.typecheckCmd}\"` : ''})`\n },\n }\n}\n\nasync function defaultRunPostCheck(\n cmd: string,\n cwd: string,\n signal?: AbortSignal,\n): Promise<{ exitCode: number; stdout: string; stderr: string }> {\n const { spawn } = await import('node:child_process')\n return new Promise((resolve, reject) => {\n const child = spawn('sh', ['-c', cmd], { cwd, stdio: 'pipe' })\n let stdout = ''\n let stderr = ''\n child.stdout?.on('data', (c) => {\n stdout += String(c)\n })\n child.stderr?.on('data', (c) => {\n stderr += String(c)\n })\n if (signal) {\n const onAbort = () => {\n if (!child.killed) child.kill('SIGTERM')\n }\n if (signal.aborted) onAbort()\n else signal.addEventListener('abort', onAbort, { once: true })\n }\n const killTimer = setTimeout(() => {\n if (!child.killed) child.kill('SIGTERM')\n }, DEFAULT_POSTCHECK_TIMEOUT_MS)\n if (typeof (killTimer as { unref?: () => void }).unref === 'function') {\n ;(killTimer as { unref: () => void }).unref()\n }\n child.on('error', (err) => {\n clearTimeout(killTimer)\n reject(err)\n })\n child.on('close', (code) => {\n clearTimeout(killTimer)\n resolve({ exitCode: code ?? -1, stdout, stderr })\n })\n })\n}\n","/**\n * @experimental\n *\n * Helpers extracted from `bin.ts` so the env-detection + executor-selection\n * logic is unit-testable without spawning a subprocess. The bin imports from\n * here; tests import from here directly.\n */\n\nimport type { SandboxClient } from '../runtime'\nimport {\n createFleetWorkspaceExecutor,\n createSiblingSandboxExecutor,\n type DelegationExecutor,\n type FleetHandle,\n} from './executor'\nimport { createInProcessExecutor } from './in-process-executor'\nimport type { LocalHarness } from './local-harness'\n\n/** @experimental */\nexport interface DetectExecutorArgs {\n sandboxClient: SandboxClient\n /** Raw env (defaults to `process.env`). Pass an explicit map for tests. */\n env?: Record<string, string | undefined>\n /**\n * Override how a fleet handle is resolved from the client + fleet id. The\n * default reads `client.fleets.get(fleetId)` and validates the returned\n * shape against the structural `FleetHandle` contract.\n */\n resolveFleet?: (client: SandboxClient, fleetId: string) => Promise<FleetHandle>\n}\n\n/**\n * Pick the right executor for an MCP server invocation based on env vars.\n *\n * - `TANGLE_FLEET_ID` set → fleet-workspace placement; resolves the handle\n * via `sandboxClient.fleets.get(...)`.\n * - Otherwise → sibling-sandbox placement; each delegation creates a fresh\n * sandbox via `sandboxClient.create(...)`.\n *\n * Fails loud (throws) when fleet mode is requested but the SDK shape is\n * incompatible — the operator chose fleet semantics, silently degrading to\n * sibling mode would lie about workspace topology.\n *\n * @experimental\n */\nexport async function detectExecutor(args: DetectExecutorArgs): Promise<DelegationExecutor> {\n const env = args.env ?? process.env\n\n // In-process (Phase 2.8): parent harness sets AGENT_RUNTIME_IN_SANDBOX=1\n // and points us at the workspace root. Highest-priority — when this is\n // set, delegations spawn local harness CLIs on git worktrees in the\n // SAME filesystem instead of provisioning sibling sandboxes.\n if (env.AGENT_RUNTIME_IN_SANDBOX === '1') {\n const repoRoot = env.AGENT_RUNTIME_REPO_ROOT?.trim()\n if (!repoRoot) {\n throw new Error(\n 'agent-runtime-mcp: AGENT_RUNTIME_IN_SANDBOX=1 requires AGENT_RUNTIME_REPO_ROOT to point at the workspace root',\n )\n }\n return createInProcessExecutor({\n repoRoot,\n harnesses: parseHarnesses(env.AGENT_RUNTIME_LOCAL_HARNESSES),\n testCmd: env.AGENT_RUNTIME_TEST_CMD?.trim() || undefined,\n typecheckCmd: env.AGENT_RUNTIME_TYPECHECK_CMD?.trim() || undefined,\n })\n }\n\n const fleetId = parseFleetId(env.TANGLE_FLEET_ID)\n if (!fleetId) {\n return createSiblingSandboxExecutor({ client: args.sandboxClient })\n }\n const resolveFleet = args.resolveFleet ?? defaultResolveFleet\n const fleet = await resolveFleet(args.sandboxClient, fleetId)\n const excludeMachineIds = parseList(env.TANGLE_FLEET_EXCLUDE_MACHINES)\n return createFleetWorkspaceExecutor({\n fleet,\n excludeMachineIds,\n })\n}\n\nconst KNOWN_HARNESSES: ReadonlyArray<LocalHarness> = ['claude', 'codex', 'opencode']\n\nfunction parseHarnesses(raw: string | undefined): ReadonlyArray<LocalHarness> | undefined {\n if (!raw) return undefined\n const parts = raw\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean)\n if (parts.length === 0) return undefined\n for (const part of parts) {\n if (!KNOWN_HARNESSES.includes(part as LocalHarness)) {\n throw new Error(\n `agent-runtime-mcp: AGENT_RUNTIME_LOCAL_HARNESSES contains unknown harness \"${part}\". Expected: ${KNOWN_HARNESSES.join(', ')}.`,\n )\n }\n }\n return parts as LocalHarness[]\n}\n\ninterface FleetsApi {\n get(fleetId: string): Promise<unknown>\n}\n\nasync function defaultResolveFleet(\n sandboxClient: SandboxClient,\n fleetId: string,\n): Promise<FleetHandle> {\n const fleets = (sandboxClient as unknown as { fleets?: FleetsApi }).fleets\n if (!fleets || typeof fleets.get !== 'function') {\n throw new Error(\n 'agent-runtime-mcp: the configured sandbox client does not expose `.fleets.get`; upgrade @tangle-network/sandbox to >= 0.2.1 or unset TANGLE_FLEET_ID.',\n )\n }\n const raw = await fleets.get(fleetId)\n if (!raw || typeof raw !== 'object') {\n throw new Error(`agent-runtime-mcp: fleets.get(${fleetId}) returned no handle`)\n }\n const handle = raw as Partial<FleetHandle>\n if (typeof handle.fleetId !== 'string' || !Array.isArray(handle.ids)) {\n throw new Error(\n `agent-runtime-mcp: fleet handle for ${fleetId} is missing fleetId/ids — incompatible sandbox SDK shape`,\n )\n }\n if (typeof handle.sandbox !== 'function') {\n throw new Error(\n `agent-runtime-mcp: fleet handle for ${fleetId} is missing sandbox(machineId) — incompatible sandbox SDK shape`,\n )\n }\n return handle as FleetHandle\n}\n\nfunction parseFleetId(raw: string | undefined): string | undefined {\n if (typeof raw !== 'string') return undefined\n const trimmed = raw.trim()\n return trimmed.length > 0 ? trimmed : undefined\n}\n\nfunction parseList(raw: string | undefined): string[] | undefined {\n if (!raw) return undefined\n const list = raw\n .split(',')\n .map((entry) => entry.trim())\n .filter(Boolean)\n return list.length > 0 ? list : undefined\n}\n","/**\n * @experimental\n *\n * Trace context propagation for MCP subprocess.\n *\n * When the MCP server is launched as a child process by a sandbox harness,\n * the parent passes trace context via environment variables:\n *\n * TRACE_ID=<current-run-trace-id>\n * PARENT_SPAN_ID=<span-that-dispatched-the-delegation>\n *\n * The MCP server reads these at startup and uses them as the root of its\n * internal trace tree. All spans emitted by `runLoop` invocations inside\n * the MCP are children of the parent's delegation span.\n *\n * When these env vars are absent, the MCP generates a fresh trace root —\n * the server operates standalone without trace joining.\n */\n\nimport type { OtelExporter } from '../otel-export'\nimport { buildLoopOtelSpans, createOtelExporter } from '../otel-export'\nimport type { LoopTraceEmitter, LoopTraceEvent } from '../runtime/types'\n\nexport interface TraceContext {\n /** Trace id inherited from the parent process, or a fresh one. */\n traceId: string\n /** Parent span id from the delegation that launched this MCP server. */\n parentSpanId?: string\n}\n\n/**\n * Read trace context from the process environment.\n * Returns a context with inherited ids or a freshly generated root.\n */\nexport function readTraceContextFromEnv(): TraceContext {\n const traceId = process.env.TRACE_ID || generateTraceId()\n const parentSpanId = process.env.PARENT_SPAN_ID || undefined\n return { traceId, parentSpanId }\n}\n\n/**\n * Create a LoopTraceEmitter that:\n * 1. Parents all spans under the inherited PARENT_SPAN_ID.\n * 2. Exports spans to OTEL when OTEL_EXPORTER_OTLP_ENDPOINT is set.\n *\n * Returns both the emitter and the optional exporter handle for shutdown.\n */\nexport function createPropagatingTraceEmitter(ctx: TraceContext): {\n emitter: LoopTraceEmitter\n exporter: OtelExporter | undefined\n context: TraceContext\n} {\n const exporter = createOtelExporter()\n\n // Buffer events per loop run, then emit the full nested span tree on\n // `loop.ended` so the topology hierarchy (loop → round → branch) reaches the\n // OTLP collector — not a flat list of zero-duration point spans. A run that\n // never reaches `loop.ended` (hard abort) drops its buffer; acceptable for\n // the short-lived MCP subprocess.\n const buffers = new Map<string, LoopTraceEvent[]>()\n\n const emitter: LoopTraceEmitter = {\n emit(event: LoopTraceEvent) {\n if (!exporter) return\n const buf = buffers.get(event.runId)\n if (buf) buf.push(event)\n else buffers.set(event.runId, [event])\n if (event.kind === 'loop.ended') {\n const events = buffers.get(event.runId) ?? [event]\n buffers.delete(event.runId)\n for (const span of buildLoopOtelSpans(events, ctx.traceId, ctx.parentSpanId)) {\n exporter.exportSpan(span)\n }\n }\n },\n }\n\n return { emitter, exporter, context: ctx }\n}\n\n/**\n * Build env vars to pass to a child MCP subprocess so it inherits the\n * current trace context.\n */\nexport function traceContextToEnv(ctx: TraceContext): Record<string, string> {\n const env: Record<string, string> = { TRACE_ID: ctx.traceId }\n if (ctx.parentSpanId) env.PARENT_SPAN_ID = ctx.parentSpanId\n return env\n}\n\nfunction generateTraceId(): string {\n const bytes = new Uint8Array(16)\n if (typeof globalThis.crypto?.getRandomValues === 'function') {\n globalThis.crypto.getRandomValues(bytes)\n } else {\n for (let i = 0; i < 16; i++) bytes[i] = Math.floor(Math.random() * 256)\n }\n return Array.from(bytes)\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('')\n}\n"],"mappings":"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","names":[]}
@@ -1,6 +1,3 @@
1
- import {
2
- runCoderChecks
3
- } from "./chunk-7QYOXFCD.js";
4
1
  import {
5
2
  UI_LENSES
6
3
  } from "./chunk-WIR4HOOJ.js";
@@ -2572,6 +2569,31 @@ function errMessage(err) {
2572
2569
  }
2573
2570
 
2574
2571
  // src/runtime/personify/combinators.ts
2572
+ function selectValidWinner(opts) {
2573
+ const strategy = opts?.strategy ?? "highest-score";
2574
+ const sizeOfIter = (iter) => {
2575
+ const out = iter.output;
2576
+ if (out === void 0 || opts?.sizeOf === void 0) return Number.POSITIVE_INFINITY;
2577
+ const deliverable = out.kind === "done" ? out.deliverable : out;
2578
+ return opts.sizeOf(deliverable);
2579
+ };
2580
+ return (iterations) => {
2581
+ const valid = iterations.filter(
2582
+ (iter) => iter.output !== void 0 && !iter.error && iter.verdict?.valid === true
2583
+ );
2584
+ if (valid.length === 0) return void 0;
2585
+ switch (strategy) {
2586
+ case "first-valid":
2587
+ return [...valid].sort((a, b) => a.index - b.index)[0];
2588
+ case "smallest-artifact":
2589
+ return [...valid].sort((a, b) => sizeOfIter(a) - sizeOfIter(b) || a.index - b.index)[0];
2590
+ default:
2591
+ return [...valid].sort(
2592
+ (a, b) => (b.verdict?.score ?? 0) - (a.verdict?.score ?? 0) || a.index - b.index
2593
+ )[0];
2594
+ }
2595
+ };
2596
+ }
2575
2597
  function pipeline(stages) {
2576
2598
  if (stages.length === 0) {
2577
2599
  throw new ValidationError("pipeline: at least one stage is required");
@@ -3500,7 +3522,7 @@ function ensureGitOk(step, result) {
3500
3522
  }
3501
3523
  }
3502
3524
  async function createWorktree(options) {
3503
- const variants = options.variantsDir ?? ".coder-variants";
3525
+ const variants = options.variantsDir ?? ".agent-worktrees";
3504
3526
  const baseRef = options.baseRef ?? "HEAD";
3505
3527
  const branch = `delegate/${options.runId}`;
3506
3528
  const path2 = `${options.repoRoot.replace(/\/+$/, "")}/${variants}/${options.runId}`;
@@ -6880,98 +6902,6 @@ function authoredWorker(profile, opts) {
6880
6902
  return { name: profile.name, act: async () => "", executorSpec: spec };
6881
6903
  }
6882
6904
 
6883
- // src/runtime/supervise/coder-deliverable.ts
6884
- function coderDeliverable(options = {}) {
6885
- const require2 = new Set(options.require ?? []);
6886
- const constraints = {
6887
- ...options.maxDiffLines !== void 0 ? { maxDiffLines: options.maxDiffLines } : {},
6888
- ...options.forbiddenPaths !== void 0 ? { forbiddenPaths: options.forbiddenPaths } : {}
6889
- };
6890
- return {
6891
- describe: "coder patch: no-op/secret/forbidden/diff-size + required test/typecheck pass",
6892
- check(artifact) {
6893
- const input = {
6894
- patch: artifact.patch,
6895
- testsPassed: signalPass(artifact.checks?.tests?.passed, require2.has("tests")),
6896
- typecheckPassed: signalPass(artifact.checks?.typecheck?.passed, require2.has("typecheck"))
6897
- };
6898
- return runCoderChecks(input, constraints).valid === true;
6899
- }
6900
- };
6901
- }
6902
- function signalPass(value, required) {
6903
- if (value !== void 0) return value;
6904
- return !required;
6905
- }
6906
-
6907
- // src/runtime/supervise/coder-fanout.ts
6908
- function worktreeCoderFanout(options) {
6909
- const deliverable = coderDeliverable({
6910
- ...options.maxDiffLines !== void 0 ? { maxDiffLines: options.maxDiffLines } : {},
6911
- ...options.forbiddenPaths !== void 0 ? { forbiddenPaths: options.forbiddenPaths } : {},
6912
- ...options.require !== void 0 ? { require: options.require } : {}
6913
- });
6914
- const itemSpec = (item) => {
6915
- const executor = gateOnDeliverable(
6916
- createWorktreeCliExecutor({
6917
- repoRoot: options.repoRoot,
6918
- profile: item.profile,
6919
- harness: item.harness,
6920
- taskPrompt: options.taskPrompt,
6921
- ...item.runId ? { runId: item.runId } : {},
6922
- ...item.baseRef ? { baseRef: item.baseRef } : {},
6923
- ...options.testCmd !== void 0 ? { testCmd: options.testCmd } : {},
6924
- ...options.typecheckCmd !== void 0 ? { typecheckCmd: options.typecheckCmd } : {},
6925
- ...options.harnessTimeoutMs !== void 0 ? { harnessTimeoutMs: options.harnessTimeoutMs } : {},
6926
- ...options.runGit ? { runGit: options.runGit } : {},
6927
- ...options.runHarness ? { runHarness: options.runHarness } : {},
6928
- ...options.runCommand ? { runCommand: options.runCommand } : {}
6929
- }),
6930
- deliverable
6931
- );
6932
- return { profile: item.profile, harness: null, executor };
6933
- };
6934
- const selectWinner = winnerSelectorFor(options.winnerStrategy ?? "highest-score");
6935
- return fanout(options.harnesses, {
6936
- itemTask: () => options.taskPrompt,
6937
- label: (item, i) => `${item.name}:${i}`,
6938
- itemSpec: (item) => itemSpec(item),
6939
- selectWinner
6940
- });
6941
- }
6942
- function winnerSelectorFor(strategy) {
6943
- return (iterations) => {
6944
- const valid = iterations.filter(
6945
- (iter) => iter.output !== void 0 && !iter.error && iter.verdict?.valid === true
6946
- );
6947
- if (valid.length === 0) return void 0;
6948
- switch (strategy) {
6949
- case "first-valid":
6950
- return [...valid].sort((a, b) => a.index - b.index)[0];
6951
- case "smallest-diff":
6952
- return [...valid].sort((a, b) => diffLines(a) - diffLines(b) || a.index - b.index)[0];
6953
- default:
6954
- return [...valid].sort(
6955
- (a, b) => (b.verdict?.score ?? 0) - (a.verdict?.score ?? 0) || a.index - b.index
6956
- )[0];
6957
- }
6958
- };
6959
- }
6960
- function diffLines(iter) {
6961
- const artifact = artifactOf(iter.output);
6962
- if (!artifact) return Number.POSITIVE_INFINITY;
6963
- return artifact.stats.insertions + artifact.stats.deletions;
6964
- }
6965
- function artifactOf(output) {
6966
- if (!output) return void 0;
6967
- if (isArtifact(output)) return output;
6968
- if (output.kind === "done" && isArtifact(output.deliverable)) return output.deliverable;
6969
- return void 0;
6970
- }
6971
- function isArtifact(value) {
6972
- return value !== null && typeof value === "object" && typeof value.patch === "string" && typeof value.stats === "object";
6973
- }
6974
-
6975
6905
  // src/runtime/supervise/event-bus.ts
6976
6906
  function createEventBus(now = Date.now) {
6977
6907
  const queue = [];
@@ -9734,6 +9664,122 @@ function watchTrace(source, opts = {}) {
9734
9664
  });
9735
9665
  }
9736
9666
 
9667
+ // src/runtime/supervise/patch-checks.ts
9668
+ var DEFAULT_MAX_DIFF_LINES = 400;
9669
+ var secretPathPattern = /(^|\/)(\.env(\.|$)|.*\.(pem|key|p12|pfx|keystore|wallet)|id_rsa|id_ed25519|secrets?\.json|credentials?\.json)$/i;
9670
+ function touchedPathsFromPatch(patch) {
9671
+ const out = /* @__PURE__ */ new Set();
9672
+ for (const line of patch.split(/\r?\n/)) {
9673
+ if (line.startsWith("+++ ") || line.startsWith("--- ")) {
9674
+ const rest = line.slice(4).trim();
9675
+ if (rest === "/dev/null") continue;
9676
+ const stripped = rest.startsWith("a/") || rest.startsWith("b/") ? rest.slice(2) : rest;
9677
+ out.add(stripped);
9678
+ }
9679
+ }
9680
+ return [...out];
9681
+ }
9682
+ function countDiffLines(patch) {
9683
+ let count = 0;
9684
+ for (const line of patch.split(/\r?\n/)) {
9685
+ if ((line.startsWith("+") || line.startsWith("-")) && !line.startsWith("+++") && !line.startsWith("---")) {
9686
+ count += 1;
9687
+ }
9688
+ }
9689
+ return count;
9690
+ }
9691
+ function isNonEmptyPatch(patch) {
9692
+ return touchedPathsFromPatch(patch).length > 0 && patch.trim().length > 0;
9693
+ }
9694
+ function touchesSecretPath(patch) {
9695
+ return touchedPathsFromPatch(patch).filter((p) => secretPathPattern.test(p));
9696
+ }
9697
+ function runCoderChecks(input, constraints = {}) {
9698
+ const maxDiff = constraints.maxDiffLines ?? DEFAULT_MAX_DIFF_LINES;
9699
+ const forbidden = constraints.forbiddenPaths ?? [];
9700
+ const scores = {};
9701
+ const notes = [];
9702
+ let pass = true;
9703
+ const touched = touchedPathsFromPatch(input.patch);
9704
+ if (touched.length === 0 || input.patch.trim().length === 0) {
9705
+ pass = false;
9706
+ scores.nonEmpty = 0;
9707
+ notes.push("empty patch \u2014 no files changed");
9708
+ } else {
9709
+ scores.nonEmpty = 1;
9710
+ }
9711
+ const touchedSecrets = touched.filter((p) => secretPathPattern.test(p));
9712
+ if (touchedSecrets.length > 0) {
9713
+ pass = false;
9714
+ scores.noSecrets = 0;
9715
+ notes.push(`touched secret-shaped paths: ${touchedSecrets.join(", ")}`);
9716
+ } else {
9717
+ scores.noSecrets = 1;
9718
+ }
9719
+ const touchedForbidden = forbidden.filter((path2) => {
9720
+ const prefix = path2.endsWith("/") ? path2 : `${path2}/`;
9721
+ const exact = prefix.slice(0, -1);
9722
+ return touched.some((p) => p === exact || p.startsWith(prefix));
9723
+ });
9724
+ if (touchedForbidden.length > 0) {
9725
+ pass = false;
9726
+ scores.forbiddenPath = 0;
9727
+ notes.push(`touched forbidden paths: ${touchedForbidden.join(", ")}`);
9728
+ } else {
9729
+ scores.forbiddenPath = 1;
9730
+ }
9731
+ const diffLines = countDiffLines(input.patch);
9732
+ if (diffLines > maxDiff) {
9733
+ pass = false;
9734
+ scores.diffSize = 0;
9735
+ notes.push(`diff ${diffLines} lines exceeds cap ${maxDiff}`);
9736
+ } else {
9737
+ scores.diffSize = maxDiff === 0 ? 0 : Math.max(0, 1 - diffLines / maxDiff);
9738
+ }
9739
+ scores.tests = input.testsPassed ? 1 : 0;
9740
+ scores.typecheck = input.typecheckPassed ? 1 : 0;
9741
+ if (!input.testsPassed) {
9742
+ pass = false;
9743
+ notes.push("tests failed");
9744
+ }
9745
+ if (!input.typecheckPassed) {
9746
+ pass = false;
9747
+ notes.push("typecheck failed");
9748
+ }
9749
+ const score = 0.5 * scores.tests + 0.3 * scores.typecheck + 0.2 * scores.diffSize;
9750
+ const verdict = {
9751
+ valid: pass,
9752
+ score: Number.isFinite(score) ? score : 0,
9753
+ scores
9754
+ };
9755
+ if (notes.length > 0) verdict.notes = notes.join("; ");
9756
+ return verdict;
9757
+ }
9758
+
9759
+ // src/runtime/supervise/patch-deliverable.ts
9760
+ function patchDelivered(options = {}) {
9761
+ const require2 = new Set(options.require ?? []);
9762
+ const constraints = {
9763
+ ...options.maxDiffLines !== void 0 ? { maxDiffLines: options.maxDiffLines } : {},
9764
+ ...options.forbiddenPaths !== void 0 ? { forbiddenPaths: options.forbiddenPaths } : {}
9765
+ };
9766
+ return {
9767
+ describe: "patch: no-op/secret/forbidden/diff-size + required test/typecheck pass",
9768
+ check(artifact) {
9769
+ const input = {
9770
+ patch: artifact.patch,
9771
+ testsPassed: signalPass(artifact.checks?.tests?.passed, require2.has("tests")),
9772
+ typecheckPassed: signalPass(artifact.checks?.typecheck?.passed, require2.has("typecheck"))
9773
+ };
9774
+ return runCoderChecks(input, constraints).valid === true;
9775
+ }
9776
+ };
9777
+ }
9778
+ function signalPass(value, required) {
9779
+ if (value !== void 0) return value;
9780
+ return !required;
9781
+ }
9782
+
9737
9783
  // src/runtime/supervise/router-driver-chat.ts
9738
9784
  function routerDriverChat(c, opts = {}) {
9739
9785
  const temperature = opts.temperature ?? 0.4;
@@ -9982,6 +10028,45 @@ async function analyzeTrace(source, runId = "worker") {
9982
10028
  return { trajectory, stuckLoop, toolWaste };
9983
10029
  }
9984
10030
 
10031
+ // src/runtime/supervise/worktree-fanout.ts
10032
+ function worktreeFanout(options) {
10033
+ const deliverable = options.deliverable ?? patchDelivered({
10034
+ ...options.maxDiffLines !== void 0 ? { maxDiffLines: options.maxDiffLines } : {},
10035
+ ...options.forbiddenPaths !== void 0 ? { forbiddenPaths: options.forbiddenPaths } : {},
10036
+ ...options.require !== void 0 ? { require: options.require } : {}
10037
+ });
10038
+ const itemSpec = (item) => {
10039
+ const executor = gateOnDeliverable(
10040
+ createWorktreeCliExecutor({
10041
+ repoRoot: options.repoRoot,
10042
+ profile: item.profile,
10043
+ harness: item.harness,
10044
+ taskPrompt: options.taskPrompt,
10045
+ ...item.runId ? { runId: item.runId } : {},
10046
+ ...item.baseRef ? { baseRef: item.baseRef } : {},
10047
+ ...options.testCmd !== void 0 ? { testCmd: options.testCmd } : {},
10048
+ ...options.typecheckCmd !== void 0 ? { typecheckCmd: options.typecheckCmd } : {},
10049
+ ...options.harnessTimeoutMs !== void 0 ? { harnessTimeoutMs: options.harnessTimeoutMs } : {},
10050
+ ...options.runGit ? { runGit: options.runGit } : {},
10051
+ ...options.runHarness ? { runHarness: options.runHarness } : {},
10052
+ ...options.runCommand ? { runCommand: options.runCommand } : {}
10053
+ }),
10054
+ deliverable
10055
+ );
10056
+ return { profile: item.profile, harness: null, executor };
10057
+ };
10058
+ const selectWinner = selectValidWinner({
10059
+ strategy: options.winnerStrategy ?? "highest-score",
10060
+ sizeOf: (a) => a.stats.insertions + a.stats.deletions
10061
+ });
10062
+ return fanout(options.harnesses, {
10063
+ itemTask: () => options.taskPrompt,
10064
+ label: (item, i) => `${item.name}:${i}`,
10065
+ itemSpec: (item) => itemSpec(item),
10066
+ selectWinner
10067
+ });
10068
+ }
10069
+
9985
10070
  // src/runtime/verifier-environment.ts
9986
10071
  var submitTool = {
9987
10072
  type: "function",
@@ -10311,6 +10396,7 @@ export {
10311
10396
  nestedScopeSeamKey,
10312
10397
  createScope,
10313
10398
  settledToIteration,
10399
+ selectValidWinner,
10314
10400
  pipeline,
10315
10401
  fanout,
10316
10402
  loopUntil,
@@ -10372,8 +10458,6 @@ export {
10372
10458
  asAuthoredProfile,
10373
10459
  supervisorSkill,
10374
10460
  authoredWorker,
10375
- coderDeliverable,
10376
- worktreeCoderFanout,
10377
10461
  createEventBus,
10378
10462
  createCoordinationTools,
10379
10463
  coordinationDriverAgent,
@@ -10431,6 +10515,12 @@ export {
10431
10515
  serveCoordinationMcp,
10432
10516
  defaultToolDetectors,
10433
10517
  watchTrace,
10518
+ touchedPathsFromPatch,
10519
+ countDiffLines,
10520
+ isNonEmptyPatch,
10521
+ touchesSecretPath,
10522
+ runCoderChecks,
10523
+ patchDelivered,
10434
10524
  routerDriverChat,
10435
10525
  toToolSpan,
10436
10526
  decodeOpencodePart,
@@ -10442,6 +10532,7 @@ export {
10442
10532
  createPartsTraceSource,
10443
10533
  sandboxSessionTraceSource,
10444
10534
  analyzeTrace,
10535
+ worktreeFanout,
10445
10536
  createVerifierEnvironment,
10446
10537
  createWaterfallCollector,
10447
10538
  localShell,
@@ -10449,4 +10540,4 @@ export {
10449
10540
  jjWorkspace,
10450
10541
  runInWorkspace
10451
10542
  };
10452
- //# sourceMappingURL=chunk-45D64J7B.js.map
10543
+ //# sourceMappingURL=chunk-VCOT7XEQ.js.map