@tangle-network/agent-eval 0.72.0 → 0.72.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/dist/adapters/http.d.ts +1 -1
  3. package/dist/adapters/langchain.d.ts +1 -1
  4. package/dist/adapters/otel.d.ts +3 -2
  5. package/dist/agent-profile-DYRboYWu.d.ts +364 -0
  6. package/dist/analyst/index.d.ts +221 -0
  7. package/dist/analyst/index.js +371 -0
  8. package/dist/analyst/index.js.map +1 -0
  9. package/dist/analyst-t7zZS3TV.d.ts +88 -0
  10. package/dist/campaign/index.d.ts +518 -9
  11. package/dist/campaign/index.js +672 -22
  12. package/dist/campaign/index.js.map +1 -1
  13. package/dist/chunk-7W4SM7FD.js +1075 -0
  14. package/dist/chunk-7W4SM7FD.js.map +1 -0
  15. package/dist/{chunk-AIWHLG7J.js → chunk-GJJNJVIR.js} +11 -11
  16. package/dist/chunk-JHA3ZGSO.js +1496 -0
  17. package/dist/chunk-JHA3ZGSO.js.map +1 -0
  18. package/dist/{chunk-4QJN7RDX.js → chunk-JYE3WOTE.js} +55 -7
  19. package/dist/{chunk-4QJN7RDX.js.map → chunk-JYE3WOTE.js.map} +1 -1
  20. package/dist/chunk-LB2UOI5F.js +412 -0
  21. package/dist/chunk-LB2UOI5F.js.map +1 -0
  22. package/dist/{chunk-ODGETRTM.js → chunk-VUINJM5M.js} +234 -1415
  23. package/dist/chunk-VUINJM5M.js.map +1 -0
  24. package/dist/chunk-WYIHD6EB.js +1044 -0
  25. package/dist/chunk-WYIHD6EB.js.map +1 -0
  26. package/dist/{chunk-UD6EF73X.js → chunk-XPILG2CA.js} +119 -2
  27. package/dist/chunk-XPILG2CA.js.map +1 -0
  28. package/dist/contract/index.d.ts +17 -13
  29. package/dist/contract/index.js +13 -7
  30. package/dist/contract/index.js.map +1 -1
  31. package/dist/{control-DxvZeV5X.d.ts → control-BgA6BYTm.d.ts} +1 -1
  32. package/dist/control.d.ts +2 -2
  33. package/dist/{feedback-trajectory-8hKC5EOb.d.ts → feedback-trajectory-B3rErRsh.d.ts} +1 -1
  34. package/dist/harness-optimizer-EnEnQPsr.d.ts +106 -0
  35. package/dist/hosted/index.d.ts +223 -2
  36. package/dist/index.d.ts +49 -1323
  37. package/dist/index.js +353 -2496
  38. package/dist/index.js.map +1 -1
  39. package/dist/{index-BGBrVS24.d.ts → insight-report-Df3lxYXM.d.ts} +1 -221
  40. package/dist/kind-factory-DW9XWPvM.d.ts +172 -0
  41. package/dist/multi-layer-verifier-DlWCXuxL.d.ts +141 -0
  42. package/dist/openapi.json +1 -1
  43. package/dist/pareto-E-pembql.d.ts +81 -0
  44. package/dist/{provenance-C69gLUXH.d.ts → provenance-B-TFszPW.d.ts} +131 -4
  45. package/dist/redact-B40YG2M_.d.ts +45 -0
  46. package/dist/registry-DuVYiTvw.d.ts +128 -0
  47. package/dist/{researcher-WJvIpX3L.d.ts → researcher-C_KJyIGg.d.ts} +1 -141
  48. package/dist/rl.d.ts +4 -3
  49. package/dist/rl.js +4 -4
  50. package/dist/run-critic-BAIjX99r.d.ts +56 -0
  51. package/dist/{run-improvement-loop-Bzamo6GB.d.ts → run-improvement-loop-BqYH2vCR.d.ts} +25 -1
  52. package/dist/semantic-concept-judge-CV9Wlx4t.d.ts +650 -0
  53. package/dist/{store-jzKpMl16.d.ts → store-GmBE2pZZ.d.ts} +1 -1
  54. package/dist/traces.d.ts +371 -308
  55. package/dist/traces.js +43 -18
  56. package/dist/{types-CnmZ2bkP.d.ts → types-Bba0vl1V.d.ts} +1 -1
  57. package/dist/{registry-BGKyX6bw.d.ts → types-CRD68aH7.d.ts} +3 -128
  58. package/dist/wire/index.d.ts +1 -1
  59. package/dist/workflow/index.d.ts +494 -0
  60. package/dist/workflow/index.js +2177 -0
  61. package/dist/workflow/index.js.map +1 -0
  62. package/docs/design/self-improvement-roadmap.md +106 -0
  63. package/package.json +36 -12
  64. package/dist/agent-profile-DzcPHR1Z.d.ts +0 -114
  65. package/dist/chunk-ODGETRTM.js.map +0 -1
  66. package/dist/chunk-SL55X4VN.js +0 -186
  67. package/dist/chunk-SL55X4VN.js.map +0 -1
  68. package/dist/chunk-UD6EF73X.js.map +0 -1
  69. /package/dist/{chunk-AIWHLG7J.js.map → chunk-GJJNJVIR.js.map} +0 -0
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/campaign/skill-patch.ts","../../src/campaign/drivers/skill-opt.ts","../../src/campaign/labeled-store/fs-adapter.ts","../../src/campaign/presets/run-skill-opt.ts","../../src/campaign/presets/compare-drivers.ts","../../src/campaign/presets/run-profile-matrix.ts","../../src/campaign/worktree/index.ts"],"sourcesContent":["/**\n * @experimental\n *\n * SkillOpt patch primitives (Microsoft, arXiv:2605.23904 — \"Executive\n * Strategy for Self-Evolving Agent Skills\"). Where GEPA regenerates a surface\n * by reflection, SkillOpt emits BOUNDED, anchored edits to ONE skill document\n * — add / delete / replace — and accepts an edit only if it strictly improves\n * a held-out score. Bounded edits are the \"textual learning rate\": small,\n * reversible, and cheap to accept/reject, so a good rule introduced earlier is\n * not overwritten by a later sweeping rewrite.\n *\n * This module applies a patch deterministically and reports, per op, what\n * applied and what could not (a missing anchor is a rejected op, never a\n * silently dropped one). Pure, no I/O.\n */\n\n/** A single bounded edit against a skill surface.\n * - `add` — insert `text` after the first line containing `after`\n * (append to the end when `after` is absent/empty).\n * - `delete` — remove the first line containing `anchor`.\n * - `replace` — replace the first line containing `anchor` with `text`.\n * `text` may be multi-line; it is spliced in as multiple lines. Anchors match\n * the FIRST line that contains the substring (deterministic; SkillOpt is\n * expected to anchor on unique text). */\nexport type SkillPatchOp =\n | { op: 'add'; after?: string; text: string }\n | { op: 'delete'; anchor: string }\n | { op: 'replace'; anchor: string; text: string }\n\n/** A named, attributable bundle of ops the optimizer proposes as one edit. */\nexport interface SkillPatch {\n label: string\n rationale: string\n ops: SkillPatchOp[]\n}\n\nexport interface SkillPatchRejection {\n op: SkillPatchOp\n reason: string\n}\n\nexport interface ApplySkillPatchResult {\n surface: string\n /** Count of ops that mutated the surface. */\n applied: number\n /** Ops that could not apply (unanchored / empty), with the reason. The\n * surface still reflects every APPLIED op — partial application is honest,\n * and the caller decides whether a partial patch is worth scoring. */\n rejected: SkillPatchRejection[]\n}\n\n/**\n * Apply a SkillOpt patch to a text surface. Ops apply in array order against\n * the evolving line buffer (an `add after X` followed by a `delete X` sees the\n * inserted lines). A missing anchor rejects only that op; the rest still apply.\n */\nexport function applySkillPatch(surface: string, patch: SkillPatch): ApplySkillPatchResult {\n let lines = surface.split('\\n')\n let applied = 0\n const rejected: SkillPatchRejection[] = []\n const findLine = (anchor: string): number => lines.findIndex((l) => l.includes(anchor))\n\n for (const op of patch.ops) {\n if (op.op === 'add') {\n if (typeof op.text !== 'string' || op.text.trim() === '') {\n rejected.push({ op, reason: 'empty add text' })\n continue\n }\n const insert = op.text.split('\\n')\n if (op.after === undefined || op.after === '') {\n lines = [...lines, ...insert]\n applied++\n continue\n }\n const idx = findLine(op.after)\n if (idx === -1) {\n rejected.push({ op, reason: `add anchor not found: ${truncate(op.after)}` })\n continue\n }\n lines = [...lines.slice(0, idx + 1), ...insert, ...lines.slice(idx + 1)]\n applied++\n } else if (op.op === 'delete') {\n const idx = findLine(op.anchor)\n if (idx === -1) {\n rejected.push({ op, reason: `delete anchor not found: ${truncate(op.anchor)}` })\n continue\n }\n lines = [...lines.slice(0, idx), ...lines.slice(idx + 1)]\n applied++\n } else {\n // replace\n const idx = findLine(op.anchor)\n if (idx === -1) {\n rejected.push({ op, reason: `replace anchor not found: ${truncate(op.anchor)}` })\n continue\n }\n if (typeof op.text !== 'string') {\n rejected.push({ op, reason: 'replace text missing' })\n continue\n }\n lines = [...lines.slice(0, idx), ...op.text.split('\\n'), ...lines.slice(idx + 1)]\n applied++\n }\n }\n\n return { surface: lines.join('\\n'), applied, rejected }\n}\n\n/** Total ops in a patch — the edit-budget axis (SkillOpt's \"textual learning\n * rate\" caps this per epoch). */\nexport function patchEditCount(patch: SkillPatch): number {\n return patch.ops.length\n}\n\nfunction truncate(s: string, max = 48): string {\n return s.length <= max ? s : `${s.slice(0, max)}…`\n}\n","/**\n * @experimental\n *\n * `skillOptDriver` — a patch-mode `ImprovementDriver` implementing SkillOpt\n * (Microsoft, arXiv:2605.23904). Where `gepaDriver` regenerates the whole\n * surface by reflection, SkillOpt proposes BOUNDED, anchored edits\n * (add/delete/replace) to ONE skill document, so a good rule introduced\n * earlier is not clobbered by a later sweeping rewrite. The edit budget is the\n * paper's \"textual learning rate\"; a rejected-edit buffer + a slow-update\n * meta-note steer the optimizer away from dead ends.\n *\n * This module is the PROPOSER — the LLM call that turns evidence into\n * structured patches. The accept-only-if-held-out-improves loop, the budget\n * annealing, and the rejected buffer live in the `runSkillOpt` preset, which\n * owns the epoch hill-climb. The driver also conforms to `ImprovementDriver`\n * (`propose` applies its patches to the current surface and returns the\n * candidate surfaces) so it is a drop-in for `runOptimization` and a fair\n * entrant in `compareDrivers`.\n */\n\nimport { callLlm, type LlmClientOptions } from '../../llm-client'\nimport { applySkillPatch, type SkillPatch, type SkillPatchOp } from '../skill-patch'\nimport type { ImprovementDriver, ProposeContext, ProposedCandidate } from '../types'\n\nconst SKILLOPT_SYSTEM =\n 'You are a SkillOpt optimizer. You improve ONE skill document by proposing ' +\n 'BOUNDED, anchored edits — never a full rewrite. Output ONLY a JSON object of ' +\n 'shape {\"patches\":[{\"label\":string,\"rationale\":string,\"ops\":[op,...]}]} where ' +\n 'each op is one of: {\"op\":\"add\",\"after\":<exact substring of an existing line, ' +\n 'or omit to append>,\"text\":<new line(s)>}, {\"op\":\"delete\",\"anchor\":<exact ' +\n 'substring of the line to remove>}, {\"op\":\"replace\",\"anchor\":<exact substring ' +\n 'of the line to replace>,\"text\":<replacement line(s)>}. Anchors MUST be ' +\n 'verbatim substrings of lines that exist in the document. No prose outside JSON.'\n\n/** Evidence the optimizer reflects on: where the current surface is weakest.\n * Computed by the caller (the preset uses a TRAIN campaign so proposals never\n * see the held-out split; the generic loop derives it from history). */\nexport interface SkillOptEvidence {\n /** Lowest-scoring scenarios (drives WHICH behavior to patch). */\n weakScenarios: Array<{ scenarioId: string; composite: number }>\n /** Lowest-scoring judge dimensions (drives WHAT to patch for). */\n weakDimensions: Array<{ dimension: string; score: number }>\n}\n\n/** A patch that was tried and not accepted — fed back to the model so it does\n * not re-propose a dead end (SkillOpt's rejected-edit buffer). */\nexport interface RejectedEdit {\n label: string\n rationale: string\n reason: string\n}\n\nexport interface ProposePatchesArgs {\n surface: string\n evidence: SkillOptEvidence\n /** Max ops per patch this round (the annealed textual learning rate). */\n editBudget: number\n rejectedBuffer: RejectedEdit[]\n /** Slow-update meta guidance accumulated across epochs. */\n metaNote?: string\n /** How many candidate patches to propose. */\n count: number\n signal: AbortSignal\n}\n\nexport interface SkillOptDriverOptions {\n llm: LlmClientOptions\n model: string\n /** What the skill document governs — orients the prompt. */\n target: string\n /** Default ops-per-patch cap when used as a bare `ImprovementDriver`. The\n * `runSkillOpt` preset overrides this per epoch as it anneals. Default 3. */\n editBudget?: number\n temperature?: number\n maxTokens?: number\n /** Top-K weak scenarios/dimensions surfaced as evidence. Default 3. */\n evidenceK?: number\n}\n\nexport interface SkillOptDriver extends ImprovementDriver {\n /** Patch-native path used by `runSkillOpt` (the SkillOpt epoch loop owns\n * acceptance/budget/buffer). Returns structured patches, NOT surfaces. */\n proposePatches(args: ProposePatchesArgs): Promise<SkillPatch[]>\n}\n\nexport function skillOptDriver(opts: SkillOptDriverOptions): SkillOptDriver {\n const evidenceK = opts.evidenceK ?? 3\n const defaultBudget = opts.editBudget ?? 3\n\n async function proposePatches(args: ProposePatchesArgs): Promise<SkillPatch[]> {\n const userPrompt = buildPatchPrompt({\n target: opts.target,\n surface: args.surface,\n evidence: args.evidence,\n editBudget: args.editBudget,\n rejectedBuffer: args.rejectedBuffer,\n metaNote: args.metaNote,\n count: args.count,\n })\n const result = await callLlm(\n {\n model: opts.model,\n messages: [\n { role: 'system', content: SKILLOPT_SYSTEM },\n { role: 'user', content: userPrompt },\n ],\n jsonMode: true,\n temperature: opts.temperature ?? 0.6,\n maxTokens: opts.maxTokens ?? 4000,\n },\n opts.llm,\n )\n return parseSkillPatchResponse(result.content, args.count, args.editBudget)\n }\n\n return {\n kind: 'skill-opt',\n proposePatches,\n async propose(ctx: ProposeContext): Promise<ProposedCandidate[]> {\n if (typeof ctx.currentSurface !== 'string') {\n throw new Error(\n 'skillOptDriver: surface must be a string skill document (got a CodeSurface). SkillOpt patches text.',\n )\n }\n const surface = ctx.currentSurface\n const patches = await proposePatches({\n surface,\n evidence: evidenceFromHistory(ctx, evidenceK),\n editBudget: defaultBudget,\n rejectedBuffer: [],\n count: ctx.populationSize,\n signal: ctx.signal,\n })\n const out: ProposedCandidate[] = []\n const seen = new Set<string>()\n for (const patch of patches) {\n const { surface: candidate, applied } = applySkillPatch(surface, patch)\n if (applied === 0 || candidate === surface || seen.has(candidate)) continue\n seen.add(candidate)\n out.push({ surface: candidate, label: patch.label, rationale: patch.rationale })\n if (out.length >= ctx.populationSize) break\n }\n return out\n },\n }\n}\n\n/** Derive evidence from the loop's generation history (generic-driver path):\n * the prior best candidate's worst scenarios + weakest dimensions. Empty on\n * generation 0. */\nfunction evidenceFromHistory(ctx: ProposeContext, k: number): SkillOptEvidence {\n const last = ctx.history.at(-1)\n if (!last || last.candidates.length === 0) return { weakScenarios: [], weakDimensions: [] }\n const best = [...last.candidates].sort((a, b) => b.composite - a.composite)[0]\n if (!best) return { weakScenarios: [], weakDimensions: [] }\n const weakScenarios = [...best.scenarios].sort((a, b) => a.composite - b.composite).slice(0, k)\n const weakDimensions = Object.entries(best.dimensions)\n .sort((a, b) => a[1] - b[1])\n .slice(0, k)\n .map(([dimension, score]) => ({ dimension, score }))\n return { weakScenarios, weakDimensions }\n}\n\nfunction buildPatchPrompt(args: {\n target: string\n surface: string\n evidence: SkillOptEvidence\n editBudget: number\n rejectedBuffer: RejectedEdit[]\n metaNote?: string\n count: number\n}): string {\n const lines: string[] = [\n `Skill document governs: ${args.target}.`,\n '',\n 'Current skill document:',\n '```',\n args.surface,\n '```',\n '',\n `Propose ${args.count} candidate patch(es). Each patch is a SMALL bundle of`,\n `at most ${args.editBudget} op(s). Anchors must be verbatim substrings of`,\n 'existing lines. Prefer adding a specific missing rule or sharpening a vague',\n 'one over deleting; never rewrite the whole document.',\n ]\n if (args.evidence.weakScenarios.length > 0) {\n lines.push(\n '',\n 'Weakest scenarios (patch to fix these):',\n ...args.evidence.weakScenarios.map((s) => `- ${s.scenarioId} (${s.composite.toFixed(2)})`),\n )\n }\n if (args.evidence.weakDimensions.length > 0) {\n lines.push(\n '',\n 'Weakest dimensions (what to improve):',\n ...args.evidence.weakDimensions.map((d) => `- ${d.dimension} (${d.score.toFixed(2)})`),\n )\n }\n if (args.rejectedBuffer.length > 0) {\n lines.push(\n '',\n 'Already tried and REJECTED (do not repeat or restate these edits):',\n ...args.rejectedBuffer.map((e) => `- ${e.label}: ${e.rationale} — ${e.reason}`),\n )\n }\n if (args.metaNote) {\n lines.push('', `Strategy note from prior epochs: ${args.metaNote}`)\n }\n return lines.join('\\n')\n}\n\n/** Parse + validate the patch response. Throws `SkillPatchParseError` when the\n * response is not valid JSON at all (a router/model failure the caller must\n * see — never a silent no-op epoch). Returns `[]` only for the legitimate\n * \"valid JSON, zero usable patches\" case. Malformed ops within a patch are\n * dropped (not silently mutated); each patch is truncated to the edit budget. */\nexport class SkillPatchParseError extends Error {\n constructor(message: string) {\n super(message)\n this.name = 'SkillPatchParseError'\n }\n}\n\nexport function parseSkillPatchResponse(\n raw: string,\n maxPatches: number,\n editBudget: number,\n): SkillPatch[] {\n let text = raw.trim()\n if (text.startsWith('```')) text = text.replace(/^```(?:json)?\\n?/, '').replace(/\\n?```$/, '')\n const start = text.indexOf('{')\n const end = text.lastIndexOf('}')\n if (start < 0 || end <= start) {\n throw new SkillPatchParseError(\n `parseSkillPatchResponse: response was not valid JSON (no object found): ${snippet(raw)}`,\n )\n }\n let parsed: { patches?: unknown }\n try {\n parsed = JSON.parse(text.slice(start, end + 1))\n } catch (err) {\n throw new SkillPatchParseError(\n `parseSkillPatchResponse: response was not valid JSON (${\n err instanceof Error ? err.message : String(err)\n }): ${snippet(raw)}`,\n )\n }\n const rawPatches = Array.isArray(parsed.patches) ? parsed.patches : []\n const out: SkillPatch[] = []\n for (const rp of rawPatches) {\n if (typeof rp !== 'object' || rp === null) continue\n const obj = rp as Record<string, unknown>\n const ops = Array.isArray(obj.ops) ? obj.ops.map(normalizeOp).filter(isOp) : []\n if (ops.length === 0) continue\n out.push({\n label: typeof obj.label === 'string' ? obj.label : 'patch',\n rationale: typeof obj.rationale === 'string' ? obj.rationale : '',\n ops: ops.slice(0, editBudget),\n })\n if (out.length >= maxPatches) break\n }\n return out\n}\n\nfunction normalizeOp(raw: unknown): SkillPatchOp | null {\n if (typeof raw !== 'object' || raw === null) return null\n const o = raw as Record<string, unknown>\n if (o.op === 'add') {\n if (typeof o.text !== 'string') return null\n const op: SkillPatchOp = { op: 'add', text: o.text }\n if (typeof o.after === 'string') op.after = o.after\n return op\n }\n if (o.op === 'delete') {\n if (typeof o.anchor !== 'string') return null\n return { op: 'delete', anchor: o.anchor }\n }\n if (o.op === 'replace') {\n if (typeof o.anchor !== 'string' || typeof o.text !== 'string') return null\n return { op: 'replace', anchor: o.anchor, text: o.text }\n }\n return null\n}\n\nfunction isOp(op: SkillPatchOp | null): op is SkillPatchOp {\n return op !== null\n}\n\nfunction snippet(s: string, max = 120): string {\n const t = s.trim().replace(/\\s+/g, ' ')\n return t.length <= max ? t : `${t.slice(0, max)}…`\n}\n","/**\n * @experimental\n *\n * Filesystem `LabeledScenarioStore` adapter. The default capture sink for\n * traces + eval artifacts. Production deployments typically swap for a\n * Turso/SQLite adapter (same interface).\n *\n * Records land as one JSONL file per source under `<root>/<source>.jsonl`.\n * Each line is a `LabeledScenarioRecord`. Append-only — no in-place edits.\n *\n * Safety properties enforced at write-time:\n *\n * - **Provenance required**: writes without `source`, `sourceVersionHash`,\n * `capturedAt`, `redactionStatus` are rejected. Closes the alignment\n * reviewer's data-poisoning gap.\n * - **Per-source rate limits**: optional `rateLimitBucket` + `maxWritesPerMinute`\n * stops a single tenant/source from flooding the store.\n *\n * Safety properties enforced at sample-time:\n *\n * - **Required split + capturedBefore**: substrate refuses to sample without\n * an explicit `split` ('train' | 'test') AND a temporal cutoff. Eliminates\n * accidental train/test contamination.\n * - **Default training-source filter**: when the store is sampled with\n * `split: 'train'`, production-trace records are EXCLUDED unless the\n * caller passes `filter.source: 'production-trace'` explicitly. Closes\n * the contamination-by-default gap flagged by the senior eval engineer.\n */\n\nimport { createHash } from 'node:crypto'\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'\nimport { join } from 'node:path'\nimport type {\n LabeledScenarioRecord,\n LabeledScenarioSampleArgs,\n LabeledScenarioSource,\n LabeledScenarioStore,\n LabeledScenarioWrite,\n LabelTrust,\n} from '../types'\nimport { labelTrustRank } from '../types'\n\nexport interface FsLabeledScenarioStoreOptions {\n /** Root directory for JSONL files. Created if missing. */\n root: string\n /** Per-source rate limit. When set, writes exceeding the cap are rejected\n * with a typed error. Default: no limit. */\n maxWritesPerMinutePerBucket?: number\n /** Test seam — override `Date.now()` for deterministic tests. */\n now?: () => number\n}\n\nexport class LabeledScenarioStoreError extends Error {\n constructor(\n public readonly code: string,\n message: string,\n ) {\n super(message)\n this.name = 'LabeledScenarioStoreError'\n }\n}\n\ninterface RateLimitState {\n bucket: string\n windowStartMs: number\n count: number\n}\n\nexport class FsLabeledScenarioStore implements LabeledScenarioStore {\n private readonly now: () => number\n private readonly rateLimits = new Map<string, RateLimitState>()\n\n constructor(private readonly options: FsLabeledScenarioStoreOptions) {\n if (!existsSync(options.root)) mkdirSync(options.root, { recursive: true })\n this.now = options.now ?? Date.now\n }\n\n async observe(write: LabeledScenarioWrite): Promise<void> {\n this.assertProvenance(write)\n this.assertRateLimit(write)\n const record = this.toRecord(write)\n const path = this.pathForSource(write.source)\n const line = `${JSON.stringify(record)}\\n`\n // Append atomically. For high-throughput a writev-friendly buffered\n // implementation lands in the Turso adapter; FS adapter is for tests +\n // local dev + small workloads.\n appendLine(path, line)\n }\n\n async sample(args: LabeledScenarioSampleArgs): Promise<LabeledScenarioRecord[]> {\n if (!args.split) {\n throw new LabeledScenarioStoreError(\n 'split_required',\n 'sample() requires an explicit `split` (train | test) — substrate refuses ambiguous reads',\n )\n }\n if (!args.capturedBefore) {\n throw new LabeledScenarioStoreError(\n 'capturedBefore_required',\n 'sample() requires an explicit `capturedBefore` timestamp for temporal-split discipline',\n )\n }\n\n const all: LabeledScenarioRecord[] = []\n for (const source of ALL_SOURCES) {\n // Default training-source filter: when sampling train, EXCLUDE\n // production-trace records unless the caller asks for them.\n if (args.split === 'train' && source === 'production-trace') {\n const explicit = sourceFilterContains(args.filter?.source, 'production-trace')\n if (!explicit) continue\n }\n const path = this.pathForSource(source)\n if (!existsSync(path)) continue\n const lines = readFileSync(path, 'utf8').split('\\n').filter(Boolean)\n for (const line of lines) {\n let record: LabeledScenarioRecord\n try {\n record = JSON.parse(line) as LabeledScenarioRecord\n } catch {\n continue\n }\n if (!matchesFilter(record, args, source)) continue\n all.push(record)\n }\n }\n\n // Deterministic order: by capturedAt ascending, then recordHash.\n all.sort((a, b) => {\n if (a.capturedAt !== b.capturedAt) return a.capturedAt.localeCompare(b.capturedAt)\n return a.recordHash.localeCompare(b.recordHash)\n })\n\n return all.slice(0, args.count)\n }\n\n async size(): Promise<{\n train: number\n test: number\n bySource: Record<string, number>\n byTrust: Record<LabelTrust, number>\n }> {\n const bySource: Record<string, number> = {}\n const byTrust: Record<LabelTrust, number> = {\n unverified: 0,\n 'verified-signal': 0,\n 'human-rated': 0,\n }\n let total = 0\n for (const source of ALL_SOURCES) {\n const path = this.pathForSource(source)\n if (!existsSync(path)) {\n bySource[source] = 0\n continue\n }\n const lines = readFileSync(path, 'utf8').split('\\n').filter(Boolean)\n bySource[source] = lines.length\n total += lines.length\n for (const line of lines) {\n let trust: LabelTrust = 'unverified'\n try {\n trust = (JSON.parse(line) as LabeledScenarioRecord).labelTrust ?? 'unverified'\n } catch {\n // A malformed line counts as unverified — never silently gold.\n }\n byTrust[trust] += 1\n }\n }\n // FS adapter doesn't track split assignments per-record (split is\n // computed at sample-time based on `capturedBefore`). For size(), we\n // report `train`+`test` as the same total — split is a sampling concept.\n return { train: total, test: total, bySource, byTrust }\n }\n\n private assertProvenance(write: LabeledScenarioWrite): void {\n if (!write.source) {\n throw new LabeledScenarioStoreError(\n 'missing_source',\n 'LabeledScenarioWrite requires `source`',\n )\n }\n if (!write.sourceVersionHash || write.sourceVersionHash.length === 0) {\n throw new LabeledScenarioStoreError(\n 'missing_source_version',\n 'LabeledScenarioWrite requires `sourceVersionHash` (git sha or substrate version)',\n )\n }\n if (!write.capturedAt) {\n throw new LabeledScenarioStoreError(\n 'missing_captured_at',\n 'LabeledScenarioWrite requires `capturedAt` ISO timestamp',\n )\n }\n if (!write.redactionStatus) {\n throw new LabeledScenarioStoreError(\n 'missing_redaction_status',\n 'LabeledScenarioWrite requires explicit `redactionStatus` — raw / redacted-pii / redacted-secrets / fully-redacted',\n )\n }\n if (!ALL_SOURCES.includes(write.source)) {\n throw new LabeledScenarioStoreError(\n 'unknown_source',\n `LabeledScenarioWrite.source must be one of: ${ALL_SOURCES.join(', ')}`,\n )\n }\n }\n\n private assertRateLimit(write: LabeledScenarioWrite): void {\n const cap = this.options.maxWritesPerMinutePerBucket\n if (!cap || !write.rateLimitBucket) return\n const now = this.now()\n const windowMs = 60_000\n let state = this.rateLimits.get(write.rateLimitBucket)\n if (!state || now - state.windowStartMs >= windowMs) {\n state = { bucket: write.rateLimitBucket, windowStartMs: now, count: 0 }\n this.rateLimits.set(write.rateLimitBucket, state)\n }\n if (state.count >= cap) {\n throw new LabeledScenarioStoreError(\n 'rate_limit_exceeded',\n `LabeledScenarioStore: bucket ${write.rateLimitBucket} exceeded ${cap} writes/min`,\n )\n }\n state.count += 1\n }\n\n private toRecord(write: LabeledScenarioWrite): LabeledScenarioRecord {\n const recordHash = sha256(\n JSON.stringify({\n id: write.scenario.id,\n src: write.source,\n at: write.capturedAt,\n ver: write.sourceVersionHash,\n }),\n )\n // FS adapter assigns split at sample-time, but we cache a hint here\n // based on capturedAt vs the world's \"now\" — sampler overrides this.\n return {\n ...write,\n recordHash,\n split: 'train',\n }\n }\n\n private pathForSource(source: string): string {\n return join(this.options.root, `${source}.jsonl`)\n }\n}\n\nconst ALL_SOURCES: LabeledScenarioWrite['source'][] = [\n 'production-trace',\n 'eval-run',\n 'manual',\n 'red-team',\n 'synthetic',\n]\n\nfunction sourceFilterContains(\n filter: LabeledScenarioSource | LabeledScenarioSource[] | undefined,\n needle: LabeledScenarioSource,\n): boolean {\n if (!filter) return false\n if (Array.isArray(filter)) return filter.includes(needle)\n return filter === needle\n}\n\nfunction matchesFilter(\n record: LabeledScenarioRecord,\n args: LabeledScenarioSampleArgs,\n source: string,\n): boolean {\n // Temporal cutoff — train must be capturedAt < capturedBefore.\n if (args.split === 'train' && record.capturedAt >= args.capturedBefore) return false\n if (args.split === 'test' && record.capturedAt < args.capturedBefore) return false\n\n const f = args.filter\n if (!f) return true\n if (f.kind && record.scenario.kind !== f.kind) return false\n if (f.source) {\n const sources = Array.isArray(f.source) ? f.source : [f.source]\n if (!sources.includes(source as never)) return false\n }\n if (f.minComposite !== undefined || f.maxComposite !== undefined) {\n const composites = Object.values(record.judgeScores).map((s) => s.composite)\n const max = composites.length === 0 ? 0 : Math.max(...composites)\n if (f.minComposite !== undefined && max < f.minComposite) return false\n if (f.maxComposite !== undefined && max > f.maxComposite) return false\n }\n if (f.minTrust !== undefined && labelTrustRank(record.labelTrust) < labelTrustRank(f.minTrust)) {\n return false\n }\n return true\n}\n\nfunction sha256(input: string): string {\n return createHash('sha256').update(input).digest('hex').slice(0, 16)\n}\n\nfunction appendLine(path: string, line: string): void {\n if (existsSync(path)) {\n const existing = readFileSync(path, 'utf8')\n writeFileSync(path, existing + line)\n } else {\n writeFileSync(path, line)\n }\n}\n","/**\n * @experimental\n *\n * `runSkillOpt` — the SkillOpt epoch hill-climb (Microsoft, arXiv:2605.23904).\n * Unlike `runOptimization`'s population/promote-top-K search, SkillOpt is a\n * sequential, held-out-gated hill-climb on ONE skill document:\n *\n * each epoch:\n * 1. reflect on the CURRENT surface's weakest TRAIN scenarios/dimensions\n * (never the held-out split — proposals must not see the acceptance axis)\n * 2. propose ≤ `patchesPerEpoch` bounded patches (≤ `editBudget` ops each)\n * 3. apply each; score the candidate on the HELD-OUT split\n * 4. ACCEPT the first patch that STRICTLY improves the held-out composite;\n * otherwise push it to the rejected-edit buffer (fed back so the model\n * does not re-propose dead ends)\n * 5. anneal the edit budget down after consecutive rejections (the\n * \"textual learning rate\" decay); refresh the slow-update meta note\n * 6. stop at `maxEpochs` or after `patience` epochs with no acceptance\n *\n * The accept-only-if-held-out-improves rule is the same discipline as\n * `HeldOutGate`/`defaultProductionGate`, applied per edit instead of once at\n * the end — which is why the held-out composite is monotonically\n * non-decreasing and a regression can never ship. `runCampaign` is the\n * measurement; `applySkillPatch` applies the edits; `skillOptDriver` proposes\n * them.\n */\n\nimport type { RejectedEdit, SkillOptDriver, SkillOptEvidence } from '../drivers/skill-opt'\nimport { type RunCampaignOptions, runCampaign } from '../run-campaign'\nimport { campaignBreakdown, campaignMeanComposite } from '../score-utils'\nimport { applySkillPatch } from '../skill-patch'\nimport type { CampaignResult, DispatchContext, Scenario } from '../types'\n\nexport interface RunSkillOptOptions<TScenario extends Scenario, TArtifact>\n extends Omit<RunCampaignOptions<TScenario, TArtifact>, 'dispatch' | 'scenarios'> {\n /** The skill document being optimized. */\n baselineSurface: string\n /** Dispatcher taking the CURRENT skill surface + scenario → artifact. */\n dispatchWithSurface: (\n surface: string,\n scenario: TScenario,\n ctx: DispatchContext,\n ) => Promise<TArtifact>\n driver: SkillOptDriver\n /** Scenarios the optimizer reflects on for evidence. MUST be disjoint from\n * `holdoutScenarios` — proposals never see the acceptance axis. */\n trainScenarios: TScenario[]\n /** Held-out scenarios. An edit is accepted ONLY if it strictly improves the\n * mean composite here. */\n holdoutScenarios: TScenario[]\n maxEpochs: number\n /** Candidate patches proposed per epoch. Default 2. */\n patchesPerEpoch?: number\n /** Initial ops-per-patch cap (the textual learning rate). Default 3. */\n editBudget?: number\n /** Strict acceptance margin: accept iff the held-out composite improves by\n * MORE than this. Default 0 (any strict improvement). */\n minImprovement?: number\n /** Stop after this many consecutive epochs with no acceptance. Default =\n * `maxEpochs` (never early-stop). */\n patience?: number\n /** Shrink the edit budget by 1 after 2 consecutive rejected epochs (min 1).\n * Default true. */\n budgetAnneal?: boolean\n /** Cap on the rejected-edit buffer (most-recent kept). Default 12. */\n rejectedBufferSize?: number\n /** Refresh the slow-update meta note every N epochs. Default 2. 0 disables. */\n slowMetaEvery?: number\n /** Top-K weak scenarios/dimensions surfaced as evidence each epoch. Default 3. */\n evidenceK?: number\n /** Abort signal forwarded to the patch-proposing LLM calls. */\n signal?: AbortSignal\n}\n\nexport interface AcceptedEdit {\n epoch: number\n label: string\n rationale: string\n /** Held-out composite improvement vs the surface before this edit. */\n holdoutDelta: number\n}\n\nexport interface SkillOptEpochRecord {\n epoch: number\n editBudget: number\n proposed: number\n /** The accepted edit this epoch, or null if every proposal was rejected. */\n accepted: AcceptedEdit | null\n rejected: RejectedEdit[]\n /** Held-out composite of the CURRENT surface at the END of the epoch. */\n holdoutComposite: number\n}\n\nexport interface RunSkillOptResult {\n winnerSurface: string\n baselineHoldoutComposite: number\n winnerHoldoutComposite: number\n /** `winnerHoldoutComposite - baselineHoldoutComposite` — monotonically ≥ 0\n * by construction (only strictly-improving edits are accepted). */\n lift: number\n acceptedEdits: AcceptedEdit[]\n rejectedEdits: RejectedEdit[]\n epochsRun: number\n history: SkillOptEpochRecord[]\n /** Total cost across every scoring campaign (train evidence + holdout\n * acceptance) the hill-climb ran. */\n totalCostUsd: number\n}\n\nexport async function runSkillOpt<TScenario extends Scenario, TArtifact>(\n opts: RunSkillOptOptions<TScenario, TArtifact>,\n): Promise<RunSkillOptResult> {\n if (opts.trainScenarios.length === 0) throw new Error('runSkillOpt: trainScenarios is empty')\n if (opts.holdoutScenarios.length === 0) throw new Error('runSkillOpt: holdoutScenarios is empty')\n if (!opts.judges || opts.judges.length === 0) {\n throw new Error(\n 'runSkillOpt: at least one judge is required — scoring (and therefore acceptance) is meaningless without one, and would report a silent zero lift.',\n )\n }\n // train ∩ holdout must be empty: proposals reflect on TRAIN evidence, so any\n // overlap leaks the acceptance axis into the proposal (held-out contamination).\n const holdoutIds = new Set(opts.holdoutScenarios.map((s) => s.id))\n const overlap = opts.trainScenarios.filter((s) => holdoutIds.has(s.id)).map((s) => s.id)\n if (overlap.length > 0) {\n throw new Error(\n `runSkillOpt: trainScenarios and holdoutScenarios must be disjoint (overlap: [${overlap.join(\n ', ',\n )}]) — a shared scenario leaks the held-out acceptance axis into the proposal evidence.`,\n )\n }\n\n const patchesPerEpoch = opts.patchesPerEpoch ?? 2\n const initialBudget = opts.editBudget ?? 3\n const minImprovement = opts.minImprovement ?? 0\n if (minImprovement < 0) {\n throw new Error(\n 'runSkillOpt: minImprovement must be >= 0 — a negative threshold would accept held-out regressions, breaking the monotonic-lift contract.',\n )\n }\n const patience = opts.patience ?? opts.maxEpochs\n const budgetAnneal = opts.budgetAnneal ?? true\n const rejectedBufferSize = opts.rejectedBufferSize ?? 12\n const slowMetaEvery = opts.slowMetaEvery ?? 2\n\n let totalCostUsd = 0\n const scoreHoldout = async (surface: string, tag: string): Promise<number> => {\n const campaign = await runScoringCampaign(opts, opts.holdoutScenarios, surface, tag)\n totalCostUsd += campaign.aggregates.totalCostUsd\n return campaignMeanComposite(campaign)\n }\n const evidenceK = opts.evidenceK ?? 3\n const trainEvidence = async (surface: string, tag: string): Promise<SkillOptEvidence> => {\n const campaign = await runScoringCampaign(opts, opts.trainScenarios, surface, tag)\n totalCostUsd += campaign.aggregates.totalCostUsd\n return toEvidence(campaign, evidenceK)\n }\n\n let current = opts.baselineSurface\n let currentEvidence = await trainEvidence(current, 'baseline-train')\n const baselineHoldout = await scoreHoldout(current, 'baseline-holdout')\n let currentHoldout = baselineHoldout\n\n const buffer: RejectedEdit[] = []\n const acceptedEdits: AcceptedEdit[] = []\n const rejectedAll: RejectedEdit[] = []\n const history: SkillOptEpochRecord[] = []\n let budget = initialBudget\n let sinceAccept = 0\n let metaNote: string | undefined\n let epochsRun = 0\n\n for (let epoch = 0; epoch < opts.maxEpochs; epoch++) {\n epochsRun++\n const patches = await opts.driver.proposePatches({\n surface: current,\n evidence: currentEvidence,\n editBudget: budget,\n rejectedBuffer: buffer,\n metaNote,\n count: patchesPerEpoch,\n signal: opts.signal ?? new AbortController().signal,\n })\n\n let accepted: AcceptedEdit | null = null\n const rejectedThisEpoch: RejectedEdit[] = []\n for (let i = 0; i < patches.length; i++) {\n const patch = patches[i]!\n const { surface: candidate, applied } = applySkillPatch(current, patch)\n if (applied === 0 || candidate === current) {\n rejectedThisEpoch.push({\n label: patch.label,\n rationale: patch.rationale,\n reason: 'no-op (unanchored or zero-change)',\n })\n continue\n }\n const candidateHoldout = await scoreHoldout(candidate, `epoch-${epoch}-cand-${i}-holdout`)\n if (candidateHoldout > currentHoldout + minImprovement) {\n accepted = {\n epoch,\n label: patch.label,\n rationale: patch.rationale,\n holdoutDelta: candidateHoldout - currentHoldout,\n }\n current = candidate\n currentHoldout = candidateHoldout\n // The surface changed — recompute evidence for the next epoch from it.\n currentEvidence = await trainEvidence(current, `epoch-${epoch}-train`)\n break // greedy: take the first strictly-improving edit\n }\n rejectedThisEpoch.push({\n label: patch.label,\n rationale: patch.rationale,\n reason: `held-out ${candidateHoldout.toFixed(3)} ≤ current ${currentHoldout.toFixed(3)}`,\n })\n }\n\n if (accepted) {\n acceptedEdits.push(accepted)\n sinceAccept = 0\n } else {\n sinceAccept++\n if (budgetAnneal && sinceAccept >= 2 && budget > 1) budget--\n }\n // Maintain the bounded rejected-edit buffer (steers the proposer away from\n // dead ends; capped so the prompt stays bounded).\n for (const r of rejectedThisEpoch) {\n buffer.push(r)\n rejectedAll.push(r)\n }\n while (buffer.length > rejectedBufferSize) buffer.shift()\n\n // Slow-update meta note: a cross-epoch digest refreshed on a slow cadence.\n if (slowMetaEvery > 0 && (epoch + 1) % slowMetaEvery === 0) {\n metaNote = buildMetaNote(acceptedEdits, buffer)\n }\n\n history.push({\n epoch,\n editBudget: budget,\n proposed: patches.length,\n accepted,\n rejected: rejectedThisEpoch,\n holdoutComposite: currentHoldout,\n })\n\n if (sinceAccept >= patience) break\n }\n\n return {\n winnerSurface: current,\n baselineHoldoutComposite: baselineHoldout,\n winnerHoldoutComposite: currentHoldout,\n lift: currentHoldout - baselineHoldout,\n acceptedEdits,\n rejectedEdits: rejectedAll,\n epochsRun,\n history,\n totalCostUsd,\n }\n}\n\nfunction runScoringCampaign<TScenario extends Scenario, TArtifact>(\n opts: RunSkillOptOptions<TScenario, TArtifact>,\n scenarios: TScenario[],\n surface: string,\n tag: string,\n): Promise<CampaignResult<TArtifact, TScenario>> {\n return runCampaign<TScenario, TArtifact>({\n ...opts,\n scenarios,\n dispatch: (scenario, ctx) => opts.dispatchWithSurface(surface, scenario, ctx),\n runDir: `${opts.runDir}/${tag}`,\n })\n}\n\nfunction toEvidence<TArtifact, TScenario extends Scenario>(\n campaign: CampaignResult<TArtifact, TScenario>,\n k: number,\n): SkillOptEvidence {\n const { dimensions, scenarios } = campaignBreakdown(campaign)\n const weakScenarios = [...scenarios].sort((a, b) => a.composite - b.composite).slice(0, k)\n const weakDimensions = Object.entries(dimensions)\n .sort((a, b) => a[1] - b[1])\n .slice(0, k)\n .map(([dimension, score]) => ({ dimension, score }))\n return { weakScenarios, weakDimensions }\n}\n\nfunction buildMetaNote(accepted: AcceptedEdit[], rejected: RejectedEdit[]): string {\n const parts: string[] = []\n if (accepted.length > 0) {\n parts.push(\n `Edits that improved held-out so far: ${accepted\n .map((a) => `\"${a.label}\" (+${a.holdoutDelta.toFixed(3)})`)\n .join('; ')}. Build on these.`,\n )\n }\n if (rejected.length > 0) {\n const labels = [...new Set(rejected.map((r) => r.label))].slice(0, 5)\n parts.push(`Dead ends to avoid: ${labels.join(', ')}. Try a different anchor or rule.`)\n }\n parts.push('Keep edits small and anchored to existing lines.')\n return parts.join(' ')\n}\n","/**\n * @experimental\n *\n * `compareDrivers` — a head-to-head lift benchmark across optimizer drivers on\n * ONE corpus. This is the forcing function: optimizer quality (GEPA reflection\n * vs GEPA+Pareto vs SkillOpt) becomes a NUMBER with a confidence interval, so a\n * driver regression — or shipping a simplified driver and calling it the real\n * one — turns a build red instead of going measurement-invisible.\n *\n * Every entrant is scored the SAME way: each driver returns the surface it\n * promoted, then `compareDrivers` scores the baseline + every winner on the\n * SAME held-out scenarios with the SAME judges. Apples-to-apples by\n * construction — the comparison never depends on how a driver measured itself.\n * The per-scenario held-out composites feed a paired bootstrap (`statistics.ts`)\n * for each driver's lift CI and for the pairwise \"which driver wins\" CI.\n */\n\nimport type { LlmClientOptions } from '../../llm-client'\nimport { pairedBootstrap } from '../../statistics'\nimport { gepaDriver } from '../drivers/gepa'\nimport { skillOptDriver } from '../drivers/skill-opt'\nimport { defaultProductionGate } from '../gates/default-production-gate'\nimport { type RunCampaignOptions, runCampaign } from '../run-campaign'\nimport { campaignBreakdown } from '../score-utils'\nimport type {\n CampaignResult,\n DispatchContext,\n JudgeConfig,\n MutableSurface,\n Scenario,\n} from '../types'\nimport { runImprovementLoop } from './run-improvement-loop'\nimport { runSkillOpt } from './run-skill-opt'\n\n/** What an optimizer produced: the surface it promoted + what it cost to get\n * there. `compareDrivers` does the held-out scoring itself, so an entry only\n * needs to run its loop and hand back the winner. */\nexport interface DriverEntry {\n name: string\n optimize: () => Promise<{ winnerSurface: MutableSurface; costUsd: number; durationMs?: number }>\n}\n\nexport interface DriverScore {\n name: string\n /** Mean held-out composite of the baseline (identical across drivers). */\n baselineComposite: number\n /** Mean held-out composite of this driver's promoted surface. */\n winnerComposite: number\n /** Mean per-scenario held-out lift (winner − baseline). */\n lift: number\n /** Paired-bootstrap CI of the per-scenario lift. `low > 0` ⇒ a real gain. */\n liftCi: { low: number; high: number }\n costUsd: number\n durationMs?: number\n winnerSurface: MutableSurface\n /** 1-based, by descending lift. */\n rank: number\n}\n\nexport interface DriverPairwise {\n /** Higher-ranked driver. */\n a: string\n b: string\n /** Mean per-scenario held-out delta (a − b). */\n deltaMean: number\n low: number\n high: number\n /** `a` if the CI clears 0, `b` if it is entirely negative, else `'tie'`. */\n favored: string\n}\n\nexport interface DriverComparison {\n /** Sorted by descending lift; `rank` set accordingly. */\n scores: DriverScore[]\n best: DriverScore\n /** Best vs each other driver, paired-bootstrap on the held-out winners. */\n pairwise: DriverPairwise[]\n holdoutScenarioIds: string[]\n}\n\nexport interface CompareDriversOptions<TScenario extends Scenario, TArtifact>\n extends Omit<RunCampaignOptions<TScenario, TArtifact>, 'dispatch' | 'scenarios'> {\n drivers: DriverEntry[]\n baselineSurface: MutableSurface\n /** The held-out scenarios every winner is scored on. */\n holdoutScenarios: TScenario[]\n /** Scores a surface on a scenario — the same dispatcher the drivers used. */\n dispatchWithSurface: (\n surface: MutableSurface,\n scenario: TScenario,\n ctx: DispatchContext,\n ) => Promise<TArtifact>\n /** Bootstrap resamples for the lift CIs. Default 2000. */\n resamples?: number\n /** CI confidence. Default 0.95. */\n confidence?: number\n}\n\nexport async function compareDrivers<TScenario extends Scenario, TArtifact>(\n opts: CompareDriversOptions<TScenario, TArtifact>,\n): Promise<DriverComparison> {\n if (opts.drivers.length === 0) throw new Error('compareDrivers: no drivers to compare')\n const seed = opts.seed ?? 42\n const resamples = opts.resamples ?? 2000\n const confidence = opts.confidence ?? 0.95\n\n const scoreOnHoldout = async (\n surface: MutableSurface,\n tag: string,\n ): Promise<Record<string, number>> => {\n const campaign: CampaignResult<TArtifact, TScenario> = await runCampaign<TScenario, TArtifact>({\n ...opts,\n scenarios: opts.holdoutScenarios,\n dispatch: (scenario, ctx) => opts.dispatchWithSurface(surface, scenario, ctx),\n runDir: `${opts.runDir}/${tag}`,\n })\n const byScenario: Record<string, number> = {}\n for (const { scenarioId, composite } of campaignBreakdown(campaign).scenarios) {\n byScenario[scenarioId] = composite\n }\n return byScenario\n }\n\n // The comparison axis is the DESIGNED held-out set, not whatever a campaign\n // happened to score. Align every score vector to it and FAIL LOUD if a\n // surface is missing any scenario (an errored cell / a judge that returned no\n // score). Fabricating a 0 there would silently penalize that surface and\n // corrupt the paired-bootstrap lift CI — the exact \"no silent zeros\" trap.\n const scenarioIds = [...new Set(opts.holdoutScenarios.map((s) => s.id))].sort()\n if (scenarioIds.length === 0) throw new Error('compareDrivers: holdoutScenarios is empty')\n const align = (byScenario: Record<string, number>, label: string): number[] => {\n const missing = scenarioIds.filter((id) => !(id in byScenario))\n if (missing.length > 0) {\n throw new Error(\n `compareDrivers: ${label} produced no held-out score for scenario(s) [${missing.join(\n ', ',\n )}] — a cell errored or its judges returned nothing. Refusing to fabricate a 0 (it would corrupt the lift comparison). Fix the dispatch/judge or drop the scenario.`,\n )\n }\n return scenarioIds.map((id) => byScenario[id]!)\n }\n\n const baselineArr = align(\n await scoreOnHoldout(opts.baselineSurface, 'compare-baseline'),\n 'baseline',\n )\n\n // Run + uniformly re-score every entrant on the SAME held-out axis.\n const winners: Array<{\n name: string\n winnerSurface: MutableSurface\n costUsd: number\n durationMs?: number\n arr: number[]\n }> = []\n for (const d of opts.drivers) {\n const out = await d.optimize()\n const byScenario = await scoreOnHoldout(out.winnerSurface, `compare-${slug(d.name)}`)\n winners.push({\n name: d.name,\n winnerSurface: out.winnerSurface,\n costUsd: out.costUsd,\n durationMs: out.durationMs,\n arr: align(byScenario, `driver \"${d.name}\"`),\n })\n }\n\n const scores: DriverScore[] = winners.map((w) => {\n const boot = pairedBootstrap(baselineArr, w.arr, {\n seed,\n resamples,\n confidence,\n statistic: 'mean',\n })\n const score: DriverScore = {\n name: w.name,\n baselineComposite: mean(baselineArr),\n winnerComposite: mean(w.arr),\n lift: boot.mean,\n liftCi: { low: boot.low, high: boot.high },\n costUsd: w.costUsd,\n winnerSurface: w.winnerSurface,\n rank: 0,\n }\n if (w.durationMs !== undefined) score.durationMs = w.durationMs\n return score\n })\n // Sort by lift; tie-break by lower cost (cheaper wins a tie).\n scores.sort((a, b) => b.lift - a.lift || a.costUsd - b.costUsd)\n scores.forEach((s, i) => {\n s.rank = i + 1\n })\n const best = scores[0]!\n\n const byName = new Map(winners.map((w) => [w.name, w]))\n const bestArr = byName.get(best.name)!.arr\n const pairwise: DriverPairwise[] = scores.slice(1).map((other) => {\n const otherArr = byName.get(other.name)!.arr\n // before = other, after = best ⇒ delta = best − other on the held-out set.\n const boot = pairedBootstrap(otherArr, bestArr, {\n seed,\n resamples,\n confidence,\n statistic: 'mean',\n })\n const favored = boot.low > 0 ? best.name : boot.high < 0 ? other.name : 'tie'\n return {\n a: best.name,\n b: other.name,\n deltaMean: boot.mean,\n low: boot.low,\n high: boot.high,\n favored,\n }\n })\n\n return { scores, best, pairwise, holdoutScenarioIds: scenarioIds }\n}\n\nfunction mean(xs: number[]): number {\n return xs.length === 0 ? 0 : xs.reduce((a, b) => a + b, 0) / xs.length\n}\n\nfunction slug(name: string): string {\n return name.replace(/[^a-z0-9]+/gi, '-').toLowerCase()\n}\n\n// ── Built-in entries — wire the real optimizers for a live comparison ───────\n\n/** Shared corpus + transport for the three built-in optimizer entries. */\nexport interface OptimizerEntryConfig<TScenario extends Scenario, TArtifact> {\n baselineSurface: string\n /** Training scenarios the drivers reflect on. */\n trainScenarios: TScenario[]\n /** Held-out scenarios (the gate axis + the benchmark scoring axis). */\n holdoutScenarios: TScenario[]\n dispatchWithSurface: (\n surface: MutableSurface,\n scenario: TScenario,\n ctx: DispatchContext,\n ) => Promise<TArtifact>\n judges: JudgeConfig<TArtifact, TScenario>[]\n llm: LlmClientOptions\n model: string\n target: string\n runDir: string\n seed?: number\n /** GEPA population per generation. Default 2. */\n populationSize?: number\n /** GEPA generations. Default 3. */\n maxGenerations?: number\n /** SkillOpt epochs. Default 6. */\n maxEpochs?: number\n mutationPrimitives?: string[]\n}\n\n/** GEPA, reflection-only (single-parent, no Pareto combine). */\nexport function gepaReflectionEntry<TScenario extends Scenario, TArtifact>(\n config: OptimizerEntryConfig<TScenario, TArtifact>,\n name = 'gepa-reflection',\n): DriverEntry {\n return gepaEntry(config, false, name)\n}\n\n/** GEPA with the Pareto frontier + combine-complementary-lessons. */\nexport function gepaParetoEntry<TScenario extends Scenario, TArtifact>(\n config: OptimizerEntryConfig<TScenario, TArtifact>,\n name = 'gepa-pareto',\n): DriverEntry {\n return gepaEntry(config, true, name)\n}\n\nfunction gepaEntry<TScenario extends Scenario, TArtifact>(\n config: OptimizerEntryConfig<TScenario, TArtifact>,\n combineParents: boolean,\n name: string,\n): DriverEntry {\n return {\n name,\n async optimize() {\n const started = Date.now()\n const driver = gepaDriver({\n llm: config.llm,\n model: config.model,\n target: config.target,\n combineParents,\n ...(config.mutationPrimitives ? { mutationPrimitives: config.mutationPrimitives } : {}),\n })\n const result = await runImprovementLoop<TScenario, TArtifact>({\n scenarios: config.trainScenarios,\n holdoutScenarios: config.holdoutScenarios,\n baselineSurface: config.baselineSurface,\n dispatchWithSurface: config.dispatchWithSurface,\n judges: config.judges,\n driver,\n populationSize: config.populationSize ?? 2,\n maxGenerations: config.maxGenerations ?? 3,\n gate: defaultProductionGate<TArtifact, TScenario>({\n holdoutScenarios: config.holdoutScenarios,\n deltaThreshold: 0,\n }),\n autoOnPromote: 'none',\n runDir: `${config.runDir}/${slug(name)}-loop`,\n ...(config.seed !== undefined ? { seed: config.seed } : {}),\n })\n const costUsd =\n result.baselineCampaign.aggregates.totalCostUsd +\n result.generations.reduce(\n (sum, g) =>\n sum + g.surfaces.reduce((s, sf) => s + sf.campaign.aggregates.totalCostUsd, 0),\n 0,\n )\n return { winnerSurface: result.winnerSurface, costUsd, durationMs: Date.now() - started }\n },\n }\n}\n\n/** SkillOpt patch-mode hill-climb. */\nexport function skillOptEntry<TScenario extends Scenario, TArtifact>(\n config: OptimizerEntryConfig<TScenario, TArtifact>,\n name = 'skill-opt',\n): DriverEntry {\n return {\n name,\n async optimize() {\n const started = Date.now()\n const driver = skillOptDriver({ llm: config.llm, model: config.model, target: config.target })\n const result = await runSkillOpt<TScenario, TArtifact>({\n baselineSurface: config.baselineSurface,\n dispatchWithSurface: config.dispatchWithSurface,\n judges: config.judges,\n driver,\n trainScenarios: config.trainScenarios,\n holdoutScenarios: config.holdoutScenarios,\n maxEpochs: config.maxEpochs ?? 6,\n runDir: `${config.runDir}/${slug(name)}-loop`,\n ...(config.seed !== undefined ? { seed: config.seed } : {}),\n })\n return {\n winnerSurface: result.winnerSurface,\n costUsd: result.totalCostUsd,\n durationMs: Date.now() - started,\n }\n },\n }\n}\n","/**\n * @experimental\n *\n * `runProfileMatrix` — the missing keystone between `runAgentMatrix` and the\n * backend-integrity guard.\n *\n * The gap it closes: `runAgentMatrix` is a topology-opaque scheduler whose\n * cells return a bare `{ output, verdict, costUsd }` — no `tokenUsage`, not a\n * `RunRecord`. `assertRealBackend` / `summarizeBackendIntegrity` key on\n * `RunRecord.tokenUsage`, so they cannot run on a raw matrix result. Every\n * consumer therefore hand-writes the same bridge: fan a profile × scenario\n * cartesian, call dispatch, fabricate a `RunRecord` with token usage, thread it\n * back, run the integrity guard. That hand-rolled bridge is exactly the pile of\n * bespoke `eval:*` scripts the adoption skills keep trying (and failing) to\n * forbid.\n *\n * `runProfileMatrix` IS that bridge, once:\n *\n * - axis 3 (PROFILE) = `profiles: AgentProfile[]`\n * - axis 1 (PERSONA/SCENARIO) = `scenarios: Scenario[]` (each scenario carries\n * its persona; `personaOf` groups them for the `byPersona` pivot)\n * - the scoring axis = `judges`\n *\n * It runs `runCampaign` once per profile (reusing its seeds, reps, bootstrap\n * CIs, resumability, and the `LabeledScenarioStore` capture flywheel), maps\n * every cell to a validated `RunRecord` carrying the real `tokenUsage` the\n * dispatch reported via `ctx.cost.observeTokens`, and runs `assertRealBackend`\n * BY CONSTRUCTION before returning — so a stub-backend run fails loudly instead\n * of reporting a clean 0/N leaderboard.\n *\n * Dispatch contract: a dispatch that calls an LLM MUST report usage via\n * `ctx.cost.observeTokens({ input, output })` (and cost via `ctx.cost.observe`).\n * A dispatch that reports zero tokens is indistinguishable from a stub and the\n * integrity guard treats it as one.\n */\n\nimport { createHash } from 'node:crypto'\nimport { join } from 'node:path'\nimport { type AgentProfile, agentProfileHash } from '../../agent-profile'\nimport { AgentEvalError } from '../../errors'\nimport {\n assertRealBackend,\n type BackendIntegrityReport,\n summarizeBackendIntegrity,\n} from '../../integrity/backend-integrity'\nimport { estimateCost, isModelPriced } from '../../metrics'\nimport {\n type RunOutcome,\n type RunRecord,\n type RunSplitTag,\n validateRunRecord,\n} from '../../run-record'\nimport { runCampaign } from '../run-campaign'\nimport type { CampaignStorage } from '../storage'\nimport type {\n CampaignCellResult,\n CampaignResult,\n DispatchContext,\n JudgeConfig,\n LabeledScenarioSource,\n LabeledScenarioStore,\n Scenario,\n} from '../types'\n\n/** Thrown when the matrix is misconfigured (no profiles, a profile whose model\n * lacks a snapshot version, etc.). Distinct from `BackendIntegrityError`,\n * which signals a stub backend at run time. */\nexport class ProfileMatrixError extends AgentEvalError {\n constructor(message: string) {\n super('profile_matrix', message)\n }\n}\n\n/** Dispatch for one cell: render `profile` against `scenario`, returning the\n * artifact the judges score. Report LLM usage via `ctx.cost.observeTokens`\n * and `ctx.cost.observe` — the integrity guard depends on it. */\nexport type ProfileDispatchFn<TScenario extends Scenario, TArtifact> = (\n profile: AgentProfile,\n scenario: TScenario,\n ctx: DispatchContext,\n) => Promise<TArtifact>\n\nexport interface RunProfileMatrixOptions<TScenario extends Scenario, TArtifact> {\n /** Axis 3 — the agent-under-test configurations. Each is one column. */\n profiles: AgentProfile[]\n /** Axis 1 — the persona/scenario corpus, run against every profile. */\n scenarios: TScenario[]\n /** Renders one (profile, scenario) cell. */\n dispatch: ProfileDispatchFn<TScenario, TArtifact>\n /** The scoring axis. */\n judges?: JudgeConfig<TArtifact, TScenario>[]\n /** Where each profile's campaign writes artifacts/traces. One subdir per\n * profile. */\n runDir: string\n /** Git SHA the harness ran from — stamped onto every RunRecord (mandatory\n * for paper-grade records). */\n commitSha: string\n /** Logical experiment id shared across the whole matrix so the promotion\n * gate can pair profiles on matched scenarios. Default: a hash of the\n * profile + scenario ids. */\n experimentId?: string\n /** Which split these runs belong to. Default `'search'`. */\n splitTag?: RunSplitTag\n /** Replicates per (profile, scenario) cell for CI bands. Default 1. */\n reps?: number\n /** Campaign seed (per profile). Default 42. */\n seed?: number\n /**\n * Backend-integrity posture, enforced AFTER the matrix completes:\n * - `'assert'` (default) — throw `BackendIntegrityError` if the run was a\n * stub (and, with `allowMixed:false`, if it was mixed).\n * - `'warn'` — log the verdict but never throw.\n * - `'off'` — skip the guard entirely (only for offline/replay analysis).\n */\n integrity?: 'assert' | 'warn' | 'off'\n /** Forwarded to `assertRealBackend`. Default true (tolerate partial 429\n * cascades); set false for strict CI gates. */\n allowMixed?: boolean\n /** Max concurrent cells WITHIN each profile's campaign. Default 2.\n * Profiles run sequentially so the cost ceiling is honored deterministically. */\n maxConcurrency?: number\n /** Cumulative USD cap per profile campaign. */\n costCeiling?: number\n /** Capture flywheel — forwarded to each campaign. */\n labeledStore?: LabeledScenarioStore | 'off'\n captureSource?: LabeledScenarioSource\n /** Storage backend. Default `fsCampaignStorage`. Pass\n * `inMemoryCampaignStorage()` for edge/CF-Worker/test runs. */\n storage?: CampaignStorage\n /** Test seam — override the wall clock. */\n now?: () => Date\n /** Optional persona key per scenario — drives the `byPersona` pivot. When\n * unset, `byPersona` is omitted. */\n personaOf?: (scenario: TScenario) => string\n /** Validate every produced RunRecord with `validateRunRecord` (fail-loud).\n * Default true — catches bad model snapshots and non-finite judge dims at\n * the boundary instead of letting them poison downstream analysis. */\n validate?: boolean\n /** Corpus-by-default: derive the trajectory text (`prompt` + `completion`)\n * for each cell from its artifact + scenario. When set, every produced\n * record carries `prompt`/`completion` (a `CorpusRecord`) so the run's\n * graded trajectories can be appended to the durable RL corpus with no\n * side-channel — `appendToCorpus(result.records, path)`. Fail-soft: a\n * throwing or undefined-returning extractor just omits the text. */\n corpusText?: (\n artifact: TArtifact,\n scenario: TScenario,\n ) => { prompt: string; completion: string } | undefined\n}\n\nexport interface ProfileSummary {\n profileId: string\n profileHash: string\n model: string\n /** RunRecords produced for this profile (= scenarios × reps). */\n records: number\n /** Mean composite across this profile's records. */\n meanComposite: number\n totalCostUsd: number\n /** Per-profile integrity verdict — surfaces a single profile that ran stub\n * even when the matrix as a whole looks real. */\n integrity: BackendIntegrityReport\n}\n\nexport interface ScenarioRollup {\n meanComposite: number\n n: number\n}\n\nexport interface RunProfileMatrixResult<TArtifact, TScenario extends Scenario> {\n matrixId: string\n experimentId: string\n /** One RunRecord per (profile, scenario, rep) cell — the integrity-checked,\n * paper-grade output. Feed straight into `analyzeRuns`, `HeldOutGate`,\n * scorecards, the hosted wire format. */\n records: RunRecord[]\n byProfile: Record<string, ProfileSummary>\n byScenario: Record<string, ScenarioRollup>\n /** Present only when `personaOf` was supplied. */\n byPersona?: Record<string, ScenarioRollup>\n /** Whole-matrix integrity report (the one `integrity:'assert'` enforces). */\n integrity: BackendIntegrityReport\n /** The raw per-profile campaign results, keyed by profile id. */\n campaigns: Record<string, CampaignResult<TArtifact, TScenario>>\n}\n\nfunction sanitize(id: string): string {\n return id.replace(/[^a-zA-Z0-9_-]/g, '_')\n}\n\nfunction sha(input: unknown): string {\n return createHash('sha256').update(JSON.stringify(input)).digest('hex')\n}\n\nfunction mean(xs: number[]): number {\n return xs.length === 0 ? 0 : xs.reduce((a, b) => a + b, 0) / xs.length\n}\n\nfunction cellComposite(cell: CampaignCellResult<unknown>): number {\n const composites = Object.values(cell.judgeScores).map((s) => s.composite)\n return composites.length === 0 ? 0 : mean(composites)\n}\n\ninterface BuildRecordArgs<TScenario extends Scenario, TArtifact> {\n cell: CampaignCellResult<TArtifact>\n profile: AgentProfile\n profileHash: string\n configHash: string\n experimentId: string\n splitTag: RunSplitTag\n commitSha: string\n matrixId: string\n scenario?: TScenario\n corpusText?: (\n artifact: TArtifact,\n scenario: TScenario,\n ) => { prompt: string; completion: string } | undefined\n}\n\nfunction buildRunRecord<TScenario extends Scenario, TArtifact>(\n args: BuildRecordArgs<TScenario, TArtifact>,\n): RunRecord {\n const { cell, profile, profileHash, configHash, experimentId, splitTag, commitSha, matrixId } =\n args\n const composite = cellComposite(cell)\n\n // Flatten judge dimensions (judge-prefixed to avoid collisions) into raw.\n const raw: Record<string, number> = { composite }\n const perJudge: Record<string, Record<string, number>> = {}\n const dimAccum: Record<string, number[]> = {}\n const notes: string[] = []\n for (const [judgeName, js] of Object.entries(cell.judgeScores)) {\n perJudge[judgeName] = { ...js.dimensions }\n for (const [dim, value] of Object.entries(js.dimensions)) {\n raw[`${judgeName}.${dim}`] = value\n dimAccum[dim] ??= []\n dimAccum[dim]!.push(value)\n }\n if (js.notes) notes.push(`${judgeName}: ${js.notes}`)\n }\n const perDimMean: Record<string, number> = {}\n for (const [dim, values] of Object.entries(dimAccum)) perDimMean[dim] = mean(values)\n\n // Cost / efficiency guardrail dimensions — RAW-ONLY. The composite stays the\n // judge objective (anti-Goodhart); these are tracked + dashboarded + carried\n // into the dataset, never optimized. Makes every run multi-dimensional by\n // construction (the cost/tokens/latency the cell already reports). Computed\n // ratios are guarded so a zero-cost stub or zero-quality cell never writes a\n // non-finite value into the raw bag.\n //\n // Cost precedence: source-billed > token-estimated > none. A dispatch path\n // whose provider reports real spend (cell.costUsd > 0) is authoritative. When\n // it reports $0 but tokens actually flowed, the model is unpriced AT THE\n // SOURCE (the sandbox/router can't rate it) — not a free run. We price the\n // measured tokens against the substrate table (real rate × real tokens) and\n // mark cost_estimated=1 so the estimate is never read as a billed number. A\n // model the table also can't rate stays $0 (no fabrication).\n let costUsd = cell.costUsd\n let costEstimated = false\n if (costUsd === 0 && cell.tokenUsage.output > 0 && isModelPriced(profile.model)) {\n costUsd = estimateCost(cell.tokenUsage.input, cell.tokenUsage.output, profile.model)\n costEstimated = costUsd > 0\n }\n raw.cost_usd = costUsd\n raw.cost_estimated = costEstimated ? 1 : 0\n raw.tokens_input = cell.tokenUsage.input\n raw.tokens_output = cell.tokenUsage.output\n if (typeof cell.tokenUsage.cached === 'number') raw.tokens_cached = cell.tokenUsage.cached\n raw.latency_ms = cell.durationMs\n if (costUsd > 0) {\n raw.tokens_per_dollar = (cell.tokenUsage.input + cell.tokenUsage.output) / costUsd\n }\n if (composite > 0.01) raw.cost_per_quality = costUsd / composite\n\n const outcome: RunOutcome =\n splitTag === 'holdout' ? { holdoutScore: composite, raw } : { searchScore: composite, raw }\n if (Object.keys(perJudge).length > 0) {\n outcome.judgeScores = {\n perJudge,\n perDimMean,\n composite,\n ...(notes.length > 0 ? { notes: notes.join(' | ') } : {}),\n }\n }\n\n const record: RunRecord & { prompt?: string; completion?: string } = {\n runId: `${matrixId}:${profile.id}:${cell.cellId}`,\n experimentId,\n candidateId: profile.id,\n seed: cell.seed,\n model: profile.model,\n promptHash: profileHash,\n configHash,\n commitSha,\n wallMs: cell.durationMs,\n costUsd,\n tokenUsage: cell.tokenUsage,\n outcome,\n splitTag,\n scenarioId: cell.scenarioId,\n ...(cell.error ? { failureMode: cell.error } : {}),\n }\n\n // Corpus-by-default: stamp the trajectory text onto the record (CorpusRecord\n // shape — the validator ignores the extra keys) so the run is dataset-able\n // with no side-channel. Fail-soft: a bad extractor never fails the run.\n if (args.corpusText && args.scenario) {\n try {\n const text = args.corpusText(cell.artifact, args.scenario)\n if (text && typeof text.prompt === 'string' && typeof text.completion === 'string') {\n record.prompt = text.prompt\n record.completion = text.completion\n }\n } catch {\n // extractor threw — omit trajectory text, keep the graded record.\n }\n }\n return record\n}\n\nexport async function runProfileMatrix<TScenario extends Scenario, TArtifact>(\n opts: RunProfileMatrixOptions<TScenario, TArtifact>,\n): Promise<RunProfileMatrixResult<TArtifact, TScenario>> {\n if (opts.profiles.length === 0) throw new ProfileMatrixError('profiles must not be empty')\n if (opts.scenarios.length === 0) throw new ProfileMatrixError('scenarios must not be empty')\n\n const splitTag = opts.splitTag ?? 'search'\n const seed = opts.seed ?? 42\n const validate = opts.validate ?? true\n const integrityMode = opts.integrity ?? 'assert'\n const profileIds = opts.profiles.map((p) => p.id)\n const experimentId =\n opts.experimentId ??\n `pm_${sha({ profileIds, scenarios: opts.scenarios.map((s) => s.id) }).slice(0, 16)}`\n const matrixId = `mtx_${sha({ experimentId, profileIds, seed, splitTag }).slice(0, 16)}`\n // Scenario lookup for the corpus-text extractor (records carry trajectory text).\n const scenarioById = new Map(opts.scenarios.map((s) => [s.id, s]))\n\n // Preflight: every profile must hash (non-empty model) AND its model must\n // carry a snapshot version, BEFORE any LLM spend. A probe record run through\n // validateRunRecord catches both in the exact place they'd otherwise surface\n // far downstream.\n for (const profile of opts.profiles) {\n const profileHash = agentProfileHash(profile)\n try {\n validateRunRecord({\n runId: `${matrixId}:${profile.id}:probe`,\n experimentId,\n candidateId: profile.id,\n seed,\n model: profile.model,\n promptHash: profileHash,\n configHash: profileHash,\n commitSha: opts.commitSha,\n wallMs: 0,\n costUsd: 0,\n tokenUsage: { input: 0, output: 0 },\n outcome:\n splitTag === 'holdout' ? { holdoutScore: 0, raw: {} } : { searchScore: 0, raw: {} },\n splitTag,\n })\n } catch (err) {\n throw new ProfileMatrixError(\n `profile '${profile.id}' is not recordable: ${err instanceof Error ? err.message : String(err)}`,\n )\n }\n }\n\n const records: RunRecord[] = []\n const campaigns: Record<string, CampaignResult<TArtifact, TScenario>> = {}\n const byProfile: Record<string, ProfileSummary> = {}\n\n for (const profile of opts.profiles) {\n const profileHash = agentProfileHash(profile)\n const configHash = sha({\n profile: profileHash,\n judges: (opts.judges ?? []).map((j) => j.name),\n seed,\n splitTag,\n })\n\n // Bind the profile into a campaign dispatch. Name it so the campaign's\n // manifest hash is stable + distinct per profile.\n const dispatch = (scenario: TScenario, ctx: DispatchContext): Promise<TArtifact> =>\n opts.dispatch(profile, scenario, ctx)\n Object.defineProperty(dispatch, 'name', { value: `profile_${sanitize(profile.id)}` })\n\n const campaign = await runCampaign<TScenario, TArtifact>({\n scenarios: opts.scenarios,\n dispatch,\n judges: opts.judges,\n seed,\n reps: opts.reps,\n maxConcurrency: opts.maxConcurrency,\n costCeiling: opts.costCeiling,\n labeledStore: opts.labeledStore,\n captureSource: opts.captureSource,\n storage: opts.storage,\n now: opts.now,\n runDir: join(opts.runDir, sanitize(profile.id)),\n })\n\n const profileRecords: RunRecord[] = []\n for (const cell of campaign.cells) {\n const record = buildRunRecord({\n cell,\n profile,\n profileHash,\n configHash,\n experimentId,\n splitTag,\n commitSha: opts.commitSha,\n matrixId,\n scenario: scenarioById.get(cell.scenarioId),\n corpusText: opts.corpusText,\n })\n if (validate) validateRunRecord(record)\n profileRecords.push(record)\n records.push(record)\n }\n\n // Effective cost = billed-or-priced. buildRunRecord prices the measured\n // tokens when the source reports $0 for a model it can't rate (and leaves\n // billed cost untouched otherwise), so the RunRecords are the model-aware\n // authority. Surface that same total on campaigns[id] — runCampaign's own\n // ledger only sees ctx.cost ($0 for an unpriced-at-source model), which\n // would otherwise disagree with byProfile + integrity for the same run.\n const pricedTotalCostUsd = profileRecords.reduce((a, r) => a + r.costUsd, 0)\n campaigns[profile.id] = {\n ...campaign,\n aggregates: { ...campaign.aggregates, totalCostUsd: pricedTotalCostUsd },\n }\n\n byProfile[profile.id] = {\n profileId: profile.id,\n profileHash,\n model: profile.model,\n records: profileRecords.length,\n meanComposite: mean(profileRecords.map(compositeOf)),\n totalCostUsd: pricedTotalCostUsd,\n integrity: summarizeBackendIntegrity(profileRecords),\n }\n }\n\n // Integrity by construction — the whole point of the primitive.\n const integrity = summarizeBackendIntegrity(records)\n if (integrityMode === 'assert') {\n assertRealBackend(records, { allowMixed: opts.allowMixed ?? true })\n } else if (integrityMode === 'warn' && integrity.verdict !== 'real') {\n // eslint-disable-next-line no-console\n console.warn(\n `[runProfileMatrix] backend integrity: ${integrity.verdict} — ${integrity.diagnosis}`,\n )\n }\n\n // Pivots.\n const byScenario = rollup(records, (r) => r.scenarioId)\n const byPersona = opts.personaOf\n ? rollupByPersona(records, opts.scenarios, opts.personaOf)\n : undefined\n\n return { matrixId, experimentId, records, byProfile, byScenario, byPersona, integrity, campaigns }\n}\n\n/** Composite for a produced RunRecord (the split score it carries). */\nfunction compositeOf(r: RunRecord): number {\n return r.outcome.holdoutScore ?? r.outcome.searchScore ?? 0\n}\n\nfunction rollup(\n records: RunRecord[],\n keyOf: (r: RunRecord) => string | undefined,\n): Record<string, ScenarioRollup> {\n const groups = new Map<string, number[]>()\n for (const r of records) {\n const key = keyOf(r)\n if (key === undefined) continue\n const arr = groups.get(key) ?? []\n arr.push(compositeOf(r))\n groups.set(key, arr)\n }\n const out: Record<string, ScenarioRollup> = {}\n for (const [key, xs] of groups) out[key] = { meanComposite: mean(xs), n: xs.length }\n return out\n}\n\nfunction rollupByPersona<TScenario extends Scenario>(\n records: RunRecord[],\n scenarios: TScenario[],\n personaOf: (s: TScenario) => string,\n): Record<string, ScenarioRollup> {\n const personaByScenarioId = new Map<string, string>()\n for (const s of scenarios) personaByScenarioId.set(s.id, personaOf(s))\n return rollup(records, (r) => (r.scenarioId ? personaByScenarioId.get(r.scenarioId) : undefined))\n}\n","/**\n * @experimental\n *\n * VCS-pluggable worktree adapter. One improvement = one worktree, PR-like\n * (multiple commits allowed). A code-tier driver's `propose()` creates a\n * worktree, an agent commits the change into it, and `finalize()` returns a\n * `CodeSurface{ worktreeRef }` the measurement checks out to run the worker\n * against the changed code. On promotion the worktree becomes the PR branch.\n *\n * The interface is VCS-agnostic so a future `jj` ([jj-vcs](https://github.com/jj-vcs/jj))\n * adapter can slot in without touching driver code. Only the git adapter\n * ships today. See `docs/design/self-improvement-engine.md`.\n */\n\nimport { execFileSync } from 'node:child_process'\nimport { existsSync } from 'node:fs'\nimport { basename, isAbsolute, join } from 'node:path'\nimport type { CodeSurface } from '../types'\n\nexport interface Worktree {\n /** Absolute path to the checked-out worktree directory. */\n path: string\n /** The branch the worktree is on (becomes the PR branch on promotion). */\n branch: string\n /** The ref the worktree was forked from. */\n baseRef: string\n}\n\nexport interface WorktreeAdapter {\n /** Create an isolated worktree on a fresh branch off `baseRef`. */\n create(opts: { baseRef: string; label: string }): Promise<Worktree>\n /** Commit any pending changes in the worktree, then return a CodeSurface\n * pointing at it. The agent has already written its change into\n * `worktree.path` by the time this is called. */\n finalize(worktree: Worktree, summary: string): Promise<CodeSurface>\n /** Remove the worktree (and its branch) — called for losing candidates. */\n discard(worktree: Worktree): Promise<void>\n}\n\nexport class WorktreeAdapterError extends Error {\n constructor(\n message: string,\n readonly cause?: unknown,\n ) {\n super(message)\n this.name = 'WorktreeAdapterError'\n }\n}\n\nexport interface GitWorktreeAdapterOptions {\n /** Repo root the worktrees fork from. */\n repoRoot: string\n /** Directory worktrees are created under. Default: `<repoRoot>/.worktrees`. */\n worktreeDir?: string\n /** Branch-name prefix. Default: `improve`. */\n branchPrefix?: string\n /** Test seam — defaults to a real `git` runner. */\n git?: (args: string[], cwd: string) => string\n}\n\nfunction defaultGit(args: string[], cwd: string): string {\n try {\n return execFileSync('git', args, { cwd, encoding: 'utf8' }).trim()\n } catch (err) {\n const stderr =\n err && typeof err === 'object' && 'stderr' in err\n ? String((err as { stderr: unknown }).stderr)\n : ''\n throw new WorktreeAdapterError(`git ${args.join(' ')} failed: ${stderr || String(err)}`, err)\n }\n}\n\n/** Slugify a label into a branch-safe segment. */\nfunction slug(label: string): string {\n return (\n label\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '')\n .slice(0, 48) || 'candidate'\n )\n}\n\nexport function gitWorktreeAdapter(opts: GitWorktreeAdapterOptions): WorktreeAdapter {\n const git = opts.git ?? defaultGit\n const worktreeDir = opts.worktreeDir ?? join(opts.repoRoot, '.worktrees')\n const branchPrefix = opts.branchPrefix ?? 'improve'\n\n return {\n async create({ baseRef, label }) {\n const id = `${slug(label)}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 6)}`\n const branch = `${branchPrefix}/${id}`\n const path = join(worktreeDir, id)\n git(['worktree', 'add', '-b', branch, path, baseRef], opts.repoRoot)\n return { path, branch, baseRef }\n },\n\n async finalize(worktree, summary) {\n // Stage + commit any pending changes the agent left in the worktree.\n // A no-op commit is refused by git, so only commit when the tree is dirty.\n const status = git(['status', '--porcelain'], worktree.path)\n if (status.length > 0) {\n git(['add', '-A'], worktree.path)\n git(['commit', '-m', summary], worktree.path)\n }\n return {\n kind: 'code',\n worktreeRef: worktree.path,\n baseRef: worktree.baseRef,\n summary,\n }\n },\n\n async discard(worktree) {\n // Remove the worktree, then delete its branch. Force-remove because the\n // worktree may hold uncommitted experiment state we're discarding.\n git(['worktree', 'remove', '--force', worktree.path], opts.repoRoot)\n git(['branch', '-D', worktree.branch], opts.repoRoot)\n },\n }\n}\n\n/** Resolve a `CodeSurface`'s worktreeRef to a directory the measurement can\n * run the worker in. A path ref is returned as-is; anything else is treated\n * as a ref under the adapter's worktree dir. */\nexport function resolveWorktreePath(surface: CodeSurface, worktreeDir?: string): string {\n if (isAbsolute(surface.worktreeRef) && existsSync(surface.worktreeRef)) return surface.worktreeRef\n if (worktreeDir) return join(worktreeDir, basename(surface.worktreeRef))\n return surface.worktreeRef\n}\n"],"mappings":"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","names":["createHash","join","createHash","mean","join","existsSync","join","slug"]}
1
+ {"version":3,"sources":["../../src/campaign/analyst-surface.ts","../../src/campaign/drivers/_findings-text.ts","../../src/campaign/drivers/ace.ts","../../src/campaign/drivers/guide.ts","../../src/campaign/drivers/halo.ts","../../src/campaign/drivers/memory.ts","../../src/campaign/skill-patch.ts","../../src/campaign/drivers/skill-opt.ts","../../src/campaign/drivers/trace-analyst.ts","../../src/campaign/labeled-store/fs-adapter.ts","../../src/campaign/presets/run-skill-opt.ts","../../src/campaign/presets/compare-drivers.ts","../../src/campaign/presets/playback.ts","../../src/campaign/presets/run-profile-matrix.ts","../../src/campaign/worktree/index.ts"],"sourcesContent":["/**\n * @experimental\n *\n * Make the trace-analyst's OWN prompt a GEPA-optimizable surface.\n *\n * The analyst that drives self-improvement is itself a prompt — and a\n * hand-tuned one (a hardcoded, hand-versioned `const`). This module lets the\n * loop optimize it: the analyst `actorDescription` becomes a `MutableSurface`\n * that `gepaDriver` / `haloDriver` / any `ImprovementDriver` can mutate inside\n * `runImprovementLoop` or `compareDrivers`. That is the second-order loop —\n * optimizing the optimizer's eyes, not just the agent's prompt.\n *\n * Two pieces, both deliberately small (the loop engine already exists — this\n * only supplies the analyst-shaped dispatch + an objective scorer):\n *\n * - `buildAnalystSurfaceDispatch` — `dispatchWithSurface(surface, scenario)`\n * runs `analyzeTraces` with `surface` as the actorDescription over the\n * scenario's fixed trace corpus, returning its findings.\n * - `failureModeRecallJudge` — a DETERMINISTIC judge (no LLM, no opinion)\n * that scores those findings against the scenario's GROUND-TRUTH failure\n * modes. This is what keeps optimizing the analyst prompt ungameable: the\n * labels come from objective signal (e.g. AppWorld `world.evaluate()` tells\n * us which task failed and which API calls were wrong), so we reward an\n * analyst for surfacing the failures that really happened — not for\n * pleasing a judge that could be talked into anything (Goodhart).\n *\n * Wiring (the loop is unchanged; you only pass these in):\n *\n * const dispatchWithSurface = buildAnalystSurfaceDispatch({ analystOptions: { ai } })\n * await runImprovementLoop({\n * baselineSurface: TRACE_ANALYST_ACTOR_DESCRIPTION, // the prompt under optimization\n * scenarios: trainScenarios, // labeled trace corpora\n * holdoutScenarios: heldOutScenarios,\n * dispatchWithSurface,\n * judges: [failureModeRecallJudge()],\n * driver: gepaDriver({ baseUrl, apiKey }),\n * gate: heldOutGate({ minDelta: 0.02 }),\n * autoOnPromote: 'none',\n * })\n */\n\nimport type {\n AnalyzeTracesInput,\n AnalyzeTracesOptions,\n AnalyzeTracesResult,\n} from '../trace-analyst/analyst'\nimport { analyzeTraces } from '../trace-analyst/analyst'\nimport type { DispatchContext, JudgeConfig, MutableSurface, Scenario } from './types'\n\n/**\n * A labeled trace scenario: a FIXED trace corpus plus the failure modes a\n * competent analyst MUST surface from it. The labels are ground truth — the\n * objective failures that actually occurred — which is what makes optimizing\n * the analyst prompt against them meaningful rather than circular.\n */\nexport interface AnalystScenario extends Scenario {\n kind: 'analyst-surface'\n /** OTLP-JSONL path or an in-memory store of the traces to analyze. */\n source: AnalyzeTracesOptions['source']\n /** The domain question handed to the analyst (framing lives here, not in\n * the surface under optimization). */\n question: string\n /**\n * Ground-truth failure modes a good analyst must identify. A finding \"hits\"\n * a mode when it contains ANY of the mode's case-insensitive cues. Derive\n * these from objective signal (failed task + which step broke), never from\n * the analyst's own prior output.\n */\n expectedFailureModes: Array<{ id: string; cues: string[] }>\n /**\n * Cues that mark a finding as HALLUCINATED / out-of-scope for this corpus —\n * naming a tool, error, or failure that did not occur. Presence penalizes\n * precision. Optional; omit to score recall only.\n */\n forbiddenCues?: string[]\n}\n\n/** The analyst's output for one scenario — the artifact the judge scores. */\nexport interface AnalystArtifact {\n answer: string\n findings: string[]\n /** The hardcoded-prompt version the analyst reported (provenance only; the\n * optimized surface overrides the actual prompt text used). */\n actorPromptVersion: string\n}\n\nexport interface BuildAnalystSurfaceDispatchOptions {\n /**\n * Everything `analyzeTraces` needs EXCEPT `actorDescription` (supplied by the\n * surface under optimization) and `source` (supplied by the scenario). `ai`\n * (the AxAIService) is required for a live run.\n */\n analystOptions: Omit<AnalyzeTracesOptions, 'actorDescription' | 'source'>\n /** Test seam: defaults to the real `analyzeTraces`. */\n analyze?: (\n input: AnalyzeTracesInput,\n options: AnalyzeTracesOptions,\n ) => Promise<AnalyzeTracesResult>\n}\n\nfunction surfaceToText(surface: MutableSurface): string {\n if (typeof surface === 'string') return surface\n // A code-tier surface can't be an analyst prompt — fail loud rather than\n // silently analyzing with an empty actorDescription.\n throw new Error(\n 'buildAnalystSurfaceDispatch: the analyst surface must be a string actorDescription, ' +\n `got a ${surface.kind}-tier surface (${surface.worktreeRef}). The analyst prompt is prompt-tier.`,\n )\n}\n\n/**\n * Build the `dispatchWithSurface(surface, scenario, ctx)` the improvement loop\n * calls: run the analyst with `surface` as its actorDescription over the\n * scenario's trace corpus and return its findings.\n */\nexport function buildAnalystSurfaceDispatch(\n opts: BuildAnalystSurfaceDispatchOptions,\n): (\n surface: MutableSurface,\n scenario: AnalystScenario,\n ctx: DispatchContext,\n) => Promise<AnalystArtifact> {\n const analyze = opts.analyze ?? analyzeTraces\n return async (surface, scenario, _ctx) => {\n const actorDescription = surfaceToText(surface)\n const res = await analyze(\n { question: scenario.question },\n { ...opts.analystOptions, actorDescription, source: scenario.source },\n )\n return {\n answer: res.answer,\n findings: res.findings,\n actorPromptVersion: res.actorPromptVersion,\n }\n }\n}\n\nexport interface FailureModeRecallJudgeOptions {\n /** Weight on recall when precision is also scored (forbiddenCues present).\n * Default 0.5 (equal). Recall-only when no forbiddenCues exist. */\n recallWeight?: number\n}\n\n/**\n * Deterministic, ground-truth judge for analyst findings. Composite =\n * recall of the scenario's `expectedFailureModes` (optionally blended with a\n * precision term that penalizes findings tripping `forbiddenCues`). No LLM —\n * the score is a function of the labels, so the analyst prompt is optimized\n * toward surfacing real failures, not toward a judge it can flatter.\n */\nexport function failureModeRecallJudge(\n opts: FailureModeRecallJudgeOptions = {},\n): JudgeConfig<AnalystArtifact, AnalystScenario> {\n const recallWeight = opts.recallWeight ?? 0.5\n return {\n name: 'failure-mode-recall',\n dimensions: [\n { key: 'recall', description: 'fraction of ground-truth failure modes the analyst surfaced' },\n {\n key: 'precision',\n description:\n '1 − share of findings that named a failure/tool/error absent from this corpus',\n },\n ],\n appliesTo: (s) => s.kind === 'analyst-surface',\n score({ artifact, scenario }) {\n const modes = scenario.expectedFailureModes\n if (modes.length === 0) {\n throw new Error(\n `failureModeRecallJudge: scenario '${scenario.id}' has no expectedFailureModes — refusing to score (a vacuous 1.0 would corrupt the comparison)`,\n )\n }\n const hay = artifact.findings.join('\\n').toLowerCase()\n const matched = modes.filter((m) => m.cues.some((c) => hay.includes(c.toLowerCase())))\n const recall = matched.length / modes.length\n\n const forbidden = (scenario.forbiddenCues ?? []).map((c) => c.toLowerCase())\n let precision = 1\n let hallucinated = 0\n if (forbidden.length > 0) {\n const denom = Math.max(1, artifact.findings.length)\n hallucinated = artifact.findings.filter((f) =>\n forbidden.some((c) => f.toLowerCase().includes(c)),\n ).length\n precision = 1 - hallucinated / denom\n }\n\n const composite =\n forbidden.length > 0 ? recallWeight * recall + (1 - recallWeight) * precision : recall\n const missed = modes.filter((m) => !matched.includes(m)).map((m) => m.id)\n const notes =\n `matched ${matched.length}/${modes.length} failure modes` +\n (missed.length ? `; missed [${missed.join(', ')}]` : '') +\n (hallucinated ? `; ${hallucinated} out-of-corpus finding(s)` : '')\n return { dimensions: { recall, precision }, composite, notes }\n },\n }\n}\n","/**\n * Shared finding→text helpers for the curator-style drivers (`memoryCurationDriver`\n * dedup-and-replace, `aceDriver` append-mostly). One copy so the two drivers\n * extract lessons + normalize keys identically and cannot drift apart.\n */\n\nimport type { MutableSurface } from '../types'\n\n/** A finding can be a raw string or a structured analyst finding. Pulls the\n * most actionable text (recommended_action > claim > lesson > text > message). */\nexport function findingToLesson(f: unknown): string | null {\n if (typeof f === 'string') return f.trim() || null\n if (f && typeof f === 'object') {\n const o = f as Record<string, unknown>\n const cand = o.recommended_action ?? o.claim ?? o.lesson ?? o.text ?? o.message\n if (typeof cand === 'string' && cand.trim()) return cand.trim()\n }\n return null\n}\n\n/** Normalize for dedup/idempotency: lowercase, collapse whitespace, strip\n * trailing punctuation. */\nexport function normKey(s: string): string {\n return s\n .toLowerCase()\n .replace(/\\s+/g, ' ')\n .replace(/[.;:!?\\s]+$/, '')\n .trim()\n}\n\n/** Curator drivers are prompt-tier — they manage a text block in the surface.\n * A code-tier surface has no prompt to append to; fail loud rather than\n * silently coercing. */\nexport function surfaceToText(surface: MutableSurface): string {\n if (typeof surface === 'string') return surface\n throw new Error(\n `curator driver: surface must be a string prompt, got a ${surface.kind}-tier surface (${surface.worktreeRef}) — curation is prompt-tier`,\n )\n}\n","/**\n * @experimental\n *\n * `aceDriver` — Agentic Context Engineering: an APPEND-MOSTLY curator, the\n * deliberate contrast to `memoryCurationDriver`'s dedup-and-replace. ACE's\n * thesis (arXiv:2510.04618) is that aggressively deduping/rewriting a context\n * causes \"context collapse\" — hard-won specific lessons get summarized away. So\n * the playbook GROWS by appending each generation's new lessons as provenance-\n * tagged delta bullets; existing bullets are preserved verbatim, never merged.\n *\n * Each generation it:\n * 1. reads the playbook block already in the parent surface (verbatim);\n * 2. turns this generation's `findings` into lessons, keeping only the ones not\n * already present (idempotency — a recurring finding is not re-appended, but\n * a genuinely NEW lesson always is, even if similar to an old one);\n * 3. appends the new lessons as `- [gN] <lesson>` deltas and re-emits the block.\n *\n * Bounded WITHOUT collapse: when the playbook exceeds `maxEntries`, the OLDEST\n * deltas are evicted (FIFO) — recency is kept, but no two distinct lessons are\n * ever merged into one. Deterministic (no LLM) so a lift is attributable to the\n * accumulated lessons, not a rewrite's model noise.\n *\n * Fail-loud: with no new lesson this generation it returns NO candidate (the\n * playbook is unchanged — nothing to propose), never a fabricated bullet.\n */\n\nimport type { ImprovementDriver, ProposeContext, ProposedCandidate } from '../types'\nimport { findingToLesson, normKey, surfaceToText } from './_findings-text'\n\nconst BLOCK_START = '<!-- BEGIN ace-playbook (auto-managed by aceDriver) -->'\nconst BLOCK_END = '<!-- END ace-playbook -->'\nconst DEFAULT_HEADING = '## Playbook (accumulated lessons — append-only)'\n\nexport interface AceDriverOptions {\n /** Max delta bullets retained in the playbook. On overflow the OLDEST are\n * evicted (FIFO) — never merged. Default 50 (ACE keeps a long context). */\n maxEntries?: number\n /** Heading rendered above the bullets inside the block. */\n sectionHeading?: string\n}\n\ninterface Bullet {\n /** Generation tag the lesson was first appended at. */\n gen: number\n text: string\n}\n\n/** Parse the existing playbook block into bullets, preserving order + tags. A\n * bullet line is `- [gN] <text>`; an untagged `- <text>` is tolerated (gen -1). */\nfunction parsePlaybook(surface: string): Bullet[] {\n const start = surface.indexOf(BLOCK_START)\n const end = surface.indexOf(BLOCK_END)\n if (start === -1 || end === -1 || end < start) return []\n const body = surface.slice(start + BLOCK_START.length, end)\n const out: Bullet[] = []\n for (const raw of body.split('\\n')) {\n const line = raw.trim()\n if (!line.startsWith('- ')) continue\n const item = line.slice(2).trim()\n const tag = /^\\[g(-?\\d+)\\]\\s*(.*)$/.exec(item)\n if (tag) out.push({ gen: Number(tag[1]), text: tag[2]!.trim() })\n else out.push({ gen: -1, text: item })\n }\n return out\n}\n\n/** Strip the playbook block (and surrounding blank lines) so it can be re-emitted. */\nfunction stripBlock(surface: string): string {\n const start = surface.indexOf(BLOCK_START)\n const end = surface.indexOf(BLOCK_END)\n if (start === -1 || end === -1 || end < start) return surface.trimEnd()\n return (surface.slice(0, start) + surface.slice(end + BLOCK_END.length)).trimEnd()\n}\n\nexport function aceDriver(opts: AceDriverOptions = {}): ImprovementDriver {\n const maxEntries = opts.maxEntries ?? 50\n if (maxEntries < 1) throw new Error('aceDriver: maxEntries must be >= 1')\n const heading = opts.sectionHeading ?? DEFAULT_HEADING\n\n return {\n kind: 'ace',\n async propose(ctx: ProposeContext): Promise<ProposedCandidate[]> {\n const parent = surfaceToText(ctx.currentSurface)\n const existing = parsePlaybook(parent)\n const seen = new Set(existing.map((b) => normKey(b.text)))\n\n // New lessons from this generation's findings — only those not already in\n // the playbook (idempotent; a recurring finding never duplicates a bullet).\n const fresh: Bullet[] = []\n for (const f of ctx.findings ?? []) {\n const lesson = findingToLesson(f)\n if (!lesson) continue\n const k = normKey(lesson)\n if (!k || seen.has(k)) continue\n seen.add(k)\n fresh.push({ gen: ctx.generation, text: lesson })\n }\n\n // Nothing genuinely new ⇒ the playbook is unchanged ⇒ no candidate.\n if (fresh.length === 0) return []\n\n // Append (preserving existing verbatim), then FIFO-evict the oldest on\n // overflow — recency kept, distinct lessons never merged.\n const all = [...existing, ...fresh].slice(-maxEntries)\n const block = [\n BLOCK_START,\n heading,\n ...all.map((b) => `- [g${b.gen}] ${b.text}`),\n BLOCK_END,\n ].join('\\n')\n const base = stripBlock(parent)\n const surface = base ? `${base}\\n\\n${block}` : block\n\n return [\n {\n surface,\n label: `ace-playbook +${fresh.length}`,\n rationale: `appended ${fresh.length} new lesson(s) from gen ${ctx.generation} findings (playbook now ${all.length} bullet(s), append-only)`,\n },\n ]\n },\n }\n}\n","/**\n * Driver selection guide — \"which `ImprovementDriver` do I pick, and why?\"\n *\n * The substrate ships seven drivers with overlapping shapes. This is the\n * decision table (data, not behavior): each entry says what a driver mutates,\n * how it proposes changes, when to reach for it, and its relative cost.\n * `selectDriver()` turns a goal + surface into a ranked recommendation.\n *\n * Import the actual driver functions from `@tangle-network/agent-eval/campaign`\n * (gepaDriver, skillOptDriver, aceDriver, memoryCurationDriver, haloDriver,\n * traceAnalystDriver, evolutionaryDriver); this module only helps you choose.\n */\n\nexport type DriverName =\n | 'gepa'\n | 'skillOpt'\n | 'ace'\n | 'memoryCuration'\n | 'halo'\n | 'traceAnalyst'\n | 'evolutionary'\n\n/** The mutable surface a driver targets. */\nexport type DriverSurface = 'prompt' | 'skill-doc' | 'playbook' | 'memory' | 'any'\n\n/** How a driver turns evidence into the next candidate. */\nexport type DriverStrategy =\n | 'reflective-rewrite'\n | 'anchored-patch'\n | 'append-only'\n | 'dedup-curate'\n | 'analysis-edit'\n | 'population-mutate'\n\n/** What a caller is trying to do this run. */\nexport type DriverGoal = 'explore' | 'refine' | 'accumulate' | 'benchmark'\n\nexport interface DriverGuideEntry {\n /** One-line description of the mechanism. */\n summary: string\n /** The surface the driver edits. */\n surface: DriverSurface\n /** How it proposes the next candidate. */\n strategy: DriverStrategy\n /** When to reach for this driver. */\n whenUse: string\n /** Relative LLM cost per generation. */\n cost: 'low' | 'medium' | 'high'\n /** True when the driver shells out to an external engine (extra setup). */\n external?: boolean\n}\n\nexport const DRIVER_GUIDE: Record<DriverName, DriverGuideEntry> = {\n gepa: {\n summary:\n 'Reflective full-surface rewrite: reflects on the best parent’s weakest dimensions + per-scenario scores, proposes targeted rewrites, maintains a Pareto frontier across generations.',\n surface: 'prompt',\n strategy: 'reflective-rewrite',\n whenUse:\n 'The default for a prompt/instruction surface with headroom — broad rewrites plus Pareto-optimal exploration across scenarios.',\n cost: 'medium',\n },\n skillOpt: {\n summary:\n 'Patch-mode: bounded, anchored add/delete/replace edits to ONE skill document, so a good rule introduced earlier is not clobbered by a later sweeping rewrite.',\n surface: 'skill-doc',\n strategy: 'anchored-patch',\n whenUse:\n 'Refining a skill document incrementally where accumulated rules must be preserved; the edit budget is the \"textual learning rate\".',\n cost: 'medium',\n },\n ace: {\n summary:\n 'Append-mostly playbook curator: grows the playbook with provenance-tagged delta bullets, never merging — guards against context collapse.',\n surface: 'playbook',\n strategy: 'append-only',\n whenUse:\n 'Accumulating many specific, hard-won lessons over time where dedup/rewrite would summarize away detail.',\n cost: 'low',\n },\n memoryCuration: {\n summary:\n 'Dedup-and-rank curator: builds a compact searchable memory and grafts the most relevant, most-recurrent lessons onto the surface.',\n surface: 'memory',\n strategy: 'dedup-curate',\n whenUse:\n 'Accumulating lessons while keeping the surface compact — the complement to ace when context size matters more than verbatim provenance.',\n cost: 'low',\n },\n halo: {\n summary:\n 'Wraps the real external HALO engine (Inference.net, `halo` CLI) and applies its findings to the prompt via one LLM edit.',\n surface: 'prompt',\n strategy: 'analysis-edit',\n whenUse:\n 'Benchmarking: compete HALO head-to-head against our own analysis on identical traces via compareDrivers.',\n cost: 'high',\n external: true,\n },\n traceAnalyst: {\n summary:\n 'Wraps agent-eval’s own trace-analyst engine and applies its findings to the prompt via one identical LLM edit — the symmetric opponent to haloDriver.',\n surface: 'prompt',\n strategy: 'analysis-edit',\n whenUse:\n 'Benchmarking our trace-analyst’s analysis quality against HALO (analysis-quality head-to-head), or improving from a real OTLP trace corpus.',\n cost: 'high',\n },\n evolutionary: {\n summary:\n 'Adapts a stateless Mutator (population mutate → measure → select); no generation memory beyond the current surface.',\n surface: 'any',\n strategy: 'population-mutate',\n whenUse:\n 'Blind population search when you have a Mutator and don’t need reflective reasoning over findings.',\n cost: 'medium',\n },\n}\n\n/** Goal → drivers, in preference order. The first match is the default pick. */\nconst GOAL_RANK: Record<DriverGoal, DriverName[]> = {\n explore: ['gepa', 'evolutionary'],\n refine: ['skillOpt', 'gepa'],\n accumulate: ['ace', 'memoryCuration'],\n benchmark: ['traceAnalyst', 'halo'],\n}\n\nexport interface SelectDriverCriteria {\n /** What you're trying to do this run. */\n goal: DriverGoal\n /** Restrict to drivers that edit this surface (optional). */\n surface?: DriverSurface\n}\n\nexport interface DriverRecommendation {\n name: DriverName\n entry: DriverGuideEntry\n reason: string\n}\n\n/**\n * Rank the drivers for a goal (and optional surface filter), best first.\n * Returns the recommendation list, not instances — import the chosen driver\n * function yourself. Always returns at least the goal's primary driver.\n */\nexport function selectDriver(criteria: SelectDriverCriteria): DriverRecommendation[] {\n const ranked = GOAL_RANK[criteria.goal]\n const out: DriverRecommendation[] = []\n for (const name of ranked) {\n const entry = DRIVER_GUIDE[name]\n if (criteria.surface && criteria.surface !== 'any' && entry.surface !== criteria.surface)\n continue\n out.push({\n name,\n entry,\n reason: `${criteria.goal}: ${entry.strategy} on the ${entry.surface} surface — ${entry.whenUse}`,\n })\n }\n // Surface filter can empty a goal's list; fall back to every driver on that\n // surface so the caller always gets an actionable answer, never an empty pick.\n if (out.length === 0 && criteria.surface) {\n for (const name of Object.keys(DRIVER_GUIDE) as DriverName[]) {\n const entry = DRIVER_GUIDE[name]\n if (entry.surface === criteria.surface || entry.surface === 'any') {\n out.push({ name, entry, reason: `surface match (${entry.surface}): ${entry.whenUse}` })\n }\n }\n }\n return out\n}\n","/**\n * @experimental\n *\n * `haloDriver` — wraps the REAL halo-engine (Inference.net's hierarchical\n * agentic trace analyzer, `pip install halo-engine`, repo context-labs/halo)\n * as an agent-eval `ImprovementDriver`, so HALO competes head-to-head with\n * `gepaDriver` — and with our own `traceAnalystDriver` — inside\n * `compareDrivers` on identical traces / scenarios / held-out scoring.\n *\n * It PRESERVES halo's actual working usage — `propose()` shells out to the\n * published CLI (`halo <traces.jsonl> -p <prompt> -m <model> --base-url\n * --api-key`) and uses its real RLM findings verbatim. We do NOT reimplement\n * its analysis; that would make the benchmark meaningless. The only adaptation\n * is applying HALO's findings to the current prompt surface via one LLM edit —\n * exactly what makes the comparison prompt-tier apples-to-apples with\n * `gepaDriver` (which also mutates the prompt). The analysis is HALO's; only\n * the surface-application is ours, and it is identical in spirit to how HALO's\n * own loop feeds findings to a coding agent.\n *\n * Fail-loud: no traces → throw; halo errors → throw; empty findings → throw.\n * Never fabricate a candidate (that would silently flatter or penalize HALO).\n */\n\nimport { execFile } from 'node:child_process'\nimport { mkdtempSync, writeFileSync } from 'node:fs'\nimport { tmpdir } from 'node:os'\nimport { join } from 'node:path'\nimport { promisify } from 'node:util'\nimport type { LlmClientOptions } from '../../llm-client'\nimport { callLlm } from '../../llm-client'\nimport type { ImprovementDriver, ProposeContext, ProposedCandidate } from '../types'\n\nconst execFileAsync = promisify(execFile)\n\nexport interface HaloDriverOptions {\n /** OpenAI-compatible base URL for BOTH halo's RLM analysis and the apply\n * step (e.g. the Tangle router `https://router.tangle.tools/v1`). */\n baseUrl: string\n /** Bearer key (else relies on OPENAI_API_KEY in the env halo inherits). */\n apiKey?: string\n /** Model for halo's `--model` (its RLM). Default 'gpt-5.4-mini' (halo's own default). */\n model?: string\n /** Model used to APPLY halo's findings to the prompt surface. Default = `model`. */\n applyModel?: string\n /** The real halo binary. Default 'halo' (from `pip install halo-engine`). */\n haloBin?: string\n /**\n * Resolve the OTLP traces (JSONL string) halo should analyze for THIS\n * generation — wired by the bench to the captured AppWorld OTLP for the\n * current surface. Returning empty throws (halo has nothing to analyze).\n */\n resolveTraces: (ctx: ProposeContext) => string | Promise<string>\n /** halo's analysis prompt (`-p`). Default targets the failure taxonomy. */\n analysisPrompt?: string\n /** halo `--max-depth` / `--max-turns` passthrough. */\n maxDepth?: number\n maxTurns?: number\n /** Test seam: inject a fetch for the apply-step callLlm (no network in unit tests). */\n fetchImpl?: LlmClientOptions['fetch']\n}\n\nconst DEFAULT_ANALYSIS_PROMPT =\n 'Diagnose the failures in these agent execution traces — hallucinated tool calls, redundant tool arguments, refusal loops, and semantic-correctness errors — and suggest concrete, generalizable fixes to the agent instructions.'\n\nconst APPLY_SYSTEM =\n 'You apply a trace-analysis report to an agent instruction prompt. Output ONLY the full revised prompt — no preamble, no commentary, no code fences. Make the minimal edits that address the report findings; preserve everything else verbatim.'\n\n/** Wrap the real halo-engine CLI as an ImprovementDriver (prompt-tier). */\nexport function haloDriver(opts: HaloDriverOptions): ImprovementDriver {\n const haloBin = opts.haloBin ?? 'halo'\n const model = opts.model ?? 'gpt-5.4-mini'\n return {\n kind: 'halo',\n async propose(ctx: ProposeContext): Promise<ProposedCandidate[]> {\n const parent =\n typeof ctx.currentSurface === 'string'\n ? ctx.currentSurface\n : JSON.stringify(ctx.currentSurface)\n\n // (1) Materialize the OTLP traces this generation produced.\n const traces = (await opts.resolveTraces(ctx)) ?? ''\n if (!traces.trim()) {\n throw new Error(\n 'haloDriver: resolveTraces returned no OTLP traces — the halo engine has nothing to analyze',\n )\n }\n const dir = mkdtempSync(join(tmpdir(), 'halo-driver-'))\n const tracePath = join(dir, 'traces.jsonl')\n writeFileSync(tracePath, traces.endsWith('\\n') ? traces : `${traces}\\n`)\n\n // (2) Run the REAL halo-engine on the traces (its published CLI).\n // The published halo-engine reads the base URL + key from the env\n // (OPENAI_BASE_URL / OPENAI_API_KEY, set below) — it has no --base-url /\n // --api-key flags. Pass only the flags the CLI actually exposes.\n const args = [\n tracePath,\n '-p',\n opts.analysisPrompt ?? DEFAULT_ANALYSIS_PROMPT,\n '-m',\n model,\n ...(opts.maxDepth !== undefined ? ['--max-depth', String(opts.maxDepth)] : []),\n ...(opts.maxTurns !== undefined ? ['--max-turns', String(opts.maxTurns)] : []),\n ]\n let findings: string\n try {\n const { stdout } = await execFileAsync(haloBin, args, {\n maxBuffer: 64 * 1024 * 1024,\n signal: ctx.signal,\n env: {\n ...process.env,\n ...(opts.apiKey ? { OPENAI_API_KEY: opts.apiKey } : {}),\n OPENAI_BASE_URL: opts.baseUrl,\n },\n })\n findings = stdout.trim()\n } catch (e) {\n throw new Error(\n `haloDriver: halo-engine ('${haloBin}') failed — ${e instanceof Error ? e.message : String(e)}`,\n )\n }\n if (!findings) throw new Error('haloDriver: halo-engine produced no findings')\n\n // (3) Apply HALO's real findings to the prompt surface (prompt-tier,\n // comparable to gepaDriver). HALO's analysis is preserved verbatim in\n // the rationale for full attribution.\n const applied = await callLlm(\n {\n model: opts.applyModel ?? model,\n messages: [\n { role: 'system', content: APPLY_SYSTEM },\n {\n role: 'user',\n content: `CURRENT PROMPT:\\n${parent}\\n\\nHALO TRACE-ANALYSIS REPORT:\\n${findings}\\n\\nReturn the full revised prompt.`,\n },\n ],\n },\n { baseUrl: opts.baseUrl, apiKey: opts.apiKey, fetch: opts.fetchImpl },\n )\n const text = applied.content.trim()\n if (!text || text === parent) return []\n return [\n {\n surface: text,\n label: 'halo',\n rationale: `halo-engine findings:\\n${findings.slice(0, 800)}`,\n },\n ]\n },\n }\n}\n","/**\n * @experimental\n *\n * `memoryCurationDriver` — a CURATOR `ImprovementDriver`, the complement to the\n * OPTIMIZER drivers (`gepaDriver` rewrites the prompt; this one BUILDS a\n * searchable memory of what prior trajectories taught and grafts the most\n * relevant lessons onto the surface).\n *\n * Each generation it:\n * 1. collects lessons — this generation's trace-analyst `findings` PLUS the\n * memory already carried in the parent surface (so memory accumulates\n * across generations instead of resetting);\n * 2. curates them — normalizes, deduplicates near-identical lessons, and ranks\n * by recurrence (a lesson seen across many findings outranks a one-off);\n * 3. retrieves the top-K and writes them back as a single delimited memory\n * block in the surface (idempotent — the block is replaced, never stacked,\n * so the prompt does not grow without bound).\n *\n * This is the substrate behind the \"knowledge base of working trajectories\" the\n * agent searches: the curated block IS the retrieved memory the next run reads.\n * Curation is DETERMINISTIC (no LLM) so a lift it produces is attributable to\n * the lessons, not to model noise in a rewrite. An optional `distill` LLM step\n * can compress raw findings into crisp imperatives; default is verbatim.\n *\n * Fail-loud: never fabricates a lesson. With no findings and no prior memory it\n * returns no candidate (nothing learned yet — gen 0). It does not throw on an\n * empty generation because early generations legitimately have no findings.\n */\n\nimport { callLlm, type LlmClientOptions } from '../../llm-client'\nimport type { ImprovementDriver, ProposeContext, ProposedCandidate } from '../types'\nimport { findingToLesson, normKey, surfaceToText } from './_findings-text'\n\nconst BLOCK_START = '<!-- BEGIN curated-memory (auto-managed by memoryCurationDriver) -->'\nconst BLOCK_END = '<!-- END curated-memory -->'\n\nexport interface MemoryCurationDriverOptions {\n /** Top-K lessons retained in the surface memory block. Default 12. */\n maxEntries?: number\n /** Heading rendered above the lessons inside the block. Default below. */\n sectionHeading?: string\n /**\n * Optional LLM distillation: compress raw findings into crisp, generalizable\n * one-line imperatives before curating. Omit for verbatim (deterministic).\n */\n distill?: {\n baseUrl: string\n apiKey?: string\n model: string\n fetchImpl?: LlmClientOptions['fetch']\n }\n}\n\nconst DEFAULT_HEADING = '## Learned from prior runs (curated memory)'\n\nconst DISTILL_SYSTEM =\n 'You compress raw trace-analysis findings into crisp, generalizable agent guidance. ' +\n 'Output ONLY a JSON array of strings, each one imperative lesson the agent should follow ' +\n '(e.g. \"Always fetch a resource before mutating it\"). No prose outside the JSON. ' +\n 'Deduplicate; keep the most actionable and general; drop case-specific noise.'\n\n/** Pull the lessons already curated into the parent surface's memory block. */\nfunction extractExistingLessons(text: string): string[] {\n const start = text.indexOf(BLOCK_START)\n const end = text.indexOf(BLOCK_END)\n if (start === -1 || end === -1 || end < start) return []\n return text\n .slice(start + BLOCK_START.length, end)\n .split('\\n')\n .map((l) => l.replace(/^\\s*-\\s+/, '').trim())\n .filter((l) => l && !l.startsWith('#'))\n}\n\n/** Remove the memory block (and surrounding blank lines) so we can re-emit it. */\nfunction stripBlock(text: string): string {\n const start = text.indexOf(BLOCK_START)\n const end = text.indexOf(BLOCK_END)\n if (start === -1 || end === -1 || end < start) return text.trimEnd()\n return (text.slice(0, start) + text.slice(end + BLOCK_END.length)).trimEnd()\n}\n\nasync function distillLessons(\n raw: string[],\n distill: NonNullable<MemoryCurationDriverOptions['distill']>,\n): Promise<string[]> {\n const res = await callLlm(\n {\n model: distill.model,\n messages: [\n { role: 'system', content: DISTILL_SYSTEM },\n { role: 'user', content: `Findings:\\n${raw.map((r) => `- ${r}`).join('\\n')}` },\n ],\n },\n { baseUrl: distill.baseUrl, apiKey: distill.apiKey, fetch: distill.fetchImpl },\n )\n try {\n const parsed = JSON.parse(res.content.trim())\n if (Array.isArray(parsed)) {\n const lessons = parsed.filter(\n (x): x is string => typeof x === 'string' && x.trim().length > 0,\n )\n if (lessons.length > 0) return lessons\n }\n } catch {\n // Distillation is a best-effort refinement; fall back to the verbatim\n // findings rather than dropping real lessons on a malformed LLM reply.\n }\n return raw\n}\n\n/** Build the CURATOR driver. */\nexport function memoryCurationDriver(opts: MemoryCurationDriverOptions = {}): ImprovementDriver {\n const maxEntries = opts.maxEntries ?? 12\n const heading = opts.sectionHeading ?? DEFAULT_HEADING\n return {\n kind: 'memory-curation',\n async propose(ctx: ProposeContext): Promise<ProposedCandidate[]> {\n const parent = surfaceToText(ctx.currentSurface)\n\n // (1) Collect lessons: this generation's findings + memory already in the\n // parent (accumulation across generations).\n const fresh: string[] = []\n for (const f of ctx.findings ?? []) {\n const l = findingToLesson(f)\n if (l) fresh.push(l)\n }\n const carried = extractExistingLessons(parent)\n if (fresh.length === 0 && carried.length === 0) return [] // nothing learned yet\n\n const distilled =\n opts.distill && fresh.length > 0 ? await distillLessons(fresh, opts.distill) : fresh\n\n // (2) Curate: dedup by normalized key, rank by recurrence (carried lessons\n // start with a recurrence prior of 1; each fresh occurrence adds).\n const byKey = new Map<string, { text: string; count: number }>()\n for (const l of carried) {\n const k = normKey(l)\n if (k) byKey.set(k, { text: l, count: 1 })\n }\n for (const l of distilled) {\n const k = normKey(l)\n if (!k) continue\n const e = byKey.get(k)\n if (e) e.count += 1\n else byKey.set(k, { text: l, count: 1 })\n }\n\n // (3) Rank + top-K. Stable: by count desc, then lexicographic for determinism.\n const ranked = [...byKey.values()]\n .sort((a, b) => b.count - a.count || a.text.localeCompare(b.text))\n .slice(0, maxEntries)\n if (ranked.length === 0) return []\n\n const block = [BLOCK_START, heading, ...ranked.map((e) => `- ${e.text}`), BLOCK_END].join(\n '\\n',\n )\n const next = `${stripBlock(parent)}\\n\\n${block}\\n`\n if (next === parent) return [] // no change (same lessons already curated)\n\n return [\n {\n surface: next,\n label: 'memory-curation',\n rationale: `curated ${ranked.length} lessons (from ${fresh.length} new finding(s) + ${carried.length} carried)`,\n },\n ]\n },\n }\n}\n","/**\n * @experimental\n *\n * SkillOpt patch primitives (Microsoft, arXiv:2605.23904 — \"Executive\n * Strategy for Self-Evolving Agent Skills\"). Where GEPA regenerates a surface\n * by reflection, SkillOpt emits BOUNDED, anchored edits to ONE skill document\n * — add / delete / replace — and accepts an edit only if it strictly improves\n * a held-out score. Bounded edits are the \"textual learning rate\": small,\n * reversible, and cheap to accept/reject, so a good rule introduced earlier is\n * not overwritten by a later sweeping rewrite.\n *\n * This module applies a patch deterministically and reports, per op, what\n * applied and what could not (a missing anchor is a rejected op, never a\n * silently dropped one). Pure, no I/O.\n */\n\n/** A single bounded edit against a skill surface.\n * - `add` — insert `text` after the first line containing `after`\n * (append to the end when `after` is absent/empty).\n * - `delete` — remove the first line containing `anchor`.\n * - `replace` — replace the first line containing `anchor` with `text`.\n * `text` may be multi-line; it is spliced in as multiple lines. Anchors match\n * the FIRST line that contains the substring (deterministic; SkillOpt is\n * expected to anchor on unique text). */\nexport type SkillPatchOp =\n | { op: 'add'; after?: string; text: string }\n | { op: 'delete'; anchor: string }\n | { op: 'replace'; anchor: string; text: string }\n\n/** A named, attributable bundle of ops the optimizer proposes as one edit. */\nexport interface SkillPatch {\n label: string\n rationale: string\n ops: SkillPatchOp[]\n}\n\nexport interface SkillPatchRejection {\n op: SkillPatchOp\n reason: string\n}\n\nexport interface ApplySkillPatchResult {\n surface: string\n /** Count of ops that mutated the surface. */\n applied: number\n /** Ops that could not apply (unanchored / empty), with the reason. The\n * surface still reflects every APPLIED op — partial application is honest,\n * and the caller decides whether a partial patch is worth scoring. */\n rejected: SkillPatchRejection[]\n}\n\n/**\n * Apply a SkillOpt patch to a text surface. Ops apply in array order against\n * the evolving line buffer (an `add after X` followed by a `delete X` sees the\n * inserted lines). A missing anchor rejects only that op; the rest still apply.\n */\nexport function applySkillPatch(surface: string, patch: SkillPatch): ApplySkillPatchResult {\n let lines = surface.split('\\n')\n let applied = 0\n const rejected: SkillPatchRejection[] = []\n const findLine = (anchor: string): number => lines.findIndex((l) => l.includes(anchor))\n\n for (const op of patch.ops) {\n if (op.op === 'add') {\n if (typeof op.text !== 'string' || op.text.trim() === '') {\n rejected.push({ op, reason: 'empty add text' })\n continue\n }\n const insert = op.text.split('\\n')\n if (op.after === undefined || op.after === '') {\n lines = [...lines, ...insert]\n applied++\n continue\n }\n const idx = findLine(op.after)\n if (idx === -1) {\n rejected.push({ op, reason: `add anchor not found: ${truncate(op.after)}` })\n continue\n }\n lines = [...lines.slice(0, idx + 1), ...insert, ...lines.slice(idx + 1)]\n applied++\n } else if (op.op === 'delete') {\n const idx = findLine(op.anchor)\n if (idx === -1) {\n rejected.push({ op, reason: `delete anchor not found: ${truncate(op.anchor)}` })\n continue\n }\n lines = [...lines.slice(0, idx), ...lines.slice(idx + 1)]\n applied++\n } else {\n // replace\n const idx = findLine(op.anchor)\n if (idx === -1) {\n rejected.push({ op, reason: `replace anchor not found: ${truncate(op.anchor)}` })\n continue\n }\n if (typeof op.text !== 'string') {\n rejected.push({ op, reason: 'replace text missing' })\n continue\n }\n lines = [...lines.slice(0, idx), ...op.text.split('\\n'), ...lines.slice(idx + 1)]\n applied++\n }\n }\n\n return { surface: lines.join('\\n'), applied, rejected }\n}\n\n/** Total ops in a patch — the edit-budget axis (SkillOpt's \"textual learning\n * rate\" caps this per epoch). */\nexport function patchEditCount(patch: SkillPatch): number {\n return patch.ops.length\n}\n\nfunction truncate(s: string, max = 48): string {\n return s.length <= max ? s : `${s.slice(0, max)}…`\n}\n","/**\n * @experimental\n *\n * `skillOptDriver` — a patch-mode `ImprovementDriver` implementing SkillOpt\n * (Microsoft, arXiv:2605.23904). Where `gepaDriver` regenerates the whole\n * surface by reflection, SkillOpt proposes BOUNDED, anchored edits\n * (add/delete/replace) to ONE skill document, so a good rule introduced\n * earlier is not clobbered by a later sweeping rewrite. The edit budget is the\n * paper's \"textual learning rate\"; a rejected-edit buffer + a slow-update\n * meta-note steer the optimizer away from dead ends.\n *\n * This module is the PROPOSER — the LLM call that turns evidence into\n * structured patches. The accept-only-if-held-out-improves loop, the budget\n * annealing, and the rejected buffer live in the `runSkillOpt` preset, which\n * owns the epoch hill-climb. The driver also conforms to `ImprovementDriver`\n * (`propose` applies its patches to the current surface and returns the\n * candidate surfaces) so it is a drop-in for `runOptimization` and a fair\n * entrant in `compareDrivers`.\n */\n\nimport { callLlm, type LlmClientOptions } from '../../llm-client'\nimport { renderAnalystEvidence } from '../../reflective-mutation'\nimport { applySkillPatch, type SkillPatch, type SkillPatchOp } from '../skill-patch'\nimport type { ImprovementDriver, ProposeContext, ProposedCandidate } from '../types'\n\nconst SKILLOPT_SYSTEM =\n 'You are a SkillOpt optimizer. You improve ONE skill document by proposing ' +\n 'BOUNDED, anchored edits — never a full rewrite. Output ONLY a JSON object of ' +\n 'shape {\"patches\":[{\"label\":string,\"rationale\":string,\"ops\":[op,...]}]} where ' +\n 'each op is one of: {\"op\":\"add\",\"after\":<exact substring of an existing line, ' +\n 'or omit to append>,\"text\":<new line(s)>}, {\"op\":\"delete\",\"anchor\":<exact ' +\n 'substring of the line to remove>}, {\"op\":\"replace\",\"anchor\":<exact substring ' +\n 'of the line to replace>,\"text\":<replacement line(s)>}. Anchors MUST be ' +\n 'verbatim substrings of lines that exist in the document. No prose outside JSON.'\n\n/** Evidence the optimizer reflects on: where the current surface is weakest.\n * Computed by the caller (the preset uses a TRAIN campaign so proposals never\n * see the held-out split; the generic loop derives it from history). */\nexport interface SkillOptEvidence {\n /** Lowest-scoring scenarios (drives WHICH behavior to patch). */\n weakScenarios: Array<{ scenarioId: string; composite: number }>\n /** Lowest-scoring judge dimensions (drives WHAT to patch for). */\n weakDimensions: Array<{ dimension: string; score: number }>\n}\n\n/** A patch that was tried and not accepted — fed back to the model so it does\n * not re-propose a dead end (SkillOpt's rejected-edit buffer). */\nexport interface RejectedEdit {\n label: string\n rationale: string\n reason: string\n}\n\nexport interface ProposePatchesArgs {\n surface: string\n evidence: SkillOptEvidence\n /** Max ops per patch this round (the annealed textual learning rate). */\n editBudget: number\n rejectedBuffer: RejectedEdit[]\n /** Slow-update meta guidance accumulated across epochs. */\n metaNote?: string\n /** Analyst findings + research report rendered as a prompt block (the\n * EYES→HANDS wire) so a patch targets a NAMED diagnosed root cause. Built by\n * the driver from `ctx.findings`/`ctx.report`; the patch-native `runSkillOpt`\n * path may also supply it. */\n findingsNote?: string\n /** How many candidate patches to propose. */\n count: number\n signal: AbortSignal\n}\n\nexport interface SkillOptDriverOptions {\n llm: LlmClientOptions\n model: string\n /** What the skill document governs — orients the prompt. */\n target: string\n /** Default ops-per-patch cap when used as a bare `ImprovementDriver`. The\n * `runSkillOpt` preset overrides this per epoch as it anneals. Default 3. */\n editBudget?: number\n temperature?: number\n maxTokens?: number\n /** Top-K weak scenarios/dimensions surfaced as evidence. Default 3. */\n evidenceK?: number\n}\n\nexport interface SkillOptDriver extends ImprovementDriver {\n /** Patch-native path used by `runSkillOpt` (the SkillOpt epoch loop owns\n * acceptance/budget/buffer). Returns structured patches, NOT surfaces. */\n proposePatches(args: ProposePatchesArgs): Promise<SkillPatch[]>\n}\n\nexport function skillOptDriver(opts: SkillOptDriverOptions): SkillOptDriver {\n const evidenceK = opts.evidenceK ?? 3\n const defaultBudget = opts.editBudget ?? 3\n\n async function proposePatches(args: ProposePatchesArgs): Promise<SkillPatch[]> {\n const userPrompt = buildPatchPrompt({\n target: opts.target,\n surface: args.surface,\n evidence: args.evidence,\n editBudget: args.editBudget,\n rejectedBuffer: args.rejectedBuffer,\n metaNote: args.metaNote,\n findingsNote: args.findingsNote,\n count: args.count,\n })\n const result = await callLlm(\n {\n model: opts.model,\n messages: [\n { role: 'system', content: SKILLOPT_SYSTEM },\n { role: 'user', content: userPrompt },\n ],\n jsonMode: true,\n temperature: opts.temperature ?? 0.6,\n maxTokens: opts.maxTokens ?? 4000,\n },\n opts.llm,\n )\n return parseSkillPatchResponse(result.content, args.count, args.editBudget)\n }\n\n return {\n kind: 'skill-opt',\n proposePatches,\n async propose(ctx: ProposeContext): Promise<ProposedCandidate[]> {\n if (typeof ctx.currentSurface !== 'string') {\n throw new Error(\n 'skillOptDriver: surface must be a string skill document (got a CodeSurface). SkillOpt patches text.',\n )\n }\n const surface = ctx.currentSurface\n const patches = await proposePatches({\n surface,\n evidence: evidenceFromHistory(ctx, evidenceK),\n editBudget: defaultBudget,\n rejectedBuffer: [],\n findingsNote: renderAnalystEvidence(ctx.findings, ctx.report) ?? undefined,\n count: ctx.populationSize,\n signal: ctx.signal,\n })\n const out: ProposedCandidate[] = []\n const seen = new Set<string>()\n for (const patch of patches) {\n const { surface: candidate, applied } = applySkillPatch(surface, patch)\n if (applied === 0 || candidate === surface || seen.has(candidate)) continue\n seen.add(candidate)\n out.push({ surface: candidate, label: patch.label, rationale: patch.rationale })\n if (out.length >= ctx.populationSize) break\n }\n return out\n },\n }\n}\n\n/** Derive evidence from the loop's generation history (generic-driver path):\n * the prior best candidate's worst scenarios + weakest dimensions. Empty on\n * generation 0. */\nfunction evidenceFromHistory(ctx: ProposeContext, k: number): SkillOptEvidence {\n const last = ctx.history.at(-1)\n if (!last || last.candidates.length === 0) return { weakScenarios: [], weakDimensions: [] }\n const best = [...last.candidates].sort((a, b) => b.composite - a.composite)[0]\n if (!best) return { weakScenarios: [], weakDimensions: [] }\n const weakScenarios = [...best.scenarios].sort((a, b) => a.composite - b.composite).slice(0, k)\n const weakDimensions = Object.entries(best.dimensions)\n .sort((a, b) => a[1] - b[1])\n .slice(0, k)\n .map(([dimension, score]) => ({ dimension, score }))\n return { weakScenarios, weakDimensions }\n}\n\nfunction buildPatchPrompt(args: {\n target: string\n surface: string\n evidence: SkillOptEvidence\n editBudget: number\n rejectedBuffer: RejectedEdit[]\n metaNote?: string\n findingsNote?: string\n count: number\n}): string {\n const lines: string[] = [\n `Skill document governs: ${args.target}.`,\n '',\n 'Current skill document:',\n '```',\n args.surface,\n '```',\n '',\n `Propose ${args.count} candidate patch(es). Each patch is a SMALL bundle of`,\n `at most ${args.editBudget} op(s). Anchors must be verbatim substrings of`,\n 'existing lines. Prefer adding a specific missing rule or sharpening a vague',\n 'one over deleting; never rewrite the whole document.',\n ]\n if (args.evidence.weakScenarios.length > 0) {\n lines.push(\n '',\n 'Weakest scenarios (patch to fix these):',\n ...args.evidence.weakScenarios.map((s) => `- ${s.scenarioId} (${s.composite.toFixed(2)})`),\n )\n }\n if (args.evidence.weakDimensions.length > 0) {\n lines.push(\n '',\n 'Weakest dimensions (what to improve):',\n ...args.evidence.weakDimensions.map((d) => `- ${d.dimension} (${d.score.toFixed(2)})`),\n )\n }\n if (args.rejectedBuffer.length > 0) {\n lines.push(\n '',\n 'Already tried and REJECTED (do not repeat or restate these edits):',\n ...args.rejectedBuffer.map((e) => `- ${e.label}: ${e.rationale} — ${e.reason}`),\n )\n }\n if (args.findingsNote) {\n lines.push('', args.findingsNote)\n }\n if (args.metaNote) {\n lines.push('', `Strategy note from prior epochs: ${args.metaNote}`)\n }\n return lines.join('\\n')\n}\n\n/** Parse + validate the patch response. Throws `SkillPatchParseError` when the\n * response is not valid JSON at all (a router/model failure the caller must\n * see — never a silent no-op epoch). Returns `[]` only for the legitimate\n * \"valid JSON, zero usable patches\" case. Malformed ops within a patch are\n * dropped (not silently mutated); each patch is truncated to the edit budget. */\nexport class SkillPatchParseError extends Error {\n constructor(message: string) {\n super(message)\n this.name = 'SkillPatchParseError'\n }\n}\n\nexport function parseSkillPatchResponse(\n raw: string,\n maxPatches: number,\n editBudget: number,\n): SkillPatch[] {\n let text = raw.trim()\n if (text.startsWith('```')) text = text.replace(/^```(?:json)?\\n?/, '').replace(/\\n?```$/, '')\n const start = text.indexOf('{')\n const end = text.lastIndexOf('}')\n if (start < 0 || end <= start) {\n throw new SkillPatchParseError(\n `parseSkillPatchResponse: response was not valid JSON (no object found): ${snippet(raw)}`,\n )\n }\n let parsed: { patches?: unknown }\n try {\n parsed = JSON.parse(text.slice(start, end + 1))\n } catch (err) {\n throw new SkillPatchParseError(\n `parseSkillPatchResponse: response was not valid JSON (${\n err instanceof Error ? err.message : String(err)\n }): ${snippet(raw)}`,\n )\n }\n const rawPatches = Array.isArray(parsed.patches) ? parsed.patches : []\n const out: SkillPatch[] = []\n for (const rp of rawPatches) {\n if (typeof rp !== 'object' || rp === null) continue\n const obj = rp as Record<string, unknown>\n const ops = Array.isArray(obj.ops) ? obj.ops.map(normalizeOp).filter(isOp) : []\n if (ops.length === 0) continue\n out.push({\n label: typeof obj.label === 'string' ? obj.label : 'patch',\n rationale: typeof obj.rationale === 'string' ? obj.rationale : '',\n ops: ops.slice(0, editBudget),\n })\n if (out.length >= maxPatches) break\n }\n return out\n}\n\nfunction normalizeOp(raw: unknown): SkillPatchOp | null {\n if (typeof raw !== 'object' || raw === null) return null\n const o = raw as Record<string, unknown>\n if (o.op === 'add') {\n if (typeof o.text !== 'string') return null\n const op: SkillPatchOp = { op: 'add', text: o.text }\n if (typeof o.after === 'string') op.after = o.after\n return op\n }\n if (o.op === 'delete') {\n if (typeof o.anchor !== 'string') return null\n return { op: 'delete', anchor: o.anchor }\n }\n if (o.op === 'replace') {\n if (typeof o.anchor !== 'string' || typeof o.text !== 'string') return null\n return { op: 'replace', anchor: o.anchor, text: o.text }\n }\n return null\n}\n\nfunction isOp(op: SkillPatchOp | null): op is SkillPatchOp {\n return op !== null\n}\n\nfunction snippet(s: string, max = 120): string {\n const t = s.trim().replace(/\\s+/g, ' ')\n return t.length <= max ? t : `${t.slice(0, max)}…`\n}\n","/**\n * @experimental\n *\n * `traceAnalystDriver` — wraps agent-eval's OWN trace-analyst engine\n * (`AnalystRegistry` over the agentic OTLP reader) as an `ImprovementDriver`.\n * It is the symmetric opponent to `haloDriver`: both consume the SAME OTLP\n * corpus and apply their findings to the prompt surface via one IDENTICAL\n * LLM edit, so a `compareDrivers` lift delta isolates a single variable —\n * ANALYSIS QUALITY. The benchmark answers \"is our HALO clone as good as the\n * real HALO?\" as a held-out lift CI, not a vibe.\n *\n * The fairness contract (the only thing that makes the head-to-head honest):\n * - SAME input: both engines read the identical `traces.jsonl` (haloDriver\n * hands it to the halo CLI; this driver wraps it in an `OtlpFileTraceStore`).\n * - SAME application: the apply-step here is byte-for-byte the apply-step in\n * `haloDriver` (same `APPLY_SYSTEM`, same one-shot `callLlm` prompt edit).\n * - ONLY difference: who produced the findings — the real halo-engine vs our\n * `AnalystRegistry` (whose actor prompt is a near-verbatim port of HALO's).\n *\n * Findings come from the REGISTRY (structured `AnalystFinding[]` carrying\n * area / severity / recommended_action), NOT bare `analyzeTraces` (which emits\n * `string[]`). The registry is the productized engine; raw `analyzeTraces` is\n * the unstructured escape hatch.\n *\n * Fail-loud: no traces → throw; analyst run errors → throw; zero findings →\n * throw. Never fabricate a candidate (that would silently flatter or penalize\n * our engine relative to HALO).\n */\n\nimport { mkdtempSync, writeFileSync } from 'node:fs'\nimport { tmpdir } from 'node:os'\nimport { join } from 'node:path'\nimport { ai } from '@ax-llm/ax'\nimport { createTraceAnalystKind, type TraceAnalystKindSpec } from '../../analyst/kind-factory'\nimport { DEFAULT_TRACE_ANALYST_KINDS } from '../../analyst/kinds'\nimport { AnalystRegistry } from '../../analyst/registry'\nimport type { AnalystFinding } from '../../analyst/types'\nimport type { LlmClientOptions } from '../../llm-client'\nimport { callLlm } from '../../llm-client'\nimport { OtlpFileTraceStore } from '../../trace-analyst/store-otlp'\nimport type { ImprovementDriver, ProposeContext, ProposedCandidate } from '../types'\n\nexport interface TraceAnalystDriverOptions {\n /** OpenAI-compatible base URL for BOTH the analyst's agentic reads and the\n * apply step (e.g. `https://api.deepseek.com/v1` or the Tangle router). */\n baseUrl: string\n /** Bearer key. Required — the Ax AI service has no env fallback here. */\n apiKey: string\n /** Model the analyst kinds use for their agentic trace reads. */\n model: string\n /** Model used to APPLY findings to the prompt surface. Default = `model`.\n * Keep this EQUAL to haloDriver's `applyModel` for an apples-to-apples run. */\n applyModel?: string\n /** Ax provider name. Default 'openai' — works for any OpenAI-compatible base\n * via `apiURL`. Use 'deepseek' to hit DeepSeek's native provider. */\n provider?: string\n /** Which analyst kinds to run. Default = the full shipped suite\n * (`DEFAULT_TRACE_ANALYST_KINDS`: failure-mode, knowledge-gap,\n * knowledge-poisoning, improvement). Narrow it for cost-parity runs. */\n kinds?: readonly TraceAnalystKindSpec[]\n /**\n * Resolve the OTLP traces (JSONL string) the analyst should read for THIS\n * generation — identical contract to `haloDriver.resolveTraces`, wired by\n * the bench to the captured AppWorld OTLP for the current surface. Returning\n * empty throws (the analyst has nothing to read).\n */\n resolveTraces: (ctx: ProposeContext) => string | Promise<string>\n /**\n * Override the findings producer. Default: the shipped `AnalystRegistry`\n * over `kinds`, reading the resolved traces as an `OtlpFileTraceStore`. A\n * consumer may inject a pre-built registry / alternate engine here; the\n * unit suite injects canned findings to exercise the apply path without\n * driving the agentic loop.\n */\n analyze?: (tracePath: string, ctx: ProposeContext) => Promise<ReadonlyArray<AnalystFinding>>\n /** Test seam: inject a fetch for the apply-step `callLlm` (no network in unit tests). */\n fetchImpl?: LlmClientOptions['fetch']\n}\n\nconst APPLY_SYSTEM =\n 'You apply a trace-analysis report to an agent instruction prompt. Output ONLY the full revised prompt — no preamble, no commentary, no code fences. Make the minimal edits that address the report findings; preserve everything else verbatim.'\n\n/** Render structured findings into the same report shape the apply step in\n * `haloDriver` consumes — so the application is identical across engines. */\nfunction renderFindings(findings: ReadonlyArray<AnalystFinding>): string {\n return findings\n .map((f, i) => {\n const action = f.recommended_action ? `\\n FIX: ${f.recommended_action}` : ''\n const subject = f.subject ? ` (${f.subject})` : ''\n return `${i + 1}. [${f.severity}/${f.area}]${subject} ${f.claim}${action}`\n })\n .join('\\n')\n}\n\n/** Wrap agent-eval's trace-analyst registry as an ImprovementDriver (prompt-tier). */\nexport function traceAnalystDriver(opts: TraceAnalystDriverOptions): ImprovementDriver {\n if (!opts.apiKey) throw new Error('traceAnalystDriver: apiKey is required')\n if (!opts.model) throw new Error('traceAnalystDriver: model is required')\n const kinds = opts.kinds ?? DEFAULT_TRACE_ANALYST_KINDS\n return {\n kind: 'trace-analyst',\n async propose(ctx: ProposeContext): Promise<ProposedCandidate[]> {\n const parent =\n typeof ctx.currentSurface === 'string'\n ? ctx.currentSurface\n : JSON.stringify(ctx.currentSurface)\n\n // (1) Materialize the OTLP traces this generation produced — the SAME\n // corpus haloDriver feeds to the halo CLI.\n const traces = (await opts.resolveTraces(ctx)) ?? ''\n if (!traces.trim()) {\n throw new Error(\n 'traceAnalystDriver: resolveTraces returned no OTLP traces — the analyst has nothing to read',\n )\n }\n const dir = mkdtempSync(join(tmpdir(), 'trace-analyst-driver-'))\n const tracePath = join(dir, 'traces.jsonl')\n writeFileSync(tracePath, traces.endsWith('\\n') ? traces : `${traces}\\n`)\n\n // (2) Run OUR trace-analyst engine on the traces (the registry → structured findings).\n const runAnalyze =\n opts.analyze ??\n (async (path: string, c: ProposeContext): Promise<ReadonlyArray<AnalystFinding>> => {\n const aiService = ai({\n name: opts.provider ?? 'openai',\n apiKey: opts.apiKey,\n apiURL: opts.baseUrl,\n config: { model: opts.model },\n })\n const registry = new AnalystRegistry()\n for (const spec of kinds) {\n registry.register(createTraceAnalystKind(spec, { ai: aiService, model: opts.model }))\n }\n const result = await registry.run(\n `trace-analyst-gen-${c.generation}`,\n { traceStore: new OtlpFileTraceStore({ path }) },\n { signal: c.signal },\n )\n return result.findings\n })\n\n let findings: ReadonlyArray<AnalystFinding>\n try {\n findings = await runAnalyze(tracePath, ctx)\n } catch (e) {\n throw new Error(\n `traceAnalystDriver: analyst engine failed — ${e instanceof Error ? e.message : String(e)}`,\n )\n }\n if (findings.length === 0) {\n throw new Error('traceAnalystDriver: analyst engine produced no findings')\n }\n\n // (3) Apply OUR findings to the prompt surface — IDENTICAL apply-step to\n // haloDriver, so a lift delta reflects analysis quality alone.\n const report = renderFindings(findings)\n const applied = await callLlm(\n {\n model: opts.applyModel ?? opts.model,\n messages: [\n { role: 'system', content: APPLY_SYSTEM },\n {\n role: 'user',\n content: `CURRENT PROMPT:\\n${parent}\\n\\nTRACE-ANALYSIS REPORT:\\n${report}\\n\\nReturn the full revised prompt.`,\n },\n ],\n },\n { baseUrl: opts.baseUrl, apiKey: opts.apiKey, fetch: opts.fetchImpl },\n )\n const text = applied.content.trim()\n if (!text || text === parent) return []\n return [\n {\n surface: text,\n label: 'trace-analyst',\n rationale: `trace-analyst findings (${findings.length}):\\n${report.slice(0, 800)}`,\n },\n ]\n },\n }\n}\n","/**\n * @experimental\n *\n * Filesystem `LabeledScenarioStore` adapter. The default capture sink for\n * traces + eval artifacts. Production deployments typically swap for a\n * Turso/SQLite adapter (same interface).\n *\n * Records land as one JSONL file per source under `<root>/<source>.jsonl`.\n * Each line is a `LabeledScenarioRecord`. Append-only — no in-place edits.\n *\n * Safety properties enforced at write-time:\n *\n * - **Provenance required**: writes without `source`, `sourceVersionHash`,\n * `capturedAt`, `redactionStatus` are rejected. Closes the alignment\n * reviewer's data-poisoning gap.\n * - **Per-source rate limits**: optional `rateLimitBucket` + `maxWritesPerMinute`\n * stops a single tenant/source from flooding the store.\n *\n * Safety properties enforced at sample-time:\n *\n * - **Required split + capturedBefore**: substrate refuses to sample without\n * an explicit `split` ('train' | 'test') AND a temporal cutoff. Eliminates\n * accidental train/test contamination.\n * - **Default training-source filter**: when the store is sampled with\n * `split: 'train'`, production-trace records are EXCLUDED unless the\n * caller passes `filter.source: 'production-trace'` explicitly. Closes\n * the contamination-by-default gap flagged by the senior eval engineer.\n */\n\nimport { createHash } from 'node:crypto'\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'\nimport { join } from 'node:path'\nimport type {\n LabeledScenarioRecord,\n LabeledScenarioSampleArgs,\n LabeledScenarioSource,\n LabeledScenarioStore,\n LabeledScenarioWrite,\n LabelTrust,\n} from '../types'\nimport { labelTrustRank } from '../types'\n\nexport interface FsLabeledScenarioStoreOptions {\n /** Root directory for JSONL files. Created if missing. */\n root: string\n /** Per-source rate limit. When set, writes exceeding the cap are rejected\n * with a typed error. Default: no limit. */\n maxWritesPerMinutePerBucket?: number\n /** Test seam — override `Date.now()` for deterministic tests. */\n now?: () => number\n}\n\nexport class LabeledScenarioStoreError extends Error {\n constructor(\n public readonly code: string,\n message: string,\n ) {\n super(message)\n this.name = 'LabeledScenarioStoreError'\n }\n}\n\ninterface RateLimitState {\n bucket: string\n windowStartMs: number\n count: number\n}\n\nexport class FsLabeledScenarioStore implements LabeledScenarioStore {\n private readonly now: () => number\n private readonly rateLimits = new Map<string, RateLimitState>()\n\n constructor(private readonly options: FsLabeledScenarioStoreOptions) {\n if (!existsSync(options.root)) mkdirSync(options.root, { recursive: true })\n this.now = options.now ?? Date.now\n }\n\n async observe(write: LabeledScenarioWrite): Promise<void> {\n this.assertProvenance(write)\n this.assertRateLimit(write)\n const record = this.toRecord(write)\n const path = this.pathForSource(write.source)\n const line = `${JSON.stringify(record)}\\n`\n // Append atomically. For high-throughput a writev-friendly buffered\n // implementation lands in the Turso adapter; FS adapter is for tests +\n // local dev + small workloads.\n appendLine(path, line)\n }\n\n async sample(args: LabeledScenarioSampleArgs): Promise<LabeledScenarioRecord[]> {\n if (!args.split) {\n throw new LabeledScenarioStoreError(\n 'split_required',\n 'sample() requires an explicit `split` (train | test) — substrate refuses ambiguous reads',\n )\n }\n if (!args.capturedBefore) {\n throw new LabeledScenarioStoreError(\n 'capturedBefore_required',\n 'sample() requires an explicit `capturedBefore` timestamp for temporal-split discipline',\n )\n }\n\n const all: LabeledScenarioRecord[] = []\n for (const source of ALL_SOURCES) {\n // Default training-source filter: when sampling train, EXCLUDE\n // production-trace records unless the caller asks for them.\n if (args.split === 'train' && source === 'production-trace') {\n const explicit = sourceFilterContains(args.filter?.source, 'production-trace')\n if (!explicit) continue\n }\n const path = this.pathForSource(source)\n if (!existsSync(path)) continue\n const lines = readFileSync(path, 'utf8').split('\\n').filter(Boolean)\n for (const line of lines) {\n let record: LabeledScenarioRecord\n try {\n record = JSON.parse(line) as LabeledScenarioRecord\n } catch {\n continue\n }\n if (!matchesFilter(record, args, source)) continue\n all.push(record)\n }\n }\n\n // Deterministic order: by capturedAt ascending, then recordHash.\n all.sort((a, b) => {\n if (a.capturedAt !== b.capturedAt) return a.capturedAt.localeCompare(b.capturedAt)\n return a.recordHash.localeCompare(b.recordHash)\n })\n\n return all.slice(0, args.count)\n }\n\n async size(): Promise<{\n train: number\n test: number\n bySource: Record<string, number>\n byTrust: Record<LabelTrust, number>\n }> {\n const bySource: Record<string, number> = {}\n const byTrust: Record<LabelTrust, number> = {\n unverified: 0,\n 'verified-signal': 0,\n 'human-rated': 0,\n }\n let total = 0\n for (const source of ALL_SOURCES) {\n const path = this.pathForSource(source)\n if (!existsSync(path)) {\n bySource[source] = 0\n continue\n }\n const lines = readFileSync(path, 'utf8').split('\\n').filter(Boolean)\n bySource[source] = lines.length\n total += lines.length\n for (const line of lines) {\n let trust: LabelTrust = 'unverified'\n try {\n trust = (JSON.parse(line) as LabeledScenarioRecord).labelTrust ?? 'unverified'\n } catch {\n // A malformed line counts as unverified — never silently gold.\n }\n byTrust[trust] += 1\n }\n }\n // FS adapter doesn't track split assignments per-record (split is\n // computed at sample-time based on `capturedBefore`). For size(), we\n // report `train`+`test` as the same total — split is a sampling concept.\n return { train: total, test: total, bySource, byTrust }\n }\n\n private assertProvenance(write: LabeledScenarioWrite): void {\n if (!write.source) {\n throw new LabeledScenarioStoreError(\n 'missing_source',\n 'LabeledScenarioWrite requires `source`',\n )\n }\n if (!write.sourceVersionHash || write.sourceVersionHash.length === 0) {\n throw new LabeledScenarioStoreError(\n 'missing_source_version',\n 'LabeledScenarioWrite requires `sourceVersionHash` (git sha or substrate version)',\n )\n }\n if (!write.capturedAt) {\n throw new LabeledScenarioStoreError(\n 'missing_captured_at',\n 'LabeledScenarioWrite requires `capturedAt` ISO timestamp',\n )\n }\n if (!write.redactionStatus) {\n throw new LabeledScenarioStoreError(\n 'missing_redaction_status',\n 'LabeledScenarioWrite requires explicit `redactionStatus` — raw / redacted-pii / redacted-secrets / fully-redacted',\n )\n }\n if (!ALL_SOURCES.includes(write.source)) {\n throw new LabeledScenarioStoreError(\n 'unknown_source',\n `LabeledScenarioWrite.source must be one of: ${ALL_SOURCES.join(', ')}`,\n )\n }\n }\n\n private assertRateLimit(write: LabeledScenarioWrite): void {\n const cap = this.options.maxWritesPerMinutePerBucket\n if (!cap || !write.rateLimitBucket) return\n const now = this.now()\n const windowMs = 60_000\n let state = this.rateLimits.get(write.rateLimitBucket)\n if (!state || now - state.windowStartMs >= windowMs) {\n state = { bucket: write.rateLimitBucket, windowStartMs: now, count: 0 }\n this.rateLimits.set(write.rateLimitBucket, state)\n }\n if (state.count >= cap) {\n throw new LabeledScenarioStoreError(\n 'rate_limit_exceeded',\n `LabeledScenarioStore: bucket ${write.rateLimitBucket} exceeded ${cap} writes/min`,\n )\n }\n state.count += 1\n }\n\n private toRecord(write: LabeledScenarioWrite): LabeledScenarioRecord {\n const recordHash = sha256(\n JSON.stringify({\n id: write.scenario.id,\n src: write.source,\n at: write.capturedAt,\n ver: write.sourceVersionHash,\n }),\n )\n // FS adapter assigns split at sample-time, but we cache a hint here\n // based on capturedAt vs the world's \"now\" — sampler overrides this.\n return {\n ...write,\n recordHash,\n split: 'train',\n }\n }\n\n private pathForSource(source: string): string {\n return join(this.options.root, `${source}.jsonl`)\n }\n}\n\nconst ALL_SOURCES: LabeledScenarioWrite['source'][] = [\n 'production-trace',\n 'eval-run',\n 'manual',\n 'red-team',\n 'synthetic',\n]\n\nfunction sourceFilterContains(\n filter: LabeledScenarioSource | LabeledScenarioSource[] | undefined,\n needle: LabeledScenarioSource,\n): boolean {\n if (!filter) return false\n if (Array.isArray(filter)) return filter.includes(needle)\n return filter === needle\n}\n\nfunction matchesFilter(\n record: LabeledScenarioRecord,\n args: LabeledScenarioSampleArgs,\n source: string,\n): boolean {\n // Temporal cutoff — train must be capturedAt < capturedBefore.\n if (args.split === 'train' && record.capturedAt >= args.capturedBefore) return false\n if (args.split === 'test' && record.capturedAt < args.capturedBefore) return false\n\n const f = args.filter\n if (!f) return true\n if (f.kind && record.scenario.kind !== f.kind) return false\n if (f.source) {\n const sources = Array.isArray(f.source) ? f.source : [f.source]\n if (!sources.includes(source as never)) return false\n }\n if (f.minComposite !== undefined || f.maxComposite !== undefined) {\n const composites = Object.values(record.judgeScores).map((s) => s.composite)\n const max = composites.length === 0 ? 0 : Math.max(...composites)\n if (f.minComposite !== undefined && max < f.minComposite) return false\n if (f.maxComposite !== undefined && max > f.maxComposite) return false\n }\n if (f.minTrust !== undefined && labelTrustRank(record.labelTrust) < labelTrustRank(f.minTrust)) {\n return false\n }\n return true\n}\n\nfunction sha256(input: string): string {\n return createHash('sha256').update(input).digest('hex').slice(0, 16)\n}\n\nfunction appendLine(path: string, line: string): void {\n if (existsSync(path)) {\n const existing = readFileSync(path, 'utf8')\n writeFileSync(path, existing + line)\n } else {\n writeFileSync(path, line)\n }\n}\n","/**\n * @experimental\n *\n * `runSkillOpt` — the SkillOpt epoch hill-climb (Microsoft, arXiv:2605.23904).\n * Unlike `runOptimization`'s population/promote-top-K search, SkillOpt is a\n * sequential, held-out-gated hill-climb on ONE skill document:\n *\n * each epoch:\n * 1. reflect on the CURRENT surface's weakest TRAIN scenarios/dimensions\n * (never the held-out split — proposals must not see the acceptance axis)\n * 2. propose ≤ `patchesPerEpoch` bounded patches (≤ `editBudget` ops each)\n * 3. apply each; score the candidate on the HELD-OUT split\n * 4. ACCEPT the first patch that STRICTLY improves the held-out composite;\n * otherwise push it to the rejected-edit buffer (fed back so the model\n * does not re-propose dead ends)\n * 5. anneal the edit budget down after consecutive rejections (the\n * \"textual learning rate\" decay); refresh the slow-update meta note\n * 6. stop at `maxEpochs` or after `patience` epochs with no acceptance\n *\n * The accept-only-if-held-out-improves rule is the same discipline as\n * `HeldOutGate`/`defaultProductionGate`, applied per edit instead of once at\n * the end — which is why the held-out composite is monotonically\n * non-decreasing and a regression can never ship. `runCampaign` is the\n * measurement; `applySkillPatch` applies the edits; `skillOptDriver` proposes\n * them.\n */\n\nimport type { RejectedEdit, SkillOptDriver, SkillOptEvidence } from '../drivers/skill-opt'\nimport { type RunCampaignOptions, runCampaign } from '../run-campaign'\nimport { campaignBreakdown, campaignMeanComposite } from '../score-utils'\nimport { applySkillPatch } from '../skill-patch'\nimport type { CampaignResult, DispatchContext, Scenario } from '../types'\n\nexport interface RunSkillOptOptions<TScenario extends Scenario, TArtifact>\n extends Omit<RunCampaignOptions<TScenario, TArtifact>, 'dispatch' | 'scenarios'> {\n /** The skill document being optimized. */\n baselineSurface: string\n /** Dispatcher taking the CURRENT skill surface + scenario → artifact. */\n dispatchWithSurface: (\n surface: string,\n scenario: TScenario,\n ctx: DispatchContext,\n ) => Promise<TArtifact>\n driver: SkillOptDriver\n /** Scenarios the optimizer reflects on for evidence. MUST be disjoint from\n * `holdoutScenarios` — proposals never see the acceptance axis. */\n trainScenarios: TScenario[]\n /** Held-out scenarios. An edit is accepted ONLY if it strictly improves the\n * mean composite here. */\n holdoutScenarios: TScenario[]\n maxEpochs: number\n /** Candidate patches proposed per epoch. Default 2. */\n patchesPerEpoch?: number\n /** Initial ops-per-patch cap (the textual learning rate). Default 3. */\n editBudget?: number\n /** Strict acceptance margin: accept iff the held-out composite improves by\n * MORE than this. Default 0 (any strict improvement). */\n minImprovement?: number\n /** Stop after this many consecutive epochs with no acceptance. Default =\n * `maxEpochs` (never early-stop). */\n patience?: number\n /** Shrink the edit budget by 1 after 2 consecutive rejected epochs (min 1).\n * Default true. */\n budgetAnneal?: boolean\n /** Cap on the rejected-edit buffer (most-recent kept). Default 12. */\n rejectedBufferSize?: number\n /** Refresh the slow-update meta note every N epochs. Default 2. 0 disables. */\n slowMetaEvery?: number\n /** Top-K weak scenarios/dimensions surfaced as evidence each epoch. Default 3. */\n evidenceK?: number\n /** Abort signal forwarded to the patch-proposing LLM calls. */\n signal?: AbortSignal\n}\n\nexport interface AcceptedEdit {\n epoch: number\n label: string\n rationale: string\n /** Held-out composite improvement vs the surface before this edit. */\n holdoutDelta: number\n}\n\nexport interface SkillOptEpochRecord {\n epoch: number\n editBudget: number\n proposed: number\n /** The accepted edit this epoch, or null if every proposal was rejected. */\n accepted: AcceptedEdit | null\n rejected: RejectedEdit[]\n /** Held-out composite of the CURRENT surface at the END of the epoch. */\n holdoutComposite: number\n}\n\nexport interface RunSkillOptResult {\n winnerSurface: string\n baselineHoldoutComposite: number\n winnerHoldoutComposite: number\n /** `winnerHoldoutComposite - baselineHoldoutComposite` — monotonically ≥ 0\n * by construction (only strictly-improving edits are accepted). */\n lift: number\n acceptedEdits: AcceptedEdit[]\n rejectedEdits: RejectedEdit[]\n epochsRun: number\n history: SkillOptEpochRecord[]\n /** Total cost across every scoring campaign (train evidence + holdout\n * acceptance) the hill-climb ran. */\n totalCostUsd: number\n}\n\nexport async function runSkillOpt<TScenario extends Scenario, TArtifact>(\n opts: RunSkillOptOptions<TScenario, TArtifact>,\n): Promise<RunSkillOptResult> {\n if (opts.trainScenarios.length === 0) throw new Error('runSkillOpt: trainScenarios is empty')\n if (opts.holdoutScenarios.length === 0) throw new Error('runSkillOpt: holdoutScenarios is empty')\n if (!opts.judges || opts.judges.length === 0) {\n throw new Error(\n 'runSkillOpt: at least one judge is required — scoring (and therefore acceptance) is meaningless without one, and would report a silent zero lift.',\n )\n }\n // train ∩ holdout must be empty: proposals reflect on TRAIN evidence, so any\n // overlap leaks the acceptance axis into the proposal (held-out contamination).\n const holdoutIds = new Set(opts.holdoutScenarios.map((s) => s.id))\n const overlap = opts.trainScenarios.filter((s) => holdoutIds.has(s.id)).map((s) => s.id)\n if (overlap.length > 0) {\n throw new Error(\n `runSkillOpt: trainScenarios and holdoutScenarios must be disjoint (overlap: [${overlap.join(\n ', ',\n )}]) — a shared scenario leaks the held-out acceptance axis into the proposal evidence.`,\n )\n }\n\n const patchesPerEpoch = opts.patchesPerEpoch ?? 2\n const initialBudget = opts.editBudget ?? 3\n const minImprovement = opts.minImprovement ?? 0\n if (minImprovement < 0) {\n throw new Error(\n 'runSkillOpt: minImprovement must be >= 0 — a negative threshold would accept held-out regressions, breaking the monotonic-lift contract.',\n )\n }\n const patience = opts.patience ?? opts.maxEpochs\n const budgetAnneal = opts.budgetAnneal ?? true\n const rejectedBufferSize = opts.rejectedBufferSize ?? 12\n const slowMetaEvery = opts.slowMetaEvery ?? 2\n\n let totalCostUsd = 0\n const scoreHoldout = async (surface: string, tag: string): Promise<number> => {\n const campaign = await runScoringCampaign(opts, opts.holdoutScenarios, surface, tag)\n totalCostUsd += campaign.aggregates.totalCostUsd\n return campaignMeanComposite(campaign)\n }\n const evidenceK = opts.evidenceK ?? 3\n const trainEvidence = async (surface: string, tag: string): Promise<SkillOptEvidence> => {\n const campaign = await runScoringCampaign(opts, opts.trainScenarios, surface, tag)\n totalCostUsd += campaign.aggregates.totalCostUsd\n return toEvidence(campaign, evidenceK)\n }\n\n let current = opts.baselineSurface\n let currentEvidence = await trainEvidence(current, 'baseline-train')\n const baselineHoldout = await scoreHoldout(current, 'baseline-holdout')\n let currentHoldout = baselineHoldout\n\n const buffer: RejectedEdit[] = []\n const acceptedEdits: AcceptedEdit[] = []\n const rejectedAll: RejectedEdit[] = []\n const history: SkillOptEpochRecord[] = []\n let budget = initialBudget\n let sinceAccept = 0\n let metaNote: string | undefined\n let epochsRun = 0\n\n for (let epoch = 0; epoch < opts.maxEpochs; epoch++) {\n epochsRun++\n const patches = await opts.driver.proposePatches({\n surface: current,\n evidence: currentEvidence,\n editBudget: budget,\n rejectedBuffer: buffer,\n metaNote,\n count: patchesPerEpoch,\n signal: opts.signal ?? new AbortController().signal,\n })\n\n let accepted: AcceptedEdit | null = null\n const rejectedThisEpoch: RejectedEdit[] = []\n for (let i = 0; i < patches.length; i++) {\n const patch = patches[i]!\n const { surface: candidate, applied } = applySkillPatch(current, patch)\n if (applied === 0 || candidate === current) {\n rejectedThisEpoch.push({\n label: patch.label,\n rationale: patch.rationale,\n reason: 'no-op (unanchored or zero-change)',\n })\n continue\n }\n const candidateHoldout = await scoreHoldout(candidate, `epoch-${epoch}-cand-${i}-holdout`)\n if (candidateHoldout > currentHoldout + minImprovement) {\n accepted = {\n epoch,\n label: patch.label,\n rationale: patch.rationale,\n holdoutDelta: candidateHoldout - currentHoldout,\n }\n current = candidate\n currentHoldout = candidateHoldout\n // The surface changed — recompute evidence for the next epoch from it.\n currentEvidence = await trainEvidence(current, `epoch-${epoch}-train`)\n break // greedy: take the first strictly-improving edit\n }\n rejectedThisEpoch.push({\n label: patch.label,\n rationale: patch.rationale,\n reason: `held-out ${candidateHoldout.toFixed(3)} ≤ current ${currentHoldout.toFixed(3)}`,\n })\n }\n\n if (accepted) {\n acceptedEdits.push(accepted)\n sinceAccept = 0\n } else {\n sinceAccept++\n if (budgetAnneal && sinceAccept >= 2 && budget > 1) budget--\n }\n // Maintain the bounded rejected-edit buffer (steers the proposer away from\n // dead ends; capped so the prompt stays bounded).\n for (const r of rejectedThisEpoch) {\n buffer.push(r)\n rejectedAll.push(r)\n }\n while (buffer.length > rejectedBufferSize) buffer.shift()\n\n // Slow-update meta note: a cross-epoch digest refreshed on a slow cadence.\n if (slowMetaEvery > 0 && (epoch + 1) % slowMetaEvery === 0) {\n metaNote = buildMetaNote(acceptedEdits, buffer)\n }\n\n history.push({\n epoch,\n editBudget: budget,\n proposed: patches.length,\n accepted,\n rejected: rejectedThisEpoch,\n holdoutComposite: currentHoldout,\n })\n\n if (sinceAccept >= patience) break\n }\n\n return {\n winnerSurface: current,\n baselineHoldoutComposite: baselineHoldout,\n winnerHoldoutComposite: currentHoldout,\n lift: currentHoldout - baselineHoldout,\n acceptedEdits,\n rejectedEdits: rejectedAll,\n epochsRun,\n history,\n totalCostUsd,\n }\n}\n\nfunction runScoringCampaign<TScenario extends Scenario, TArtifact>(\n opts: RunSkillOptOptions<TScenario, TArtifact>,\n scenarios: TScenario[],\n surface: string,\n tag: string,\n): Promise<CampaignResult<TArtifact, TScenario>> {\n return runCampaign<TScenario, TArtifact>({\n ...opts,\n scenarios,\n dispatch: (scenario, ctx) => opts.dispatchWithSurface(surface, scenario, ctx),\n runDir: `${opts.runDir}/${tag}`,\n })\n}\n\nfunction toEvidence<TArtifact, TScenario extends Scenario>(\n campaign: CampaignResult<TArtifact, TScenario>,\n k: number,\n): SkillOptEvidence {\n const { dimensions, scenarios } = campaignBreakdown(campaign)\n const weakScenarios = [...scenarios].sort((a, b) => a.composite - b.composite).slice(0, k)\n const weakDimensions = Object.entries(dimensions)\n .sort((a, b) => a[1] - b[1])\n .slice(0, k)\n .map(([dimension, score]) => ({ dimension, score }))\n return { weakScenarios, weakDimensions }\n}\n\nfunction buildMetaNote(accepted: AcceptedEdit[], rejected: RejectedEdit[]): string {\n const parts: string[] = []\n if (accepted.length > 0) {\n parts.push(\n `Edits that improved held-out so far: ${accepted\n .map((a) => `\"${a.label}\" (+${a.holdoutDelta.toFixed(3)})`)\n .join('; ')}. Build on these.`,\n )\n }\n if (rejected.length > 0) {\n const labels = [...new Set(rejected.map((r) => r.label))].slice(0, 5)\n parts.push(`Dead ends to avoid: ${labels.join(', ')}. Try a different anchor or rule.`)\n }\n parts.push('Keep edits small and anchored to existing lines.')\n return parts.join(' ')\n}\n","/**\n * @experimental\n *\n * `compareDrivers` — a head-to-head lift benchmark across optimizer drivers on\n * ONE corpus. This is the forcing function: optimizer quality (GEPA reflection\n * vs GEPA+Pareto vs SkillOpt) becomes a NUMBER with a confidence interval, so a\n * driver regression — or shipping a simplified driver and calling it the real\n * one — turns a build red instead of going measurement-invisible.\n *\n * Every entrant is scored the SAME way: each driver returns the surface it\n * promoted, then `compareDrivers` scores the baseline + every winner on the\n * SAME held-out scenarios with the SAME judges. Apples-to-apples by\n * construction — the comparison never depends on how a driver measured itself.\n * The per-scenario held-out composites feed a paired bootstrap (`statistics.ts`)\n * for each driver's lift CI and for the pairwise \"which driver wins\" CI.\n */\n\nimport type { LlmClientOptions } from '../../llm-client'\nimport { pairedBootstrap } from '../../statistics'\nimport { gepaDriver } from '../drivers/gepa'\nimport { skillOptDriver } from '../drivers/skill-opt'\nimport { defaultProductionGate } from '../gates/default-production-gate'\nimport { type RunCampaignOptions, runCampaign } from '../run-campaign'\nimport { campaignBreakdown } from '../score-utils'\nimport type {\n CampaignResult,\n DispatchContext,\n JudgeConfig,\n MutableSurface,\n Scenario,\n} from '../types'\nimport { type RunImprovementLoopOptions, runImprovementLoop } from './run-improvement-loop'\nimport { runSkillOpt } from './run-skill-opt'\n\n/** What an optimizer produced: the surface it promoted + what it cost to get\n * there. `compareDrivers` does the held-out scoring itself, so an entry only\n * needs to run its loop and hand back the winner. */\nexport interface DriverEntry {\n name: string\n optimize: () => Promise<{ winnerSurface: MutableSurface; costUsd: number; durationMs?: number }>\n}\n\nexport interface DriverScore {\n name: string\n /** Mean held-out composite of the baseline (identical across drivers). */\n baselineComposite: number\n /** Mean held-out composite of this driver's promoted surface. */\n winnerComposite: number\n /** Mean per-scenario held-out lift (winner − baseline). */\n lift: number\n /** Paired-bootstrap CI of the per-scenario lift. `low > 0` ⇒ a real gain. */\n liftCi: { low: number; high: number }\n costUsd: number\n durationMs?: number\n winnerSurface: MutableSurface\n /** 1-based, by descending lift. */\n rank: number\n}\n\nexport interface DriverPairwise {\n /** Higher-ranked driver. */\n a: string\n b: string\n /** Mean per-scenario held-out delta (a − b). */\n deltaMean: number\n low: number\n high: number\n /** `a` if the CI clears 0, `b` if it is entirely negative, else `'tie'`. */\n favored: string\n}\n\nexport interface DriverComparison {\n /** Sorted by descending lift; `rank` set accordingly. */\n scores: DriverScore[]\n best: DriverScore\n /** Best vs each other driver, paired-bootstrap on the held-out winners. */\n pairwise: DriverPairwise[]\n holdoutScenarioIds: string[]\n}\n\nexport interface CompareDriversOptions<TScenario extends Scenario, TArtifact>\n extends Omit<RunCampaignOptions<TScenario, TArtifact>, 'dispatch' | 'scenarios'> {\n drivers: DriverEntry[]\n baselineSurface: MutableSurface\n /** The held-out scenarios every winner is scored on. */\n holdoutScenarios: TScenario[]\n /** Scores a surface on a scenario — the same dispatcher the drivers used. */\n dispatchWithSurface: (\n surface: MutableSurface,\n scenario: TScenario,\n ctx: DispatchContext,\n ) => Promise<TArtifact>\n /** Bootstrap resamples for the lift CIs. Default 2000. */\n resamples?: number\n /** CI confidence. Default 0.95. */\n confidence?: number\n}\n\nexport async function compareDrivers<TScenario extends Scenario, TArtifact>(\n opts: CompareDriversOptions<TScenario, TArtifact>,\n): Promise<DriverComparison> {\n if (opts.drivers.length === 0) throw new Error('compareDrivers: no drivers to compare')\n const seed = opts.seed ?? 42\n const resamples = opts.resamples ?? 2000\n const confidence = opts.confidence ?? 0.95\n\n const scoreOnHoldout = async (\n surface: MutableSurface,\n tag: string,\n ): Promise<Record<string, number>> => {\n const campaign: CampaignResult<TArtifact, TScenario> = await runCampaign<TScenario, TArtifact>({\n ...opts,\n scenarios: opts.holdoutScenarios,\n dispatch: (scenario, ctx) => opts.dispatchWithSurface(surface, scenario, ctx),\n runDir: `${opts.runDir}/${tag}`,\n })\n const byScenario: Record<string, number> = {}\n for (const { scenarioId, composite } of campaignBreakdown(campaign).scenarios) {\n byScenario[scenarioId] = composite\n }\n return byScenario\n }\n\n // The comparison axis is the DESIGNED held-out set, not whatever a campaign\n // happened to score. Align every score vector to it and FAIL LOUD if a\n // surface is missing any scenario (an errored cell / a judge that returned no\n // score). Fabricating a 0 there would silently penalize that surface and\n // corrupt the paired-bootstrap lift CI — the exact \"no silent zeros\" trap.\n const scenarioIds = [...new Set(opts.holdoutScenarios.map((s) => s.id))].sort()\n if (scenarioIds.length === 0) throw new Error('compareDrivers: holdoutScenarios is empty')\n const align = (byScenario: Record<string, number>, label: string): number[] => {\n const missing = scenarioIds.filter((id) => !(id in byScenario))\n if (missing.length > 0) {\n throw new Error(\n `compareDrivers: ${label} produced no held-out score for scenario(s) [${missing.join(\n ', ',\n )}] — a cell errored or its judges returned nothing. Refusing to fabricate a 0 (it would corrupt the lift comparison). Fix the dispatch/judge or drop the scenario.`,\n )\n }\n return scenarioIds.map((id) => byScenario[id]!)\n }\n\n const baselineArr = align(\n await scoreOnHoldout(opts.baselineSurface, 'compare-baseline'),\n 'baseline',\n )\n\n // Run + uniformly re-score every entrant on the SAME held-out axis.\n const winners: Array<{\n name: string\n winnerSurface: MutableSurface\n costUsd: number\n durationMs?: number\n arr: number[]\n }> = []\n for (const d of opts.drivers) {\n const out = await d.optimize()\n const byScenario = await scoreOnHoldout(out.winnerSurface, `compare-${slug(d.name)}`)\n winners.push({\n name: d.name,\n winnerSurface: out.winnerSurface,\n costUsd: out.costUsd,\n durationMs: out.durationMs,\n arr: align(byScenario, `driver \"${d.name}\"`),\n })\n }\n\n const scores: DriverScore[] = winners.map((w) => {\n const boot = pairedBootstrap(baselineArr, w.arr, {\n seed,\n resamples,\n confidence,\n statistic: 'mean',\n })\n const score: DriverScore = {\n name: w.name,\n baselineComposite: mean(baselineArr),\n winnerComposite: mean(w.arr),\n lift: boot.mean,\n liftCi: { low: boot.low, high: boot.high },\n costUsd: w.costUsd,\n winnerSurface: w.winnerSurface,\n rank: 0,\n }\n if (w.durationMs !== undefined) score.durationMs = w.durationMs\n return score\n })\n // Sort by lift; tie-break by lower cost (cheaper wins a tie).\n scores.sort((a, b) => b.lift - a.lift || a.costUsd - b.costUsd)\n scores.forEach((s, i) => {\n s.rank = i + 1\n })\n const best = scores[0]!\n\n const byName = new Map(winners.map((w) => [w.name, w]))\n const bestArr = byName.get(best.name)!.arr\n const pairwise: DriverPairwise[] = scores.slice(1).map((other) => {\n const otherArr = byName.get(other.name)!.arr\n // before = other, after = best ⇒ delta = best − other on the held-out set.\n const boot = pairedBootstrap(otherArr, bestArr, {\n seed,\n resamples,\n confidence,\n statistic: 'mean',\n })\n const favored = boot.low > 0 ? best.name : boot.high < 0 ? other.name : 'tie'\n return {\n a: best.name,\n b: other.name,\n deltaMean: boot.mean,\n low: boot.low,\n high: boot.high,\n favored,\n }\n })\n\n return { scores, best, pairwise, holdoutScenarioIds: scenarioIds }\n}\n\nfunction mean(xs: number[]): number {\n return xs.length === 0 ? 0 : xs.reduce((a, b) => a + b, 0) / xs.length\n}\n\nfunction slug(name: string): string {\n return name.replace(/[^a-z0-9]+/gi, '-').toLowerCase()\n}\n\n// ── Built-in entries — wire the real optimizers for a live comparison ───────\n\n/** Shared corpus + transport for the three built-in optimizer entries. */\nexport interface OptimizerEntryConfig<TScenario extends Scenario, TArtifact> {\n baselineSurface: string\n /** Training scenarios the drivers reflect on. */\n trainScenarios: TScenario[]\n /** Held-out scenarios (the gate axis + the benchmark scoring axis). */\n holdoutScenarios: TScenario[]\n dispatchWithSurface: (\n surface: MutableSurface,\n scenario: TScenario,\n ctx: DispatchContext,\n ) => Promise<TArtifact>\n judges: JudgeConfig<TArtifact, TScenario>[]\n llm: LlmClientOptions\n model: string\n target: string\n runDir: string\n seed?: number\n /** GEPA population per generation. Default 2. */\n populationSize?: number\n /** GEPA generations. Default 3. */\n maxGenerations?: number\n /** SkillOpt epochs. Default 6. */\n maxEpochs?: number\n mutationPrimitives?: string[]\n /** Static findings seed forwarded to each GEPA driver's `propose()` as\n * `ctx.findings` (the EYES→HANDS wire). Forwarded by `gepaReflectionEntry` /\n * `gepaParetoEntry`; `skillOptEntry` runs findings-BLIND (see its doc). */\n findings?: unknown[]\n /** Per-generation findings producer (EYES→HANDS loop closure): after each\n * generation scores, this re-diagnoses and REPLACES `ctx.findings` for the\n * next generation's `propose()`. Reuses the `runOptimization` field type so\n * it cannot drift. GEPA entries only. */\n analyzeGeneration?: RunImprovementLoopOptions<TScenario, TArtifact>['analyzeGeneration']\n /** Phase-2 research report forwarded to `propose()` as `ctx.report`. */\n report?: unknown\n}\n\n/** GEPA, reflection-only (single-parent, no Pareto combine). */\nexport function gepaReflectionEntry<TScenario extends Scenario, TArtifact>(\n config: OptimizerEntryConfig<TScenario, TArtifact>,\n name = 'gepa-reflection',\n): DriverEntry {\n return gepaEntry(config, false, name)\n}\n\n/** GEPA with the Pareto frontier + combine-complementary-lessons. */\nexport function gepaParetoEntry<TScenario extends Scenario, TArtifact>(\n config: OptimizerEntryConfig<TScenario, TArtifact>,\n name = 'gepa-pareto',\n): DriverEntry {\n return gepaEntry(config, true, name)\n}\n\nfunction gepaEntry<TScenario extends Scenario, TArtifact>(\n config: OptimizerEntryConfig<TScenario, TArtifact>,\n combineParents: boolean,\n name: string,\n): DriverEntry {\n return {\n name,\n async optimize() {\n const started = Date.now()\n const driver = gepaDriver({\n llm: config.llm,\n model: config.model,\n target: config.target,\n combineParents,\n ...(config.mutationPrimitives ? { mutationPrimitives: config.mutationPrimitives } : {}),\n })\n const result = await runImprovementLoop<TScenario, TArtifact>({\n scenarios: config.trainScenarios,\n holdoutScenarios: config.holdoutScenarios,\n baselineSurface: config.baselineSurface,\n dispatchWithSurface: config.dispatchWithSurface,\n judges: config.judges,\n driver,\n populationSize: config.populationSize ?? 2,\n maxGenerations: config.maxGenerations ?? 3,\n gate: defaultProductionGate<TArtifact, TScenario>({\n holdoutScenarios: config.holdoutScenarios,\n deltaThreshold: 0,\n }),\n autoOnPromote: 'none',\n runDir: `${config.runDir}/${slug(name)}-loop`,\n ...(config.seed !== undefined ? { seed: config.seed } : {}),\n // EYES→HANDS: flow findings to the driver's propose(). These reach\n // runOptimization unchanged (runImprovementLoop extends RunOptimizationOptions\n // and forwards {...opts}); ctx.findings/report/analyzeGeneration are consumed there.\n ...(config.findings !== undefined ? { findings: config.findings } : {}),\n ...(config.analyzeGeneration ? { analyzeGeneration: config.analyzeGeneration } : {}),\n ...(config.report !== undefined ? { report: config.report } : {}),\n })\n const costUsd =\n result.baselineCampaign.aggregates.totalCostUsd +\n result.generations.reduce(\n (sum, g) =>\n sum + g.surfaces.reduce((s, sf) => s + sf.campaign.aggregates.totalCostUsd, 0),\n 0,\n )\n return { winnerSurface: result.winnerSurface, costUsd, durationMs: Date.now() - started }\n },\n }\n}\n\n/** SkillOpt patch-mode hill-climb. Runs findings-BLIND: `runSkillOpt` owns its\n * own epoch acceptance/budget loop and does not thread `analyzeGeneration`, so\n * `config.findings` is intentionally NOT forwarded here. In a findings-fed\n * comparison this entry is the blind control — do not read its result as\n * findings-fed. (Threading findings into the SkillOpt epoch loop is a separate\n * refactor, deferred not faked.) */\nexport function skillOptEntry<TScenario extends Scenario, TArtifact>(\n config: OptimizerEntryConfig<TScenario, TArtifact>,\n name = 'skill-opt',\n): DriverEntry {\n return {\n name,\n async optimize() {\n const started = Date.now()\n const driver = skillOptDriver({ llm: config.llm, model: config.model, target: config.target })\n const result = await runSkillOpt<TScenario, TArtifact>({\n baselineSurface: config.baselineSurface,\n dispatchWithSurface: config.dispatchWithSurface,\n judges: config.judges,\n driver,\n trainScenarios: config.trainScenarios,\n holdoutScenarios: config.holdoutScenarios,\n maxEpochs: config.maxEpochs ?? 6,\n runDir: `${config.runDir}/${slug(name)}-loop`,\n ...(config.seed !== undefined ? { seed: config.seed } : {}),\n })\n return {\n winnerSurface: result.winnerSurface,\n costUsd: result.totalCostUsd,\n durationMs: Date.now() - started,\n }\n },\n }\n}\n","/**\n * Product-flow playback — drive the REAL product through a user story and\n * score the produced state per requirement (the launch \"Jira tick-off\").\n *\n * This is the substrate adapter + contract only. It plugs a `PlaybackDriver`\n * into the existing `runProfileMatrix` dispatch seam: a driver drives the real\n * product (a Playwright UI session or a sandbox workspace) and returns the\n * runtime event stream; `extractProducedState` + `verifyCompletion` then score\n * each requirement PASS/FAIL. The concrete drivers live in consumers — they\n * depend on browser / runtime infra the substrate must not import — so\n * agent-eval owns the seam, the `UserStory` contract, and the scoreboard.\n */\n\nimport type { AgentProfile } from '../../agent-profile'\nimport {\n type CompletionRequirement,\n type CompletionVerdict,\n type CorrectnessChecker,\n type ProducedState,\n verifyCompletion,\n} from '../../completion-verifier'\nimport { extractProducedState, type RuntimeEventLike } from '../../produced-state'\nimport type { DispatchContext, Scenario } from '../types'\nimport type { ProfileDispatchFn } from './run-profile-matrix'\n\n/** One step of a user story — what the user does. The driver interprets\n * `payload` (a Playwright selector + action, or a sandbox chat turn). */\nexport interface PlaybackStep {\n /** Human-readable action, captured verbatim in the UX narrative. */\n action: string\n /** Driver-specific payload (e.g. `{ selector, fill }` or `{ turn }`). */\n payload?: Record<string, unknown>\n}\n\n/**\n * A user story = a runnable product journey plus the requirements that define\n * \"this story works\". Each requirement is one Jira ticket line. Extends\n * `Scenario` so a catalog drops straight into `runProfileMatrix({ scenarios })`.\n */\nexport interface UserStory extends Scenario {\n /** Human-readable story title (the ticket headline). */\n title: string\n /** Ordered steps the driver executes. */\n steps: PlaybackStep[]\n /** What must hold in the produced state for the story to pass. */\n requirements: CompletionRequirement[]\n}\n\n/** Dispatch context plus the profile under test (which cheap model, etc.). */\nexport interface PlaybackContext extends DispatchContext {\n profile: AgentProfile\n}\n\n/**\n * Drives the real product through a story and returns the runtime event stream\n * `extractProducedState` consumes. Implemented by CONSUMERS —\n * `SandboxPlaybackDriver` (real API / sandbox workspace) and\n * `PlaywrightPlaybackDriver` (real UI) — because they depend on runtime /\n * browser infra the substrate must not import. The driver MUST report LLM\n * usage via `ctx.cost.observeTokens` so the backend-integrity guard sees real\n * tokens (a run that never reports tokens reads as a stub).\n */\nexport interface PlaybackDriver<TStory extends UserStory = UserStory> {\n run(story: TStory, ctx: PlaybackContext): Promise<readonly RuntimeEventLike[]>\n}\n\n/**\n * Adapt a `PlaybackDriver` into a `runProfileMatrix` dispatch. The artifact the\n * matrix scores is the `ProducedState` extracted from the driver's event\n * stream — grade it with `scoreUserStory` (or a judge wrapping it).\n */\nexport function makePlaybackDispatch<TStory extends UserStory>(\n driver: PlaybackDriver<TStory>,\n): ProfileDispatchFn<TStory, ProducedState> {\n return async (profile, scenario, ctx) => {\n const events = await driver.run(scenario, { ...ctx, profile })\n return extractProducedState(events)\n }\n}\n\n/** A scored user story — the completion verdict plus its human title. */\nexport interface UserStoryVerdict extends CompletionVerdict {\n title: string\n}\n\n/**\n * Score one story's produced state against its requirements. Thin wrapper over\n * `verifyCompletion` that builds the gold from the story and returns a\n * per-requirement PASS/FAIL verdict. `checkCorrectness` is injected — a\n * deterministic stub in tests, `createLlmCorrectnessChecker` in production.\n */\nexport async function scoreUserStory(\n story: UserStory,\n state: ProducedState,\n checkCorrectness: CorrectnessChecker,\n): Promise<UserStoryVerdict> {\n const verdict = await verifyCompletion(\n { taskId: story.id, requirements: story.requirements },\n state,\n checkCorrectness,\n )\n return { ...verdict, title: story.title }\n}\n\n/** One row of the launch scoreboard — story × requirement → PASS/FAIL. */\nexport interface ScoreboardRow {\n storyId: string\n storyTitle: string\n reqId: string\n reqTitle: string\n status: 'PASS' | 'FAIL'\n evidence: string[]\n}\n\n/**\n * Flatten story verdicts into the per-requirement scoreboard — the literal\n * Jira tick-off: one row per (story, requirement) with PASS/FAIL and the\n * evidence behind the verdict.\n */\nexport function userStoryScoreboard(verdicts: readonly UserStoryVerdict[]): ScoreboardRow[] {\n const rows: ScoreboardRow[] = []\n for (const v of verdicts) {\n for (const r of v.requirements) {\n rows.push({\n storyId: v.taskId,\n storyTitle: v.title,\n reqId: r.reqId,\n reqTitle: r.title,\n status: r.satisfied ? 'PASS' : 'FAIL',\n evidence: r.evidence,\n })\n }\n }\n return rows\n}\n\n/** Launch-readiness headline counts rolled up from the per-requirement rows. */\nexport interface ScoreboardSummary {\n /** Distinct user stories on the board. */\n stories: number\n /** Stories whose every requirement passed. */\n storiesFullyComplete: number\n /** Total (story, requirement) rows. */\n requirements: number\n /** Rows with status PASS. */\n passed: number\n /** Rows with status FAIL. */\n failed: number\n /** passed / requirements; 0 when there are no rows. */\n passRate: number\n}\n\n/** Roll the per-requirement rows up into the launch headline counts. */\nexport function scoreboardSummary(rows: readonly ScoreboardRow[]): ScoreboardSummary {\n const byStory = new Map<string, { total: number; passed: number }>()\n let passed = 0\n for (const r of rows) {\n const s = byStory.get(r.storyId) ?? { total: 0, passed: 0 }\n s.total++\n if (r.status === 'PASS') {\n s.passed++\n passed++\n }\n byStory.set(r.storyId, s)\n }\n let storiesFullyComplete = 0\n for (const s of byStory.values()) if (s.total > 0 && s.passed === s.total) storiesFullyComplete++\n return {\n stories: byStory.size,\n storiesFullyComplete,\n requirements: rows.length,\n passed,\n failed: rows.length - passed,\n passRate: rows.length === 0 ? 0 : passed / rows.length,\n }\n}\n\nexport interface ScoreboardRenderOptions {\n /** Document H1. Defaults to a generic playback title. */\n title?: string\n /** Key/value run metadata rendered under the headline (runId, backend, model, date). */\n meta?: Record<string, string>\n /** Max chars of joined evidence shown per row. Default 160. */\n maxEvidenceChars?: number\n}\n\nfunction escapeCell(s: string): string {\n return s.replace(/\\|/g, '\\\\|').replace(/\\r?\\n/g, ' ')\n}\n\nfunction truncate(s: string, max: number): string {\n return s.length <= max ? s : `${s.slice(0, Math.max(0, max - 1))}…`\n}\n\n/**\n * Render the scoreboard as a launch-readiness Markdown document — the literal\n * \"tick off every user story\" artifact: a headline roll-up, the open tickets\n * (FAIL rows) up top as the launch blockers, then a per-story table of\n * requirement → PASS/FAIL with the evidence behind each verdict. Pure: same\n * rows in, same bytes out (no clock/random), so it is safe to snapshot.\n */\nexport function renderScoreboardMarkdown(\n rows: readonly ScoreboardRow[],\n opts: ScoreboardRenderOptions = {},\n): string {\n const maxEv = opts.maxEvidenceChars ?? 160\n const sum = scoreboardSummary(rows)\n const pct = (n: number) => `${Math.round(n * 100)}%`\n const ev = (e: string[]) => escapeCell(truncate(e.join('; '), maxEv)) || '—'\n const out: string[] = [`# ${opts.title ?? 'Product-flow playback scoreboard'}`, '']\n if (opts.meta) {\n for (const [k, v] of Object.entries(opts.meta)) out.push(`- **${k}:** ${v}`)\n out.push('')\n }\n out.push(\n `**${sum.storiesFullyComplete}/${sum.stories}** user stories fully shipped · ` +\n `**${sum.passed}/${sum.requirements}** requirements passing (${pct(sum.passRate)}) · ` +\n `**${sum.failed}** open`,\n '',\n )\n const fails = rows.filter((r) => r.status === 'FAIL')\n if (fails.length > 0) {\n out.push('## Open tickets', '', '| Story | Requirement | Evidence |', '| --- | --- | --- |')\n for (const r of fails) {\n out.push(`| ${escapeCell(r.storyTitle)} | ${escapeCell(r.reqTitle)} | ${ev(r.evidence)} |`)\n }\n out.push('')\n } else {\n out.push('_All requirements passing — no open tickets._', '')\n }\n out.push('## Per-story tick-off', '')\n for (const storyId of [...new Set(rows.map((r) => r.storyId))]) {\n const storyRows = rows.filter((r) => r.storyId === storyId)\n const passed = storyRows.filter((r) => r.status === 'PASS').length\n const mark = passed === storyRows.length ? '✅' : '⚠️'\n out.push(\n `### ${escapeCell(storyRows[0]!.storyTitle)} — ${passed}/${storyRows.length} ${mark}`,\n '',\n '| Requirement | Status | Evidence |',\n '| --- | --- | --- |',\n )\n for (const r of storyRows) {\n out.push(\n `| ${escapeCell(r.reqTitle)} | ${r.status === 'PASS' ? '✅ PASS' : '❌ FAIL'} | ${ev(r.evidence)} |`,\n )\n }\n out.push('')\n }\n return out.join('\\n')\n}\n","/**\n * @experimental\n *\n * `runProfileMatrix` — the missing keystone between `runAgentMatrix` and the\n * backend-integrity guard.\n *\n * The gap it closes: `runAgentMatrix` is a topology-opaque scheduler whose\n * cells return a bare `{ output, verdict, costUsd }` — no `tokenUsage`, not a\n * `RunRecord`. `assertRealBackend` / `summarizeBackendIntegrity` key on\n * `RunRecord.tokenUsage`, so they cannot run on a raw matrix result. Every\n * consumer therefore hand-writes the same bridge: fan a profile × scenario\n * cartesian, call dispatch, fabricate a `RunRecord` with token usage, thread it\n * back, run the integrity guard. That hand-rolled bridge is exactly the pile of\n * bespoke `eval:*` scripts the adoption skills keep trying (and failing) to\n * forbid.\n *\n * `runProfileMatrix` IS that bridge, once:\n *\n * - axis 3 (PROFILE) = `profiles: AgentProfile[]`\n * - axis 1 (PERSONA/SCENARIO) = `scenarios: Scenario[]` (each scenario carries\n * its persona; `personaOf` groups them for the `byPersona` pivot)\n * - the scoring axis = `judges`\n *\n * It runs `runCampaign` once per profile (reusing its seeds, reps, bootstrap\n * CIs, resumability, and the `LabeledScenarioStore` capture flywheel), maps\n * every cell to a validated `RunRecord` carrying the real `tokenUsage` the\n * dispatch reported via `ctx.cost.observeTokens`, and runs `assertRealBackend`\n * BY CONSTRUCTION before returning — so a stub-backend run fails loudly instead\n * of reporting a clean 0/N leaderboard.\n *\n * Dispatch contract: a dispatch that calls an LLM MUST report usage via\n * `ctx.cost.observeTokens({ input, output })` (and cost via `ctx.cost.observe`).\n * A dispatch that reports zero tokens is indistinguishable from a stub and the\n * integrity guard treats it as one.\n */\n\nimport { createHash } from 'node:crypto'\nimport { join } from 'node:path'\nimport { type AgentProfile, agentProfileHash } from '../../agent-profile'\nimport { AgentEvalError } from '../../errors'\nimport {\n assertRealBackend,\n type BackendIntegrityReport,\n summarizeBackendIntegrity,\n} from '../../integrity/backend-integrity'\nimport { estimateCost, isModelPriced } from '../../metrics'\nimport {\n type RunOutcome,\n type RunRecord,\n type RunSplitTag,\n validateRunRecord,\n} from '../../run-record'\nimport { runCampaign } from '../run-campaign'\nimport type { CampaignStorage } from '../storage'\nimport type {\n CampaignCellResult,\n CampaignResult,\n DispatchContext,\n JudgeConfig,\n LabeledScenarioSource,\n LabeledScenarioStore,\n Scenario,\n} from '../types'\n\n/** Thrown when the matrix is misconfigured (no profiles, a profile whose model\n * lacks a snapshot version, etc.). Distinct from `BackendIntegrityError`,\n * which signals a stub backend at run time. */\nexport class ProfileMatrixError extends AgentEvalError {\n constructor(message: string) {\n super('profile_matrix', message)\n }\n}\n\n/** Dispatch for one cell: render `profile` against `scenario`, returning the\n * artifact the judges score. Report LLM usage via `ctx.cost.observeTokens`\n * and `ctx.cost.observe` — the integrity guard depends on it. */\nexport type ProfileDispatchFn<TScenario extends Scenario, TArtifact> = (\n profile: AgentProfile,\n scenario: TScenario,\n ctx: DispatchContext,\n) => Promise<TArtifact>\n\nexport interface RunProfileMatrixOptions<TScenario extends Scenario, TArtifact> {\n /** Axis 3 — the agent-under-test configurations. Each is one column. */\n profiles: AgentProfile[]\n /** Axis 1 — the persona/scenario corpus, run against every profile. */\n scenarios: TScenario[]\n /** Renders one (profile, scenario) cell. */\n dispatch: ProfileDispatchFn<TScenario, TArtifact>\n /** The scoring axis. */\n judges?: JudgeConfig<TArtifact, TScenario>[]\n /** Where each profile's campaign writes artifacts/traces. One subdir per\n * profile. */\n runDir: string\n /** Git SHA the harness ran from — stamped onto every RunRecord (mandatory\n * for paper-grade records). */\n commitSha: string\n /** Logical experiment id shared across the whole matrix so the promotion\n * gate can pair profiles on matched scenarios. Default: a hash of the\n * profile + scenario ids. */\n experimentId?: string\n /** Which split these runs belong to. Default `'search'`. */\n splitTag?: RunSplitTag\n /** Replicates per (profile, scenario) cell for CI bands. Default 1. */\n reps?: number\n /** Campaign seed (per profile). Default 42. */\n seed?: number\n /**\n * Backend-integrity posture, enforced AFTER the matrix completes:\n * - `'assert'` (default) — throw `BackendIntegrityError` if the run was a\n * stub (and, with `allowMixed:false`, if it was mixed).\n * - `'warn'` — log the verdict but never throw.\n * - `'off'` — skip the guard entirely (only for offline/replay analysis).\n */\n integrity?: 'assert' | 'warn' | 'off'\n /** Forwarded to `assertRealBackend`. Default true (tolerate partial 429\n * cascades); set false for strict CI gates. */\n allowMixed?: boolean\n /** Max concurrent cells WITHIN each profile's campaign. Default 2.\n * Profiles run sequentially so the cost ceiling is honored deterministically. */\n maxConcurrency?: number\n /** Cumulative USD cap per profile campaign. */\n costCeiling?: number\n /** Capture flywheel — forwarded to each campaign. */\n labeledStore?: LabeledScenarioStore | 'off'\n captureSource?: LabeledScenarioSource\n /** Storage backend. Default `fsCampaignStorage`. Pass\n * `inMemoryCampaignStorage()` for edge/CF-Worker/test runs. */\n storage?: CampaignStorage\n /** Test seam — override the wall clock. */\n now?: () => Date\n /** Optional persona key per scenario — drives the `byPersona` pivot. When\n * unset, `byPersona` is omitted. */\n personaOf?: (scenario: TScenario) => string\n /** Validate every produced RunRecord with `validateRunRecord` (fail-loud).\n * Default true — catches bad model snapshots and non-finite judge dims at\n * the boundary instead of letting them poison downstream analysis. */\n validate?: boolean\n /** Corpus-by-default: derive the trajectory text (`prompt` + `completion`)\n * for each cell from its artifact + scenario. When set, every produced\n * record carries `prompt`/`completion` (a `CorpusRecord`) so the run's\n * graded trajectories can be appended to the durable RL corpus with no\n * side-channel — `appendToCorpus(result.records, path)`. Fail-soft: a\n * throwing or undefined-returning extractor just omits the text. */\n corpusText?: (\n artifact: TArtifact,\n scenario: TScenario,\n ) => { prompt: string; completion: string } | undefined\n}\n\nexport interface ProfileSummary {\n profileId: string\n profileHash: string\n model: string\n /** RunRecords produced for this profile (= scenarios × reps). */\n records: number\n /** Mean composite across this profile's records. */\n meanComposite: number\n totalCostUsd: number\n /** Per-profile integrity verdict — surfaces a single profile that ran stub\n * even when the matrix as a whole looks real. */\n integrity: BackendIntegrityReport\n}\n\nexport interface ScenarioRollup {\n meanComposite: number\n n: number\n}\n\nexport interface RunProfileMatrixResult<TArtifact, TScenario extends Scenario> {\n matrixId: string\n experimentId: string\n /** One RunRecord per (profile, scenario, rep) cell — the integrity-checked,\n * paper-grade output. Feed straight into `analyzeRuns`, `HeldOutGate`,\n * scorecards, the hosted wire format. */\n records: RunRecord[]\n byProfile: Record<string, ProfileSummary>\n byScenario: Record<string, ScenarioRollup>\n /** Present only when `personaOf` was supplied. */\n byPersona?: Record<string, ScenarioRollup>\n /** Whole-matrix integrity report (the one `integrity:'assert'` enforces). */\n integrity: BackendIntegrityReport\n /** The raw per-profile campaign results, keyed by profile id. */\n campaigns: Record<string, CampaignResult<TArtifact, TScenario>>\n}\n\nfunction sanitize(id: string): string {\n return id.replace(/[^a-zA-Z0-9_-]/g, '_')\n}\n\nfunction sha(input: unknown): string {\n return createHash('sha256').update(JSON.stringify(input)).digest('hex')\n}\n\nfunction mean(xs: number[]): number {\n return xs.length === 0 ? 0 : xs.reduce((a, b) => a + b, 0) / xs.length\n}\n\nfunction cellComposite(cell: CampaignCellResult<unknown>): number {\n const composites = Object.values(cell.judgeScores).map((s) => s.composite)\n return composites.length === 0 ? 0 : mean(composites)\n}\n\ninterface BuildRecordArgs<TScenario extends Scenario, TArtifact> {\n cell: CampaignCellResult<TArtifact>\n profile: AgentProfile\n profileHash: string\n configHash: string\n experimentId: string\n splitTag: RunSplitTag\n commitSha: string\n matrixId: string\n scenario?: TScenario\n corpusText?: (\n artifact: TArtifact,\n scenario: TScenario,\n ) => { prompt: string; completion: string } | undefined\n}\n\nfunction buildRunRecord<TScenario extends Scenario, TArtifact>(\n args: BuildRecordArgs<TScenario, TArtifact>,\n): RunRecord {\n const { cell, profile, profileHash, configHash, experimentId, splitTag, commitSha, matrixId } =\n args\n const composite = cellComposite(cell)\n\n // Flatten judge dimensions (judge-prefixed to avoid collisions) into raw.\n const raw: Record<string, number> = { composite }\n const perJudge: Record<string, Record<string, number>> = {}\n const dimAccum: Record<string, number[]> = {}\n const notes: string[] = []\n for (const [judgeName, js] of Object.entries(cell.judgeScores)) {\n perJudge[judgeName] = { ...js.dimensions }\n for (const [dim, value] of Object.entries(js.dimensions)) {\n raw[`${judgeName}.${dim}`] = value\n dimAccum[dim] ??= []\n dimAccum[dim]!.push(value)\n }\n if (js.notes) notes.push(`${judgeName}: ${js.notes}`)\n }\n const perDimMean: Record<string, number> = {}\n for (const [dim, values] of Object.entries(dimAccum)) perDimMean[dim] = mean(values)\n\n // Cost / efficiency guardrail dimensions — RAW-ONLY. The composite stays the\n // judge objective (anti-Goodhart); these are tracked + dashboarded + carried\n // into the dataset, never optimized. Makes every run multi-dimensional by\n // construction (the cost/tokens/latency the cell already reports). Computed\n // ratios are guarded so a zero-cost stub or zero-quality cell never writes a\n // non-finite value into the raw bag.\n //\n // Cost precedence: source-billed > token-estimated > none. A dispatch path\n // whose provider reports real spend (cell.costUsd > 0) is authoritative. When\n // it reports $0 but tokens actually flowed, the model is unpriced AT THE\n // SOURCE (the sandbox/router can't rate it) — not a free run. We price the\n // measured tokens against the substrate table (real rate × real tokens) and\n // mark cost_estimated=1 so the estimate is never read as a billed number. A\n // model the table also can't rate stays $0 (no fabrication).\n let costUsd = cell.costUsd\n let costEstimated = false\n if (costUsd === 0 && cell.tokenUsage.output > 0 && isModelPriced(profile.model)) {\n costUsd = estimateCost(cell.tokenUsage.input, cell.tokenUsage.output, profile.model)\n costEstimated = costUsd > 0\n }\n raw.cost_usd = costUsd\n raw.cost_estimated = costEstimated ? 1 : 0\n raw.tokens_input = cell.tokenUsage.input\n raw.tokens_output = cell.tokenUsage.output\n if (typeof cell.tokenUsage.cached === 'number') raw.tokens_cached = cell.tokenUsage.cached\n raw.latency_ms = cell.durationMs\n if (costUsd > 0) {\n raw.tokens_per_dollar = (cell.tokenUsage.input + cell.tokenUsage.output) / costUsd\n }\n if (composite > 0.01) raw.cost_per_quality = costUsd / composite\n\n const outcome: RunOutcome =\n splitTag === 'holdout' ? { holdoutScore: composite, raw } : { searchScore: composite, raw }\n if (Object.keys(perJudge).length > 0) {\n outcome.judgeScores = {\n perJudge,\n perDimMean,\n composite,\n ...(notes.length > 0 ? { notes: notes.join(' | ') } : {}),\n }\n }\n\n const record: RunRecord & { prompt?: string; completion?: string } = {\n runId: `${matrixId}:${profile.id}:${cell.cellId}`,\n experimentId,\n candidateId: profile.id,\n seed: cell.seed,\n model: profile.model,\n promptHash: profileHash,\n configHash,\n commitSha,\n wallMs: cell.durationMs,\n costUsd,\n tokenUsage: cell.tokenUsage,\n outcome,\n splitTag,\n scenarioId: cell.scenarioId,\n ...(cell.error ? { failureMode: cell.error } : {}),\n }\n\n // Corpus-by-default: stamp the trajectory text onto the record (CorpusRecord\n // shape — the validator ignores the extra keys) so the run is dataset-able\n // with no side-channel. Fail-soft: a bad extractor never fails the run.\n if (args.corpusText && args.scenario) {\n try {\n const text = args.corpusText(cell.artifact, args.scenario)\n if (text && typeof text.prompt === 'string' && typeof text.completion === 'string') {\n record.prompt = text.prompt\n record.completion = text.completion\n }\n } catch {\n // extractor threw — omit trajectory text, keep the graded record.\n }\n }\n return record\n}\n\nexport async function runProfileMatrix<TScenario extends Scenario, TArtifact>(\n opts: RunProfileMatrixOptions<TScenario, TArtifact>,\n): Promise<RunProfileMatrixResult<TArtifact, TScenario>> {\n if (opts.profiles.length === 0) throw new ProfileMatrixError('profiles must not be empty')\n if (opts.scenarios.length === 0) throw new ProfileMatrixError('scenarios must not be empty')\n\n const splitTag = opts.splitTag ?? 'search'\n const seed = opts.seed ?? 42\n const validate = opts.validate ?? true\n const integrityMode = opts.integrity ?? 'assert'\n const profileIds = opts.profiles.map((p) => p.id)\n const experimentId =\n opts.experimentId ??\n `pm_${sha({ profileIds, scenarios: opts.scenarios.map((s) => s.id) }).slice(0, 16)}`\n const matrixId = `mtx_${sha({ experimentId, profileIds, seed, splitTag }).slice(0, 16)}`\n // Scenario lookup for the corpus-text extractor (records carry trajectory text).\n const scenarioById = new Map(opts.scenarios.map((s) => [s.id, s]))\n\n // Preflight: every profile must hash (non-empty model) AND its model must\n // carry a snapshot version, BEFORE any LLM spend. A probe record run through\n // validateRunRecord catches both in the exact place they'd otherwise surface\n // far downstream.\n for (const profile of opts.profiles) {\n const profileHash = agentProfileHash(profile)\n try {\n validateRunRecord({\n runId: `${matrixId}:${profile.id}:probe`,\n experimentId,\n candidateId: profile.id,\n seed,\n model: profile.model,\n promptHash: profileHash,\n configHash: profileHash,\n commitSha: opts.commitSha,\n wallMs: 0,\n costUsd: 0,\n tokenUsage: { input: 0, output: 0 },\n outcome:\n splitTag === 'holdout' ? { holdoutScore: 0, raw: {} } : { searchScore: 0, raw: {} },\n splitTag,\n })\n } catch (err) {\n throw new ProfileMatrixError(\n `profile '${profile.id}' is not recordable: ${err instanceof Error ? err.message : String(err)}`,\n )\n }\n }\n\n const records: RunRecord[] = []\n const campaigns: Record<string, CampaignResult<TArtifact, TScenario>> = {}\n const byProfile: Record<string, ProfileSummary> = {}\n\n for (const profile of opts.profiles) {\n const profileHash = agentProfileHash(profile)\n const configHash = sha({\n profile: profileHash,\n judges: (opts.judges ?? []).map((j) => j.name),\n seed,\n splitTag,\n })\n\n // Bind the profile into a campaign dispatch. Name it so the campaign's\n // manifest hash is stable + distinct per profile.\n const dispatch = (scenario: TScenario, ctx: DispatchContext): Promise<TArtifact> =>\n opts.dispatch(profile, scenario, ctx)\n Object.defineProperty(dispatch, 'name', { value: `profile_${sanitize(profile.id)}` })\n\n const campaign = await runCampaign<TScenario, TArtifact>({\n scenarios: opts.scenarios,\n dispatch,\n judges: opts.judges,\n seed,\n reps: opts.reps,\n maxConcurrency: opts.maxConcurrency,\n costCeiling: opts.costCeiling,\n labeledStore: opts.labeledStore,\n captureSource: opts.captureSource,\n storage: opts.storage,\n now: opts.now,\n runDir: join(opts.runDir, sanitize(profile.id)),\n })\n\n const profileRecords: RunRecord[] = []\n for (const cell of campaign.cells) {\n const record = buildRunRecord({\n cell,\n profile,\n profileHash,\n configHash,\n experimentId,\n splitTag,\n commitSha: opts.commitSha,\n matrixId,\n scenario: scenarioById.get(cell.scenarioId),\n corpusText: opts.corpusText,\n })\n if (validate) validateRunRecord(record)\n profileRecords.push(record)\n records.push(record)\n }\n\n // Effective cost = billed-or-priced. buildRunRecord prices the measured\n // tokens when the source reports $0 for a model it can't rate (and leaves\n // billed cost untouched otherwise), so the RunRecords are the model-aware\n // authority. Surface that same total on campaigns[id] — runCampaign's own\n // ledger only sees ctx.cost ($0 for an unpriced-at-source model), which\n // would otherwise disagree with byProfile + integrity for the same run.\n const pricedTotalCostUsd = profileRecords.reduce((a, r) => a + r.costUsd, 0)\n campaigns[profile.id] = {\n ...campaign,\n aggregates: { ...campaign.aggregates, totalCostUsd: pricedTotalCostUsd },\n }\n\n byProfile[profile.id] = {\n profileId: profile.id,\n profileHash,\n model: profile.model,\n records: profileRecords.length,\n meanComposite: mean(profileRecords.map(compositeOf)),\n totalCostUsd: pricedTotalCostUsd,\n integrity: summarizeBackendIntegrity(profileRecords),\n }\n }\n\n // Integrity by construction — the whole point of the primitive.\n const integrity = summarizeBackendIntegrity(records)\n if (integrityMode === 'assert') {\n assertRealBackend(records, { allowMixed: opts.allowMixed ?? true })\n } else if (integrityMode === 'warn' && integrity.verdict !== 'real') {\n // eslint-disable-next-line no-console\n console.warn(\n `[runProfileMatrix] backend integrity: ${integrity.verdict} — ${integrity.diagnosis}`,\n )\n }\n\n // Pivots.\n const byScenario = rollup(records, (r) => r.scenarioId)\n const byPersona = opts.personaOf\n ? rollupByPersona(records, opts.scenarios, opts.personaOf)\n : undefined\n\n return { matrixId, experimentId, records, byProfile, byScenario, byPersona, integrity, campaigns }\n}\n\n/** Composite for a produced RunRecord (the split score it carries). */\nfunction compositeOf(r: RunRecord): number {\n return r.outcome.holdoutScore ?? r.outcome.searchScore ?? 0\n}\n\nfunction rollup(\n records: RunRecord[],\n keyOf: (r: RunRecord) => string | undefined,\n): Record<string, ScenarioRollup> {\n const groups = new Map<string, number[]>()\n for (const r of records) {\n const key = keyOf(r)\n if (key === undefined) continue\n const arr = groups.get(key) ?? []\n arr.push(compositeOf(r))\n groups.set(key, arr)\n }\n const out: Record<string, ScenarioRollup> = {}\n for (const [key, xs] of groups) out[key] = { meanComposite: mean(xs), n: xs.length }\n return out\n}\n\nfunction rollupByPersona<TScenario extends Scenario>(\n records: RunRecord[],\n scenarios: TScenario[],\n personaOf: (s: TScenario) => string,\n): Record<string, ScenarioRollup> {\n const personaByScenarioId = new Map<string, string>()\n for (const s of scenarios) personaByScenarioId.set(s.id, personaOf(s))\n return rollup(records, (r) => (r.scenarioId ? personaByScenarioId.get(r.scenarioId) : undefined))\n}\n","/**\n * @experimental\n *\n * VCS-pluggable worktree adapter. One improvement = one worktree, PR-like\n * (multiple commits allowed). A code-tier driver's `propose()` creates a\n * worktree, an agent commits the change into it, and `finalize()` returns a\n * `CodeSurface{ worktreeRef }` the measurement checks out to run the worker\n * against the changed code. On promotion the worktree becomes the PR branch.\n *\n * The interface is VCS-agnostic so a future `jj` ([jj-vcs](https://github.com/jj-vcs/jj))\n * adapter can slot in without touching driver code. Only the git adapter\n * ships today. See `docs/design/self-improvement-engine.md`.\n */\n\nimport { execFileSync } from 'node:child_process'\nimport { existsSync } from 'node:fs'\nimport { basename, isAbsolute, join } from 'node:path'\nimport type { CodeSurface } from '../types'\n\nexport interface Worktree {\n /** Absolute path to the checked-out worktree directory. */\n path: string\n /** The branch the worktree is on (becomes the PR branch on promotion). */\n branch: string\n /** The ref the worktree was forked from. */\n baseRef: string\n}\n\nexport interface WorktreeAdapter {\n /** Create an isolated worktree on a fresh branch off `baseRef`. */\n create(opts: { baseRef: string; label: string }): Promise<Worktree>\n /** Commit any pending changes in the worktree, then return a CodeSurface\n * pointing at it. The agent has already written its change into\n * `worktree.path` by the time this is called. */\n finalize(worktree: Worktree, summary: string): Promise<CodeSurface>\n /** Remove the worktree (and its branch) — called for losing candidates. */\n discard(worktree: Worktree): Promise<void>\n}\n\nexport class WorktreeAdapterError extends Error {\n constructor(\n message: string,\n readonly cause?: unknown,\n ) {\n super(message)\n this.name = 'WorktreeAdapterError'\n }\n}\n\nexport interface GitWorktreeAdapterOptions {\n /** Repo root the worktrees fork from. */\n repoRoot: string\n /** Directory worktrees are created under. Default: `<repoRoot>/.worktrees`. */\n worktreeDir?: string\n /** Branch-name prefix. Default: `improve`. */\n branchPrefix?: string\n /** Test seam — defaults to a real `git` runner. */\n git?: (args: string[], cwd: string) => string\n}\n\nfunction defaultGit(args: string[], cwd: string): string {\n try {\n return execFileSync('git', args, { cwd, encoding: 'utf8' }).trim()\n } catch (err) {\n const stderr =\n err && typeof err === 'object' && 'stderr' in err\n ? String((err as { stderr: unknown }).stderr)\n : ''\n throw new WorktreeAdapterError(`git ${args.join(' ')} failed: ${stderr || String(err)}`, err)\n }\n}\n\n/** Slugify a label into a branch-safe segment. */\nfunction slug(label: string): string {\n return (\n label\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '')\n .slice(0, 48) || 'candidate'\n )\n}\n\nexport function gitWorktreeAdapter(opts: GitWorktreeAdapterOptions): WorktreeAdapter {\n const git = opts.git ?? defaultGit\n const worktreeDir = opts.worktreeDir ?? join(opts.repoRoot, '.worktrees')\n const branchPrefix = opts.branchPrefix ?? 'improve'\n\n return {\n async create({ baseRef, label }) {\n const id = `${slug(label)}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 6)}`\n const branch = `${branchPrefix}/${id}`\n const path = join(worktreeDir, id)\n git(['worktree', 'add', '-b', branch, path, baseRef], opts.repoRoot)\n return { path, branch, baseRef }\n },\n\n async finalize(worktree, summary) {\n // Stage + commit any pending changes the agent left in the worktree.\n // A no-op commit is refused by git, so only commit when the tree is dirty.\n const status = git(['status', '--porcelain'], worktree.path)\n if (status.length > 0) {\n git(['add', '-A'], worktree.path)\n git(['commit', '-m', summary], worktree.path)\n }\n return {\n kind: 'code',\n worktreeRef: worktree.path,\n baseRef: worktree.baseRef,\n summary,\n }\n },\n\n async discard(worktree) {\n // Remove the worktree, then delete its branch. Force-remove because the\n // worktree may hold uncommitted experiment state we're discarding.\n git(['worktree', 'remove', '--force', worktree.path], opts.repoRoot)\n git(['branch', '-D', worktree.branch], opts.repoRoot)\n },\n }\n}\n\n/** Resolve a `CodeSurface`'s worktreeRef to a directory the measurement can\n * run the worker in. A path ref is returned as-is; anything else is treated\n * as a ref under the adapter's worktree dir. */\nexport function resolveWorktreePath(surface: CodeSurface, worktreeDir?: string): string {\n if (isAbsolute(surface.worktreeRef) && existsSync(surface.worktreeRef)) return surface.worktreeRef\n if (worktreeDir) return join(worktreeDir, basename(surface.worktreeRef))\n return surface.worktreeRef\n}\n"],"mappings":"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","names":["surfaceToText","surfaceToText","BLOCK_START","BLOCK_END","DEFAULT_HEADING","stripBlock","surfaceToText","mkdtempSync","writeFileSync","tmpdir","join","APPLY_SYSTEM","mkdtempSync","join","tmpdir","writeFileSync","writeFileSync","join","join","writeFileSync","truncate","createHash","join","createHash","mean","join","existsSync","join","slug"]}