@tangle-network/agent-runtime 0.113.0 → 0.114.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 (63) hide show
  1. package/dist/{activation-DGozpA_7.js → activation-DlKl7-1o.js} +3 -3
  2. package/dist/{activation-DGozpA_7.js.map → activation-DlKl7-1o.js.map} +1 -1
  3. package/dist/agent.d.ts +18 -7
  4. package/dist/agent.js +123 -64
  5. package/dist/agent.js.map +1 -1
  6. package/dist/candidate-execution/index.js +4 -4
  7. package/dist/{candidate-execution-Co3sRC_7.js → candidate-execution-CfpJrd3o.js} +4 -4
  8. package/dist/{candidate-execution-Co3sRC_7.js.map → candidate-execution-CfpJrd3o.js.map} +1 -1
  9. package/dist/{environment-provider-BsHpW4Dp.js → environment-provider-CCaEhA-l.js} +38 -4
  10. package/dist/environment-provider-CCaEhA-l.js.map +1 -0
  11. package/dist/{environment-provider-DG-cSx89.d.ts → environment-provider-Cygthiy3.d.ts} +40 -1
  12. package/dist/environment-provider.d.ts +1 -1
  13. package/dist/environment-provider.js +1 -1
  14. package/dist/{improvement-cycle-DxBZsG33.js → improvement-cycle-vLye8pYb.js} +4 -4
  15. package/dist/{improvement-cycle-DxBZsG33.js.map → improvement-cycle-vLye8pYb.js.map} +1 -1
  16. package/dist/{index-DmXPCQ2X.d.ts → index-BLf-SZ2b.d.ts} +6 -6
  17. package/dist/{index-BdnhmGUH.d.ts → index-D-lNUfea.d.ts} +147 -9
  18. package/dist/{index-B-DkjCqQ.d.ts → index-YpvLKzIX.d.ts} +3 -3
  19. package/dist/index.d.ts +7 -7
  20. package/dist/index.js +11 -11
  21. package/dist/intelligence.d.ts +3 -3
  22. package/dist/intelligence.js +5 -5
  23. package/dist/kernel.d.ts +4 -4
  24. package/dist/kernel.js +7 -7
  25. package/dist/{knowledge-h7sDHsnd.js → knowledge-BTsA9n6L.js} +5 -5
  26. package/dist/{knowledge-h7sDHsnd.js.map → knowledge-BTsA9n6L.js.map} +1 -1
  27. package/dist/knowledge.d.ts +1 -1
  28. package/dist/knowledge.js +1 -1
  29. package/dist/{local-harness-Dh8PJ0ot.d.ts → local-harness-BnB1E9nM.d.ts} +92 -2
  30. package/dist/{loop-runner-bin-DN8491Y_.d.ts → loop-runner-bin-Cg_8UKZR.d.ts} +3 -3
  31. package/dist/{loop-runner-bin-D1TTr39X.js → loop-runner-bin-CuBMmlMJ.js} +3 -3
  32. package/dist/{loop-runner-bin-D1TTr39X.js.map → loop-runner-bin-CuBMmlMJ.js.map} +1 -1
  33. package/dist/loop-runner-bin.d.ts +1 -1
  34. package/dist/loop-runner-bin.js +1 -1
  35. package/dist/mcp/bin.js +1 -1
  36. package/dist/mcp/index.d.ts +2 -2
  37. package/dist/mcp/index.js +4 -4
  38. package/dist/{openai-tools-B1lRpTZr.js → openai-tools-VAbzps5G.js} +2 -2
  39. package/dist/{openai-tools-B1lRpTZr.js.map → openai-tools-VAbzps5G.js.map} +1 -1
  40. package/dist/{prepare-BKVdOn0w.js → prepare-BHQBb02e.js} +2 -2
  41. package/dist/{prepare-BKVdOn0w.js.map → prepare-BHQBb02e.js.map} +1 -1
  42. package/dist/primeintellect/index.d.ts +1 -1
  43. package/dist/{protected-model-port-BtldAE9j.js → protected-model-port-DqAH1Z2M.js} +2 -2
  44. package/dist/{protected-model-port-BtldAE9j.js.map → protected-model-port-DqAH1Z2M.js.map} +1 -1
  45. package/dist/{redact-BkasKlyd.d.ts → redact-BRaHUFMf.d.ts} +2 -2
  46. package/dist/{runtime-Cs2e63LL.js → runtime-DQ5seHEu.js} +8 -5
  47. package/dist/runtime-DQ5seHEu.js.map +1 -0
  48. package/dist/{spawn-journal-DLhnom3e.js → spawn-journal-DCPbicXB.js} +2 -1
  49. package/dist/{spawn-journal-DLhnom3e.js.map → spawn-journal-DCPbicXB.js.map} +1 -1
  50. package/dist/{structural-rollout-DXmSoA9q.js → structural-rollout-C7vF83fV.js} +3 -3
  51. package/dist/{structural-rollout-DXmSoA9q.js.map → structural-rollout-C7vF83fV.js.map} +1 -1
  52. package/dist/{supervise-S7glOjJH.js → supervise-tdxMJYem.js} +476 -31
  53. package/dist/supervise-tdxMJYem.js.map +1 -0
  54. package/dist/{supervisor-zebR4ICs.js → supervisor-DKqolBGI.js} +234 -23
  55. package/dist/supervisor-DKqolBGI.js.map +1 -0
  56. package/dist/testing.js +9 -9
  57. package/dist/{workspace-archive-CYYxZyA7.js → workspace-archive-DXzJq7WP.js} +2 -2
  58. package/dist/{workspace-archive-CYYxZyA7.js.map → workspace-archive-DXzJq7WP.js.map} +1 -1
  59. package/package.json +1 -1
  60. package/dist/environment-provider-BsHpW4Dp.js.map +0 -1
  61. package/dist/runtime-Cs2e63LL.js.map +0 -1
  62. package/dist/supervise-S7glOjJH.js.map +0 -1
  63. package/dist/supervisor-zebR4ICs.js.map +0 -1
package/dist/agent.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"agent.js","names":[],"sources":["../src/agent/surfaces.ts","../src/agent/define-agent.ts","../src/agent/improvement-adapter.ts","../src/agent/profile-materialization.ts","../src/agent/sandbox-act.ts"],"sourcesContent":["/**\n * `AgentSurfaces` — declarative map of the mutable file/directory paths\n * the self-improvement loop can edit on behalf of an agent.\n *\n * The substrate uses this map to resolve every parsed `FindingSubject`\n * (from agent-eval) to a real on-disk path. No per-vertical glue;\n * no fabricated paths; no silent `existsSync(...)` skips that hide\n * misconfiguration from the operator.\n *\n * Surfaces are validated at `defineAgent` time — missing paths fail\n * loud with a list of every offender. A surface that's not needed\n * (e.g. an agent with no RAG corpora) is simply omitted; the loop\n * refuses to route those subjects rather than fabricating a target.\n */\n\nimport { existsSync, statSync } from 'node:fs'\nimport { isAbsolute, join, relative, resolve, sep } from 'node:path'\nimport type { FindingSubject } from '@tangle-network/agent-eval'\n\n/**\n * Surface declarations. Every path is repo-relative (or absolute) at\n * `defineAgent` time. At resolution time, paths are joined against the\n * agent's `repoRoot`.\n *\n * `systemPrompt`, `tools`, `personas` are DIRECTORIES; the loop appends\n * `<section>.md`, `<tool>/README.md`, `<persona-id>.yaml` etc.\n * `rubric`, `outputSchema` are SINGLE FILES; the loop edits them in\n * place.\n *\n * `knowledge` is the agent-knowledge root (typically `.agent-knowledge`);\n * `applyKnowledgeWriteBlocks` writes pages relative to it.\n *\n * Optional surfaces (`scaffolding`, `memory`, `rag`, `outputSchema`)\n * can be omitted — the loop will reject findings targeting them with a\n * clear log message instead of fabricating a path.\n */\nexport interface AgentSurfaces {\n /** Directory containing one markdown file per system-prompt section. */\n systemPrompt: string\n /** Directory containing one subdir per tool (`<tool>/README.md`). */\n tools: string\n /** Single file (TypeScript module) defining the rubric weights + dimensions. */\n rubric: string\n /** Knowledge-base root; typically `.agent-knowledge`. */\n knowledge: string\n /** Directory containing one YAML/JSON file per persona. */\n personas: string\n /** Optional: directory containing scaffolding rules (precondition checks, retry policies). */\n scaffolding?: string\n /** Optional: memory store path (JSONL / SQLite / DB). */\n memory?: string\n /** Optional: directory containing RAG corpora (`<corpus>/<doc-id>.md`). */\n rag?: string\n /** Optional: single file defining the output schema (Zod / JSON Schema). */\n outputSchema?: string\n /** Optional: directory containing Agent Skill packages. */\n skills?: string\n /** Optional: directory containing MCP server/tool configuration. */\n mcp?: string\n /** Optional: directory containing hook definitions. */\n hooks?: string\n /** Optional: directory containing subagent definitions. */\n subagents?: string\n /** Optional: directory containing orchestration/workflow policies. */\n workflows?: string\n /** Optional: single file containing rollout-policy settings. */\n rolloutPolicy?: string\n /** Optional: single canonical AgentProfile file. */\n agentProfile?: string\n /** Optional: source root for code findings. */\n code?: string\n}\n\nexport interface ResolvedSurface {\n /** Absolute filesystem path the operator can `cat` / `vim`. */\n absolutePath: string\n /** Repo-relative path for PR descriptions, diffs, audit logs. */\n repoRelativePath: string\n /** Whether the path currently exists on disk. */\n exists: boolean\n /** The substrate's intent: edit an existing file or create a new one. */\n intent: 'edit-existing' | 'create-new'\n}\n\n/**\n * Resolve a parsed `FindingSubject` to the file path the substrate\n * should edit (or create) on disk.\n *\n * Returns `null` when:\n * - the subject targets a surface the agent didn't declare\n * (e.g. `rag:*` when `surfaces.rag` is undefined), OR\n * - the subject is a `cluster` (failure-mode emits these as evidence,\n * not actionable mutations — they don't route to a file).\n *\n * Returns a `ResolvedSurface` with `intent: 'create-new'` when the\n * subject names a path that doesn't yet exist (e.g. a new wiki page).\n * The caller chooses whether to honour the create — for tightly-managed\n * surfaces like `systemPrompt` it's usually a contract violation\n * (the analyst named a section that doesn't exist); for `knowledge`\n * it's the whole point.\n */\nexport function resolveSubjectPath(\n subject: FindingSubject,\n surfaces: AgentSurfaces,\n repoRoot: string,\n): ResolvedSurface | null {\n const candidates = candidatePathsForSubject(subject, surfaces)\n if (candidates.length === 0) return null\n\n // Probe candidates in order, preferring the first one that exists on disk.\n // Lets the substrate accept both the flat `<section>.md` convention and\n // the skill-dir `<section>/SKILL.md` convention without forcing one layout.\n // When none exists, fall back to the first candidate (canonical create-new).\n for (const rel of candidates) {\n const abs = isAbsolute(rel) ? rel : join(repoRoot, rel)\n if (existsSync(abs)) {\n return { absolutePath: abs, repoRelativePath: rel, exists: true, intent: 'edit-existing' }\n }\n }\n const fallback = candidates[0]!\n const fallbackAbs = isAbsolute(fallback) ? fallback : join(repoRoot, fallback)\n return {\n absolutePath: fallbackAbs,\n repoRelativePath: fallback,\n exists: false,\n intent: 'create-new',\n }\n}\n\nfunction candidatePathsForSubject(\n subject: FindingSubject,\n surfaces: AgentSurfaces,\n): ReadonlyArray<string> {\n switch (subject.kind) {\n case 'knowledge.wiki':\n case 'knowledge.stale':\n return optionalPath(safeJoin(surfaces.knowledge, `${subject.slug}.md`))\n case 'knowledge.claim':\n // Claims land in a per-topic claims directory under the knowledge root.\n return optionalPath(safeJoin(surfaces.knowledge, 'claims', `${slugify(subject.topic)}.md`))\n case 'knowledge.raw':\n return optionalPath(safeJoin(surfaces.knowledge, 'raw', `${subject.sourceId}.md`))\n case 'system-prompt': {\n const slug = slugify(subject.section)\n // Prefer flat layout for create-new (canonical); probe skill-dir layout\n // in case the existing repo (tax/legal/gtm/creative) uses\n // `<section>/SKILL.md` already.\n return [\n safeJoin(surfaces.systemPrompt, `${slug}.md`),\n safeJoin(surfaces.systemPrompt, slug, 'SKILL.md'),\n safeJoin(surfaces.systemPrompt, slug, 'index.md'),\n ].filter((path): path is string => path !== null)\n }\n case 'skill': {\n if (!surfaces.skills) return []\n return [\n safeJoin(surfaces.skills, subject.name, 'SKILL.md'),\n safeJoin(surfaces.skills, `${subject.name}.md`),\n ].filter((path): path is string => path !== null)\n }\n case 'tool-doc':\n if (subject.aspect) {\n return optionalPath(safeJoin(surfaces.tools, subject.tool, `${slugify(subject.aspect)}.md`))\n }\n // tool-doc default: `<tool>/README.md`; also probe `<tool>.md` for flat\n // tool-list repos.\n return [\n safeJoin(surfaces.tools, subject.tool, 'README.md'),\n safeJoin(surfaces.tools, `${subject.tool}.md`),\n ].filter((path): path is string => path !== null)\n case 'new-tool':\n return optionalPath(safeJoin(surfaces.tools, subject.name, 'README.md'))\n case 'mcp':\n if (!surfaces.mcp) return []\n return subject.tool\n ? optionalPath(safeJoin(surfaces.mcp, subject.server, `${subject.tool}.md`))\n : [\n safeJoin(surfaces.mcp, `${subject.server}.json`),\n safeJoin(surfaces.mcp, subject.server, 'README.md'),\n ].filter((path): path is string => path !== null)\n case 'hook':\n if (!surfaces.hooks) return []\n return [\n safeJoin(surfaces.hooks, `${subject.name}.md`),\n safeJoin(surfaces.hooks, `${subject.name}.json`),\n ].filter((path): path is string => path !== null)\n case 'subagent':\n if (!surfaces.subagents) return []\n return [\n safeJoin(surfaces.subagents, `${subject.name}.md`),\n safeJoin(surfaces.subagents, `${subject.name}.yaml`),\n safeJoin(surfaces.subagents, `${subject.name}.json`),\n ].filter((path): path is string => path !== null)\n case 'workflow':\n if (!surfaces.workflows) return []\n return [\n safeJoin(surfaces.workflows, `${subject.name}.md`),\n safeJoin(surfaces.workflows, `${subject.name}.yaml`),\n safeJoin(surfaces.workflows, `${subject.name}.json`),\n ].filter((path): path is string => path !== null)\n case 'rollout-policy':\n return surfaces.rolloutPolicy ? [surfaces.rolloutPolicy] : []\n case 'agent-profile':\n return surfaces.agentProfile ? [surfaces.agentProfile] : []\n case 'code': {\n if (!surfaces.code) return []\n const path = safeJoin(surfaces.code, subject.path)\n return path ? [path] : []\n }\n case 'rag':\n if (!surfaces.rag) return []\n return optionalPath(safeJoin(surfaces.rag, subject.corpus, `${subject.docId}.md`))\n case 'memory':\n if (!surfaces.memory) return []\n return optionalPath(safeJoin(surfaces.memory, `${slugify(subject.key)}.json`))\n case 'scaffolding':\n if (!surfaces.scaffolding) return []\n return optionalPath(safeJoin(surfaces.scaffolding, `${slugify(subject.concern)}.md`))\n case 'output-schema':\n if (!surfaces.outputSchema) return []\n return [surfaces.outputSchema]\n case 'websearch.outdated':\n case 'prior-run-summary':\n // Stale signals don't map to a single file — handled by the knowledge\n // adapter as `agent-knowledge:stale:*` after operator review.\n return []\n case 'cluster':\n // failure-mode cluster labels are evidence, not mutations.\n return []\n }\n}\n\nfunction safeJoin(root: string, ...children: string[]): string | null {\n if (children.some((child) => child.includes('\\0') || isAbsolute(child))) return null\n const rootAbsolute = resolve(root)\n const targetAbsolute = resolve(rootAbsolute, ...children)\n const escaped = relative(rootAbsolute, targetAbsolute)\n if (escaped === '..' || escaped.startsWith(`..${sep}`) || isAbsolute(escaped)) return null\n return join(root, ...children)\n}\n\nfunction optionalPath(path: string | null): string[] {\n return path ? [path] : []\n}\n\nfunction slugify(s: string): string {\n return (\n s\n .toLowerCase()\n .replace(/[^a-z0-9-]+/g, '-')\n .replace(/^-+|-+$/g, '')\n .slice(0, 200) || 'untitled'\n )\n}\n\n/**\n * Validate that every declared surface exists on disk under `repoRoot`.\n *\n * Returns an array of `SurfaceValidationIssue` — empty when all required\n * surfaces resolve. `defineAgent` throws with the issues rendered, so\n * a misconfigured manifest fails at startup (not at the first finding\n * the loop produces 20 minutes later).\n */\nexport interface SurfaceValidationIssue {\n surface: keyof AgentSurfaces\n path: string\n reason: 'missing' | 'not-directory' | 'not-file'\n}\n\n/** Validate an `AgentSurfaces` map on disk — missing paths fail loud at `defineAgent` time instead of silently skipping self-improvement edits. */\nexport function validateSurfaces(\n surfaces: AgentSurfaces,\n repoRoot: string,\n): ReadonlyArray<SurfaceValidationIssue> {\n const issues: SurfaceValidationIssue[] = []\n const dirSurfaces: ReadonlyArray<keyof AgentSurfaces> = [\n 'systemPrompt',\n 'tools',\n 'personas',\n 'knowledge',\n ]\n const fileSurfaces: ReadonlyArray<keyof AgentSurfaces> = ['rubric']\n const optionalDirSurfaces: ReadonlyArray<keyof AgentSurfaces> = [\n 'scaffolding',\n 'memory',\n 'rag',\n 'skills',\n 'mcp',\n 'hooks',\n 'subagents',\n 'workflows',\n 'code',\n ]\n const optionalFileSurfaces: ReadonlyArray<keyof AgentSurfaces> = [\n 'outputSchema',\n 'rolloutPolicy',\n 'agentProfile',\n ]\n\n for (const key of dirSurfaces) {\n const p = surfaces[key] as string | undefined\n if (!p) {\n issues.push({ surface: key, path: '', reason: 'missing' })\n continue\n }\n const abs = isAbsolute(p) ? p : join(repoRoot, p)\n if (!existsSync(abs)) {\n issues.push({ surface: key, path: p, reason: 'missing' })\n } else if (!statSync(abs).isDirectory()) {\n issues.push({ surface: key, path: p, reason: 'not-directory' })\n }\n }\n for (const key of fileSurfaces) {\n const p = surfaces[key] as string | undefined\n if (!p) {\n issues.push({ surface: key, path: '', reason: 'missing' })\n continue\n }\n const abs = isAbsolute(p) ? p : join(repoRoot, p)\n if (!existsSync(abs)) {\n issues.push({ surface: key, path: p, reason: 'missing' })\n } else if (!statSync(abs).isFile()) {\n issues.push({ surface: key, path: p, reason: 'not-file' })\n }\n }\n for (const key of [...optionalDirSurfaces, ...optionalFileSurfaces]) {\n const p = surfaces[key] as string | undefined\n if (p === undefined) continue\n const abs = isAbsolute(p) ? p : join(repoRoot, p)\n if (!existsSync(abs)) {\n issues.push({ surface: key, path: p, reason: 'missing' })\n continue\n }\n const expectedDirectory = optionalDirSurfaces.includes(key)\n if (expectedDirectory && !statSync(abs).isDirectory()) {\n issues.push({ surface: key, path: p, reason: 'not-directory' })\n } else if (!expectedDirectory && !statSync(abs).isFile()) {\n issues.push({ surface: key, path: p, reason: 'not-file' })\n }\n }\n return issues\n}\n\n/** Format a list of surface validation issues into a human-readable error string. */\nexport function renderSurfaceIssues(\n issues: ReadonlyArray<SurfaceValidationIssue>,\n repoRoot: string,\n): string {\n if (issues.length === 0) return ''\n const lines = issues.map(\n (i) => ` - ${i.surface}: ${i.path ? `\"${i.path}\"` : '<not set>'} (${i.reason})`,\n )\n return [\n `Agent surface validation failed against repoRoot=${repoRoot}:`,\n ...lines,\n '',\n 'Fix the manifest: every required surface must point at an existing',\n 'directory (systemPrompt / tools / personas / knowledge) or file',\n '(rubric). Optional surfaces (scaffolding / memory / rag / outputSchema)',\n 'may be omitted; the loop will reject findings targeting omitted',\n 'surfaces rather than fabricating a path.',\n ].join('\\n')\n}\n","/**\n * `defineAgent` — typed, validated manifest API for declarative agent\n * configuration. The substrate consumes this manifest to wire the\n * canonical eval pattern + analyst self-improvement loop without any\n * per-vertical glue.\n *\n * Design goal: scale to 1000s of vertical agents. Every agent declares\n * its surfaces, rubric, runtime, and analyst configuration in ~50 lines.\n * No per-vertical `ImprovementProposalSource`. No per-vertical CLI. No\n * fabricated paths.\n *\n * Validation: `defineAgent` runs `validateSurfaces` synchronously and\n * throws a structured error if any required surface is missing on\n * disk. The cost is one filesystem stat per surface (cheap); the\n * benefit is a manifest that can't ship broken.\n */\n\nimport type { TraceAnalystDefinition } from '@tangle-network/agent-eval'\nimport type { RuntimeStreamEvent } from '../types'\nimport { type AgentSurfaces, renderSurfaceIssues, validateSurfaces } from './surfaces'\n\n// ── manifest ─────────────────────────────────────────────────────────\n\n/**\n * The full agent manifest. Each agent ships ONE of these.\n *\n * Generics:\n * `TPersona` — the agent's persona shape (loaded from\n * `surfaces.personas`). Defaults to `unknown` so the substrate's\n * persona discovery (`loadPersonas`) can accept anything; per-agent\n * code re-narrows when it matters.\n * `TRunOutput` — the shape `runtime.act` returns. Used by the rubric\n * scorers and emitted into the trace.\n */\nexport interface AgentManifest<TPersona = unknown, TRunOutput = unknown> {\n /**\n * Stable identifier — used as `projectId` in traces, as the analyst\n * loop's `runId` prefix, and as the namespace under which findings\n * are persisted. MUST match the agent's repo name to keep\n * cross-repo telemetry joinable.\n */\n id: string\n\n /**\n * Filesystem root the substrate resolves surface paths against.\n * Typically `process.cwd()` or a fixed absolute path. Use an\n * absolute path when the agent's tests may run from subdirectories\n * (vitest sometimes shifts cwd).\n */\n repoRoot: string\n\n /**\n * Map of mutable surfaces the self-improvement loop can edit. See\n * `AgentSurfaces` — required: `systemPrompt`, `tools`, `rubric`,\n * `knowledge`, `personas`. Optional: `scaffolding`, `memory`, `rag`,\n * `outputSchema`.\n *\n * Every required path is validated at `defineAgent` time. Missing\n * paths throw with the full list of offenders.\n */\n surfaces: AgentSurfaces\n\n /**\n * Rubric the substrate uses to score each run. Dimensions × weights\n * × judges. The substrate computes the weighted composite and\n * stamps it into the RunRecord.\n */\n rubric: AgentRubric<TRunOutput>\n\n /**\n * Runtime adapter — how the substrate INVOKES the agent against a\n * persona. The `act` function takes a persona + a context (with the\n * tracer the substrate threads through for span emission) and\n * returns the run output the rubric will score.\n *\n * The agent's existing production runtime goes in here; the\n * substrate is intentionally thin around it.\n */\n runtime: AgentRuntime<TPersona, TRunOutput>\n\n /**\n * Persona discovery — the substrate loads personas via this function\n * at eval start. Can read from `surfaces.personas`, an API, or be\n * hardcoded. The substrate calls it once per `runAgentEval` call;\n * persona ordering is preserved.\n */\n personas: () => Promise<ReadonlyArray<TPersona>>\n\n /**\n * Analyst kinds the substrate runs against each persona's trace.\n * Defaults to `DEFAULT_TRACE_ANALYST_KINDS` from agent-eval. Per-agent\n * authors can prune (e.g. skip `knowledge-poisoning` when there's no\n * knowledge base) or extend (custom domain kinds).\n *\n * Empty array disables the loop — useful for `pnpm eval --no-analyst`.\n */\n analystKinds: ReadonlyArray<TraceAnalystDefinition>\n\n /**\n * Analyst LLM configuration. The substrate uses these for all four\n * kinds (override per-kind via `analystKinds` if needed).\n */\n analyst: AnalystConfig\n}\n\nexport interface AgentRubric<TRunOutput> {\n /** Dimensions composing the weighted score. Weights sum to 1.0 by convention. */\n dimensions: ReadonlyArray<RubricDimension<TRunOutput>>\n /**\n * Optional judges layered on top of deterministic dimensions. Each\n * judge returns a score per dimension; the substrate averages judges\n * (mean by default) for the LLM contribution.\n */\n judges?: ReadonlyArray<JudgeConfig<TRunOutput>>\n}\n\nexport interface RubricDimension<TRunOutput> {\n /** Unique identifier — appears in finding subjects (`rubric:<id>`). */\n id: string\n /** 0..1 — weight in the composite. */\n weight: number\n /**\n * Deterministic scorer: given the persona + run output, returns a\n * 0..1 score. The substrate sums weight × score across dimensions\n * for the deterministic composite; judges supplement subjective dims.\n */\n score: (input: { persona: unknown; output: TRunOutput }) => number\n /** Optional human-readable label for reports. */\n label?: string\n}\n\nexport interface JudgeConfig<TRunOutput> {\n /** Judge identifier — appears in trace spans + manifest. */\n id: string\n /** Model snapshot to invoke. Pin the snapshot (`claude-sonnet-4-6@2025-04-15`); the validator rejects bare aliases. */\n model: string\n /** Dimensions this judge scores. */\n dimensions: ReadonlyArray<string>\n /**\n * Optional rubric anchors — text examples the judge sees as a\n * few-shot prompt to calibrate. STRONGLY recommended for subjective\n * dimensions; required by the calibration gate (Pearson ≥0.7).\n */\n anchors?: ReadonlyArray<{ input: string; output: TRunOutput; expected: Record<string, number> }>\n}\n\nexport interface AgentRuntime<TPersona, TRunOutput> {\n /**\n * Invoke the agent against one persona. Returns BOTH:\n * - `events`: an `AsyncIterable<RuntimeStreamEvent>` the chat-centric\n * product consumes verbatim (SSE / WebSocket / inline render).\n * **Streaming is mandatory — never collapse this to a single Promise.**\n * The agent's existing `runChatTurn` (or equivalent async generator)\n * plugs in here directly.\n * - `output`: a `Promise<TRunOutput>` resolved AFTER the event stream\n * drains. The eval substrate awaits this for rubric scoring; chat\n * products usually ignore it (they already rendered incrementally).\n *\n * Implementation contract:\n * 1. `act` MUST return immediately (synchronous construction of the\n * `events` iterator + the `output` promise).\n * 2. Iterating `events` drives the underlying LLM/tool calls — the\n * caller chooses when to consume.\n * 3. `output` resolves only after the iterator yields its terminal\n * event (typically `task_end`); see `collectAgentRun` helper.\n *\n * `ctx.emitter` is the substrate-threaded `TraceEmitter` — runtimes\n * SHOULD record LLM/tool spans through it for capture integrity.\n * `ctx.deadlineMs` is wall-clock; the runtime SHOULD honour for graceful\n * cancel. `ctx.signal` is the standard abort signal.\n */\n act: (persona: TPersona, ctx: AgentRunContext) => AgentRunInvocation<TRunOutput>\n}\n\nexport interface AgentRunInvocation<TRunOutput> {\n /** Live stream of typed runtime events. Consumed by chat UX directly. */\n events: AsyncIterable<RuntimeStreamEvent>\n /** Final structured output the rubric scores. Resolves after `events` drains. */\n output: Promise<TRunOutput>\n}\n\n/**\n * Stub for agents whose `runtime.act` is not yet wired to the substrate's\n * eval path. Preserves the streaming contract (empty event stream + a\n * rejected `output` promise that tells the caller exactly what to fix).\n *\n * Per-vertical manifests usually start with this stub and replace it with\n * the agent's real streaming runtime (`runChatTurn` or equivalent) once\n * the eval path consumes the manifest end-to-end.\n */\nexport function unimplementedAgentRun<TRunOutput = unknown>(\n reason = 'AgentRuntime.act is not yet wired for this manifest',\n): AgentRunInvocation<TRunOutput> {\n return {\n events: (async function* empty(): AsyncIterable<RuntimeStreamEvent> {})(),\n output: Promise.reject(new Error(reason)),\n }\n}\n\n/**\n * Drain `act`'s `events` into an array AND await its `output`. Useful for\n * eval / outcome-measurement code paths that don't care about live\n * rendering. The events array is preserved so the substrate can inspect\n * tool calls / readiness / questions retrospectively.\n *\n * IMPORTANT: chat-centric UX MUST NOT call this — it defeats streaming\n * (no incremental render). Use `for await (const ev of invocation.events)`\n * directly in the chat surface.\n */\nexport async function collectAgentRun<TRunOutput>(\n invocation: AgentRunInvocation<TRunOutput>,\n): Promise<{ events: ReadonlyArray<RuntimeStreamEvent>; output: TRunOutput }> {\n const events: RuntimeStreamEvent[] = []\n for await (const ev of invocation.events) events.push(ev)\n const output = await invocation.output\n return { events, output }\n}\n\nexport interface AgentRunContext {\n /** Substrate-managed trace emitter. */\n emitter: import('@tangle-network/agent-eval').TraceEmitter\n /** Stable run id for this persona × variant cell. */\n runId: string\n /** Variant the runtime is exercising (e.g. `'baseline'`, `'source-grounded'`). */\n variantId?: string\n /** Wall-clock deadline (epoch ms). The runtime SHOULD honour for graceful cancel. */\n deadlineMs?: number\n /** Optional abort signal. */\n signal?: AbortSignal\n}\n\nexport interface AnalystConfig {\n /** Model the analyst kinds use. Override per-kind via `analystKinds[i].cost.models`. */\n model: string\n /** Optional total budget across all kinds for one run. Substrate enforces via `BudgetGuard`. */\n budgetUsd?: number\n /** Backend hint for the AxAIService factory — same shape every kind uses. */\n backend?: {\n name?: 'openai' | 'router'\n apiKey?: string\n baseUrl?: string\n }\n}\n\n// ── factory + validation ─────────────────────────────────────────────\n\n/** Thrown when `defineAgent` finds a required surface missing on disk. */\nexport class AgentManifestError extends Error {\n constructor(\n message: string,\n public readonly agentId: string,\n public readonly issues: ReadonlyArray<unknown> = [],\n ) {\n super(message)\n this.name = 'AgentManifestError'\n }\n}\n\n/**\n * Construct a validated agent manifest. Throws `AgentManifestError`\n * if any required surface is missing on disk.\n *\n * Generics: pass your persona / output types if you want narrowed\n * `runtime.act` signatures:\n * `defineAgent<TaxPersona, TaxRunOutput>({ ... })`\n *\n * Most callers don't need the generics — the substrate operates on\n * `unknown` payloads internally and the manifest's `score` /\n * `runtime.act` see the typed shapes via TypeScript inference at\n * the call site.\n */\nexport function defineAgent<TPersona = unknown, TRunOutput = unknown>(\n manifest: AgentManifest<TPersona, TRunOutput>,\n): AgentManifest<TPersona, TRunOutput> {\n if (!manifest.id || manifest.id.trim().length === 0) {\n throw new AgentManifestError('defineAgent: `id` is required', manifest.id ?? '')\n }\n if (!manifest.repoRoot || manifest.repoRoot.trim().length === 0) {\n throw new AgentManifestError('defineAgent: `repoRoot` is required', manifest.id)\n }\n const issues = validateSurfaces(manifest.surfaces, manifest.repoRoot)\n if (issues.length > 0) {\n throw new AgentManifestError(\n renderSurfaceIssues(issues, manifest.repoRoot),\n manifest.id,\n issues,\n )\n }\n // Lightweight rubric sanity: weights sum to ~1.0 (no hard requirement —\n // the substrate normalizes — but flag wildly miscalibrated weights).\n const total = manifest.rubric.dimensions.reduce((acc, d) => acc + d.weight, 0)\n if (manifest.rubric.dimensions.length > 0 && (total < 0.5 || total > 1.5)) {\n throw new AgentManifestError(\n `defineAgent(${manifest.id}): rubric dimension weights sum to ${total.toFixed(3)} — should be ~1.0`,\n manifest.id,\n )\n }\n return manifest\n}\n","/**\n * Surface improvement proposer — resolves analyst findings into LLM-drafted\n * candidate patches without changing the caller's repository.\n *\n * The proposer parses each finding's `subject` via\n * `parseFindingSubject` (agent-eval), resolves it to a real file path\n * via the agent's `AgentSurfaces`, reads the current content, and asks\n * an LLM to draft a unified-diff patch given the finding + current\n * content + per-kind editing-discipline rules.\n *\n * Fail-loud rules:\n * - Findings whose subject doesn't parse → counted in `errors`.\n * - Findings whose subject targets an undeclared surface → counted in\n * `errors` with the offending kind in the message.\n * - Findings whose target path doesn't exist AND the kind isn't a\n * create-new variant (`new-tool`, `knowledge.wiki`) → counted in\n * `errors` with the resolved path in the message.\n * - LLM drafts that fail JSON-schema validation → counted in\n * `errors` with the schema issue.\n *\n * No silent skips. Every dropped finding has a recorded reason the\n * loop's report surfaces.\n */\n\nimport { createHash } from 'node:crypto'\nimport { readFileSync } from 'node:fs'\nimport type { AnalystFinding, FindingSubject } from '@tangle-network/agent-eval'\nimport { parseFindingSubject } from '@tangle-network/agent-eval/analyst'\nimport type { ImprovementProposalSource } from '../analyst-loop/types'\nimport type { AgentSurfaces, ResolvedSurface } from './surfaces'\nimport { resolveSubjectPath } from './surfaces'\n\n// ── proposal shape ───────────────────────────────────────────────────\n\nexport interface SurfaceImprovementEdit {\n /** Stable id derived from the source finding so re-proposals are idempotent. */\n id: string\n /** The finding that produced this edit — for revert + audit trail. */\n sourceFindingId: string\n /** Parsed subject; included so the apply step doesn't re-parse. */\n subject: FindingSubject\n /** Resolved on-disk target. */\n target: ResolvedSurface\n /** SHA-256 of the current file content the patch was drafted against. */\n baseSha256: string\n /** Unified-diff patch the LLM drafted (relative to `target.absolutePath`). */\n patch: string\n /** One-line summary the operator sees in the report / PR title. */\n summary: string\n /** Multi-line rationale for the PR body — finding context + LLM reasoning. */\n rationale: string\n /** Carry-forward from the finding so the apply gate can check the threshold. */\n confidence: number\n /** Carry-forward severity for prioritization. */\n severity: AnalystFinding['severity']\n}\n\nexport interface CreateSurfaceImprovementProposerOptions {\n surfaces: AgentSurfaces\n repoRoot: string\n /**\n * LLM-draft callback. Given a finding + current file content + the\n * resolved target, returns a unified-diff patch + summary + rationale.\n *\n * Required — the substrate doesn't ship a hardcoded prompt; the agent\n * author picks the model (Haiku for cheap routine drafts, Sonnet for\n * substantive prompt rewrites, etc.) via this callback.\n */\n draftPatch: (input: DraftPatchInput) => Promise<DraftPatchOutput>\n /**\n * When the resolved target doesn't exist, allow the substrate to\n * CREATE the file (for `knowledge.wiki`, `new-tool` subjects). Default\n * true for those kinds, false for `system-prompt` / `rubric` / etc.\n * (named sections that don't exist are a contract violation, not a\n * scaffolding opportunity).\n */\n allowCreateForKinds?: ReadonlyArray<FindingSubject['kind']>\n}\n\nexport interface DraftPatchInput {\n finding: AnalystFinding\n subject: FindingSubject\n target: ResolvedSurface\n /** Current file content (empty string when `intent === 'create-new'`). */\n currentContent: string\n}\n\nexport interface DraftPatchOutput {\n /** Unified diff against the current file content. Empty string skips this finding. */\n patch: string\n /** One-line summary for the operator. */\n summary: string\n /** Multi-line rationale for the PR body. */\n rationale: string\n}\n\n// ── factory ──────────────────────────────────────────────────────────\n\nconst DEFAULT_CREATE_KINDS: ReadonlyArray<FindingSubject['kind']> = [\n 'knowledge.wiki',\n 'knowledge.claim',\n 'knowledge.raw',\n 'new-tool',\n]\n\n/** Resolve each finding to a real surface and draft a detached patch candidate. */\nexport function createSurfaceImprovementProposer(\n opts: CreateSurfaceImprovementProposerOptions,\n): ImprovementProposalSource<SurfaceImprovementEdit> {\n const allowCreate = opts.allowCreateForKinds ?? DEFAULT_CREATE_KINDS\n\n return {\n async proposeFromFindings(findings) {\n const edits: SurfaceImprovementEdit[] = []\n const errors: Array<{ findingId: string; subject: string; message: string }> = []\n let skipped = 0\n\n for (const f of findings) {\n const subject = parseFindingSubject(f.subject)\n if (subject === null) {\n if (f.subject !== undefined) {\n errors.push({\n findingId: f.finding_id,\n subject: f.subject,\n message: 'subject does not parse against the finding-subject grammar',\n })\n } else {\n // Subject-less findings are descriptive, not actionable —\n // legitimate; count in `skipped` not `errors`.\n skipped += 1\n }\n continue\n }\n\n // `cluster` findings (failure-mode) are evidence, not mutations.\n if (subject.kind === 'cluster') {\n skipped += 1\n continue\n }\n\n // Knowledge findings flow to the knowledge proposal source so they do not double-route.\n if (subject.kind.startsWith('knowledge.')) {\n skipped += 1\n continue\n }\n\n const target = resolveSubjectPath(subject, opts.surfaces, opts.repoRoot)\n if (target === null) {\n errors.push({\n findingId: f.finding_id,\n subject: f.subject ?? '',\n message: `subject kind \"${subject.kind}\" targets an undeclared surface; declare it in AgentSurfaces or stop emitting this subject`,\n })\n continue\n }\n\n if (target.intent === 'create-new' && !allowCreate.includes(subject.kind)) {\n errors.push({\n findingId: f.finding_id,\n subject: f.subject ?? '',\n message: `target ${target.repoRelativePath} does not exist; the kind \"${subject.kind}\" requires an existing target (analyst named a section that isn't in the codebase)`,\n })\n continue\n }\n\n const currentContent = target.exists ? readFileSync(target.absolutePath, 'utf-8') : ''\n\n let draft: DraftPatchOutput\n try {\n draft = await opts.draftPatch({ finding: f, subject, target, currentContent })\n } catch (err) {\n errors.push({\n findingId: f.finding_id,\n subject: f.subject ?? '',\n message: `draftPatch threw: ${err instanceof Error ? err.message : String(err)}`,\n })\n continue\n }\n\n if (draft.patch.trim().length === 0) {\n skipped += 1\n continue\n }\n\n edits.push({\n id: `imp-${f.finding_id}`,\n sourceFindingId: f.finding_id,\n subject,\n target,\n baseSha256: sha256(currentContent),\n patch: draft.patch,\n summary: draft.summary,\n rationale: draft.rationale,\n confidence: f.confidence,\n severity: f.severity,\n })\n }\n\n return { edits, skipped, errors }\n },\n }\n}\n\nfunction sha256(s: string): string {\n return createHash('sha256').update(s, 'utf-8').digest('hex')\n}\n","import { ValidationError } from '../errors'\n\n/** Known AgentProfile axes a run path may or may not carry into execution. */\nexport const AGENT_PROFILE_MATERIALIZATION_AXES = [\n 'identity',\n 'name',\n 'model',\n 'prompt',\n 'systemPrompt',\n 'instructions',\n 'resources',\n 'files',\n 'resourceInstructions',\n 'skills',\n 'resourceTools',\n 'resourceAgents',\n 'commands',\n 'tools',\n 'permissions',\n 'mcp',\n 'mcpConnections',\n 'connections',\n 'subagents',\n 'hooks',\n 'modes',\n 'confidential',\n 'metadata',\n 'extensions',\n] as const\n\nexport type KnownAgentProfileMaterializationAxis =\n (typeof AGENT_PROFILE_MATERIALIZATION_AXES)[number]\n\n/** AgentProfile axis name, with `custom:<name>` reserved for caller-owned extensions. */\nexport type AgentProfileMaterializationAxis =\n | KnownAgentProfileMaterializationAxis\n | `custom:${string}`\n\n/** Declares which AgentProfile axes a concrete run path really carries. */\nexport interface ProfileMaterializationContract {\n /** Human-readable run path, e.g. `createSandboxAct` or `prompt-only-message`. */\n name: string\n /** Profile axes this run path actually carries into execution. */\n axes: readonly AgentProfileMaterializationAxis[]\n}\n\n/** One changed AgentProfile axis that would be dropped by a run path. */\nexport interface ProfileMaterializationIssue {\n contract: string\n axis: AgentProfileMaterializationAxis\n reason: 'unsupported-axis'\n supportedAxes: readonly AgentProfileMaterializationAxis[]\n}\n\n/** Input for declaring a run path's profile-axis support. */\nexport interface DefineProfileMaterializationContractOptions {\n name: string\n axes: readonly AgentProfileMaterializationAxis[]\n}\n\n/** Input for checking a candidate diff against a run path. */\nexport interface ValidateProfileMaterializationOptions {\n contract: ProfileMaterializationContract\n changedAxes: readonly AgentProfileMaterializationAxis[]\n}\n\n/** Input for throwing on dropped profile axes. */\nexport interface AssertProfileMaterializationOptions extends ValidateProfileMaterializationOptions {\n /** Extra label included in the thrown error, usually the caller or run id. */\n context?: string\n}\n\nconst KNOWN_AXIS_SET = new Set<string>(AGENT_PROFILE_MATERIALIZATION_AXES)\n\nconst AXIS_PARENTS: Partial<\n Record<KnownAgentProfileMaterializationAxis, KnownAgentProfileMaterializationAxis>\n> = {\n name: 'identity',\n systemPrompt: 'prompt',\n instructions: 'prompt',\n files: 'resources',\n resourceInstructions: 'resources',\n skills: 'resources',\n resourceTools: 'resources',\n resourceAgents: 'resources',\n commands: 'resources',\n mcpConnections: 'mcp',\n}\n\n/** Materialization contract for `createSandboxAct`, which forwards the full AgentProfile. */\nexport const sandboxActProfileMaterialization = defineProfileMaterializationContract({\n name: 'createSandboxAct',\n axes: [\n 'identity',\n 'model',\n 'prompt',\n 'resources',\n 'tools',\n 'permissions',\n 'mcp',\n 'connections',\n 'subagents',\n 'hooks',\n 'modes',\n 'confidential',\n 'metadata',\n 'extensions',\n ],\n})\n\n/** Materialization contract for a run path that only injects prompt text. */\nexport const promptOnlyProfileMaterialization = defineProfileMaterializationContract({\n name: 'prompt-only-message',\n axes: ['prompt'],\n})\n\n/** Materialization contract for a run path that injects prompt text plus inline resources. */\nexport const promptResourceProfileMaterialization = defineProfileMaterializationContract({\n name: 'prompt-resource-attachment',\n axes: ['prompt', 'resources'],\n})\n\n/** Define the profile axes a concrete run path actually carries into execution. */\nexport function defineProfileMaterializationContract(\n options: DefineProfileMaterializationContractOptions,\n): ProfileMaterializationContract {\n const name = options.name.trim()\n if (!name) {\n throw new ValidationError('defineProfileMaterializationContract: name is required')\n }\n return {\n name,\n axes: normalizeAxes(options.axes, `${name}.axes`),\n }\n}\n\n/** Return every changed profile axis that the selected run path would drop. */\nexport function validateProfileMaterialization(\n options: ValidateProfileMaterializationOptions,\n): readonly ProfileMaterializationIssue[] {\n const changedAxes = normalizeAxes(options.changedAxes, 'changedAxes')\n const supported = new Set<string>(\n normalizeAxes(options.contract.axes, `${options.contract.name}.axes`),\n )\n const issues: ProfileMaterializationIssue[] = []\n for (const axis of changedAxes) {\n if (isAxisSupported(axis, supported)) continue\n issues.push({\n contract: options.contract.name,\n axis,\n reason: 'unsupported-axis',\n supportedAxes: [...supported] as AgentProfileMaterializationAxis[],\n })\n }\n return issues\n}\n\n/** Throw when a candidate changes axes the selected run path cannot carry. */\nexport function assertProfileMaterialization(options: AssertProfileMaterializationOptions): void {\n const issues = validateProfileMaterialization(options)\n if (issues.length === 0) return\n throw new ValidationError(renderProfileMaterializationIssues(issues, options.context))\n}\n\n/** Format profile-axis drop issues into a concise operator-facing error. */\nexport function renderProfileMaterializationIssues(\n issues: readonly ProfileMaterializationIssue[],\n context?: string,\n): string {\n if (issues.length === 0) return ''\n const contract = issues[0]?.contract ?? '<unknown>'\n const prefix = context ? `${context}: ` : ''\n const droppedAxes = issues.map((issue) => issue.axis).join(', ')\n const supportedAxes = issues[0]?.supportedAxes.join(', ') || '<none>'\n return [\n `${prefix}profile materialization would drop axis changes on \"${contract}\": ${droppedAxes}.`,\n `Supported axes: ${supportedAxes}.`,\n 'Use a run path that carries those AgentProfile axes, or remove them from the candidate.',\n ].join('\\n')\n}\n\nfunction normalizeAxes(\n axes: readonly AgentProfileMaterializationAxis[],\n label: string,\n): AgentProfileMaterializationAxis[] {\n const out: AgentProfileMaterializationAxis[] = []\n const seen = new Set<string>()\n for (const raw of axes) {\n const axis = normalizeAxis(raw, label)\n if (seen.has(axis)) continue\n seen.add(axis)\n out.push(axis)\n }\n return out\n}\n\nfunction normalizeAxis(\n raw: AgentProfileMaterializationAxis,\n label: string,\n): AgentProfileMaterializationAxis {\n if (typeof raw !== 'string') {\n throw new ValidationError(`${label}: profile axis must be a string`)\n }\n const axis = raw.trim()\n if (!axis) {\n throw new ValidationError(`${label}: profile axis must be non-empty`)\n }\n if (!KNOWN_AXIS_SET.has(axis) && !axis.startsWith('custom:')) {\n throw new ValidationError(\n `${label}: unknown profile axis \"${axis}\". Use a known axis or custom:<name>.`,\n )\n }\n return axis as AgentProfileMaterializationAxis\n}\n\nfunction isAxisSupported(\n axis: AgentProfileMaterializationAxis,\n supported: ReadonlySet<string>,\n): boolean {\n if (supported.has(axis)) return true\n let parent = AXIS_PARENTS[axis as KnownAgentProfileMaterializationAxis]\n while (parent) {\n if (supported.has(parent)) return true\n parent = AXIS_PARENTS[parent]\n }\n return false\n}\n","/**\n * Sandbox bridge for `AgentRuntime.act` — prod-faithful eval execution.\n *\n * The point of this adapter is parity: the eval substrate must run the agent\n * through the SAME profile the production chat turn uses, or scorecard numbers\n * grade a profile that never ships. `createSandboxAct` boots a sandbox with the\n * agent's profile (the caller's `baseProfile`, with optional per-persona\n * overrides) through the loop kernel's own {@link createSandboxForSpec},\n * streams the `streamPrompt` events mapped to the `RuntimeStreamEvent`\n * vocabulary, and resolves the `OutputAdapter`-parsed output for rubric scoring\n * — satisfying the `act` streaming contract with one code path shared by chat\n * and eval.\n *\n * Agents with a bespoke streaming chat turn should wire THAT into `act`\n * directly (the contract is designed for it); this adapter is the default for\n * agents whose turn is a plain prod-profile sandbox dispatch — notably the\n * agents agent-builder generates.\n */\n\nimport type {\n AgentProfile,\n AgentProfileFileMount,\n AgentProfileMcpServer,\n} from '@tangle-network/agent-interface'\nimport type { SandboxEvent } from '@tangle-network/sandbox'\nimport type { AgentRunSpec, OutputAdapter, SandboxClient } from '../runtime'\nimport { mapSandboxEvent } from '../runtime'\nimport { createSandboxForSpec } from '../runtime/run-loop'\nimport type { RuntimeStreamEvent } from '../types'\nimport type { AgentRunContext, AgentRunInvocation } from './define-agent'\nimport {\n type AgentProfileMaterializationAxis,\n assertProfileMaterialization,\n sandboxActProfileMaterialization,\n} from './profile-materialization'\n\n/** Per-persona profile-merge slots applied over the base profile (§1.5: the caller authors the\n * per-persona profile). Each slot overlays the base; an absent slot leaves the base untouched. */\nexport interface SandboxActComposeOverrides {\n /** Replace the base profile's system prompt (e.g. a workspace-augmented prompt). */\n systemPrompt?: string\n /** Extra file mounts layered after the base profile's `resources.files`. */\n extraFiles?: AgentProfileFileMount[]\n /** Override the profile `name`. Defaults to the base profile's name. */\n name?: string\n /** Box built-in tool ON/OFF flags merged over the base profile's `tools` (overlay wins per key). */\n tools?: Record<string, boolean>\n /** MCP connections merged over the base profile's `mcp` (overlay wins per key). */\n mcpConnections?: Record<string, AgentProfileMcpServer>\n}\n\nexport interface CreateSandboxActOptions<TPersona, TRunOutput> {\n /** Canonical agent profile — the same one the prod chat turn uses. */\n baseProfile: AgentProfile\n /** Sandbox client used to boot the per-run sandbox. */\n sandboxClient: SandboxClient\n /** Persona → prompt. Pure; the eval cell's input. */\n buildPrompt: (persona: TPersona) => string\n /** Sandbox event stream → typed output the rubric scores. */\n output: OutputAdapter<TRunOutput>\n /**\n * Per-persona profile overrides (workspace-augmented system prompt, extra\n * file mounts, tool flags, MCP connections). Overlaid onto `baseProfile`.\n */\n compose?: (persona: TPersona) => SandboxActComposeOverrides\n /** Sandbox-SDK overrides forwarded to `createSandboxForSpec`. */\n sandboxOverrides?: AgentRunSpec<unknown>['sandboxOverrides']\n /** Optional changed axes the caller expects this path to carry. */\n requiredProfileAxes?: readonly AgentProfileMaterializationAxis[]\n /** Stable run name surfaced in mapped `llm_call` events. */\n name?: string\n /** Override the `SandboxEvent → RuntimeStreamEvent` mapper. */\n mapEvent?: (\n event: SandboxEvent,\n opts: { agentRunName?: string },\n ) => RuntimeStreamEvent | undefined\n}\n\n/**\n * Build an `AgentRuntime.act` implementation backed by a single prod-profile\n * sandbox run. The returned function honours the `act` contract: it returns\n * synchronously with a live `events` iterator and an `output` promise that\n * resolves only after the iterator drains.\n */\nexport function createSandboxAct<TPersona, TRunOutput>(\n options: CreateSandboxActOptions<TPersona, TRunOutput>,\n): (persona: TPersona, ctx: AgentRunContext) => AgentRunInvocation<TRunOutput> {\n assertProfileMaterialization({\n contract: sandboxActProfileMaterialization,\n changedAxes: options.requiredProfileAxes ?? [],\n context: 'createSandboxAct',\n })\n const mapEvent = options.mapEvent ?? mapSandboxEvent\n\n return (persona: TPersona, ctx: AgentRunContext): AgentRunInvocation<TRunOutput> => {\n const profile = applyComposeOverrides(options.baseProfile, options.compose?.(persona))\n const agentRunName = options.name ?? profile.name ?? 'agent'\n const message = options.buildPrompt(persona)\n const signal = ctx.signal ?? new AbortController().signal\n\n const raw: SandboxEvent[] = []\n let settle!: (value: TRunOutput) => void\n let fail!: (err: unknown) => void\n const output = new Promise<TRunOutput>((resolve, reject) => {\n settle = resolve\n fail = reject\n })\n // The output promise rejects when the stream errors; if the caller ignores\n // `output` (chat UX) the rejection is still observed by the events iterator\n // throwing. Attach a no-op catch so an ignored rejection is never \"unhandled\".\n output.catch(() => {})\n\n const spec: AgentRunSpec<unknown> = {\n profile,\n taskToPrompt: () => message,\n name: agentRunName,\n ...(options.sandboxOverrides ? { sandboxOverrides: options.sandboxOverrides } : {}),\n }\n\n async function* events(): AsyncIterable<RuntimeStreamEvent> {\n try {\n const box = await createSandboxForSpec(options.sandboxClient, spec, signal)\n for await (const event of box.streamPrompt(message, { signal })) {\n raw.push(event)\n const mapped = mapEvent(event, { agentRunName })\n if (mapped) yield mapped\n }\n settle(options.output.parse(raw))\n } catch (err) {\n fail(err)\n throw err\n }\n }\n\n return { events: events(), output }\n }\n}\n\n/** Overlay the per-persona overrides onto the base profile. Each slot merges over the base; an\n * absent override leaves the base profile untouched. */\nfunction applyComposeOverrides(\n base: AgentProfile,\n overrides: SandboxActComposeOverrides | undefined,\n): AgentProfile {\n if (!overrides) return base\n const prompt = overrides.systemPrompt\n ? { ...base.prompt, systemPrompt: overrides.systemPrompt }\n : base.prompt\n const mergedTools = overrides.tools ? { ...(base.tools ?? {}), ...overrides.tools } : base.tools\n const mergedMcp = overrides.mcpConnections\n ? { ...(base.mcp ?? {}), ...overrides.mcpConnections }\n : base.mcp\n const baseFiles = base.resources?.files ?? []\n const mergedFiles: AgentProfileFileMount[] = overrides.extraFiles?.length\n ? [...baseFiles, ...overrides.extraFiles]\n : [...baseFiles]\n return {\n ...base,\n name: overrides.name ?? base.name,\n prompt,\n ...(mergedTools ? { tools: mergedTools } : {}),\n ...(mergedMcp ? { mcp: mergedMcp } : {}),\n resources: { ...base.resources, files: mergedFiles },\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"agent.js","names":[],"sources":["../src/agent/surfaces.ts","../src/agent/define-agent.ts","../src/agent/improvement-adapter.ts","../src/agent/profile-materialization.ts","../src/agent/sandbox-act.ts"],"sourcesContent":["/**\n * `AgentSurfaces` — declarative map of the mutable file/directory paths\n * the self-improvement loop can edit on behalf of an agent.\n *\n * The substrate uses this map to resolve every parsed `FindingSubject`\n * (from agent-eval) to a real on-disk path. No per-vertical glue;\n * no fabricated paths; no silent `existsSync(...)` skips that hide\n * misconfiguration from the operator.\n *\n * Surfaces are validated at `defineAgent` time — missing paths fail\n * loud with a list of every offender. A surface that's not needed\n * (e.g. an agent with no RAG corpora) is simply omitted; the loop\n * refuses to route those subjects rather than fabricating a target.\n */\n\nimport { existsSync, statSync } from 'node:fs'\nimport { isAbsolute, join, relative, resolve, sep } from 'node:path'\nimport type { FindingSubject } from '@tangle-network/agent-eval'\n\n/**\n * Surface declarations. Every path is repo-relative (or absolute) at\n * `defineAgent` time. At resolution time, paths are joined against the\n * agent's `repoRoot`.\n *\n * `systemPrompt`, `tools`, `personas` are DIRECTORIES; the loop appends\n * `<section>.md`, `<tool>/README.md`, `<persona-id>.yaml` etc.\n * `rubric`, `outputSchema` are SINGLE FILES; the loop edits them in\n * place.\n *\n * `knowledge` is the agent-knowledge root (typically `.agent-knowledge`);\n * `applyKnowledgeWriteBlocks` writes pages relative to it.\n *\n * Optional surfaces (`scaffolding`, `memory`, `rag`, `outputSchema`)\n * can be omitted — the loop will reject findings targeting them with a\n * clear log message instead of fabricating a path.\n */\nexport interface AgentSurfaces {\n /** Directory containing one markdown file per system-prompt section. */\n systemPrompt: string\n /** Directory containing one subdir per tool (`<tool>/README.md`). */\n tools: string\n /** Single file (TypeScript module) defining the rubric weights + dimensions. */\n rubric: string\n /** Knowledge-base root; typically `.agent-knowledge`. */\n knowledge: string\n /** Directory containing one YAML/JSON file per persona. */\n personas: string\n /** Optional: directory containing scaffolding rules (precondition checks, retry policies). */\n scaffolding?: string\n /** Optional: memory store path (JSONL / SQLite / DB). */\n memory?: string\n /** Optional: directory containing RAG corpora (`<corpus>/<doc-id>.md`). */\n rag?: string\n /** Optional: single file defining the output schema (Zod / JSON Schema). */\n outputSchema?: string\n /** Optional: directory containing Agent Skill packages. */\n skills?: string\n /** Optional: directory containing MCP server/tool configuration. */\n mcp?: string\n /** Optional: directory containing hook definitions. */\n hooks?: string\n /** Optional: directory containing subagent definitions. */\n subagents?: string\n /** Optional: directory containing orchestration/workflow policies. */\n workflows?: string\n /** Optional: single file containing rollout-policy settings. */\n rolloutPolicy?: string\n /** Optional: single canonical AgentProfile file. */\n agentProfile?: string\n /** Optional: source root for code findings. */\n code?: string\n}\n\nexport interface ResolvedSurface {\n /** Absolute filesystem path the operator can `cat` / `vim`. */\n absolutePath: string\n /** Repo-relative path for PR descriptions, diffs, audit logs. */\n repoRelativePath: string\n /** Whether the path currently exists on disk. */\n exists: boolean\n /** The substrate's intent: edit an existing file or create a new one. */\n intent: 'edit-existing' | 'create-new'\n}\n\n/**\n * Resolve a parsed `FindingSubject` to the file path the substrate\n * should edit (or create) on disk.\n *\n * Returns `null` when:\n * - the subject targets a surface the agent didn't declare\n * (e.g. `rag:*` when `surfaces.rag` is undefined), OR\n * - the subject is a `cluster` (failure-mode emits these as evidence,\n * not actionable mutations — they don't route to a file).\n *\n * Returns a `ResolvedSurface` with `intent: 'create-new'` when the\n * subject names a path that doesn't yet exist (e.g. a new wiki page).\n * The caller chooses whether to honour the create — for tightly-managed\n * surfaces like `systemPrompt` it's usually a contract violation\n * (the analyst named a section that doesn't exist); for `knowledge`\n * it's the whole point.\n */\nexport function resolveSubjectPath(\n subject: FindingSubject,\n surfaces: AgentSurfaces,\n repoRoot: string,\n): ResolvedSurface | null {\n const candidates = candidatePathsForSubject(subject, surfaces)\n if (candidates.length === 0) return null\n\n // Probe candidates in order, preferring the first one that exists on disk.\n // Lets the substrate accept both the flat `<section>.md` convention and\n // the skill-dir `<section>/SKILL.md` convention without forcing one layout.\n // When none exists, fall back to the first candidate (canonical create-new).\n for (const rel of candidates) {\n const abs = isAbsolute(rel) ? rel : join(repoRoot, rel)\n if (existsSync(abs)) {\n return { absolutePath: abs, repoRelativePath: rel, exists: true, intent: 'edit-existing' }\n }\n }\n const fallback = candidates[0]!\n const fallbackAbs = isAbsolute(fallback) ? fallback : join(repoRoot, fallback)\n return {\n absolutePath: fallbackAbs,\n repoRelativePath: fallback,\n exists: false,\n intent: 'create-new',\n }\n}\n\nfunction candidatePathsForSubject(\n subject: FindingSubject,\n surfaces: AgentSurfaces,\n): ReadonlyArray<string> {\n switch (subject.kind) {\n case 'knowledge.wiki':\n case 'knowledge.stale':\n return optionalPath(safeJoin(surfaces.knowledge, `${subject.slug}.md`))\n case 'knowledge.claim':\n // Claims land in a per-topic claims directory under the knowledge root.\n return optionalPath(safeJoin(surfaces.knowledge, 'claims', `${slugify(subject.topic)}.md`))\n case 'knowledge.raw':\n return optionalPath(safeJoin(surfaces.knowledge, 'raw', `${subject.sourceId}.md`))\n case 'system-prompt': {\n const slug = slugify(subject.section)\n // Prefer flat layout for create-new (canonical); probe skill-dir layout\n // in case the existing repo (tax/legal/gtm/creative) uses\n // `<section>/SKILL.md` already.\n return [\n safeJoin(surfaces.systemPrompt, `${slug}.md`),\n safeJoin(surfaces.systemPrompt, slug, 'SKILL.md'),\n safeJoin(surfaces.systemPrompt, slug, 'index.md'),\n ].filter((path): path is string => path !== null)\n }\n case 'skill': {\n if (!surfaces.skills) return []\n return [\n safeJoin(surfaces.skills, subject.name, 'SKILL.md'),\n safeJoin(surfaces.skills, `${subject.name}.md`),\n ].filter((path): path is string => path !== null)\n }\n case 'tool-doc':\n if (subject.aspect) {\n return optionalPath(safeJoin(surfaces.tools, subject.tool, `${slugify(subject.aspect)}.md`))\n }\n // tool-doc default: `<tool>/README.md`; also probe `<tool>.md` for flat\n // tool-list repos.\n return [\n safeJoin(surfaces.tools, subject.tool, 'README.md'),\n safeJoin(surfaces.tools, `${subject.tool}.md`),\n ].filter((path): path is string => path !== null)\n case 'new-tool':\n return optionalPath(safeJoin(surfaces.tools, subject.name, 'README.md'))\n case 'mcp':\n if (!surfaces.mcp) return []\n return subject.tool\n ? optionalPath(safeJoin(surfaces.mcp, subject.server, `${subject.tool}.md`))\n : [\n safeJoin(surfaces.mcp, `${subject.server}.json`),\n safeJoin(surfaces.mcp, subject.server, 'README.md'),\n ].filter((path): path is string => path !== null)\n case 'hook':\n if (!surfaces.hooks) return []\n return [\n safeJoin(surfaces.hooks, `${subject.name}.md`),\n safeJoin(surfaces.hooks, `${subject.name}.json`),\n ].filter((path): path is string => path !== null)\n case 'subagent':\n if (!surfaces.subagents) return []\n return [\n safeJoin(surfaces.subagents, `${subject.name}.md`),\n safeJoin(surfaces.subagents, `${subject.name}.yaml`),\n safeJoin(surfaces.subagents, `${subject.name}.json`),\n ].filter((path): path is string => path !== null)\n case 'workflow':\n if (!surfaces.workflows) return []\n return [\n safeJoin(surfaces.workflows, `${subject.name}.md`),\n safeJoin(surfaces.workflows, `${subject.name}.yaml`),\n safeJoin(surfaces.workflows, `${subject.name}.json`),\n ].filter((path): path is string => path !== null)\n case 'rollout-policy':\n return surfaces.rolloutPolicy ? [surfaces.rolloutPolicy] : []\n case 'agent-profile':\n return surfaces.agentProfile ? [surfaces.agentProfile] : []\n case 'code': {\n if (!surfaces.code) return []\n const path = safeJoin(surfaces.code, subject.path)\n return path ? [path] : []\n }\n case 'rag':\n if (!surfaces.rag) return []\n return optionalPath(safeJoin(surfaces.rag, subject.corpus, `${subject.docId}.md`))\n case 'memory':\n if (!surfaces.memory) return []\n return optionalPath(safeJoin(surfaces.memory, `${slugify(subject.key)}.json`))\n case 'scaffolding':\n if (!surfaces.scaffolding) return []\n return optionalPath(safeJoin(surfaces.scaffolding, `${slugify(subject.concern)}.md`))\n case 'output-schema':\n if (!surfaces.outputSchema) return []\n return [surfaces.outputSchema]\n case 'websearch.outdated':\n case 'prior-run-summary':\n // Stale signals don't map to a single file — handled by the knowledge\n // adapter as `agent-knowledge:stale:*` after operator review.\n return []\n case 'cluster':\n // failure-mode cluster labels are evidence, not mutations.\n return []\n }\n}\n\nfunction safeJoin(root: string, ...children: string[]): string | null {\n if (children.some((child) => child.includes('\\0') || isAbsolute(child))) return null\n const rootAbsolute = resolve(root)\n const targetAbsolute = resolve(rootAbsolute, ...children)\n const escaped = relative(rootAbsolute, targetAbsolute)\n if (escaped === '..' || escaped.startsWith(`..${sep}`) || isAbsolute(escaped)) return null\n return join(root, ...children)\n}\n\nfunction optionalPath(path: string | null): string[] {\n return path ? [path] : []\n}\n\nfunction slugify(s: string): string {\n return (\n s\n .toLowerCase()\n .replace(/[^a-z0-9-]+/g, '-')\n .replace(/^-+|-+$/g, '')\n .slice(0, 200) || 'untitled'\n )\n}\n\n/**\n * Validate that every declared surface exists on disk under `repoRoot`.\n *\n * Returns an array of `SurfaceValidationIssue` — empty when all required\n * surfaces resolve. `defineAgent` throws with the issues rendered, so\n * a misconfigured manifest fails at startup (not at the first finding\n * the loop produces 20 minutes later).\n */\nexport interface SurfaceValidationIssue {\n surface: keyof AgentSurfaces\n path: string\n reason: 'missing' | 'not-directory' | 'not-file'\n}\n\n/** Validate an `AgentSurfaces` map on disk — missing paths fail loud at `defineAgent` time instead of silently skipping self-improvement edits. */\nexport function validateSurfaces(\n surfaces: AgentSurfaces,\n repoRoot: string,\n): ReadonlyArray<SurfaceValidationIssue> {\n const issues: SurfaceValidationIssue[] = []\n const dirSurfaces: ReadonlyArray<keyof AgentSurfaces> = [\n 'systemPrompt',\n 'tools',\n 'personas',\n 'knowledge',\n ]\n const fileSurfaces: ReadonlyArray<keyof AgentSurfaces> = ['rubric']\n const optionalDirSurfaces: ReadonlyArray<keyof AgentSurfaces> = [\n 'scaffolding',\n 'memory',\n 'rag',\n 'skills',\n 'mcp',\n 'hooks',\n 'subagents',\n 'workflows',\n 'code',\n ]\n const optionalFileSurfaces: ReadonlyArray<keyof AgentSurfaces> = [\n 'outputSchema',\n 'rolloutPolicy',\n 'agentProfile',\n ]\n\n for (const key of dirSurfaces) {\n const p = surfaces[key] as string | undefined\n if (!p) {\n issues.push({ surface: key, path: '', reason: 'missing' })\n continue\n }\n const abs = isAbsolute(p) ? p : join(repoRoot, p)\n if (!existsSync(abs)) {\n issues.push({ surface: key, path: p, reason: 'missing' })\n } else if (!statSync(abs).isDirectory()) {\n issues.push({ surface: key, path: p, reason: 'not-directory' })\n }\n }\n for (const key of fileSurfaces) {\n const p = surfaces[key] as string | undefined\n if (!p) {\n issues.push({ surface: key, path: '', reason: 'missing' })\n continue\n }\n const abs = isAbsolute(p) ? p : join(repoRoot, p)\n if (!existsSync(abs)) {\n issues.push({ surface: key, path: p, reason: 'missing' })\n } else if (!statSync(abs).isFile()) {\n issues.push({ surface: key, path: p, reason: 'not-file' })\n }\n }\n for (const key of [...optionalDirSurfaces, ...optionalFileSurfaces]) {\n const p = surfaces[key] as string | undefined\n if (p === undefined) continue\n const abs = isAbsolute(p) ? p : join(repoRoot, p)\n if (!existsSync(abs)) {\n issues.push({ surface: key, path: p, reason: 'missing' })\n continue\n }\n const expectedDirectory = optionalDirSurfaces.includes(key)\n if (expectedDirectory && !statSync(abs).isDirectory()) {\n issues.push({ surface: key, path: p, reason: 'not-directory' })\n } else if (!expectedDirectory && !statSync(abs).isFile()) {\n issues.push({ surface: key, path: p, reason: 'not-file' })\n }\n }\n return issues\n}\n\n/** Format a list of surface validation issues into a human-readable error string. */\nexport function renderSurfaceIssues(\n issues: ReadonlyArray<SurfaceValidationIssue>,\n repoRoot: string,\n): string {\n if (issues.length === 0) return ''\n const lines = issues.map(\n (i) => ` - ${i.surface}: ${i.path ? `\"${i.path}\"` : '<not set>'} (${i.reason})`,\n )\n return [\n `Agent surface validation failed against repoRoot=${repoRoot}:`,\n ...lines,\n '',\n 'Fix the manifest: every required surface must point at an existing',\n 'directory (systemPrompt / tools / personas / knowledge) or file',\n '(rubric). Optional surfaces (scaffolding / memory / rag / outputSchema)',\n 'may be omitted; the loop will reject findings targeting omitted',\n 'surfaces rather than fabricating a path.',\n ].join('\\n')\n}\n","/**\n * `defineAgent` — typed, validated manifest API for declarative agent\n * configuration. The substrate consumes this manifest to wire the\n * canonical eval pattern + analyst self-improvement loop without any\n * per-vertical glue.\n *\n * Design goal: scale to 1000s of vertical agents. Every agent declares\n * its surfaces, rubric, runtime, and analyst configuration in ~50 lines.\n * No per-vertical `ImprovementProposalSource`. No per-vertical CLI. No\n * fabricated paths.\n *\n * Validation: `defineAgent` runs `validateSurfaces` synchronously and\n * throws a structured error if any required surface is missing on\n * disk. The cost is one filesystem stat per surface (cheap); the\n * benefit is a manifest that can't ship broken.\n */\n\nimport type { TraceAnalystDefinition } from '@tangle-network/agent-eval'\nimport type { RuntimeStreamEvent } from '../types'\nimport { type AgentSurfaces, renderSurfaceIssues, validateSurfaces } from './surfaces'\n\n// ── manifest ─────────────────────────────────────────────────────────\n\n/**\n * The full agent manifest. Each agent ships ONE of these.\n *\n * Generics:\n * `TPersona` — the agent's persona shape (loaded from\n * `surfaces.personas`). Defaults to `unknown` so the substrate's\n * persona discovery (`loadPersonas`) can accept anything; per-agent\n * code re-narrows when it matters.\n * `TRunOutput` — the shape `runtime.act` returns. Used by the rubric\n * scorers and emitted into the trace.\n */\nexport interface AgentManifest<TPersona = unknown, TRunOutput = unknown> {\n /**\n * Stable identifier — used as `projectId` in traces, as the analyst\n * loop's `runId` prefix, and as the namespace under which findings\n * are persisted. MUST match the agent's repo name to keep\n * cross-repo telemetry joinable.\n */\n id: string\n\n /**\n * Filesystem root the substrate resolves surface paths against.\n * Typically `process.cwd()` or a fixed absolute path. Use an\n * absolute path when the agent's tests may run from subdirectories\n * (vitest sometimes shifts cwd).\n */\n repoRoot: string\n\n /**\n * Map of mutable surfaces the self-improvement loop can edit. See\n * `AgentSurfaces` — required: `systemPrompt`, `tools`, `rubric`,\n * `knowledge`, `personas`. Optional: `scaffolding`, `memory`, `rag`,\n * `outputSchema`.\n *\n * Every required path is validated at `defineAgent` time. Missing\n * paths throw with the full list of offenders.\n */\n surfaces: AgentSurfaces\n\n /**\n * Rubric the substrate uses to score each run. Dimensions × weights\n * × judges. The substrate computes the weighted composite and\n * stamps it into the RunRecord.\n */\n rubric: AgentRubric<TRunOutput>\n\n /**\n * Runtime adapter — how the substrate INVOKES the agent against a\n * persona. The `act` function takes a persona + a context (with the\n * tracer the substrate threads through for span emission) and\n * returns the run output the rubric will score.\n *\n * The agent's existing production runtime goes in here; the\n * substrate is intentionally thin around it.\n */\n runtime: AgentRuntime<TPersona, TRunOutput>\n\n /**\n * Persona discovery — the substrate loads personas via this function\n * at eval start. Can read from `surfaces.personas`, an API, or be\n * hardcoded. The substrate calls it once per `runAgentEval` call;\n * persona ordering is preserved.\n */\n personas: () => Promise<ReadonlyArray<TPersona>>\n\n /**\n * Analyst kinds the substrate runs against each persona's trace.\n * Defaults to `DEFAULT_TRACE_ANALYST_KINDS` from agent-eval. Per-agent\n * authors can prune (e.g. skip `knowledge-poisoning` when there's no\n * knowledge base) or extend (custom domain kinds).\n *\n * Empty array disables the loop — useful for `pnpm eval --no-analyst`.\n */\n analystKinds: ReadonlyArray<TraceAnalystDefinition>\n\n /**\n * Analyst LLM configuration. The substrate uses these for all four\n * kinds (override per-kind via `analystKinds` if needed).\n */\n analyst: AnalystConfig\n}\n\nexport interface AgentRubric<TRunOutput> {\n /** Dimensions composing the weighted score. Weights sum to 1.0 by convention. */\n dimensions: ReadonlyArray<RubricDimension<TRunOutput>>\n /**\n * Optional judges layered on top of deterministic dimensions. Each\n * judge returns a score per dimension; the substrate averages judges\n * (mean by default) for the LLM contribution.\n */\n judges?: ReadonlyArray<JudgeConfig<TRunOutput>>\n}\n\nexport interface RubricDimension<TRunOutput> {\n /** Unique identifier — appears in finding subjects (`rubric:<id>`). */\n id: string\n /** 0..1 — weight in the composite. */\n weight: number\n /**\n * Deterministic scorer: given the persona + run output, returns a\n * 0..1 score. The substrate sums weight × score across dimensions\n * for the deterministic composite; judges supplement subjective dims.\n */\n score: (input: { persona: unknown; output: TRunOutput }) => number\n /** Optional human-readable label for reports. */\n label?: string\n}\n\nexport interface JudgeConfig<TRunOutput> {\n /** Judge identifier — appears in trace spans + manifest. */\n id: string\n /** Model snapshot to invoke. Pin the snapshot (`claude-sonnet-4-6@2025-04-15`); the validator rejects bare aliases. */\n model: string\n /** Dimensions this judge scores. */\n dimensions: ReadonlyArray<string>\n /**\n * Optional rubric anchors — text examples the judge sees as a\n * few-shot prompt to calibrate. STRONGLY recommended for subjective\n * dimensions; required by the calibration gate (Pearson ≥0.7).\n */\n anchors?: ReadonlyArray<{ input: string; output: TRunOutput; expected: Record<string, number> }>\n}\n\nexport interface AgentRuntime<TPersona, TRunOutput> {\n /**\n * Invoke the agent against one persona. Returns BOTH:\n * - `events`: an `AsyncIterable<RuntimeStreamEvent>` the chat-centric\n * product consumes verbatim (SSE / WebSocket / inline render).\n * **Streaming is mandatory — never collapse this to a single Promise.**\n * The agent's existing `runChatTurn` (or equivalent async generator)\n * plugs in here directly.\n * - `output`: a `Promise<TRunOutput>` resolved AFTER the event stream\n * drains. The eval substrate awaits this for rubric scoring; chat\n * products usually ignore it (they already rendered incrementally).\n *\n * Implementation contract:\n * 1. `act` MUST return immediately (synchronous construction of the\n * `events` iterator + the `output` promise).\n * 2. Iterating `events` drives the underlying LLM/tool calls — the\n * caller chooses when to consume.\n * 3. `output` resolves only after the iterator yields its terminal\n * event (typically `task_end`); see `collectAgentRun` helper.\n *\n * `ctx.emitter` is the substrate-threaded `TraceEmitter` — runtimes\n * SHOULD record LLM/tool spans through it for capture integrity.\n * `ctx.deadlineMs` is wall-clock; the runtime SHOULD honour for graceful\n * cancel. `ctx.signal` is the standard abort signal.\n */\n act: (persona: TPersona, ctx: AgentRunContext) => AgentRunInvocation<TRunOutput>\n}\n\nexport interface AgentRunInvocation<TRunOutput> {\n /** Live stream of typed runtime events. Consumed by chat UX directly. */\n events: AsyncIterable<RuntimeStreamEvent>\n /** Final structured output the rubric scores. Resolves after `events` drains. */\n output: Promise<TRunOutput>\n}\n\n/**\n * Stub for agents whose `runtime.act` is not yet wired to the substrate's\n * eval path. Preserves the streaming contract (empty event stream + a\n * rejected `output` promise that tells the caller exactly what to fix).\n *\n * Per-vertical manifests usually start with this stub and replace it with\n * the agent's real streaming runtime (`runChatTurn` or equivalent) once\n * the eval path consumes the manifest end-to-end.\n */\nexport function unimplementedAgentRun<TRunOutput = unknown>(\n reason = 'AgentRuntime.act is not yet wired for this manifest',\n): AgentRunInvocation<TRunOutput> {\n return {\n events: (async function* empty(): AsyncIterable<RuntimeStreamEvent> {})(),\n output: Promise.reject(new Error(reason)),\n }\n}\n\n/**\n * Drain `act`'s `events` into an array AND await its `output`. Useful for\n * eval / outcome-measurement code paths that don't care about live\n * rendering. The events array is preserved so the substrate can inspect\n * tool calls / readiness / questions retrospectively.\n *\n * IMPORTANT: chat-centric UX MUST NOT call this — it defeats streaming\n * (no incremental render). Use `for await (const ev of invocation.events)`\n * directly in the chat surface.\n */\nexport async function collectAgentRun<TRunOutput>(\n invocation: AgentRunInvocation<TRunOutput>,\n): Promise<{ events: ReadonlyArray<RuntimeStreamEvent>; output: TRunOutput }> {\n const events: RuntimeStreamEvent[] = []\n for await (const ev of invocation.events) events.push(ev)\n const output = await invocation.output\n return { events, output }\n}\n\nexport interface AgentRunContext {\n /** Substrate-managed trace emitter. */\n emitter: import('@tangle-network/agent-eval').TraceEmitter\n /** Stable run id for this persona × variant cell. */\n runId: string\n /** Variant the runtime is exercising (e.g. `'baseline'`, `'source-grounded'`). */\n variantId?: string\n /** Wall-clock deadline (epoch ms). The runtime SHOULD honour for graceful cancel. */\n deadlineMs?: number\n /** Optional abort signal. */\n signal?: AbortSignal\n}\n\nexport interface AnalystConfig {\n /** Model the analyst kinds use. Override per-kind via `analystKinds[i].cost.models`. */\n model: string\n /** Optional total budget across all kinds for one run. Substrate enforces via `BudgetGuard`. */\n budgetUsd?: number\n /** Backend hint for the AxAIService factory — same shape every kind uses. */\n backend?: {\n name?: 'openai' | 'router'\n apiKey?: string\n baseUrl?: string\n }\n}\n\n// ── factory + validation ─────────────────────────────────────────────\n\n/** Thrown when `defineAgent` finds a required surface missing on disk. */\nexport class AgentManifestError extends Error {\n constructor(\n message: string,\n public readonly agentId: string,\n public readonly issues: ReadonlyArray<unknown> = [],\n ) {\n super(message)\n this.name = 'AgentManifestError'\n }\n}\n\n/**\n * Construct a validated agent manifest. Throws `AgentManifestError`\n * if any required surface is missing on disk.\n *\n * Generics: pass your persona / output types if you want narrowed\n * `runtime.act` signatures:\n * `defineAgent<TaxPersona, TaxRunOutput>({ ... })`\n *\n * Most callers don't need the generics — the substrate operates on\n * `unknown` payloads internally and the manifest's `score` /\n * `runtime.act` see the typed shapes via TypeScript inference at\n * the call site.\n */\nexport function defineAgent<TPersona = unknown, TRunOutput = unknown>(\n manifest: AgentManifest<TPersona, TRunOutput>,\n): AgentManifest<TPersona, TRunOutput> {\n if (!manifest.id || manifest.id.trim().length === 0) {\n throw new AgentManifestError('defineAgent: `id` is required', manifest.id ?? '')\n }\n if (!manifest.repoRoot || manifest.repoRoot.trim().length === 0) {\n throw new AgentManifestError('defineAgent: `repoRoot` is required', manifest.id)\n }\n const issues = validateSurfaces(manifest.surfaces, manifest.repoRoot)\n if (issues.length > 0) {\n throw new AgentManifestError(\n renderSurfaceIssues(issues, manifest.repoRoot),\n manifest.id,\n issues,\n )\n }\n // Lightweight rubric sanity: weights sum to ~1.0 (no hard requirement —\n // the substrate normalizes — but flag wildly miscalibrated weights).\n const total = manifest.rubric.dimensions.reduce((acc, d) => acc + d.weight, 0)\n if (manifest.rubric.dimensions.length > 0 && (total < 0.5 || total > 1.5)) {\n throw new AgentManifestError(\n `defineAgent(${manifest.id}): rubric dimension weights sum to ${total.toFixed(3)} — should be ~1.0`,\n manifest.id,\n )\n }\n return manifest\n}\n","/**\n * Surface improvement proposer — resolves analyst findings into LLM-drafted\n * candidate patches without changing the caller's repository.\n *\n * The proposer parses each finding's `subject` via\n * `parseFindingSubject` (agent-eval), resolves it to a real file path\n * via the agent's `AgentSurfaces`, reads the current content, and asks\n * an LLM to draft a unified-diff patch given the finding + current\n * content + per-kind editing-discipline rules.\n *\n * Fail-loud rules:\n * - Findings whose subject doesn't parse → counted in `errors`.\n * - Findings whose subject targets an undeclared surface → counted in\n * `errors` with the offending kind in the message.\n * - Findings whose target path doesn't exist AND the kind isn't a\n * create-new variant (`new-tool`, `knowledge.wiki`) → counted in\n * `errors` with the resolved path in the message.\n * - LLM drafts that fail JSON-schema validation → counted in\n * `errors` with the schema issue.\n *\n * No silent skips. Every dropped finding has a recorded reason the\n * loop's report surfaces.\n */\n\nimport { createHash } from 'node:crypto'\nimport { readFileSync } from 'node:fs'\nimport type { AnalystFinding, FindingSubject } from '@tangle-network/agent-eval'\nimport { parseFindingSubject } from '@tangle-network/agent-eval/analyst'\nimport type { ImprovementProposalSource } from '../analyst-loop/types'\nimport type { AgentSurfaces, ResolvedSurface } from './surfaces'\nimport { resolveSubjectPath } from './surfaces'\n\n// ── proposal shape ───────────────────────────────────────────────────\n\nexport interface SurfaceImprovementEdit {\n /** Stable id derived from the source finding so re-proposals are idempotent. */\n id: string\n /** The finding that produced this edit — for revert + audit trail. */\n sourceFindingId: string\n /** Parsed subject; included so the apply step doesn't re-parse. */\n subject: FindingSubject\n /** Resolved on-disk target. */\n target: ResolvedSurface\n /** SHA-256 of the current file content the patch was drafted against. */\n baseSha256: string\n /** Unified-diff patch the LLM drafted (relative to `target.absolutePath`). */\n patch: string\n /** One-line summary the operator sees in the report / PR title. */\n summary: string\n /** Multi-line rationale for the PR body — finding context + LLM reasoning. */\n rationale: string\n /** Carry-forward from the finding so the apply gate can check the threshold. */\n confidence: number\n /** Carry-forward severity for prioritization. */\n severity: AnalystFinding['severity']\n}\n\nexport interface CreateSurfaceImprovementProposerOptions {\n surfaces: AgentSurfaces\n repoRoot: string\n /**\n * LLM-draft callback. Given a finding + current file content + the\n * resolved target, returns a unified-diff patch + summary + rationale.\n *\n * Required — the substrate doesn't ship a hardcoded prompt; the agent\n * author picks the model (Haiku for cheap routine drafts, Sonnet for\n * substantive prompt rewrites, etc.) via this callback.\n */\n draftPatch: (input: DraftPatchInput) => Promise<DraftPatchOutput>\n /**\n * When the resolved target doesn't exist, allow the substrate to\n * CREATE the file (for `knowledge.wiki`, `new-tool` subjects). Default\n * true for those kinds, false for `system-prompt` / `rubric` / etc.\n * (named sections that don't exist are a contract violation, not a\n * scaffolding opportunity).\n */\n allowCreateForKinds?: ReadonlyArray<FindingSubject['kind']>\n}\n\nexport interface DraftPatchInput {\n finding: AnalystFinding\n subject: FindingSubject\n target: ResolvedSurface\n /** Current file content (empty string when `intent === 'create-new'`). */\n currentContent: string\n}\n\nexport interface DraftPatchOutput {\n /** Unified diff against the current file content. Empty string skips this finding. */\n patch: string\n /** One-line summary for the operator. */\n summary: string\n /** Multi-line rationale for the PR body. */\n rationale: string\n}\n\n// ── factory ──────────────────────────────────────────────────────────\n\nconst DEFAULT_CREATE_KINDS: ReadonlyArray<FindingSubject['kind']> = [\n 'knowledge.wiki',\n 'knowledge.claim',\n 'knowledge.raw',\n 'new-tool',\n]\n\n/** Resolve each finding to a real surface and draft a detached patch candidate. */\nexport function createSurfaceImprovementProposer(\n opts: CreateSurfaceImprovementProposerOptions,\n): ImprovementProposalSource<SurfaceImprovementEdit> {\n const allowCreate = opts.allowCreateForKinds ?? DEFAULT_CREATE_KINDS\n\n return {\n async proposeFromFindings(findings) {\n const edits: SurfaceImprovementEdit[] = []\n const errors: Array<{ findingId: string; subject: string; message: string }> = []\n let skipped = 0\n\n for (const f of findings) {\n const subject = parseFindingSubject(f.subject)\n if (subject === null) {\n if (f.subject !== undefined) {\n errors.push({\n findingId: f.finding_id,\n subject: f.subject,\n message: 'subject does not parse against the finding-subject grammar',\n })\n } else {\n // Subject-less findings are descriptive, not actionable —\n // legitimate; count in `skipped` not `errors`.\n skipped += 1\n }\n continue\n }\n\n // `cluster` findings (failure-mode) are evidence, not mutations.\n if (subject.kind === 'cluster') {\n skipped += 1\n continue\n }\n\n // Knowledge findings flow to the knowledge proposal source so they do not double-route.\n if (subject.kind.startsWith('knowledge.')) {\n skipped += 1\n continue\n }\n\n const target = resolveSubjectPath(subject, opts.surfaces, opts.repoRoot)\n if (target === null) {\n errors.push({\n findingId: f.finding_id,\n subject: f.subject ?? '',\n message: `subject kind \"${subject.kind}\" targets an undeclared surface; declare it in AgentSurfaces or stop emitting this subject`,\n })\n continue\n }\n\n if (target.intent === 'create-new' && !allowCreate.includes(subject.kind)) {\n errors.push({\n findingId: f.finding_id,\n subject: f.subject ?? '',\n message: `target ${target.repoRelativePath} does not exist; the kind \"${subject.kind}\" requires an existing target (analyst named a section that isn't in the codebase)`,\n })\n continue\n }\n\n const currentContent = target.exists ? readFileSync(target.absolutePath, 'utf-8') : ''\n\n let draft: DraftPatchOutput\n try {\n draft = await opts.draftPatch({ finding: f, subject, target, currentContent })\n } catch (err) {\n errors.push({\n findingId: f.finding_id,\n subject: f.subject ?? '',\n message: `draftPatch threw: ${err instanceof Error ? err.message : String(err)}`,\n })\n continue\n }\n\n if (draft.patch.trim().length === 0) {\n skipped += 1\n continue\n }\n\n edits.push({\n id: `imp-${f.finding_id}`,\n sourceFindingId: f.finding_id,\n subject,\n target,\n baseSha256: sha256(currentContent),\n patch: draft.patch,\n summary: draft.summary,\n rationale: draft.rationale,\n confidence: f.confidence,\n severity: f.severity,\n })\n }\n\n return { edits, skipped, errors }\n },\n }\n}\n\nfunction sha256(s: string): string {\n return createHash('sha256').update(s, 'utf-8').digest('hex')\n}\n","import {\n AGENT_PROFILE_MATERIALIZATION_AXES,\n type CanonicalAgentProfileMaterializationAxis,\n} from '@tangle-network/agent-interface'\nimport { ValidationError } from '../errors'\n\n/**\n * The canonical AgentProfile leaves, re-exported from `@tangle-network/agent-interface`.\n *\n * These are LEAVES only: `modelReasoningEffort`, not `model`; `systemPrompt`, not `prompt`. A\n * contract must name every leaf it carries, because claiming a compound parent while dropping one\n * of its children is exactly the silent-drop this module exists to catch.\n */\nexport { AGENT_PROFILE_MATERIALIZATION_AXES }\n\nexport type KnownAgentProfileMaterializationAxis = CanonicalAgentProfileMaterializationAxis\n\n/** AgentProfile axis name, with `custom:<name>` reserved for caller-owned extensions. */\nexport type AgentProfileMaterializationAxis =\n | KnownAgentProfileMaterializationAxis\n | `custom:${string}`\n\n/** Declares which AgentProfile axes a concrete run path really carries. */\nexport interface ProfileMaterializationContract {\n /** Human-readable run path, e.g. `createSandboxAct` or `prompt-only-message`. */\n name: string\n /** Profile axes this run path actually carries into execution. */\n axes: readonly AgentProfileMaterializationAxis[]\n}\n\n/** One changed AgentProfile axis that would be dropped by a run path. */\nexport interface ProfileMaterializationIssue {\n contract: string\n axis: AgentProfileMaterializationAxis\n reason: 'unsupported-axis'\n supportedAxes: readonly AgentProfileMaterializationAxis[]\n}\n\n/** Input for declaring a run path's profile-axis support. */\nexport interface DefineProfileMaterializationContractOptions {\n name: string\n axes: readonly AgentProfileMaterializationAxis[]\n}\n\n/** Input for checking a candidate diff against a run path. */\nexport interface ValidateProfileMaterializationOptions {\n contract: ProfileMaterializationContract\n changedAxes: readonly AgentProfileMaterializationAxis[]\n}\n\n/** Input for throwing on dropped profile axes. */\nexport interface AssertProfileMaterializationOptions extends ValidateProfileMaterializationOptions {\n /** Extra label included in the thrown error, usually the caller or run id. */\n context?: string\n}\n\nconst KNOWN_AXIS_SET = new Set<string>(AGENT_PROFILE_MATERIALIZATION_AXES)\n\n/**\n * Compound AgentProfile properties and the canonical leaves they cover.\n *\n * agent-interface publishes two axis vocabularies, and this module has to sit between them:\n * `profileMaterializationAxes` emits canonical LEAVES, while `changedAgentProfileAxes` emits\n * DIFF axes, which are compound property names (`model`, `prompt`, `resources`, `identity`) for\n * everything except the already-scalar properties. A changed-axis input is therefore expanded\n * through this map, so both producers compose with this validator.\n *\n * A CONTRACT may still only name leaves. Expanding an input is safe — it asks about more, never\n * less — whereas letting a contract claim a parent is what silently swallows a dropped child.\n */\nconst compoundAxisLeaves: Record<string, readonly CanonicalAgentProfileMaterializationAxis[]> = {\n identity: ['name', 'description', 'version', 'tags'],\n prompt: ['systemPrompt', 'instructions'],\n model: ['modelDefault', 'modelSmall', 'modelProvider', 'modelReasoningEffort', 'modelMetadata'],\n resources: [\n 'files',\n 'resourceTools',\n 'skills',\n 'resourceAgents',\n 'commands',\n 'resourceInstructions',\n 'resourceFailOnError',\n ],\n mcpConnections: ['mcp'],\n}\n\n/**\n * Materialization contract for `createSandboxAct`.\n *\n * `createSandboxAct` hands the whole `AgentProfile` to the sandbox as `backend.profile`, so every\n * profile leaf crosses the boundary. `buildBackendOptions` resolves the runner from an explicit\n * `sandboxOverrides.backend.type`, then `profile.metadata.backendType`, then `profile.harness`,\n * so a candidate that changes only `harness` runs on the harness it declares — and one declaring\n * a harness the sandbox cannot run throws rather than running elsewhere and reporting success.\n */\nexport const sandboxActProfileMaterialization = defineProfileMaterializationContract({\n name: 'createSandboxAct',\n axes: [\n 'name',\n 'description',\n 'version',\n 'tags',\n 'harness',\n 'systemPrompt',\n 'instructions',\n 'modelDefault',\n 'modelSmall',\n 'modelProvider',\n 'modelReasoningEffort',\n 'modelMetadata',\n 'permissions',\n 'tools',\n 'mcp',\n 'connections',\n 'subagents',\n 'files',\n 'resourceTools',\n 'skills',\n 'resourceAgents',\n 'commands',\n 'resourceInstructions',\n 'resourceFailOnError',\n 'hooks',\n 'modes',\n 'confidential',\n 'metadata',\n 'extensions',\n ],\n})\n\n/** Materialization contract for a run path that only injects prompt text. */\nexport const promptOnlyProfileMaterialization = defineProfileMaterializationContract({\n name: 'prompt-only-message',\n axes: ['systemPrompt', 'instructions'],\n})\n\n/**\n * Materialization contract for a run path that injects prompt text plus inline resources.\n *\n * `resourceFailOnError` is absent: it is a resolution POLICY the attaching path would have to\n * enforce, and inlining resource content does not carry it.\n */\nexport const promptResourceProfileMaterialization = defineProfileMaterializationContract({\n name: 'prompt-resource-attachment',\n axes: [\n 'systemPrompt',\n 'instructions',\n 'files',\n 'resourceTools',\n 'skills',\n 'resourceAgents',\n 'commands',\n 'resourceInstructions',\n ],\n})\n\n/** Define the profile axes a concrete run path actually carries into execution. */\nexport function defineProfileMaterializationContract(\n options: DefineProfileMaterializationContractOptions,\n): ProfileMaterializationContract {\n const name = options.name.trim()\n if (!name) {\n throw new ValidationError('defineProfileMaterializationContract: name is required')\n }\n return {\n name,\n axes: normalizeContractAxes(options.axes, `${name}.axes`),\n }\n}\n\n/** Return every changed profile axis that the selected run path would drop. */\nexport function validateProfileMaterialization(\n options: ValidateProfileMaterializationOptions,\n): readonly ProfileMaterializationIssue[] {\n const changedAxes = normalizeChangedAxes(options.changedAxes, 'changedAxes')\n const supported = new Set<string>(\n normalizeContractAxes(options.contract.axes, `${options.contract.name}.axes`),\n )\n const issues: ProfileMaterializationIssue[] = []\n for (const axis of changedAxes) {\n if (isAxisSupported(axis, supported)) continue\n issues.push({\n contract: options.contract.name,\n axis,\n reason: 'unsupported-axis',\n supportedAxes: [...supported] as AgentProfileMaterializationAxis[],\n })\n }\n return issues\n}\n\n/** Throw when a candidate changes axes the selected run path cannot carry. */\nexport function assertProfileMaterialization(options: AssertProfileMaterializationOptions): void {\n const issues = validateProfileMaterialization(options)\n if (issues.length === 0) return\n throw new ValidationError(renderProfileMaterializationIssues(issues, options.context))\n}\n\n/** Format profile-axis drop issues into a concise operator-facing error. */\nexport function renderProfileMaterializationIssues(\n issues: readonly ProfileMaterializationIssue[],\n context?: string,\n): string {\n if (issues.length === 0) return ''\n const contract = issues[0]?.contract ?? '<unknown>'\n const prefix = context ? `${context}: ` : ''\n const droppedAxes = issues.map((issue) => issue.axis).join(', ')\n const supportedAxes = issues[0]?.supportedAxes.join(', ') || '<none>'\n return [\n `${prefix}profile materialization would drop axis changes on \"${contract}\": ${droppedAxes}.`,\n `Supported axes: ${supportedAxes}.`,\n 'Use a run path that carries those AgentProfile axes, or remove them from the candidate.',\n ].join('\\n')\n}\n\n/** Contract side: leaves (or `custom:`) only. A parent claim would hide a dropped child. */\nfunction normalizeContractAxes(\n axes: readonly AgentProfileMaterializationAxis[],\n label: string,\n): AgentProfileMaterializationAxis[] {\n return dedupe(axes.map((raw) => assertLeafAxis(raw, label)))\n}\n\n/**\n * Input side: leaves, `custom:`, and compound diff axes, which expand to their leaves so\n * `changedAgentProfileAxes` output composes with a leaf-only contract.\n */\nfunction normalizeChangedAxes(\n axes: readonly AgentProfileMaterializationAxis[],\n label: string,\n): AgentProfileMaterializationAxis[] {\n const out: AgentProfileMaterializationAxis[] = []\n for (const raw of axes) {\n const axis = readAxisName(raw, label)\n const leaves = compoundAxisLeaves[axis]\n if (leaves && !KNOWN_AXIS_SET.has(axis)) {\n out.push(...leaves)\n continue\n }\n out.push(assertLeafAxis(raw, label))\n }\n return dedupe(out)\n}\n\nfunction dedupe(\n axes: readonly AgentProfileMaterializationAxis[],\n): AgentProfileMaterializationAxis[] {\n const out: AgentProfileMaterializationAxis[] = []\n const seen = new Set<string>()\n for (const axis of axes) {\n if (seen.has(axis)) continue\n seen.add(axis)\n out.push(axis)\n }\n return out\n}\n\nfunction readAxisName(raw: AgentProfileMaterializationAxis, label: string): string {\n if (typeof raw !== 'string') {\n throw new ValidationError(`${label}: profile axis must be a string`)\n }\n const axis = raw.trim()\n if (!axis) {\n throw new ValidationError(`${label}: profile axis must be non-empty`)\n }\n return axis\n}\n\nfunction assertLeafAxis(\n raw: AgentProfileMaterializationAxis,\n label: string,\n): AgentProfileMaterializationAxis {\n const axis = readAxisName(raw, label)\n if (!KNOWN_AXIS_SET.has(axis) && !axis.startsWith('custom:')) {\n const leaves = compoundAxisLeaves[axis]\n if (leaves) {\n throw new ValidationError(\n `${label}: \"${axis}\" is a compound AgentProfile property, not a materialization axis. ` +\n `Name the exact leaves this path carries: ${leaves.join(', ')}.`,\n )\n }\n throw new ValidationError(\n `${label}: unknown profile axis \"${axis}\". Use a known axis or custom:<name>.`,\n )\n }\n return axis as AgentProfileMaterializationAxis\n}\n\nfunction isAxisSupported(\n axis: AgentProfileMaterializationAxis,\n supported: ReadonlySet<string>,\n): boolean {\n return supported.has(axis)\n}\n","/**\n * Sandbox bridge for `AgentRuntime.act` — prod-faithful eval execution.\n *\n * The point of this adapter is parity: the eval substrate must run the agent\n * through the SAME profile the production chat turn uses, or scorecard numbers\n * grade a profile that never ships. `createSandboxAct` boots a sandbox with the\n * agent's profile (the caller's `baseProfile`, with optional per-persona\n * overrides) through the loop kernel's own {@link createSandboxForSpec},\n * streams the `streamPrompt` events mapped to the `RuntimeStreamEvent`\n * vocabulary, and resolves the `OutputAdapter`-parsed output for rubric scoring\n * — satisfying the `act` streaming contract with one code path shared by chat\n * and eval.\n *\n * Agents with a bespoke streaming chat turn should wire THAT into `act`\n * directly (the contract is designed for it); this adapter is the default for\n * agents whose turn is a plain prod-profile sandbox dispatch — notably the\n * agents agent-builder generates.\n */\n\nimport type {\n AgentProfile,\n AgentProfileFileMount,\n AgentProfileMcpServer,\n} from '@tangle-network/agent-interface'\nimport type { SandboxEvent } from '@tangle-network/sandbox'\nimport type { AgentRunSpec, OutputAdapter, SandboxClient } from '../runtime'\nimport { mapSandboxEvent } from '../runtime'\nimport { createSandboxForSpec } from '../runtime/run-loop'\nimport type { RuntimeStreamEvent } from '../types'\nimport type { AgentRunContext, AgentRunInvocation } from './define-agent'\nimport {\n type AgentProfileMaterializationAxis,\n assertProfileMaterialization,\n sandboxActProfileMaterialization,\n} from './profile-materialization'\n\n/** Per-persona profile-merge slots applied over the base profile (§1.5: the caller authors the\n * per-persona profile). Each slot overlays the base; an absent slot leaves the base untouched. */\nexport interface SandboxActComposeOverrides {\n /** Replace the base profile's system prompt (e.g. a workspace-augmented prompt). */\n systemPrompt?: string\n /** Extra file mounts layered after the base profile's `resources.files`. */\n extraFiles?: AgentProfileFileMount[]\n /** Override the profile `name`. Defaults to the base profile's name. */\n name?: string\n /** Box built-in tool ON/OFF flags merged over the base profile's `tools` (overlay wins per key). */\n tools?: Record<string, boolean>\n /** MCP connections merged over the base profile's `mcp` (overlay wins per key). */\n mcpConnections?: Record<string, AgentProfileMcpServer>\n}\n\nexport interface CreateSandboxActOptions<TPersona, TRunOutput> {\n /** Canonical agent profile — the same one the prod chat turn uses. */\n baseProfile: AgentProfile\n /** Sandbox client used to boot the per-run sandbox. */\n sandboxClient: SandboxClient\n /** Persona → prompt. Pure; the eval cell's input. */\n buildPrompt: (persona: TPersona) => string\n /** Sandbox event stream → typed output the rubric scores. */\n output: OutputAdapter<TRunOutput>\n /**\n * Per-persona profile overrides (workspace-augmented system prompt, extra\n * file mounts, tool flags, MCP connections). Overlaid onto `baseProfile`.\n */\n compose?: (persona: TPersona) => SandboxActComposeOverrides\n /** Sandbox-SDK overrides forwarded to `createSandboxForSpec`. */\n sandboxOverrides?: AgentRunSpec<unknown>['sandboxOverrides']\n /** Optional changed axes the caller expects this path to carry. */\n requiredProfileAxes?: readonly AgentProfileMaterializationAxis[]\n /** Stable run name surfaced in mapped `llm_call` events. */\n name?: string\n /** Override the `SandboxEvent → RuntimeStreamEvent` mapper. */\n mapEvent?: (\n event: SandboxEvent,\n opts: { agentRunName?: string },\n ) => RuntimeStreamEvent | undefined\n}\n\n/**\n * Build an `AgentRuntime.act` implementation backed by a single prod-profile\n * sandbox run. The returned function honours the `act` contract: it returns\n * synchronously with a live `events` iterator and an `output` promise that\n * resolves only after the iterator drains.\n */\nexport function createSandboxAct<TPersona, TRunOutput>(\n options: CreateSandboxActOptions<TPersona, TRunOutput>,\n): (persona: TPersona, ctx: AgentRunContext) => AgentRunInvocation<TRunOutput> {\n assertProfileMaterialization({\n contract: sandboxActProfileMaterialization,\n changedAxes: options.requiredProfileAxes ?? [],\n context: 'createSandboxAct',\n })\n const mapEvent = options.mapEvent ?? mapSandboxEvent\n\n return (persona: TPersona, ctx: AgentRunContext): AgentRunInvocation<TRunOutput> => {\n const profile = applyComposeOverrides(options.baseProfile, options.compose?.(persona))\n const agentRunName = options.name ?? profile.name ?? 'agent'\n const message = options.buildPrompt(persona)\n const signal = ctx.signal ?? new AbortController().signal\n\n const raw: SandboxEvent[] = []\n let settle!: (value: TRunOutput) => void\n let fail!: (err: unknown) => void\n const output = new Promise<TRunOutput>((resolve, reject) => {\n settle = resolve\n fail = reject\n })\n // The output promise rejects when the stream errors; if the caller ignores\n // `output` (chat UX) the rejection is still observed by the events iterator\n // throwing. Attach a no-op catch so an ignored rejection is never \"unhandled\".\n output.catch(() => {})\n\n const spec: AgentRunSpec<unknown> = {\n profile,\n taskToPrompt: () => message,\n name: agentRunName,\n ...(options.sandboxOverrides ? { sandboxOverrides: options.sandboxOverrides } : {}),\n }\n\n async function* events(): AsyncIterable<RuntimeStreamEvent> {\n try {\n const box = await createSandboxForSpec(options.sandboxClient, spec, signal)\n for await (const event of box.streamPrompt(message, { signal })) {\n raw.push(event)\n const mapped = mapEvent(event, { agentRunName })\n if (mapped) yield mapped\n }\n settle(options.output.parse(raw))\n } catch (err) {\n fail(err)\n throw err\n }\n }\n\n return { events: events(), output }\n }\n}\n\n/** Overlay the per-persona overrides onto the base profile. Each slot merges over the base; an\n * absent override leaves the base profile untouched. */\nfunction applyComposeOverrides(\n base: AgentProfile,\n overrides: SandboxActComposeOverrides | undefined,\n): AgentProfile {\n if (!overrides) return base\n const prompt = overrides.systemPrompt\n ? { ...base.prompt, systemPrompt: overrides.systemPrompt }\n : base.prompt\n const mergedTools = overrides.tools ? { ...(base.tools ?? {}), ...overrides.tools } : base.tools\n const mergedMcp = overrides.mcpConnections\n ? { ...(base.mcp ?? {}), ...overrides.mcpConnections }\n : base.mcp\n const baseFiles = base.resources?.files ?? []\n const mergedFiles: AgentProfileFileMount[] = overrides.extraFiles?.length\n ? [...baseFiles, ...overrides.extraFiles]\n : [...baseFiles]\n return {\n ...base,\n name: overrides.name ?? base.name,\n prompt,\n ...(mergedTools ? { tools: mergedTools } : {}),\n ...(mergedMcp ? { mcp: mergedMcp } : {}),\n resources: { ...base.resources, files: mergedFiles },\n }\n}\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
- import { $ as parseExactAgentProfile, K as applyExactAgentProfileDiff, S as CANDIDATE_TRACE_TAGS, _ as candidateExecutionClaim, a as persistCandidateOutputArtifact, c as CANDIDATE_KNOWLEDGE_ROOT_ENV, et as parseExactAgentProfileDiff, f as verifyAgentCandidateBundle, h as InMemoryAgentCandidateExecutionClaimStore, l as candidateKnowledgeExecutionPaths, n as executePreparedAgentCandidate, q as assertCandidateProfileBinding, s as CANDIDATE_KNOWLEDGE_RETRIEVAL_CONFIG_ENV, t as prepareAgentCandidateExecution, u as AGENT_CANDIDATE_EXECUTION_SUPPORT, x as CANDIDATE_TRACE_ENV } from "../prepare-BKVdOn0w.js";
2
- import { i as sealAgentCandidateBundle, n as captureAgentCandidateWorkspaceFiles, r as createAgentCandidateWorkspacePort, t as captureAgentCandidateWorkspace } from "../workspace-archive-CYYxZyA7.js";
3
- import { i as buildAgentCandidateBundle, n as disposePreparedAgentCandidateExecution, r as FileAgentCandidateExecutionClaimStore, t as recoverExpiredAgentCandidateExecution } from "../candidate-execution-Co3sRC_7.js";
4
- import { n as exactProcessProviderAsCandidateExecutor, t as createProtectedAgentCandidateModelPort } from "../protected-model-port-BtldAE9j.js";
1
+ import { $ as parseExactAgentProfile, K as applyExactAgentProfileDiff, S as CANDIDATE_TRACE_TAGS, _ as candidateExecutionClaim, a as persistCandidateOutputArtifact, c as CANDIDATE_KNOWLEDGE_ROOT_ENV, et as parseExactAgentProfileDiff, f as verifyAgentCandidateBundle, h as InMemoryAgentCandidateExecutionClaimStore, l as candidateKnowledgeExecutionPaths, n as executePreparedAgentCandidate, q as assertCandidateProfileBinding, s as CANDIDATE_KNOWLEDGE_RETRIEVAL_CONFIG_ENV, t as prepareAgentCandidateExecution, u as AGENT_CANDIDATE_EXECUTION_SUPPORT, x as CANDIDATE_TRACE_ENV } from "../prepare-BHQBb02e.js";
2
+ import { i as sealAgentCandidateBundle, n as captureAgentCandidateWorkspaceFiles, r as createAgentCandidateWorkspacePort, t as captureAgentCandidateWorkspace } from "../workspace-archive-DXzJq7WP.js";
3
+ import { i as buildAgentCandidateBundle, n as disposePreparedAgentCandidateExecution, r as FileAgentCandidateExecutionClaimStore, t as recoverExpiredAgentCandidateExecution } from "../candidate-execution-CfpJrd3o.js";
4
+ import { n as exactProcessProviderAsCandidateExecutor, t as createProtectedAgentCandidateModelPort } from "../protected-model-port-DqAH1Z2M.js";
5
5
  export { AGENT_CANDIDATE_EXECUTION_SUPPORT, CANDIDATE_KNOWLEDGE_RETRIEVAL_CONFIG_ENV, CANDIDATE_KNOWLEDGE_ROOT_ENV, CANDIDATE_TRACE_ENV, CANDIDATE_TRACE_TAGS, FileAgentCandidateExecutionClaimStore, InMemoryAgentCandidateExecutionClaimStore, applyExactAgentProfileDiff, assertCandidateProfileBinding, buildAgentCandidateBundle, candidateExecutionClaim, candidateKnowledgeExecutionPaths, captureAgentCandidateWorkspace, captureAgentCandidateWorkspaceFiles, createAgentCandidateWorkspacePort, createProtectedAgentCandidateModelPort, disposePreparedAgentCandidateExecution, exactProcessProviderAsCandidateExecutor, executePreparedAgentCandidate, parseExactAgentProfile, parseExactAgentProfileDiff, persistCandidateOutputArtifact, prepareAgentCandidateExecution, recoverExpiredAgentCandidateExecution, sealAgentCandidateBundle, verifyAgentCandidateBundle };
@@ -1,6 +1,6 @@
1
- import { $ as parseExactAgentProfile, B as rejectedStage, F as assertTerminalAllowedInPhase, H as sealTerminalDigest, I as assertTerminalMatchesClaim, K as applyExactAgentProfileDiff, L as assertTerminalMatchesStaged, M as candidateCleanupTimeout, N as withinCandidateCleanupDeadline, O as readVerifiedArtifact, P as assertRecoveryMatchesStaged, R as recoveredTerminalRecord, U as terminalRecord, V as requireStagedTerminal, X as freezeGenericAgentCandidateProfile, a as persistCandidateOutputArtifact, b as consumePreparedCandidateExecution, et as parseExactAgentProfileDiff, g as candidateClaimFileInternals, i as persistCandidateModelSettlementEvidence, j as candidateCleanupDeadline, nt as canonicalCandidateBytes, o as sealAgentCandidateExecutorStopAcknowledgement, ot as embeddedCandidateArtifact, p as sealAgentCandidateModelSettlement, r as RecoveryAgentCandidateTraceStore, tt as parseExactCandidateProfile, v as assertPreparedCandidateIntegrity, y as beginPreparedCandidateDisposal, z as rejectedFinish } from "./prepare-BKVdOn0w.js";
2
- import { i as sealAgentCandidateBundle } from "./workspace-archive-CYYxZyA7.js";
3
- import "./protected-model-port-BtldAE9j.js";
1
+ import { $ as parseExactAgentProfile, B as rejectedStage, F as assertTerminalAllowedInPhase, H as sealTerminalDigest, I as assertTerminalMatchesClaim, K as applyExactAgentProfileDiff, L as assertTerminalMatchesStaged, M as candidateCleanupTimeout, N as withinCandidateCleanupDeadline, O as readVerifiedArtifact, P as assertRecoveryMatchesStaged, R as recoveredTerminalRecord, U as terminalRecord, V as requireStagedTerminal, X as freezeGenericAgentCandidateProfile, a as persistCandidateOutputArtifact, b as consumePreparedCandidateExecution, et as parseExactAgentProfileDiff, g as candidateClaimFileInternals, i as persistCandidateModelSettlementEvidence, j as candidateCleanupDeadline, nt as canonicalCandidateBytes, o as sealAgentCandidateExecutorStopAcknowledgement, ot as embeddedCandidateArtifact, p as sealAgentCandidateModelSettlement, r as RecoveryAgentCandidateTraceStore, tt as parseExactCandidateProfile, v as assertPreparedCandidateIntegrity, y as beginPreparedCandidateDisposal, z as rejectedFinish } from "./prepare-BHQBb02e.js";
2
+ import { i as sealAgentCandidateBundle } from "./workspace-archive-DXzJq7WP.js";
3
+ import "./protected-model-port-DqAH1Z2M.js";
4
4
  import { verifyCodeSurface } from "@tangle-network/agent-eval/campaign";
5
5
  import { agentCandidateExecutionPlanMaterialSchema, agentCandidateMaterializationReceiptSchema } from "@tangle-network/agent-interface";
6
6
  import { randomUUID } from "node:crypto";
@@ -485,4 +485,4 @@ function parseCanonicalBytes(bytes, label) {
485
485
  //#endregion
486
486
  export { buildAgentCandidateBundle as i, disposePreparedAgentCandidateExecution as n, FileAgentCandidateExecutionClaimStore as r, recoverExpiredAgentCandidateExecution as t };
487
487
 
488
- //# sourceMappingURL=candidate-execution-Co3sRC_7.js.map
488
+ //# sourceMappingURL=candidate-execution-CfpJrd3o.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"candidate-execution-Co3sRC_7.js","names":[],"sources":["../src/candidate-execution/builder.ts","../src/candidate-execution/claim-file-store.ts","../src/candidate-execution/dispose.ts","../src/candidate-execution/recover.ts"],"sourcesContent":["import type { CodeSurface } from '@tangle-network/agent-eval/campaign'\nimport { verifyCodeSurface } from '@tangle-network/agent-eval/campaign'\nimport type {\n AgentCandidateCodeDisabled,\n AgentCandidateCodeNoOp,\n AgentCandidateExecution,\n AgentCandidateGitHubRepository,\n AgentCandidateKnowledge,\n AgentCandidateMemoryPolicy,\n AgentCandidateProfile,\n AgentProfile,\n AgentProfileDiff,\n} from '@tangle-network/agent-interface'\nimport { type AgentCandidateBundleInput, sealAgentCandidateBundle } from './bundle'\nimport { embeddedCandidateArtifact } from './digest'\nimport {\n applyExactAgentProfileDiff,\n freezeGenericAgentCandidateProfile,\n parseExactAgentProfile,\n parseExactAgentProfileDiff,\n parseExactCandidateProfile,\n} from './profile'\n\n/** A complete profile that can be frozen without losing behavior. */\nexport type AgentCandidateProfileSource =\n | {\n kind: 'profile'\n profile: AgentProfile\n }\n | {\n kind: 'profile-diffs'\n base: AgentProfile\n /** Applied in order before the resulting profile is frozen into the bundle. */\n diffs: readonly AgentProfileDiff[]\n }\n | {\n kind: 'candidate-profile'\n /** Already converted to the closed, secret-free candidate profile contract. */\n profile: AgentCandidateProfile\n }\n\n/** The only accepted path from an agent-eval code candidate to executable bytes. */\nexport interface AgentCandidateCodeSurfaceSource {\n kind: 'code-surface'\n surface: CodeSurface\n repository: AgentCandidateGitHubRepository\n /** Optional parent directory used to resolve a relative `surface.worktreeRef`. */\n worktreeDir?: string\n}\n\n/** Explicit control/no-op code or one finalized CodeSurface whose bytes must still verify. */\nexport type AgentCandidateCodeSource =\n | AgentCandidateCodeDisabled\n | AgentCandidateCodeNoOp\n | AgentCandidateCodeSurfaceSource\n\n/** Complete measured surfaces and execution policy compiled into one candidate bundle. */\nexport interface BuildAgentCandidateBundleInput {\n profile: AgentCandidateProfileSource\n code: AgentCandidateCodeSource\n execution: AgentCandidateExecution\n knowledge?: AgentCandidateKnowledge\n memory: AgentCandidateMemoryPolicy\n}\n\n/**\n * Compile one measured profile/code candidate into the immutable execution\n * contract. Code bytes are re-read and verified by agent-eval before they are\n * embedded. The returned bundle is schema-validated, canonically digested, and\n * deeply immutable; call `verifyAgentCandidateBundle` at the execution boundary\n * to re-read external memory, repository, and workspace artifacts.\n */\nexport function buildAgentCandidateBundle(\n input: BuildAgentCandidateBundleInput,\n): ReturnType<typeof sealAgentCandidateBundle> {\n const bundle: AgentCandidateBundleInput = {\n kind: 'agent-candidate-bundle',\n digestAlgorithm: 'rfc8785-sha256',\n profile: compileCandidateProfile(input.profile),\n code: compileCandidateCode(input.code),\n execution: input.execution,\n ...(input.knowledge !== undefined ? { knowledge: input.knowledge } : {}),\n memory: input.memory,\n }\n return sealAgentCandidateBundle(bundle)\n}\n\nfunction compileCandidateProfile(source: AgentCandidateProfileSource): AgentCandidateProfile {\n if (source.kind === 'candidate-profile') {\n return parseExactCandidateProfile(source.profile)\n }\n\n if (source.kind === 'profile') {\n return freezeGenericAgentCandidateProfile(source.profile)\n }\n\n if (source.kind !== 'profile-diffs') {\n throw new Error(\n `unsupported candidate profile source: ${String((source as { kind?: unknown }).kind)}`,\n )\n }\n if (source.diffs.length === 0) {\n throw new Error('profile-diffs source requires at least one AgentProfileDiff')\n }\n let profile = parseExactAgentProfile(source.base, 'base profile')\n for (const [index, inputDiff] of source.diffs.entries()) {\n const diff = parseExactAgentProfileDiff(inputDiff, `profile diff ${index}`)\n profile = applyExactAgentProfileDiff(profile, diff, `profile diff ${index}`)\n }\n return freezeGenericAgentCandidateProfile(profile)\n}\n\nfunction compileCandidateCode(source: AgentCandidateCodeSource): AgentCandidateBundleInput['code'] {\n if (source.kind === 'disabled' || source.kind === 'no-op') return source\n if (source.kind !== 'code-surface') {\n throw new Error(\n `unsupported candidate code source: ${String((source as { kind?: unknown }).kind)}`,\n )\n }\n\n const verified = verifyCodeSurface(source.surface, source.worktreeDir)\n const patch = embeddedCandidateArtifact(verified.patchBytes)\n if (\n patch.sha256 !== source.surface.patch.sha256 ||\n patch.byteLength !== source.surface.patch.byteLength\n ) {\n throw new Error('verified CodeSurface patch bytes do not match its content identity')\n }\n return {\n kind: 'git-patch',\n repository: source.repository,\n baseCommit: source.surface.baseCommit,\n baseTree: source.surface.baseTree,\n candidateTree: source.surface.candidateTree,\n patch: { format: 'git-diff-binary', artifact: patch },\n }\n}\n","import { randomUUID } from 'node:crypto'\nimport { linkSync } from 'node:fs'\nimport { mkdir, open, unlink } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport type { Sha256Digest } from '@tangle-network/agent-interface'\n\nimport {\n type AgentCandidateExecutionAttemptRecord,\n type AgentCandidateExecutionAttemptRef,\n type AgentCandidateExecutionClaim,\n type AgentCandidateExecutionClaimResult,\n type AgentCandidateExecutionClaimStore,\n type AgentCandidateExecutionFinishResult,\n type AgentCandidateExecutionLease,\n type AgentCandidateExecutionPhase,\n type AgentCandidateExecutionPhaseResult,\n type AgentCandidateExecutionRecoveryEvidence,\n type AgentCandidateExecutionStageResult,\n type AgentCandidateExecutionTerminalRecord,\n type AgentCandidateExecutionTerminalResult,\n type AgentCandidateRetryRejection,\n candidateClaimFileInternals,\n} from './claim'\nimport {\n assertRecoveryMatchesStaged,\n assertTerminalAllowedInPhase,\n assertTerminalMatchesClaim,\n assertTerminalMatchesStaged,\n recoveredTerminalRecord,\n rejectedFinish,\n rejectedStage,\n requireStagedTerminal,\n sealTerminalDigest,\n terminalRecord,\n} from './claim-terminal'\nimport { canonicalCandidateBytes } from './digest'\n\nconst {\n assertExpiredLease,\n assertLease,\n assertSameSlot,\n assertUnexpiredLease,\n attemptRecord,\n claimSlot,\n leaseDigest,\n newLease,\n readClaim,\n readClaimIfPresent,\n readTerminal,\n readTerminalIfPresent,\n readTransitionIfPresent,\n rejectedExistingClaim,\n rejectedRetry,\n retryRejection,\n sealAttemptRef,\n sealClaim,\n sealLease,\n} = candidateClaimFileInternals\n\nexport interface FileAgentCandidateExecutionClaimStoreOptions {\n /** Evaluator-owned directory shared by every process allowed to execute candidates. */\n directory: string\n /** Testable evaluator clock; defaults to `Date.now`. */\n now?: () => number\n}\n\n/** Cross-process lifecycle implemented as fsynced, create-if-absent records. */\nexport class FileAgentCandidateExecutionClaimStore implements AgentCandidateExecutionClaimStore {\n private readonly directory: string\n private readonly now: () => number\n\n constructor(options: FileAgentCandidateExecutionClaimStoreOptions) {\n if (options.directory.length === 0) {\n throw new Error('candidate execution claim directory must not be empty')\n }\n this.directory = options.directory\n this.now = options.now ?? Date.now\n }\n\n async tryClaim(\n requested: AgentCandidateExecutionClaim,\n ): Promise<AgentCandidateExecutionClaimResult> {\n const claim = sealClaim(requested)\n await mkdir(this.directory, { recursive: true })\n const claimPath = this.claimPath(claim)\n const existing = await readClaimIfPresent(claimPath)\n if (existing) {\n assertSameSlot(existing.claim, claim, claimPath)\n return rejectedExistingClaim(existing.claim, claim)\n }\n assertUnexpiredLease(claim.leaseExpiresAtMs, this.now())\n const retryFailure = await this.retryFailure(claim)\n if (retryFailure) return rejectedRetry(claim, retryFailure)\n\n const lease = newLease(claim)\n const acquired = await writeRecordIfAbsent(this.directory, claimPath, {\n ...claim,\n phase: 'claimed',\n leaseDigest: leaseDigest(lease),\n })\n if (acquired) return Object.freeze({ acquired: true, claim, lease })\n\n const winner = await readClaim(claimPath)\n assertSameSlot(winner.claim, claim, claimPath)\n return rejectedExistingClaim(winner.claim, claim)\n }\n\n async getAttempt(\n requestedAttempt: AgentCandidateExecutionAttemptRef,\n ): Promise<AgentCandidateExecutionAttemptRecord | undefined> {\n return await this.storedAttempt(sealAttemptRef(requestedAttempt))\n }\n\n async markCandidateMayRun(\n requestedLease: AgentCandidateExecutionLease,\n ): Promise<AgentCandidateExecutionPhaseResult> {\n const lease = sealLease(requestedLease)\n const claimPath = this.claimPath(lease)\n const stored = await readClaim(claimPath)\n assertSameSlot(stored.claim, lease, claimPath)\n assertLease(stored.leaseDigest, stored.claim.leaseExpiresAtMs, lease)\n const state = await this.transitionState(stored.claim)\n if (state.phase === 'candidate-may-run') {\n return Object.freeze({ marked: false, phase: 'candidate-may-run' })\n }\n if (state.staged) {\n throw new Error('candidate execution terminal was staged before candidate-may-run phase')\n }\n assertUnexpiredLease(stored.claim.leaseExpiresAtMs, this.now())\n const marked = await writeRecordIfAbsent(\n this.directory,\n this.transitionPath(stored.claim, 1),\n {\n kind: 'candidate-execution-phase',\n executionId: stored.claim.executionId,\n attempt: stored.claim.attempt,\n executionPlanDigest: stored.claim.executionPlanDigest,\n phase: 'candidate-may-run',\n },\n this.ownerPublication(stored.claim),\n )\n if (marked) return Object.freeze({ marked: true, phase: 'candidate-may-run' })\n const winner = await this.transitionState(stored.claim)\n if (winner.phase === 'candidate-may-run') {\n return Object.freeze({ marked: false, phase: 'candidate-may-run' })\n }\n throw new Error('candidate execution terminal was staged before candidate-may-run phase')\n }\n\n async stageTerminal(\n requestedLease: AgentCandidateExecutionLease,\n result: AgentCandidateExecutionTerminalResult,\n ): Promise<AgentCandidateExecutionStageResult> {\n const lease = sealLease(requestedLease)\n const claimPath = this.claimPath(lease)\n const stored = await readClaim(claimPath)\n assertSameSlot(stored.claim, lease, claimPath)\n assertLease(stored.leaseDigest, stored.claim.leaseExpiresAtMs, lease)\n const terminal = terminalRecord(stored.claim, result)\n const state = await this.transitionState(stored.claim)\n if (state.staged) return rejectedStage(state.staged, terminal)\n assertTerminalAllowedInPhase(state.phase, terminal)\n assertUnexpiredLease(stored.claim.leaseExpiresAtMs, this.now())\n const transition = state.phase === 'claimed' ? 1 : 2\n const staged = await writeRecordIfAbsent(\n this.directory,\n this.transitionPath(stored.claim, transition),\n {\n kind: 'candidate-execution-pending-terminal',\n terminal,\n },\n this.ownerPublication(stored.claim),\n )\n if (staged) return Object.freeze({ staged: true, terminal })\n const winner = await this.transitionState(stored.claim)\n if (!winner.staged) {\n throw new Error('candidate execution phase transition won while staging terminal')\n }\n return rejectedStage(winner.staged, terminal)\n }\n\n async finish(\n requestedLease: AgentCandidateExecutionLease,\n requestedTerminalDigest: Sha256Digest,\n ): Promise<AgentCandidateExecutionFinishResult> {\n const lease = sealLease(requestedLease)\n const terminalDigest = sealTerminalDigest(requestedTerminalDigest)\n const claimPath = this.claimPath(lease)\n const stored = await readClaim(claimPath)\n assertSameSlot(stored.claim, lease, claimPath)\n assertLease(stored.leaseDigest, stored.claim.leaseExpiresAtMs, lease)\n const state = await this.transitionState(stored.claim)\n const staged = requireStagedTerminal(state.staged, terminalDigest)\n const terminalPath = this.terminalPath(lease)\n const existing = await readTerminalIfPresent(terminalPath)\n if (existing) {\n assertTerminalMatchesClaim(existing, stored.claim, terminalPath)\n assertTerminalMatchesStaged(existing, staged, terminalPath)\n return rejectedFinish(existing, terminalDigest)\n }\n assertUnexpiredLease(stored.claim.leaseExpiresAtMs, this.now())\n const finished = await writeRecordIfAbsent(\n this.directory,\n terminalPath,\n {\n terminal: staged,\n },\n this.ownerPublication(stored.claim),\n )\n if (finished) return Object.freeze({ finished: true, terminal: staged })\n const winner = await readTerminal(terminalPath)\n assertSameSlot(winner, lease, terminalPath)\n assertTerminalMatchesClaim(winner, stored.claim, terminalPath)\n assertTerminalMatchesStaged(winner, staged, terminalPath)\n return rejectedFinish(winner, terminalDigest)\n }\n\n async recoverExpired(\n requestedAttempt: AgentCandidateExecutionAttemptRef,\n evidence: AgentCandidateExecutionRecoveryEvidence,\n ): Promise<AgentCandidateExecutionFinishResult> {\n const attempt = sealAttemptRef(requestedAttempt)\n const record = await this.storedAttempt(attempt)\n if (!record) throw new Error('candidate execution recovery does not name an acquired attempt')\n const recovered = recoveredTerminalRecord(record.claim, record.phase, evidence)\n if (record.staged) assertRecoveryMatchesStaged(record.staged, recovered)\n const requestedDigest = record.staged?.terminalDigest ?? recovered.terminalDigest\n if (record.terminal) return rejectedFinish(record.terminal, requestedDigest)\n assertExpiredLease(record.claim.leaseExpiresAtMs, this.now())\n\n let staged = record.staged\n if (!staged) {\n const transition = record.phase === 'claimed' ? 1 : 2\n const didStage = await writeRecordIfAbsent(\n this.directory,\n this.transitionPath(record.claim, transition),\n {\n kind: 'candidate-execution-pending-terminal',\n terminal: recovered,\n },\n )\n if (didStage) {\n staged = recovered\n } else {\n const winner = await this.transitionState(record.claim)\n if (!winner.staged) {\n throw new Error(\n 'candidate execution recovery lost terminal staging to a phase transition',\n )\n }\n assertRecoveryMatchesStaged(winner.staged, recovered)\n staged = winner.staged\n }\n }\n\n const terminalPath = this.terminalPath(attempt)\n const didFinish = await writeRecordIfAbsent(this.directory, terminalPath, {\n terminal: staged,\n })\n if (didFinish) return Object.freeze({ finished: true, terminal: staged })\n const winner = await readTerminal(terminalPath)\n assertSameSlot(winner, attempt, terminalPath)\n assertTerminalMatchesClaim(winner, record.claim, terminalPath)\n assertTerminalMatchesStaged(winner, staged, terminalPath)\n return rejectedFinish(winner, staged.terminalDigest)\n }\n\n private async storedAttempt(\n claim: Pick<AgentCandidateExecutionClaim, 'executionId' | 'attempt'>,\n ): Promise<AgentCandidateExecutionAttemptRecord | undefined> {\n const claimPath = this.claimPath(claim)\n const stored = await readClaimIfPresent(claimPath)\n if (!stored) return undefined\n assertSameSlot(stored.claim, claim, claimPath)\n const state = await this.transitionState(stored.claim)\n const terminalPath = this.terminalPath(claim)\n const terminal = await readTerminalIfPresent(terminalPath)\n if (terminal) {\n assertTerminalMatchesClaim(terminal, stored.claim, terminalPath)\n if (!state.staged) {\n throw new Error(\n `candidate execution terminal record at ${terminalPath} has no staged outbox`,\n )\n }\n assertTerminalMatchesStaged(terminal, state.staged, terminalPath)\n }\n return attemptRecord(stored.claim, state.phase, state.staged, terminal)\n }\n\n private async transitionState(claim: AgentCandidateExecutionClaim): Promise<{\n phase: AgentCandidateExecutionPhase\n staged?: AgentCandidateExecutionTerminalRecord\n }> {\n const firstPath = this.transitionPath(claim, 1)\n const first = await readTransitionIfPresent(firstPath, claim)\n if (!first) return { phase: 'claimed' }\n if (first.kind === 'pending') return { phase: 'claimed', staged: first.terminal }\n const secondPath = this.transitionPath(claim, 2)\n const second = await readTransitionIfPresent(secondPath, claim)\n if (!second) return { phase: 'candidate-may-run' }\n if (second.kind !== 'pending') {\n throw new Error(`candidate execution transition at ${secondPath} repeats the phase marker`)\n }\n return { phase: 'candidate-may-run', staged: second.terminal }\n }\n\n private async retryFailure(\n claim: AgentCandidateExecutionClaim,\n ): Promise<AgentCandidateRetryRejection | undefined> {\n if (claim.attempt === 1) return undefined\n return retryRejection(\n claim,\n await this.storedAttempt({\n executionId: claim.executionId,\n attempt: claim.attempt - 1,\n }),\n )\n }\n\n private ownerPublication(claim: AgentCandidateExecutionClaim): {\n authorizePublish: () => true\n } {\n return {\n authorizePublish: () => {\n assertUnexpiredLease(claim.leaseExpiresAtMs, this.now())\n return true\n },\n }\n }\n\n private claimPath(claim: Pick<AgentCandidateExecutionClaim, 'executionId' | 'attempt'>): string {\n return join(this.directory, `${claimSlot(claim)}.claim.json`)\n }\n\n private terminalPath(\n claim: Pick<AgentCandidateExecutionClaim, 'executionId' | 'attempt'>,\n ): string {\n return join(this.directory, `${claimSlot(claim)}.terminal.json`)\n }\n\n private transitionPath(\n claim: Pick<AgentCandidateExecutionClaim, 'executionId' | 'attempt'>,\n ordinal: 1 | 2,\n ): string {\n return join(this.directory, `${claimSlot(claim)}.transition-${ordinal}.json`)\n }\n}\n\nasync function writeRecordIfAbsent(\n directory: string,\n destination: string,\n record: object,\n options: {\n /** Synchronous authorization checked after temp fsync, immediately before atomic publication. */\n authorizePublish?: () => true\n } = {},\n): Promise<boolean> {\n const temporaryPath = join(directory, `.candidate-execution-${process.pid}-${randomUUID()}.tmp`)\n const handle = await open(temporaryPath, 'wx', 0o600)\n try {\n await handle.writeFile(\n Buffer.concat([Buffer.from(canonicalCandidateBytes(record)), Buffer.from('\\n')]),\n )\n await handle.sync()\n } finally {\n await handle.close()\n }\n\n let written = false\n try {\n if (options.authorizePublish && options.authorizePublish() !== true) {\n throw new Error('candidate execution record publication was not authorized')\n }\n // Authorization and the atomic filesystem call are one synchronous critical\n // section so the event loop cannot advance an injected lease clock between them.\n linkSync(temporaryPath, destination)\n written = true\n await syncDirectory(directory)\n } catch (error) {\n if (!isNodeError(error, 'EEXIST')) throw error\n } finally {\n await unlink(temporaryPath).catch((error: unknown) => {\n if (!isNodeError(error, 'ENOENT')) throw error\n })\n }\n return written\n}\n\nasync function syncDirectory(directory: string): Promise<void> {\n const handle = await open(directory, 'r')\n try {\n await handle.sync()\n } finally {\n await handle.close()\n }\n}\n\nfunction isNodeError(error: unknown, code: string): boolean {\n return (\n error !== null &&\n typeof error === 'object' &&\n 'code' in error &&\n (error as { code?: unknown }).code === code\n )\n}\n","import { candidateCleanupDeadline, withinCandidateCleanupDeadline } from './cleanup'\nimport { sealAgentCandidateModelSettlement } from './model-settlement'\nimport {\n assertPreparedCandidateIntegrity,\n beginPreparedCandidateDisposal,\n consumePreparedCandidateExecution,\n} from './prepared-state'\nimport type { PreparedAgentCandidateExecution } from './types'\n\nexport interface DisposePreparedAgentCandidateOptions {\n cleanupTimeoutMs?: number\n}\n\n/** Revoke reservations held by a prepared candidate that will not be executed. */\nexport async function disposePreparedAgentCandidateExecution(\n prepared: PreparedAgentCandidateExecution,\n options: DisposePreparedAgentCandidateOptions = {},\n): Promise<{ disposed: true }> {\n const initialState = assertPreparedCandidateIntegrity(prepared)\n const cleanupTimeoutMs = options.cleanupTimeoutMs ?? initialState.cleanupTimeoutMs\n if (cleanupTimeoutMs > initialState.cleanupTimeoutMs) {\n throw new Error('disposal cleanup timeout exceeds the frozen preparation bound')\n }\n const cleanupDeadlineAtMs = candidateCleanupDeadline(cleanupTimeoutMs)\n const state = beginPreparedCandidateDisposal(prepared)\n const cleanup: Array<Promise<unknown>> = []\n\n if (state.memory.mode === 'isolated') {\n const reservation = state.memoryReservation\n if (!reservation) throw new Error('isolated memory reservation is missing')\n cleanup.push(\n withinCandidateCleanupDeadline(\n async () => {\n const closed = await state.ports.memory.close({\n executionId: state.executionId,\n preparationId: reservation.preparationId,\n accessDigest: reservation.accessDigest,\n effectiveNamespace: reservation.effectiveNamespace,\n reason: 'abandoned',\n })\n if (closed.closed !== true || Object.keys(closed).some((key) => key !== 'closed')) {\n throw new Error('abandoned isolated memory access did not acknowledge closure')\n }\n },\n cleanupDeadlineAtMs,\n 'isolated memory disposal',\n ),\n )\n }\n\n cleanup.push(\n withinCandidateCleanupDeadline(\n async () => {\n const settlement = sealAgentCandidateModelSettlement(\n await state.ports.models.settleGrant({\n executionId: state.executionId,\n preparationId: state.preparationId,\n grantDigest: state.modelReservation.digest,\n resolved: state.resolvedModel,\n reason: 'abandoned',\n }),\n {\n preparationId: state.preparationId,\n grantDigest: state.modelReservation.digest,\n model: state.resolvedModel.model,\n },\n )\n if (settlement.usage.modelCalls !== 0) {\n throw new Error('unexecuted model reservation unexpectedly contains calls')\n }\n },\n cleanupDeadlineAtMs,\n 'model reservation disposal',\n ),\n )\n\n const results = await Promise.allSettled(cleanup)\n const failures = results\n .filter((result): result is PromiseRejectedResult => result.status === 'rejected')\n .map((result) => result.reason)\n if (failures.length > 0) {\n consumePreparedCandidateExecution(prepared, 'disposal-failed')\n throw new AggregateError(failures, 'candidate preparation disposal failed')\n }\n\n consumePreparedCandidateExecution(prepared, 'disposed')\n return Object.freeze({ disposed: true as const })\n}\n","import type { TraceStore } from '@tangle-network/agent-eval'\nimport type {\n AgentCandidateExecutionPlanMaterial,\n AgentCandidateMaterializationReceipt,\n} from '@tangle-network/agent-interface'\nimport {\n agentCandidateExecutionPlanMaterialSchema,\n agentCandidateMaterializationReceiptSchema,\n} from '@tangle-network/agent-interface'\n\nimport { readVerifiedArtifact } from './artifacts'\nimport type {\n AgentCandidateExecutionAttemptRef,\n AgentCandidateExecutionClaim,\n AgentCandidateExecutionClaimStore,\n AgentCandidateExecutionFinishResult,\n} from './claim'\nimport {\n candidateCleanupDeadline,\n candidateCleanupTimeout,\n withinCandidateCleanupDeadline,\n} from './cleanup'\nimport { canonicalCandidateBytes } from './digest'\nimport { sealAgentCandidateExecutorStopAcknowledgement } from './executor-capture'\nimport { sealAgentCandidateModelSettlement } from './model-settlement'\nimport { persistCandidateModelSettlementEvidence } from './outcome-evidence'\nimport { persistCandidateOutputArtifact } from './output-artifacts'\nimport { RecoveryAgentCandidateTraceStore } from './protected-trace-store'\nimport type {\n AgentCandidateExecutionPorts,\n AgentCandidateExecutorPort,\n AgentCandidateOutputArtifactPort,\n} from './types'\n\nexport interface RecoverExpiredAgentCandidateOptions {\n attempt: AgentCandidateExecutionAttemptRef\n claimStore: AgentCandidateExecutionClaimStore\n executor: AgentCandidateExecutorPort\n traceStore: TraceStore\n ports: Pick<AgentCandidateExecutionPorts, 'models' | 'memory'>\n outputArtifacts: AgentCandidateOutputArtifactPort\n cleanupTimeoutMs?: number\n /** Evaluator clock; must be the same clock used by the claim store. */\n now?: () => number\n}\n\n/** Close an expired crashed attempt from persisted non-secret handles, then record failure. */\nexport async function recoverExpiredAgentCandidateExecution(\n options: RecoverExpiredAgentCandidateOptions,\n): Promise<AgentCandidateExecutionFinishResult> {\n const record = await options.claimStore.getAttempt(options.attempt)\n if (!record) throw new Error('candidate execution recovery attempt is missing')\n if (record.terminal) {\n return Object.freeze({ finished: false, terminal: record.terminal, exactReplay: true })\n }\n const cleanupTimeoutMs = candidateCleanupTimeout(\n options.cleanupTimeoutMs ?? record.claim.cleanup.cleanupTimeoutMs,\n )\n if (cleanupTimeoutMs > record.claim.cleanup.cleanupTimeoutMs) {\n throw new Error('recovery cleanup timeout exceeds the frozen preparation bound')\n }\n\n const now = options.now ?? Date.now\n if (now() < record.claim.leaseExpiresAtMs) {\n throw new Error('candidate execution lease has not expired')\n }\n\n const cleanupDeadlineAtMs = candidateCleanupDeadline(cleanupTimeoutMs)\n const recoveryTraceStore = new RecoveryAgentCandidateTraceStore(options.traceStore)\n const preparation = withinCandidateCleanupDeadline(\n () => readRecoveryPreparation(record.claim, options.outputArtifacts),\n cleanupDeadlineAtMs,\n 'expired candidate preparation evidence read',\n )\n const processClosure = withinCandidateCleanupDeadline(\n async (cleanupSignal) => {\n const stopped = await options.executor.stop(\n {\n executionId: record.claim.executionId,\n executionPlanDigest: record.claim.executionPlanDigest,\n },\n {\n traceStore: recoveryTraceStore,\n reason: 'failed',\n signal: cleanupSignal,\n deadlineAtMs: cleanupDeadlineAtMs,\n },\n )\n sealAgentCandidateExecutorStopAcknowledgement(stopped)\n if (options.executor.dispose) {\n const disposed = await options.executor.dispose(\n {\n executionId: record.claim.executionId,\n executionPlanDigest: record.claim.executionPlanDigest,\n },\n { signal: cleanupSignal },\n )\n if (disposed.disposed !== true || Object.keys(disposed).some((key) => key !== 'disposed')) {\n throw new Error('expired candidate executor did not acknowledge resource disposal')\n }\n }\n return { stopped: true as const }\n },\n cleanupDeadlineAtMs,\n 'expired candidate process termination',\n )\n\n const modelClosure = withinCandidateCleanupDeadline(\n async () =>\n sealAgentCandidateModelSettlement(\n await options.ports.models.settleGrant({\n executionId: record.claim.executionId,\n preparationId: record.claim.cleanup.preparationId,\n grantDigest: record.claim.cleanup.modelGrantDigest,\n resolved: record.claim.cleanup.resolvedModel,\n reason: 'failed',\n }),\n {\n preparationId: record.claim.cleanup.preparationId,\n grantDigest: record.claim.cleanup.modelGrantDigest,\n model: record.claim.cleanup.resolvedModel.model,\n },\n ),\n cleanupDeadlineAtMs,\n 'expired candidate model settlement',\n )\n\n const memoryClosure = record.claim.cleanup.memory\n ? withinCandidateCleanupDeadline(\n async () => {\n const memory = record.claim.cleanup.memory\n if (!memory) throw new Error('expired candidate memory handle is missing')\n const closed = await options.ports.memory.close({\n executionId: record.claim.executionId,\n preparationId: record.claim.cleanup.preparationId,\n accessDigest: memory.accessDigest,\n effectiveNamespace: memory.effectiveNamespace,\n reason: 'failed',\n })\n if (closed.closed !== true || Object.keys(closed).some((key) => key !== 'closed')) {\n throw new Error('expired candidate memory did not acknowledge closure')\n }\n return { closed: true as const }\n },\n cleanupDeadlineAtMs,\n 'expired candidate memory closure',\n )\n : undefined\n\n const closureOutcomes = Promise.allSettled([\n modelClosure,\n memoryClosure ?? Promise.resolve(undefined),\n ] as const)\n const [preparationOutcome, processOutcome] = await Promise.allSettled([\n preparation,\n processClosure,\n ] as const)\n const failures: unknown[] = [preparationOutcome, processOutcome]\n .filter((outcome): outcome is PromiseRejectedResult => outcome.status === 'rejected')\n .map((outcome) => outcome.reason)\n const [modelOutcome, memoryOutcome] = await closureOutcomes\n for (const outcome of [modelOutcome, memoryOutcome]) {\n if (outcome.status === 'rejected') failures.push(outcome.reason)\n }\n if (failures.length > 0) {\n throw new AggregateError(failures, 'expired candidate cleanup could not be proven')\n }\n\n if (modelOutcome.status !== 'fulfilled') {\n throw new Error('expired candidate model settlement was not recovered')\n }\n const model = modelOutcome.value\n const modelSettlement = await withinCandidateCleanupDeadline(\n () =>\n persistCandidateModelSettlementEvidence(\n {\n executionId: record.claim.executionId,\n executionPlanDigest: record.claim.executionPlanDigest,\n resolvedModel: record.claim.cleanup.resolvedModel,\n },\n model,\n options.outputArtifacts,\n ),\n cleanupDeadlineAtMs,\n 'expired candidate model-settlement persistence',\n )\n const failureClass =\n record.phase === 'claimed' && model.usage.modelCalls === 0\n ? 'pre-model-infrastructure'\n : 'unknown'\n const failureEvidence = await withinCandidateCleanupDeadline(\n () =>\n persistCandidateOutputArtifact(options.outputArtifacts, {\n executionId: record.claim.executionId,\n purpose: 'failure-evidence',\n bytes: canonicalCandidateBytes({\n kind: 'agent-candidate-recovery-failure',\n executionId: record.claim.executionId,\n attempt: record.claim.attempt,\n bundleDigest: record.claim.bundleDigest,\n executionPlanDigest: record.claim.executionPlanDigest,\n materializationReceiptDigest:\n record.claim.preparationEvidence.materializationReceipt.sha256,\n failureClass,\n processStopped: true,\n modelSettlementDigest: modelSettlement.digest,\n memoryClosed: record.claim.cleanup.memory !== undefined,\n }),\n }),\n cleanupDeadlineAtMs,\n 'expired candidate failure-evidence persistence',\n )\n const memory = record.claim.cleanup.memory\n return await options.claimStore.recoverExpired(options.attempt, {\n failureClass,\n usage: model.usage,\n modelSettlement: modelSettlement.artifact,\n failureEvidence,\n process: {\n stopped: true,\n executionPlanDigest: record.claim.executionPlanDigest,\n },\n model: {\n closed: true,\n preparationId: record.claim.cleanup.preparationId,\n grantDigest: record.claim.cleanup.modelGrantDigest,\n },\n ...(memory\n ? {\n memory: {\n closed: true,\n preparationId: record.claim.cleanup.preparationId,\n accessDigest: memory.accessDigest,\n effectiveNamespace: memory.effectiveNamespace,\n },\n }\n : {}),\n })\n}\n\nasync function readRecoveryPreparation(\n claim: AgentCandidateExecutionClaim,\n artifacts: AgentCandidateOutputArtifactPort,\n): Promise<{\n plan: AgentCandidateExecutionPlanMaterial\n receipt: AgentCandidateMaterializationReceipt\n}> {\n const [planBytes, receiptBytes] = await Promise.all([\n readVerifiedArtifact(claim.preparationEvidence.executionPlan, artifacts),\n readVerifiedArtifact(claim.preparationEvidence.materializationReceipt, artifacts),\n ])\n const plan = agentCandidateExecutionPlanMaterialSchema.parse(\n parseCanonicalBytes(planBytes, 'plan'),\n )\n if (claim.preparationEvidence.executionPlan.sha256 !== claim.executionPlanDigest) {\n throw new Error('recovery execution plan artifact does not match the claimed digest')\n }\n const receiptMaterial = parseCanonicalBytes(receiptBytes, 'materialization receipt')\n const receipt = agentCandidateMaterializationReceiptSchema.parse({\n ...receiptMaterial,\n digest: claim.preparationEvidence.materializationReceipt.sha256,\n })\n if (\n receipt.bundleDigest !== claim.bundleDigest ||\n receipt.executionPlan.digest !== claim.executionPlanDigest ||\n plan.runCell.bundleDigest !== claim.bundleDigest ||\n plan.executionId !== claim.executionId\n ) {\n throw new Error('recovery preparation evidence does not match the durable claim')\n }\n return { plan, receipt }\n}\n\nfunction parseCanonicalBytes(bytes: Uint8Array, label: string): Record<string, unknown> {\n let parsed: unknown\n try {\n parsed = JSON.parse(Buffer.from(bytes).toString('utf8'))\n } catch (error) {\n throw new Error(`candidate recovery ${label} is not JSON`, { cause: error })\n }\n if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {\n throw new Error(`candidate recovery ${label} must be an object`)\n }\n if (!Buffer.from(canonicalCandidateBytes(parsed)).equals(Buffer.from(bytes))) {\n throw new Error(`candidate recovery ${label} bytes are not canonical`)\n }\n return parsed as Record<string, unknown>\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"candidate-execution-CfpJrd3o.js","names":[],"sources":["../src/candidate-execution/builder.ts","../src/candidate-execution/claim-file-store.ts","../src/candidate-execution/dispose.ts","../src/candidate-execution/recover.ts"],"sourcesContent":["import type { CodeSurface } from '@tangle-network/agent-eval/campaign'\nimport { verifyCodeSurface } from '@tangle-network/agent-eval/campaign'\nimport type {\n AgentCandidateCodeDisabled,\n AgentCandidateCodeNoOp,\n AgentCandidateExecution,\n AgentCandidateGitHubRepository,\n AgentCandidateKnowledge,\n AgentCandidateMemoryPolicy,\n AgentCandidateProfile,\n AgentProfile,\n AgentProfileDiff,\n} from '@tangle-network/agent-interface'\nimport { type AgentCandidateBundleInput, sealAgentCandidateBundle } from './bundle'\nimport { embeddedCandidateArtifact } from './digest'\nimport {\n applyExactAgentProfileDiff,\n freezeGenericAgentCandidateProfile,\n parseExactAgentProfile,\n parseExactAgentProfileDiff,\n parseExactCandidateProfile,\n} from './profile'\n\n/** A complete profile that can be frozen without losing behavior. */\nexport type AgentCandidateProfileSource =\n | {\n kind: 'profile'\n profile: AgentProfile\n }\n | {\n kind: 'profile-diffs'\n base: AgentProfile\n /** Applied in order before the resulting profile is frozen into the bundle. */\n diffs: readonly AgentProfileDiff[]\n }\n | {\n kind: 'candidate-profile'\n /** Already converted to the closed, secret-free candidate profile contract. */\n profile: AgentCandidateProfile\n }\n\n/** The only accepted path from an agent-eval code candidate to executable bytes. */\nexport interface AgentCandidateCodeSurfaceSource {\n kind: 'code-surface'\n surface: CodeSurface\n repository: AgentCandidateGitHubRepository\n /** Optional parent directory used to resolve a relative `surface.worktreeRef`. */\n worktreeDir?: string\n}\n\n/** Explicit control/no-op code or one finalized CodeSurface whose bytes must still verify. */\nexport type AgentCandidateCodeSource =\n | AgentCandidateCodeDisabled\n | AgentCandidateCodeNoOp\n | AgentCandidateCodeSurfaceSource\n\n/** Complete measured surfaces and execution policy compiled into one candidate bundle. */\nexport interface BuildAgentCandidateBundleInput {\n profile: AgentCandidateProfileSource\n code: AgentCandidateCodeSource\n execution: AgentCandidateExecution\n knowledge?: AgentCandidateKnowledge\n memory: AgentCandidateMemoryPolicy\n}\n\n/**\n * Compile one measured profile/code candidate into the immutable execution\n * contract. Code bytes are re-read and verified by agent-eval before they are\n * embedded. The returned bundle is schema-validated, canonically digested, and\n * deeply immutable; call `verifyAgentCandidateBundle` at the execution boundary\n * to re-read external memory, repository, and workspace artifacts.\n */\nexport function buildAgentCandidateBundle(\n input: BuildAgentCandidateBundleInput,\n): ReturnType<typeof sealAgentCandidateBundle> {\n const bundle: AgentCandidateBundleInput = {\n kind: 'agent-candidate-bundle',\n digestAlgorithm: 'rfc8785-sha256',\n profile: compileCandidateProfile(input.profile),\n code: compileCandidateCode(input.code),\n execution: input.execution,\n ...(input.knowledge !== undefined ? { knowledge: input.knowledge } : {}),\n memory: input.memory,\n }\n return sealAgentCandidateBundle(bundle)\n}\n\nfunction compileCandidateProfile(source: AgentCandidateProfileSource): AgentCandidateProfile {\n if (source.kind === 'candidate-profile') {\n return parseExactCandidateProfile(source.profile)\n }\n\n if (source.kind === 'profile') {\n return freezeGenericAgentCandidateProfile(source.profile)\n }\n\n if (source.kind !== 'profile-diffs') {\n throw new Error(\n `unsupported candidate profile source: ${String((source as { kind?: unknown }).kind)}`,\n )\n }\n if (source.diffs.length === 0) {\n throw new Error('profile-diffs source requires at least one AgentProfileDiff')\n }\n let profile = parseExactAgentProfile(source.base, 'base profile')\n for (const [index, inputDiff] of source.diffs.entries()) {\n const diff = parseExactAgentProfileDiff(inputDiff, `profile diff ${index}`)\n profile = applyExactAgentProfileDiff(profile, diff, `profile diff ${index}`)\n }\n return freezeGenericAgentCandidateProfile(profile)\n}\n\nfunction compileCandidateCode(source: AgentCandidateCodeSource): AgentCandidateBundleInput['code'] {\n if (source.kind === 'disabled' || source.kind === 'no-op') return source\n if (source.kind !== 'code-surface') {\n throw new Error(\n `unsupported candidate code source: ${String((source as { kind?: unknown }).kind)}`,\n )\n }\n\n const verified = verifyCodeSurface(source.surface, source.worktreeDir)\n const patch = embeddedCandidateArtifact(verified.patchBytes)\n if (\n patch.sha256 !== source.surface.patch.sha256 ||\n patch.byteLength !== source.surface.patch.byteLength\n ) {\n throw new Error('verified CodeSurface patch bytes do not match its content identity')\n }\n return {\n kind: 'git-patch',\n repository: source.repository,\n baseCommit: source.surface.baseCommit,\n baseTree: source.surface.baseTree,\n candidateTree: source.surface.candidateTree,\n patch: { format: 'git-diff-binary', artifact: patch },\n }\n}\n","import { randomUUID } from 'node:crypto'\nimport { linkSync } from 'node:fs'\nimport { mkdir, open, unlink } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport type { Sha256Digest } from '@tangle-network/agent-interface'\n\nimport {\n type AgentCandidateExecutionAttemptRecord,\n type AgentCandidateExecutionAttemptRef,\n type AgentCandidateExecutionClaim,\n type AgentCandidateExecutionClaimResult,\n type AgentCandidateExecutionClaimStore,\n type AgentCandidateExecutionFinishResult,\n type AgentCandidateExecutionLease,\n type AgentCandidateExecutionPhase,\n type AgentCandidateExecutionPhaseResult,\n type AgentCandidateExecutionRecoveryEvidence,\n type AgentCandidateExecutionStageResult,\n type AgentCandidateExecutionTerminalRecord,\n type AgentCandidateExecutionTerminalResult,\n type AgentCandidateRetryRejection,\n candidateClaimFileInternals,\n} from './claim'\nimport {\n assertRecoveryMatchesStaged,\n assertTerminalAllowedInPhase,\n assertTerminalMatchesClaim,\n assertTerminalMatchesStaged,\n recoveredTerminalRecord,\n rejectedFinish,\n rejectedStage,\n requireStagedTerminal,\n sealTerminalDigest,\n terminalRecord,\n} from './claim-terminal'\nimport { canonicalCandidateBytes } from './digest'\n\nconst {\n assertExpiredLease,\n assertLease,\n assertSameSlot,\n assertUnexpiredLease,\n attemptRecord,\n claimSlot,\n leaseDigest,\n newLease,\n readClaim,\n readClaimIfPresent,\n readTerminal,\n readTerminalIfPresent,\n readTransitionIfPresent,\n rejectedExistingClaim,\n rejectedRetry,\n retryRejection,\n sealAttemptRef,\n sealClaim,\n sealLease,\n} = candidateClaimFileInternals\n\nexport interface FileAgentCandidateExecutionClaimStoreOptions {\n /** Evaluator-owned directory shared by every process allowed to execute candidates. */\n directory: string\n /** Testable evaluator clock; defaults to `Date.now`. */\n now?: () => number\n}\n\n/** Cross-process lifecycle implemented as fsynced, create-if-absent records. */\nexport class FileAgentCandidateExecutionClaimStore implements AgentCandidateExecutionClaimStore {\n private readonly directory: string\n private readonly now: () => number\n\n constructor(options: FileAgentCandidateExecutionClaimStoreOptions) {\n if (options.directory.length === 0) {\n throw new Error('candidate execution claim directory must not be empty')\n }\n this.directory = options.directory\n this.now = options.now ?? Date.now\n }\n\n async tryClaim(\n requested: AgentCandidateExecutionClaim,\n ): Promise<AgentCandidateExecutionClaimResult> {\n const claim = sealClaim(requested)\n await mkdir(this.directory, { recursive: true })\n const claimPath = this.claimPath(claim)\n const existing = await readClaimIfPresent(claimPath)\n if (existing) {\n assertSameSlot(existing.claim, claim, claimPath)\n return rejectedExistingClaim(existing.claim, claim)\n }\n assertUnexpiredLease(claim.leaseExpiresAtMs, this.now())\n const retryFailure = await this.retryFailure(claim)\n if (retryFailure) return rejectedRetry(claim, retryFailure)\n\n const lease = newLease(claim)\n const acquired = await writeRecordIfAbsent(this.directory, claimPath, {\n ...claim,\n phase: 'claimed',\n leaseDigest: leaseDigest(lease),\n })\n if (acquired) return Object.freeze({ acquired: true, claim, lease })\n\n const winner = await readClaim(claimPath)\n assertSameSlot(winner.claim, claim, claimPath)\n return rejectedExistingClaim(winner.claim, claim)\n }\n\n async getAttempt(\n requestedAttempt: AgentCandidateExecutionAttemptRef,\n ): Promise<AgentCandidateExecutionAttemptRecord | undefined> {\n return await this.storedAttempt(sealAttemptRef(requestedAttempt))\n }\n\n async markCandidateMayRun(\n requestedLease: AgentCandidateExecutionLease,\n ): Promise<AgentCandidateExecutionPhaseResult> {\n const lease = sealLease(requestedLease)\n const claimPath = this.claimPath(lease)\n const stored = await readClaim(claimPath)\n assertSameSlot(stored.claim, lease, claimPath)\n assertLease(stored.leaseDigest, stored.claim.leaseExpiresAtMs, lease)\n const state = await this.transitionState(stored.claim)\n if (state.phase === 'candidate-may-run') {\n return Object.freeze({ marked: false, phase: 'candidate-may-run' })\n }\n if (state.staged) {\n throw new Error('candidate execution terminal was staged before candidate-may-run phase')\n }\n assertUnexpiredLease(stored.claim.leaseExpiresAtMs, this.now())\n const marked = await writeRecordIfAbsent(\n this.directory,\n this.transitionPath(stored.claim, 1),\n {\n kind: 'candidate-execution-phase',\n executionId: stored.claim.executionId,\n attempt: stored.claim.attempt,\n executionPlanDigest: stored.claim.executionPlanDigest,\n phase: 'candidate-may-run',\n },\n this.ownerPublication(stored.claim),\n )\n if (marked) return Object.freeze({ marked: true, phase: 'candidate-may-run' })\n const winner = await this.transitionState(stored.claim)\n if (winner.phase === 'candidate-may-run') {\n return Object.freeze({ marked: false, phase: 'candidate-may-run' })\n }\n throw new Error('candidate execution terminal was staged before candidate-may-run phase')\n }\n\n async stageTerminal(\n requestedLease: AgentCandidateExecutionLease,\n result: AgentCandidateExecutionTerminalResult,\n ): Promise<AgentCandidateExecutionStageResult> {\n const lease = sealLease(requestedLease)\n const claimPath = this.claimPath(lease)\n const stored = await readClaim(claimPath)\n assertSameSlot(stored.claim, lease, claimPath)\n assertLease(stored.leaseDigest, stored.claim.leaseExpiresAtMs, lease)\n const terminal = terminalRecord(stored.claim, result)\n const state = await this.transitionState(stored.claim)\n if (state.staged) return rejectedStage(state.staged, terminal)\n assertTerminalAllowedInPhase(state.phase, terminal)\n assertUnexpiredLease(stored.claim.leaseExpiresAtMs, this.now())\n const transition = state.phase === 'claimed' ? 1 : 2\n const staged = await writeRecordIfAbsent(\n this.directory,\n this.transitionPath(stored.claim, transition),\n {\n kind: 'candidate-execution-pending-terminal',\n terminal,\n },\n this.ownerPublication(stored.claim),\n )\n if (staged) return Object.freeze({ staged: true, terminal })\n const winner = await this.transitionState(stored.claim)\n if (!winner.staged) {\n throw new Error('candidate execution phase transition won while staging terminal')\n }\n return rejectedStage(winner.staged, terminal)\n }\n\n async finish(\n requestedLease: AgentCandidateExecutionLease,\n requestedTerminalDigest: Sha256Digest,\n ): Promise<AgentCandidateExecutionFinishResult> {\n const lease = sealLease(requestedLease)\n const terminalDigest = sealTerminalDigest(requestedTerminalDigest)\n const claimPath = this.claimPath(lease)\n const stored = await readClaim(claimPath)\n assertSameSlot(stored.claim, lease, claimPath)\n assertLease(stored.leaseDigest, stored.claim.leaseExpiresAtMs, lease)\n const state = await this.transitionState(stored.claim)\n const staged = requireStagedTerminal(state.staged, terminalDigest)\n const terminalPath = this.terminalPath(lease)\n const existing = await readTerminalIfPresent(terminalPath)\n if (existing) {\n assertTerminalMatchesClaim(existing, stored.claim, terminalPath)\n assertTerminalMatchesStaged(existing, staged, terminalPath)\n return rejectedFinish(existing, terminalDigest)\n }\n assertUnexpiredLease(stored.claim.leaseExpiresAtMs, this.now())\n const finished = await writeRecordIfAbsent(\n this.directory,\n terminalPath,\n {\n terminal: staged,\n },\n this.ownerPublication(stored.claim),\n )\n if (finished) return Object.freeze({ finished: true, terminal: staged })\n const winner = await readTerminal(terminalPath)\n assertSameSlot(winner, lease, terminalPath)\n assertTerminalMatchesClaim(winner, stored.claim, terminalPath)\n assertTerminalMatchesStaged(winner, staged, terminalPath)\n return rejectedFinish(winner, terminalDigest)\n }\n\n async recoverExpired(\n requestedAttempt: AgentCandidateExecutionAttemptRef,\n evidence: AgentCandidateExecutionRecoveryEvidence,\n ): Promise<AgentCandidateExecutionFinishResult> {\n const attempt = sealAttemptRef(requestedAttempt)\n const record = await this.storedAttempt(attempt)\n if (!record) throw new Error('candidate execution recovery does not name an acquired attempt')\n const recovered = recoveredTerminalRecord(record.claim, record.phase, evidence)\n if (record.staged) assertRecoveryMatchesStaged(record.staged, recovered)\n const requestedDigest = record.staged?.terminalDigest ?? recovered.terminalDigest\n if (record.terminal) return rejectedFinish(record.terminal, requestedDigest)\n assertExpiredLease(record.claim.leaseExpiresAtMs, this.now())\n\n let staged = record.staged\n if (!staged) {\n const transition = record.phase === 'claimed' ? 1 : 2\n const didStage = await writeRecordIfAbsent(\n this.directory,\n this.transitionPath(record.claim, transition),\n {\n kind: 'candidate-execution-pending-terminal',\n terminal: recovered,\n },\n )\n if (didStage) {\n staged = recovered\n } else {\n const winner = await this.transitionState(record.claim)\n if (!winner.staged) {\n throw new Error(\n 'candidate execution recovery lost terminal staging to a phase transition',\n )\n }\n assertRecoveryMatchesStaged(winner.staged, recovered)\n staged = winner.staged\n }\n }\n\n const terminalPath = this.terminalPath(attempt)\n const didFinish = await writeRecordIfAbsent(this.directory, terminalPath, {\n terminal: staged,\n })\n if (didFinish) return Object.freeze({ finished: true, terminal: staged })\n const winner = await readTerminal(terminalPath)\n assertSameSlot(winner, attempt, terminalPath)\n assertTerminalMatchesClaim(winner, record.claim, terminalPath)\n assertTerminalMatchesStaged(winner, staged, terminalPath)\n return rejectedFinish(winner, staged.terminalDigest)\n }\n\n private async storedAttempt(\n claim: Pick<AgentCandidateExecutionClaim, 'executionId' | 'attempt'>,\n ): Promise<AgentCandidateExecutionAttemptRecord | undefined> {\n const claimPath = this.claimPath(claim)\n const stored = await readClaimIfPresent(claimPath)\n if (!stored) return undefined\n assertSameSlot(stored.claim, claim, claimPath)\n const state = await this.transitionState(stored.claim)\n const terminalPath = this.terminalPath(claim)\n const terminal = await readTerminalIfPresent(terminalPath)\n if (terminal) {\n assertTerminalMatchesClaim(terminal, stored.claim, terminalPath)\n if (!state.staged) {\n throw new Error(\n `candidate execution terminal record at ${terminalPath} has no staged outbox`,\n )\n }\n assertTerminalMatchesStaged(terminal, state.staged, terminalPath)\n }\n return attemptRecord(stored.claim, state.phase, state.staged, terminal)\n }\n\n private async transitionState(claim: AgentCandidateExecutionClaim): Promise<{\n phase: AgentCandidateExecutionPhase\n staged?: AgentCandidateExecutionTerminalRecord\n }> {\n const firstPath = this.transitionPath(claim, 1)\n const first = await readTransitionIfPresent(firstPath, claim)\n if (!first) return { phase: 'claimed' }\n if (first.kind === 'pending') return { phase: 'claimed', staged: first.terminal }\n const secondPath = this.transitionPath(claim, 2)\n const second = await readTransitionIfPresent(secondPath, claim)\n if (!second) return { phase: 'candidate-may-run' }\n if (second.kind !== 'pending') {\n throw new Error(`candidate execution transition at ${secondPath} repeats the phase marker`)\n }\n return { phase: 'candidate-may-run', staged: second.terminal }\n }\n\n private async retryFailure(\n claim: AgentCandidateExecutionClaim,\n ): Promise<AgentCandidateRetryRejection | undefined> {\n if (claim.attempt === 1) return undefined\n return retryRejection(\n claim,\n await this.storedAttempt({\n executionId: claim.executionId,\n attempt: claim.attempt - 1,\n }),\n )\n }\n\n private ownerPublication(claim: AgentCandidateExecutionClaim): {\n authorizePublish: () => true\n } {\n return {\n authorizePublish: () => {\n assertUnexpiredLease(claim.leaseExpiresAtMs, this.now())\n return true\n },\n }\n }\n\n private claimPath(claim: Pick<AgentCandidateExecutionClaim, 'executionId' | 'attempt'>): string {\n return join(this.directory, `${claimSlot(claim)}.claim.json`)\n }\n\n private terminalPath(\n claim: Pick<AgentCandidateExecutionClaim, 'executionId' | 'attempt'>,\n ): string {\n return join(this.directory, `${claimSlot(claim)}.terminal.json`)\n }\n\n private transitionPath(\n claim: Pick<AgentCandidateExecutionClaim, 'executionId' | 'attempt'>,\n ordinal: 1 | 2,\n ): string {\n return join(this.directory, `${claimSlot(claim)}.transition-${ordinal}.json`)\n }\n}\n\nasync function writeRecordIfAbsent(\n directory: string,\n destination: string,\n record: object,\n options: {\n /** Synchronous authorization checked after temp fsync, immediately before atomic publication. */\n authorizePublish?: () => true\n } = {},\n): Promise<boolean> {\n const temporaryPath = join(directory, `.candidate-execution-${process.pid}-${randomUUID()}.tmp`)\n const handle = await open(temporaryPath, 'wx', 0o600)\n try {\n await handle.writeFile(\n Buffer.concat([Buffer.from(canonicalCandidateBytes(record)), Buffer.from('\\n')]),\n )\n await handle.sync()\n } finally {\n await handle.close()\n }\n\n let written = false\n try {\n if (options.authorizePublish && options.authorizePublish() !== true) {\n throw new Error('candidate execution record publication was not authorized')\n }\n // Authorization and the atomic filesystem call are one synchronous critical\n // section so the event loop cannot advance an injected lease clock between them.\n linkSync(temporaryPath, destination)\n written = true\n await syncDirectory(directory)\n } catch (error) {\n if (!isNodeError(error, 'EEXIST')) throw error\n } finally {\n await unlink(temporaryPath).catch((error: unknown) => {\n if (!isNodeError(error, 'ENOENT')) throw error\n })\n }\n return written\n}\n\nasync function syncDirectory(directory: string): Promise<void> {\n const handle = await open(directory, 'r')\n try {\n await handle.sync()\n } finally {\n await handle.close()\n }\n}\n\nfunction isNodeError(error: unknown, code: string): boolean {\n return (\n error !== null &&\n typeof error === 'object' &&\n 'code' in error &&\n (error as { code?: unknown }).code === code\n )\n}\n","import { candidateCleanupDeadline, withinCandidateCleanupDeadline } from './cleanup'\nimport { sealAgentCandidateModelSettlement } from './model-settlement'\nimport {\n assertPreparedCandidateIntegrity,\n beginPreparedCandidateDisposal,\n consumePreparedCandidateExecution,\n} from './prepared-state'\nimport type { PreparedAgentCandidateExecution } from './types'\n\nexport interface DisposePreparedAgentCandidateOptions {\n cleanupTimeoutMs?: number\n}\n\n/** Revoke reservations held by a prepared candidate that will not be executed. */\nexport async function disposePreparedAgentCandidateExecution(\n prepared: PreparedAgentCandidateExecution,\n options: DisposePreparedAgentCandidateOptions = {},\n): Promise<{ disposed: true }> {\n const initialState = assertPreparedCandidateIntegrity(prepared)\n const cleanupTimeoutMs = options.cleanupTimeoutMs ?? initialState.cleanupTimeoutMs\n if (cleanupTimeoutMs > initialState.cleanupTimeoutMs) {\n throw new Error('disposal cleanup timeout exceeds the frozen preparation bound')\n }\n const cleanupDeadlineAtMs = candidateCleanupDeadline(cleanupTimeoutMs)\n const state = beginPreparedCandidateDisposal(prepared)\n const cleanup: Array<Promise<unknown>> = []\n\n if (state.memory.mode === 'isolated') {\n const reservation = state.memoryReservation\n if (!reservation) throw new Error('isolated memory reservation is missing')\n cleanup.push(\n withinCandidateCleanupDeadline(\n async () => {\n const closed = await state.ports.memory.close({\n executionId: state.executionId,\n preparationId: reservation.preparationId,\n accessDigest: reservation.accessDigest,\n effectiveNamespace: reservation.effectiveNamespace,\n reason: 'abandoned',\n })\n if (closed.closed !== true || Object.keys(closed).some((key) => key !== 'closed')) {\n throw new Error('abandoned isolated memory access did not acknowledge closure')\n }\n },\n cleanupDeadlineAtMs,\n 'isolated memory disposal',\n ),\n )\n }\n\n cleanup.push(\n withinCandidateCleanupDeadline(\n async () => {\n const settlement = sealAgentCandidateModelSettlement(\n await state.ports.models.settleGrant({\n executionId: state.executionId,\n preparationId: state.preparationId,\n grantDigest: state.modelReservation.digest,\n resolved: state.resolvedModel,\n reason: 'abandoned',\n }),\n {\n preparationId: state.preparationId,\n grantDigest: state.modelReservation.digest,\n model: state.resolvedModel.model,\n },\n )\n if (settlement.usage.modelCalls !== 0) {\n throw new Error('unexecuted model reservation unexpectedly contains calls')\n }\n },\n cleanupDeadlineAtMs,\n 'model reservation disposal',\n ),\n )\n\n const results = await Promise.allSettled(cleanup)\n const failures = results\n .filter((result): result is PromiseRejectedResult => result.status === 'rejected')\n .map((result) => result.reason)\n if (failures.length > 0) {\n consumePreparedCandidateExecution(prepared, 'disposal-failed')\n throw new AggregateError(failures, 'candidate preparation disposal failed')\n }\n\n consumePreparedCandidateExecution(prepared, 'disposed')\n return Object.freeze({ disposed: true as const })\n}\n","import type { TraceStore } from '@tangle-network/agent-eval'\nimport type {\n AgentCandidateExecutionPlanMaterial,\n AgentCandidateMaterializationReceipt,\n} from '@tangle-network/agent-interface'\nimport {\n agentCandidateExecutionPlanMaterialSchema,\n agentCandidateMaterializationReceiptSchema,\n} from '@tangle-network/agent-interface'\n\nimport { readVerifiedArtifact } from './artifacts'\nimport type {\n AgentCandidateExecutionAttemptRef,\n AgentCandidateExecutionClaim,\n AgentCandidateExecutionClaimStore,\n AgentCandidateExecutionFinishResult,\n} from './claim'\nimport {\n candidateCleanupDeadline,\n candidateCleanupTimeout,\n withinCandidateCleanupDeadline,\n} from './cleanup'\nimport { canonicalCandidateBytes } from './digest'\nimport { sealAgentCandidateExecutorStopAcknowledgement } from './executor-capture'\nimport { sealAgentCandidateModelSettlement } from './model-settlement'\nimport { persistCandidateModelSettlementEvidence } from './outcome-evidence'\nimport { persistCandidateOutputArtifact } from './output-artifacts'\nimport { RecoveryAgentCandidateTraceStore } from './protected-trace-store'\nimport type {\n AgentCandidateExecutionPorts,\n AgentCandidateExecutorPort,\n AgentCandidateOutputArtifactPort,\n} from './types'\n\nexport interface RecoverExpiredAgentCandidateOptions {\n attempt: AgentCandidateExecutionAttemptRef\n claimStore: AgentCandidateExecutionClaimStore\n executor: AgentCandidateExecutorPort\n traceStore: TraceStore\n ports: Pick<AgentCandidateExecutionPorts, 'models' | 'memory'>\n outputArtifacts: AgentCandidateOutputArtifactPort\n cleanupTimeoutMs?: number\n /** Evaluator clock; must be the same clock used by the claim store. */\n now?: () => number\n}\n\n/** Close an expired crashed attempt from persisted non-secret handles, then record failure. */\nexport async function recoverExpiredAgentCandidateExecution(\n options: RecoverExpiredAgentCandidateOptions,\n): Promise<AgentCandidateExecutionFinishResult> {\n const record = await options.claimStore.getAttempt(options.attempt)\n if (!record) throw new Error('candidate execution recovery attempt is missing')\n if (record.terminal) {\n return Object.freeze({ finished: false, terminal: record.terminal, exactReplay: true })\n }\n const cleanupTimeoutMs = candidateCleanupTimeout(\n options.cleanupTimeoutMs ?? record.claim.cleanup.cleanupTimeoutMs,\n )\n if (cleanupTimeoutMs > record.claim.cleanup.cleanupTimeoutMs) {\n throw new Error('recovery cleanup timeout exceeds the frozen preparation bound')\n }\n\n const now = options.now ?? Date.now\n if (now() < record.claim.leaseExpiresAtMs) {\n throw new Error('candidate execution lease has not expired')\n }\n\n const cleanupDeadlineAtMs = candidateCleanupDeadline(cleanupTimeoutMs)\n const recoveryTraceStore = new RecoveryAgentCandidateTraceStore(options.traceStore)\n const preparation = withinCandidateCleanupDeadline(\n () => readRecoveryPreparation(record.claim, options.outputArtifacts),\n cleanupDeadlineAtMs,\n 'expired candidate preparation evidence read',\n )\n const processClosure = withinCandidateCleanupDeadline(\n async (cleanupSignal) => {\n const stopped = await options.executor.stop(\n {\n executionId: record.claim.executionId,\n executionPlanDigest: record.claim.executionPlanDigest,\n },\n {\n traceStore: recoveryTraceStore,\n reason: 'failed',\n signal: cleanupSignal,\n deadlineAtMs: cleanupDeadlineAtMs,\n },\n )\n sealAgentCandidateExecutorStopAcknowledgement(stopped)\n if (options.executor.dispose) {\n const disposed = await options.executor.dispose(\n {\n executionId: record.claim.executionId,\n executionPlanDigest: record.claim.executionPlanDigest,\n },\n { signal: cleanupSignal },\n )\n if (disposed.disposed !== true || Object.keys(disposed).some((key) => key !== 'disposed')) {\n throw new Error('expired candidate executor did not acknowledge resource disposal')\n }\n }\n return { stopped: true as const }\n },\n cleanupDeadlineAtMs,\n 'expired candidate process termination',\n )\n\n const modelClosure = withinCandidateCleanupDeadline(\n async () =>\n sealAgentCandidateModelSettlement(\n await options.ports.models.settleGrant({\n executionId: record.claim.executionId,\n preparationId: record.claim.cleanup.preparationId,\n grantDigest: record.claim.cleanup.modelGrantDigest,\n resolved: record.claim.cleanup.resolvedModel,\n reason: 'failed',\n }),\n {\n preparationId: record.claim.cleanup.preparationId,\n grantDigest: record.claim.cleanup.modelGrantDigest,\n model: record.claim.cleanup.resolvedModel.model,\n },\n ),\n cleanupDeadlineAtMs,\n 'expired candidate model settlement',\n )\n\n const memoryClosure = record.claim.cleanup.memory\n ? withinCandidateCleanupDeadline(\n async () => {\n const memory = record.claim.cleanup.memory\n if (!memory) throw new Error('expired candidate memory handle is missing')\n const closed = await options.ports.memory.close({\n executionId: record.claim.executionId,\n preparationId: record.claim.cleanup.preparationId,\n accessDigest: memory.accessDigest,\n effectiveNamespace: memory.effectiveNamespace,\n reason: 'failed',\n })\n if (closed.closed !== true || Object.keys(closed).some((key) => key !== 'closed')) {\n throw new Error('expired candidate memory did not acknowledge closure')\n }\n return { closed: true as const }\n },\n cleanupDeadlineAtMs,\n 'expired candidate memory closure',\n )\n : undefined\n\n const closureOutcomes = Promise.allSettled([\n modelClosure,\n memoryClosure ?? Promise.resolve(undefined),\n ] as const)\n const [preparationOutcome, processOutcome] = await Promise.allSettled([\n preparation,\n processClosure,\n ] as const)\n const failures: unknown[] = [preparationOutcome, processOutcome]\n .filter((outcome): outcome is PromiseRejectedResult => outcome.status === 'rejected')\n .map((outcome) => outcome.reason)\n const [modelOutcome, memoryOutcome] = await closureOutcomes\n for (const outcome of [modelOutcome, memoryOutcome]) {\n if (outcome.status === 'rejected') failures.push(outcome.reason)\n }\n if (failures.length > 0) {\n throw new AggregateError(failures, 'expired candidate cleanup could not be proven')\n }\n\n if (modelOutcome.status !== 'fulfilled') {\n throw new Error('expired candidate model settlement was not recovered')\n }\n const model = modelOutcome.value\n const modelSettlement = await withinCandidateCleanupDeadline(\n () =>\n persistCandidateModelSettlementEvidence(\n {\n executionId: record.claim.executionId,\n executionPlanDigest: record.claim.executionPlanDigest,\n resolvedModel: record.claim.cleanup.resolvedModel,\n },\n model,\n options.outputArtifacts,\n ),\n cleanupDeadlineAtMs,\n 'expired candidate model-settlement persistence',\n )\n const failureClass =\n record.phase === 'claimed' && model.usage.modelCalls === 0\n ? 'pre-model-infrastructure'\n : 'unknown'\n const failureEvidence = await withinCandidateCleanupDeadline(\n () =>\n persistCandidateOutputArtifact(options.outputArtifacts, {\n executionId: record.claim.executionId,\n purpose: 'failure-evidence',\n bytes: canonicalCandidateBytes({\n kind: 'agent-candidate-recovery-failure',\n executionId: record.claim.executionId,\n attempt: record.claim.attempt,\n bundleDigest: record.claim.bundleDigest,\n executionPlanDigest: record.claim.executionPlanDigest,\n materializationReceiptDigest:\n record.claim.preparationEvidence.materializationReceipt.sha256,\n failureClass,\n processStopped: true,\n modelSettlementDigest: modelSettlement.digest,\n memoryClosed: record.claim.cleanup.memory !== undefined,\n }),\n }),\n cleanupDeadlineAtMs,\n 'expired candidate failure-evidence persistence',\n )\n const memory = record.claim.cleanup.memory\n return await options.claimStore.recoverExpired(options.attempt, {\n failureClass,\n usage: model.usage,\n modelSettlement: modelSettlement.artifact,\n failureEvidence,\n process: {\n stopped: true,\n executionPlanDigest: record.claim.executionPlanDigest,\n },\n model: {\n closed: true,\n preparationId: record.claim.cleanup.preparationId,\n grantDigest: record.claim.cleanup.modelGrantDigest,\n },\n ...(memory\n ? {\n memory: {\n closed: true,\n preparationId: record.claim.cleanup.preparationId,\n accessDigest: memory.accessDigest,\n effectiveNamespace: memory.effectiveNamespace,\n },\n }\n : {}),\n })\n}\n\nasync function readRecoveryPreparation(\n claim: AgentCandidateExecutionClaim,\n artifacts: AgentCandidateOutputArtifactPort,\n): Promise<{\n plan: AgentCandidateExecutionPlanMaterial\n receipt: AgentCandidateMaterializationReceipt\n}> {\n const [planBytes, receiptBytes] = await Promise.all([\n readVerifiedArtifact(claim.preparationEvidence.executionPlan, artifacts),\n readVerifiedArtifact(claim.preparationEvidence.materializationReceipt, artifacts),\n ])\n const plan = agentCandidateExecutionPlanMaterialSchema.parse(\n parseCanonicalBytes(planBytes, 'plan'),\n )\n if (claim.preparationEvidence.executionPlan.sha256 !== claim.executionPlanDigest) {\n throw new Error('recovery execution plan artifact does not match the claimed digest')\n }\n const receiptMaterial = parseCanonicalBytes(receiptBytes, 'materialization receipt')\n const receipt = agentCandidateMaterializationReceiptSchema.parse({\n ...receiptMaterial,\n digest: claim.preparationEvidence.materializationReceipt.sha256,\n })\n if (\n receipt.bundleDigest !== claim.bundleDigest ||\n receipt.executionPlan.digest !== claim.executionPlanDigest ||\n plan.runCell.bundleDigest !== claim.bundleDigest ||\n plan.executionId !== claim.executionId\n ) {\n throw new Error('recovery preparation evidence does not match the durable claim')\n }\n return { plan, receipt }\n}\n\nfunction parseCanonicalBytes(bytes: Uint8Array, label: string): Record<string, unknown> {\n let parsed: unknown\n try {\n parsed = JSON.parse(Buffer.from(bytes).toString('utf8'))\n } catch (error) {\n throw new Error(`candidate recovery ${label} is not JSON`, { cause: error })\n }\n if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {\n throw new Error(`candidate recovery ${label} must be an object`)\n }\n if (!Buffer.from(canonicalCandidateBytes(parsed)).equals(Buffer.from(bytes))) {\n throw new Error(`candidate recovery ${label} bytes are not canonical`)\n }\n return parsed as Record<string, unknown>\n}\n"],"mappings":"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"}