@tangle-network/agent-eval 0.145.22 → 0.147.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +34 -0
- package/dist/analyst/index.d.ts +13 -13
- package/dist/analyst/index.js +6 -6
- package/dist/{backend-integrity-HVmWyOaX.d.ts → backend-integrity-Bz8nSrRE.d.ts} +2 -2
- package/dist/{backend-integrity-HVmWyOaX.d.ts.map → backend-integrity-Bz8nSrRE.d.ts.map} +1 -1
- package/dist/{benchmark-DTQ1RApl.d.ts → benchmark-Cn7ZMFNW.d.ts} +3 -3
- package/dist/{benchmark-DTQ1RApl.d.ts.map → benchmark-Cn7ZMFNW.d.ts.map} +1 -1
- package/dist/{benchmark-command-CDB_yKqS.js → benchmark-command-BTiysiYU.js} +11 -11
- package/dist/{benchmark-command-CDB_yKqS.js.map → benchmark-command-BTiysiYU.js.map} +1 -1
- package/dist/benchmarks/index.d.ts +4 -4
- package/dist/benchmarks/index.js +3 -3
- package/dist/campaign/index.d.ts +8 -8
- package/dist/campaign/index.js +5 -5
- package/dist/{campaign-CbQXcARJ.js → campaign-DCDdhuv2.js} +7 -7
- package/dist/{campaign-CbQXcARJ.js.map → campaign-DCDdhuv2.js.map} +1 -1
- package/dist/{capture-fetch-BZiO2cEH.d.ts → capture-fetch-BAx3Gntt.d.ts} +2 -2
- package/dist/{capture-fetch-BZiO2cEH.d.ts.map → capture-fetch-BAx3Gntt.d.ts.map} +1 -1
- package/dist/{chat-client-BJmwfnjN.js → chat-client-BX8Wh3fn.js} +3 -3
- package/dist/{chat-client-BJmwfnjN.js.map → chat-client-BX8Wh3fn.js.map} +1 -1
- package/dist/cli.js +2 -2
- package/dist/{client-YDkU5QST.d.ts → client-BV7icIfy.d.ts} +2 -2
- package/dist/{client-YDkU5QST.d.ts.map → client-BV7icIfy.d.ts.map} +1 -1
- package/dist/contract/index.d.ts +10 -10
- package/dist/contract/index.js +9 -9
- package/dist/{cost-ledger-BSe92yAV.js → cost-ledger-B1qx30B4.js} +2 -2
- package/dist/{cost-ledger-BSe92yAV.js.map → cost-ledger-B1qx30B4.js.map} +1 -1
- package/dist/{default-registry-DONui3mA.d.ts → default-registry-BUtRMRKk.d.ts} +6 -6
- package/dist/{default-registry-DONui3mA.d.ts.map → default-registry-BUtRMRKk.d.ts.map} +1 -1
- package/dist/{define-agent-eval-BGxmy4W6.js → define-agent-eval-BqWFz3sK.js} +3 -3
- package/dist/{define-agent-eval-BGxmy4W6.js.map → define-agent-eval-BqWFz3sK.js.map} +1 -1
- package/dist/{define-agent-eval-DrpgTVPp.d.ts → define-agent-eval-D52ClbX2.d.ts} +5 -5
- package/dist/{define-agent-eval-DrpgTVPp.d.ts.map → define-agent-eval-D52ClbX2.d.ts.map} +1 -1
- package/dist/{dspy-rlm-engine-B2nst4NR.js → dspy-rlm-engine-BmtOl_kP.js} +4 -4
- package/dist/{dspy-rlm-engine-B2nst4NR.js.map → dspy-rlm-engine-BmtOl_kP.js.map} +1 -1
- package/dist/{engine-Bc3seRPe.d.ts → engine-CIy18RTX.d.ts} +4 -4
- package/dist/{engine-Bc3seRPe.d.ts.map → engine-CIy18RTX.d.ts.map} +1 -1
- package/dist/{eval-campaign-DeGLwACc.js → eval-campaign-bmZ6NIIP.js} +2 -2
- package/dist/{eval-campaign-DeGLwACc.js.map → eval-campaign-bmZ6NIIP.js.map} +1 -1
- package/dist/{exact-types-CYFbvA5U.d.ts → exact-types-rdKFzEnK.d.ts} +2 -2
- package/dist/{exact-types-CYFbvA5U.d.ts.map → exact-types-rdKFzEnK.d.ts.map} +1 -1
- package/dist/experiment/index.d.ts +5 -5
- package/dist/experiment/index.js +3 -3
- package/dist/{experiment-tracker-DWHZBAYL.d.ts → experiment-tracker-D9VHwRm-.d.ts} +6 -24
- package/dist/experiment-tracker-D9VHwRm-.d.ts.map +1 -0
- package/dist/{experiment-tracker-C29gXM4B.js → experiment-tracker-Ym6rEQT1.js} +15 -4
- package/dist/experiment-tracker-Ym6rEQT1.js.map +1 -0
- package/dist/{external-optimizer-contracts-CKEY98bK.d.ts → external-optimizer-contracts-CSjDLLmr.d.ts} +2 -2
- package/dist/{external-optimizer-contracts-CKEY98bK.d.ts.map → external-optimizer-contracts-CSjDLLmr.d.ts.map} +1 -1
- package/dist/{external-optimizer-process-DYNizz8W.js → external-optimizer-process-C4AyCcQd.js} +2 -2
- package/dist/{external-optimizer-process-DYNizz8W.js.map → external-optimizer-process-C4AyCcQd.js.map} +1 -1
- package/dist/{external-optimizer-subprocess-r6dP9DAj.js → external-optimizer-subprocess-DU1KM8yV.js} +3 -3
- package/dist/{external-optimizer-subprocess-r6dP9DAj.js.map → external-optimizer-subprocess-DU1KM8yV.js.map} +1 -1
- package/dist/{feedback-trajectory-Cg9EDxKB.d.ts → feedback-trajectory-niGeR6uJ.d.ts} +3 -3
- package/dist/{feedback-trajectory-Cg9EDxKB.d.ts.map → feedback-trajectory-niGeR6uJ.d.ts.map} +1 -1
- package/dist/fuzz.js +1 -1
- package/dist/hosted/index.d.ts +2 -2
- package/dist/{index-DGrcBMbC.d.ts → index-BjBjxiVv.d.ts} +9 -9
- package/dist/{index-DGrcBMbC.d.ts.map → index-BjBjxiVv.d.ts.map} +1 -1
- package/dist/index-CKblBxtr.d.ts +1 -0
- package/dist/{index-CevPFhDT.d.ts → index-gtjtfLEJ.d.ts} +7 -7
- package/dist/{index-CevPFhDT.d.ts.map → index-gtjtfLEJ.d.ts.map} +1 -1
- package/dist/index.d.ts +21 -51
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +16 -125
- package/dist/index.js.map +1 -1
- package/dist/{integrity-DDoeWibF.d.ts → integrity-CGfpTE5-.d.ts} +2 -2
- package/dist/{integrity-DDoeWibF.d.ts.map → integrity-CGfpTE5-.d.ts.map} +1 -1
- package/dist/{kind-factory-CPmSd58s.js → kind-factory-DmAa0h3K.js} +7 -7
- package/dist/kind-factory-DmAa0h3K.js.map +1 -0
- package/dist/{llm-client-_UE4fU7Z.js → llm-client-BMuxYoZy.js} +2 -2
- package/dist/{llm-client-_UE4fU7Z.js.map → llm-client-BMuxYoZy.js.map} +1 -1
- package/dist/{llm-judge-B7ffRF8w.js → llm-judge-DrzsVS5k.js} +4 -4
- package/dist/{llm-judge-B7ffRF8w.js.map → llm-judge-DrzsVS5k.js.map} +1 -1
- package/dist/matrix-C-2Qx1Zr.d.ts +383 -0
- package/dist/matrix-C-2Qx1Zr.d.ts.map +1 -0
- package/dist/meta-eval/index.d.ts +1 -1
- package/dist/{metrics-Cl0L1KUy.js → metrics-Qv-cpptD.js} +15 -8
- package/dist/metrics-Qv-cpptD.js.map +1 -0
- package/dist/multishot/golden/index.d.ts +230 -0
- package/dist/multishot/golden/index.d.ts.map +1 -0
- package/dist/multishot/golden/index.js +7686 -0
- package/dist/multishot/golden/index.js.map +1 -0
- package/dist/multishot/index.d.ts +2 -380
- package/dist/multishot/index.d.ts.map +1 -1
- package/dist/multishot/index.js +2 -106
- package/dist/multishot/index.js.map +1 -1
- package/dist/openapi.json +1 -1
- package/dist/{produced-state-D3k45S9a.js → produced-state-Dtx60bUQ.js} +4 -4
- package/dist/{produced-state-D3k45S9a.js.map → produced-state-Dtx60bUQ.js.map} +1 -1
- package/dist/{promotion-policy-BKi5OK5l.d.ts → promotion-policy-CewdjfCJ.d.ts} +2 -2
- package/dist/{promotion-policy-BKi5OK5l.d.ts.map → promotion-policy-CewdjfCJ.d.ts.map} +1 -1
- package/dist/{provenance-Bb7Zmyj2.d.ts → provenance-LrOEOHQb.d.ts} +6 -6
- package/dist/{provenance-Bb7Zmyj2.d.ts.map → provenance-LrOEOHQb.d.ts.map} +1 -1
- package/dist/{registry-CZgEmVXb.d.ts → registry-CaqJIDdN.d.ts} +4 -4
- package/dist/{registry-CZgEmVXb.d.ts.map → registry-CaqJIDdN.d.ts.map} +1 -1
- package/dist/reporting.d.ts +1 -1
- package/dist/reporting.js +1 -1
- package/dist/{researcher-CC305Ed-.d.ts → researcher-BySlpla_.d.ts} +3 -3
- package/dist/{researcher-CC305Ed-.d.ts.map → researcher-BySlpla_.d.ts.map} +1 -1
- package/dist/rl.d.ts +3 -3
- package/dist/rl.js +2 -2
- package/dist/{semantic-concept-judge-BsY2Q0Oq.js → semantic-concept-judge-BI7Rrl5-.js} +3 -3
- package/dist/{semantic-concept-judge-BsY2Q0Oq.js.map → semantic-concept-judge-BI7Rrl5-.js.map} +1 -1
- package/dist/{sequential-CYwq6Ff_.d.ts → sequential-BhsrMupG.d.ts} +31 -2
- package/dist/sequential-BhsrMupG.d.ts.map +1 -0
- package/dist/{sequential-Br0mAPHA.js → sequential-CzK5DarL.js} +48 -6
- package/dist/sequential-CzK5DarL.js.map +1 -0
- package/dist/series-convergence-CjO2QdRW.js.map +1 -1
- package/dist/{series-convergence-C9G-GNYK.d.ts → series-convergence-D2fsoJ2w.d.ts} +4 -7
- package/dist/{series-convergence-C9G-GNYK.d.ts.map → series-convergence-D2fsoJ2w.d.ts.map} +1 -1
- package/dist/{server-cQXve8i4.js → server-D9wQclzG.js} +3 -3
- package/dist/{server-cQXve8i4.js.map → server-D9wQclzG.js.map} +1 -1
- package/dist/{skillopt-optimization-method-C9MrMgW9.d.ts → skillopt-optimization-method-BoC1Qccx.d.ts} +5 -5
- package/dist/{skillopt-optimization-method-C9MrMgW9.d.ts.map → skillopt-optimization-method-BoC1Qccx.d.ts.map} +1 -1
- package/dist/{skillopt-optimization-method-Cv3K4DaS.js → skillopt-optimization-method-C_UrqZs2.js} +4 -4
- package/dist/{skillopt-optimization-method-Cv3K4DaS.js.map → skillopt-optimization-method-C_UrqZs2.js.map} +1 -1
- package/dist/{statistical-heldout-fvxtHnKQ.d.ts → statistical-heldout-uxSpFEjm.d.ts} +2 -2
- package/dist/{statistical-heldout-fvxtHnKQ.d.ts.map → statistical-heldout-uxSpFEjm.d.ts.map} +1 -1
- package/dist/{store-otlp-CsptLYpN.js → store-otlp-CDYWW_8N.js} +2 -2
- package/dist/{store-otlp-CsptLYpN.js.map → store-otlp-CDYWW_8N.js.map} +1 -1
- package/dist/{store-tool-spans-Cq9mFd-q.js → store-tool-spans-CykkbOlv.js} +3 -3
- package/dist/{store-tool-spans-Cq9mFd-q.js.map → store-tool-spans-CykkbOlv.js.map} +1 -1
- package/dist/{store-tool-spans-CV0hRsUp.d.ts → store-tool-spans-D5FhM0_A.d.ts} +4 -4
- package/dist/{store-tool-spans-CV0hRsUp.d.ts.map → store-tool-spans-D5FhM0_A.d.ts.map} +1 -1
- package/dist/{task-failure-attributes-CpQ4y5RD.js → task-failure-attributes--ZTP3tYO.js} +2 -2
- package/dist/{task-failure-attributes-CpQ4y5RD.js.map → task-failure-attributes--ZTP3tYO.js.map} +1 -1
- package/dist/{tool-groups-CDDXNKhd.d.ts → tool-groups-zpufabP8.d.ts} +3 -3
- package/dist/tool-groups-zpufabP8.d.ts.map +1 -0
- package/dist/trace-repair/index.d.ts +1 -1
- package/dist/traces.d.ts +7 -7
- package/dist/traces.js +4 -4
- package/dist/types-B3jzCp0p.js +108 -0
- package/dist/types-B3jzCp0p.js.map +1 -0
- package/dist/{types-oAsa-fs4.d.ts → types-BohHewKK.d.ts} +2 -2
- package/dist/{types-oAsa-fs4.d.ts.map → types-BohHewKK.d.ts.map} +1 -1
- package/dist/{types-DABZgDGV.d.ts → types-C1Bmeb8X.d.ts} +3 -3
- package/dist/{types-DABZgDGV.d.ts.map → types-C1Bmeb8X.d.ts.map} +1 -1
- package/dist/{types-CWcPguwd.d.ts → types-ColZlZtc.d.ts} +2 -2
- package/dist/{types-CWcPguwd.d.ts.map → types-ColZlZtc.d.ts.map} +1 -1
- package/dist/{types-XBRdmbj8.d.ts → types-DOhGq4S1.d.ts} +1 -7
- package/dist/{types-XBRdmbj8.d.ts.map → types-DOhGq4S1.d.ts.map} +1 -1
- package/dist/wire/index.d.ts +2 -2
- package/dist/wire/index.js +1 -1
- package/docs/multishot-golden-records.md +102 -0
- package/package.json +7 -2
- package/dist/experiment-tracker-C29gXM4B.js.map +0 -1
- package/dist/experiment-tracker-DWHZBAYL.d.ts.map +0 -1
- package/dist/index-BgHYx1QG.d.ts +0 -1
- package/dist/kind-factory-CPmSd58s.js.map +0 -1
- package/dist/metrics-Cl0L1KUy.js.map +0 -1
- package/dist/sequential-Br0mAPHA.js.map +0 -1
- package/dist/sequential-CYwq6Ff_.d.ts.map +0 -1
- package/dist/tool-groups-CDDXNKhd.d.ts.map +0 -1
|
@@ -233,12 +233,23 @@ var ExperimentTracker = class {
|
|
|
233
233
|
const experiments = await this.store.load();
|
|
234
234
|
const exp = experiments.find((e) => e.id === experimentId);
|
|
235
235
|
if (!exp) throw new ValidationError(`experiment-tracker: experiment "${experimentId}" not found`);
|
|
236
|
+
if (rep.runId !== void 0 && rep.runId.trim().length === 0) throw new ValidationError("experiment-tracker: rep runId must be non-empty when present");
|
|
237
|
+
const evidence = rep.evidence?.map((reference, index) => {
|
|
238
|
+
if (reference.uri.trim().length === 0) throw new ValidationError(`experiment-tracker: rep evidence[${index}].uri must be non-empty`);
|
|
239
|
+
return {
|
|
240
|
+
kind: reference.kind,
|
|
241
|
+
uri: reference.uri,
|
|
242
|
+
...reference.excerpt === void 0 ? {} : { excerpt: reference.excerpt }
|
|
243
|
+
};
|
|
244
|
+
});
|
|
236
245
|
const fullRep = {
|
|
237
246
|
rep: rep.rep ?? exp.reps.length,
|
|
238
247
|
score: rep.score,
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
248
|
+
timestamp: rep.timestamp ?? new Date(this.now()).toISOString(),
|
|
249
|
+
...rep.runId === void 0 ? {} : { runId: rep.runId },
|
|
250
|
+
...evidence === void 0 ? {} : { evidence },
|
|
251
|
+
...rep.passed === void 0 ? {} : { passed: rep.passed },
|
|
252
|
+
...rep.metrics === void 0 ? {} : { metrics: { ...rep.metrics } }
|
|
242
253
|
};
|
|
243
254
|
exp.reps.push(fullRep);
|
|
244
255
|
exp.stats = computeExperimentStats(exp.reps, this.thresholds);
|
|
@@ -266,4 +277,4 @@ var ExperimentTracker = class {
|
|
|
266
277
|
//#endregion
|
|
267
278
|
export { inMemoryExperimentStore as a, improvementVerdict as i, computeExperimentStats as n, fileExperimentStore as r, ExperimentTracker as t };
|
|
268
279
|
|
|
269
|
-
//# sourceMappingURL=experiment-tracker-
|
|
280
|
+
//# sourceMappingURL=experiment-tracker-Ym6rEQT1.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"experiment-tracker-Ym6rEQT1.js","names":[],"sources":["../src/experiment-tracker.ts"],"sourcesContent":["/**\n * Experiment tracker — git-provenanced experiment log with N-rep stats and a\n * KEEP / REGRESSION / NOISE verdict against a parent.\n *\n * Every loop the fleet runs reduces to the same question: \"I ran the candidate\n * N times — is the median measurably better than the parent, or is the delta\n * inside the noise band?\" The hand-rolled copies bake a fixed score scale\n * (percentage points), a fixed store path (`.evolve/experiments-v2.json`), and\n * `execSync('git …')` straight into the module. This is the canonical version:\n * provenance and persistence are injected, thresholds are configurable, and the\n * stats + verdict are pure functions you can unit-test without a git repo or a\n * filesystem.\n *\n * Stats per experiment: median / mean / min / max / iqr / stddev / passRate /\n * n, plus a `stable` flag (`iqr < iqrUnstableAbove && stddev < stddevUnstableAbove`).\n *\n * Verdict against a parent (both must have `n >= minRepsForVerdict`):\n * - NOISE — the candidate is too unstable to judge (`!stable`)\n * - KEEP — `medianDelta > keepThreshold`\n * - REGRESSION — `medianDelta < -regressionThreshold`\n * - NOISE — otherwise (delta inside the band)\n * With no parent (or insufficient reps) the verdict is the neutral ITERATE.\n */\n\nimport { execSync } from 'node:child_process'\nimport type { EvidenceRef } from './analyst/types'\nimport { iqr } from './baseline'\nimport { ValidationError } from './errors'\n\n/** Verdict for one experiment relative to its parent. ITERATE is the neutral\n * \"keep collecting reps / no parent to compare against\" state. */\nexport type ExperimentVerdict = 'KEEP' | 'ITERATE' | 'NOISE' | 'REGRESSION'\n\n/** Git provenance for the working tree an experiment was run from. */\nexport interface ExperimentProvenance {\n /** Commit sha (short or full — the tracker does not interpret it). */\n commit: string\n /** First line of the commit message. */\n message: string\n /** Files changed vs the parent commit, or a marker like 'uncommitted'. */\n changedFiles: string[]\n}\n\n/** A single repetition of an experiment, carrying the score the verdict is\n * computed on plus any free-form per-rep metrics the consumer wants kept. */\nexport interface ExperimentRep {\n /** 0-indexed repetition number within the experiment. */\n rep: number\n /** The score this rep is judged on (same scale as the thresholds). */\n score: number\n /** ISO timestamp the rep completed. */\n timestamp: string\n /** Stable execution/run identity that produced this score. */\n runId?: string\n /** Mechanically resolvable trace, artifact, metric, or finding evidence. */\n evidence?: EvidenceRef[]\n /** Whether this rep passed the consumer's own gate — folded into `passRate`. */\n passed?: boolean\n /** Free-form numeric metrics retained for later analysis. */\n metrics?: Record<string, number>\n}\n\nexport interface ExperimentStats {\n median: number\n mean: number\n min: number\n max: number\n /** Inter-quartile range of the rep scores. */\n iqr: number\n /** Population standard deviation of the rep scores. */\n stddev: number\n /** Fraction of reps with `passed === true`, over reps that set `passed`.\n * null when no rep declared a pass/fail outcome. */\n passRate: number | null\n /** Number of reps. */\n n: number\n /** True when the sample is tight enough to trust for a verdict. */\n stable: boolean\n}\n\nexport interface Experiment {\n /** Stable id for the experiment. */\n id: string\n /** Free-form label / config descriptor. */\n label: string\n /** Git provenance captured when the experiment was created. */\n provenance: ExperimentProvenance\n /** Parent experiment id this candidate is compared against, if any. */\n parentId?: string\n /** One-line summary of what changed from the parent. */\n changeSummary: string\n reps: ExperimentRep[]\n stats: ExperimentStats\n verdict: ExperimentVerdict\n /** ISO timestamp the experiment was created. */\n createdAt: string\n}\n\nexport interface ImprovementThresholds {\n /** medianDelta strictly above this ⇒ KEEP. Default 5. */\n keepThreshold?: number\n /** medianDelta strictly below the negative of this ⇒ REGRESSION. Default 5. */\n regressionThreshold?: number\n /** iqr at or above this ⇒ unstable. Default 10. */\n iqrUnstableAbove?: number\n /** stddev at or above this ⇒ unstable. Default Infinity (iqr-only stability). */\n stddevUnstableAbove?: number\n /** Reps required on BOTH candidate and parent before a verdict is rendered.\n * Default 3. */\n minRepsForVerdict?: number\n}\n\nexport interface ImprovementVerdictResult {\n verdict: ExperimentVerdict\n /** candidate.median − parent.median; null when no parent or insufficient reps. */\n medianDelta: number | null\n /** Human-readable reason for the verdict — for dashboards and logs. */\n reason: string\n}\n\nconst DEFAULTS: Required<ImprovementThresholds> = {\n keepThreshold: 5,\n regressionThreshold: 5,\n iqrUnstableAbove: 10,\n stddevUnstableAbove: Number.POSITIVE_INFINITY,\n minRepsForVerdict: 3,\n}\n\nfunction resolveThresholds(t: ImprovementThresholds | undefined): Required<ImprovementThresholds> {\n const r = { ...DEFAULTS, ...(t ?? {}) }\n if (r.keepThreshold < 0) {\n throw new ValidationError(\n `experiment-tracker: keepThreshold must be >= 0, got ${r.keepThreshold}`,\n )\n }\n if (r.regressionThreshold < 0) {\n throw new ValidationError(\n `experiment-tracker: regressionThreshold must be >= 0, got ${r.regressionThreshold}`,\n )\n }\n if (r.minRepsForVerdict < 1) {\n throw new ValidationError(\n `experiment-tracker: minRepsForVerdict must be >= 1, got ${r.minRepsForVerdict}`,\n )\n }\n return r\n}\n\nfunction median(sorted: number[]): number {\n const n = sorted.length\n if (n === 0) return 0\n const mid = Math.floor(n / 2)\n return n % 2 === 0 ? (sorted[mid - 1]! + sorted[mid]!) / 2 : sorted[mid]!\n}\n\n/** Population standard deviation (÷n). 0 for fewer than 2 values. */\nfunction stddev(values: number[], mean: number): number {\n if (values.length < 2) return 0\n const variance = values.reduce((acc, v) => acc + (v - mean) ** 2, 0) / values.length\n return Math.sqrt(variance)\n}\n\n/**\n * Compute the N-rep statistics for a set of reps. Pure — no I/O. The `stable`\n * flag is the trust gate the verdict depends on: a sample whose spread exceeds\n * the configured bounds can't distinguish a real delta from run-to-run noise.\n */\nexport function computeExperimentStats(\n reps: ExperimentRep[],\n thresholds?: ImprovementThresholds,\n): ExperimentStats {\n const t = resolveThresholds(thresholds)\n const n = reps.length\n if (n === 0) {\n return {\n median: 0,\n mean: 0,\n min: 0,\n max: 0,\n iqr: 0,\n stddev: 0,\n passRate: null,\n n: 0,\n stable: false,\n }\n }\n const scores = reps.map((r) => {\n if (!Number.isFinite(r.score)) {\n throw new ValidationError(`experiment-tracker: rep ${r.rep} has non-finite score ${r.score}`)\n }\n return r.score\n })\n const sorted = [...scores].sort((a, b) => a - b)\n const mean = scores.reduce((s, v) => s + v, 0) / n\n const sd = stddev(scores, mean)\n const spread = iqr(scores)\n const rated = reps.filter((r) => typeof r.passed === 'boolean')\n const passRate = rated.length === 0 ? null : rated.filter((r) => r.passed).length / rated.length\n const stable = spread < t.iqrUnstableAbove && sd < t.stddevUnstableAbove\n return {\n median: median(sorted),\n mean,\n min: sorted[0]!,\n max: sorted[n - 1]!,\n iqr: spread,\n stddev: sd,\n passRate,\n n,\n stable,\n }\n}\n\n/**\n * Verdict for a candidate against its parent. Pure — operates on already-computed\n * stats. KEEP/REGRESSION require both sides to have `>= minRepsForVerdict` reps\n * AND the candidate to be `stable`; otherwise the result is NOISE (unstable) or\n * ITERATE (not enough reps / no parent).\n */\nexport function improvementVerdict(\n candidate: ExperimentStats,\n parent: ExperimentStats | null,\n thresholds?: ImprovementThresholds,\n): ImprovementVerdictResult {\n const t = resolveThresholds(thresholds)\n if (!parent) {\n return {\n verdict: 'ITERATE',\n medianDelta: null,\n reason: 'no parent experiment to compare against',\n }\n }\n if (candidate.n < t.minRepsForVerdict || parent.n < t.minRepsForVerdict) {\n return {\n verdict: 'ITERATE',\n medianDelta: null,\n reason: `need >= ${t.minRepsForVerdict} reps on both sides (candidate n=${candidate.n}, parent n=${parent.n})`,\n }\n }\n if (!candidate.stable) {\n return {\n verdict: 'NOISE',\n medianDelta: candidate.median - parent.median,\n reason: `candidate unstable (iqr=${candidate.iqr}, stddev=${candidate.stddev.toFixed(2)})`,\n }\n }\n const medianDelta = candidate.median - parent.median\n if (medianDelta > t.keepThreshold) {\n return { verdict: 'KEEP', medianDelta, reason: `median +${medianDelta} > +${t.keepThreshold}` }\n }\n if (medianDelta < -t.regressionThreshold) {\n return {\n verdict: 'REGRESSION',\n medianDelta,\n reason: `median ${medianDelta} < -${t.regressionThreshold}`,\n }\n }\n return {\n verdict: 'NOISE',\n medianDelta,\n reason: `median delta ${medianDelta} inside noise band [-${t.regressionThreshold}, +${t.keepThreshold}]`,\n }\n}\n\n// ── Provenance + persistence seams ───────────────────────────────────\n\n/** Reads git provenance for the working tree. Inject a fake in tests; the\n * default implementation shells out to `git`. */\nexport type ProvenanceReader = () => ExperimentProvenance | Promise<ExperimentProvenance>\n\n/** Persistence seam for the experiment log. Inject in-memory in tests; the\n * filesystem implementation is `fileExperimentStore`. */\nexport interface ExperimentStore {\n load(): Promise<Experiment[]>\n save(experiments: Experiment[]): Promise<void>\n}\n\n/**\n * Default provenance reader: `git rev-parse HEAD`, the subject line, and the\n * files changed vs `HEAD~1`. Fail-loud — a tracker that silently logs\n * `commit: 'unknown'` corrupts the provenance the whole point of the log is to\n * carry. When the working tree genuinely has no parent commit, pass an override.\n */\nexport const gitProvenanceReader: ProvenanceReader = () => {\n const run = (cmd: string): string => execSync(cmd, { encoding: 'utf8' }).trim()\n const commit = run('git rev-parse --short HEAD')\n const message = run('git log -1 --format=%s')\n const changedRaw = run('git diff --name-only HEAD~1')\n const changedFiles = changedRaw.length === 0 ? [] : changedRaw.split('\\n').filter(Boolean)\n return { commit, message, changedFiles }\n}\n\n/** In-memory store — the default when no persistence is wanted (tests, ephemeral\n * runs). State lives on the instance. */\nexport function inMemoryExperimentStore(initial: Experiment[] = []): ExperimentStore {\n let state = initial.map((e) => structuredClone(e))\n return {\n async load() {\n return state.map((e) => structuredClone(e))\n },\n async save(experiments) {\n state = experiments.map((e) => structuredClone(e))\n },\n }\n}\n\n/** Filesystem store — a single JSON array at `path`, created on first save. */\nexport function fileExperimentStore(path: string): ExperimentStore {\n return {\n async load() {\n const fs = await import('node:fs/promises')\n try {\n const raw = await fs.readFile(path, 'utf8')\n const parsed = JSON.parse(raw)\n if (!Array.isArray(parsed)) {\n throw new ValidationError(`experiment-tracker: store at ${path} is not a JSON array`)\n }\n return parsed as Experiment[]\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') return []\n throw err\n }\n },\n async save(experiments) {\n const fs = await import('node:fs/promises')\n const pathMod = await import('node:path')\n await fs.mkdir(pathMod.dirname(path), { recursive: true })\n await fs.writeFile(path, JSON.stringify(experiments, null, 2), 'utf8')\n },\n }\n}\n\nexport interface ExperimentTrackerOptions {\n store?: ExperimentStore\n provenanceReader?: ProvenanceReader\n thresholds?: ImprovementThresholds\n /** Clock seam for deterministic timestamps in tests. Default `Date.now`. */\n now?: () => number\n}\n\nexport interface CreateExperimentInput {\n id: string\n label: string\n changeSummary: string\n parentId?: string\n /** Override provenance instead of reading from git (e.g. CI metadata). */\n provenance?: ExperimentProvenance\n}\n\n/**\n * Stateful tracker over an `ExperimentStore`. Create an experiment (provenance\n * is captured once), append reps as they complete (stats + verdict recompute on\n * every append), and read the log back for a dashboard. All persistence and git\n * access flow through the injected seams, so the tracker is fully testable\n * without a repo or disk.\n */\nexport class ExperimentTracker {\n private readonly store: ExperimentStore\n private readonly provenanceReader: ProvenanceReader\n private readonly thresholds: Required<ImprovementThresholds>\n private readonly now: () => number\n\n constructor(options: ExperimentTrackerOptions = {}) {\n this.store = options.store ?? inMemoryExperimentStore()\n this.provenanceReader = options.provenanceReader ?? gitProvenanceReader\n this.thresholds = resolveThresholds(options.thresholds)\n this.now = options.now ?? Date.now\n }\n\n async create(input: CreateExperimentInput): Promise<Experiment> {\n const experiments = await this.store.load()\n if (experiments.some((e) => e.id === input.id)) {\n throw new ValidationError(`experiment-tracker: experiment id \"${input.id}\" already exists`)\n }\n if (input.parentId && !experiments.some((e) => e.id === input.parentId)) {\n throw new ValidationError(\n `experiment-tracker: parent experiment \"${input.parentId}\" not found`,\n )\n }\n const provenance = input.provenance ?? (await this.provenanceReader())\n const experiment: Experiment = {\n id: input.id,\n label: input.label,\n provenance,\n parentId: input.parentId,\n changeSummary: input.changeSummary,\n reps: [],\n stats: computeExperimentStats([], this.thresholds),\n verdict: 'ITERATE',\n createdAt: new Date(this.now()).toISOString(),\n }\n experiments.push(experiment)\n await this.store.save(experiments)\n return structuredClone(experiment)\n }\n\n /** Append a rep (its `rep` index defaults to the current rep count) and\n * recompute stats + verdict. Returns the updated experiment. */\n async addRep(\n experimentId: string,\n rep: Omit<ExperimentRep, 'rep' | 'timestamp'> & { rep?: number; timestamp?: string },\n ): Promise<Experiment> {\n const experiments = await this.store.load()\n const exp = experiments.find((e) => e.id === experimentId)\n if (!exp)\n throw new ValidationError(`experiment-tracker: experiment \"${experimentId}\" not found`)\n if (rep.runId !== undefined && rep.runId.trim().length === 0) {\n throw new ValidationError('experiment-tracker: rep runId must be non-empty when present')\n }\n const evidence = rep.evidence?.map((reference, index) => {\n if (reference.uri.trim().length === 0) {\n throw new ValidationError(\n `experiment-tracker: rep evidence[${index}].uri must be non-empty`,\n )\n }\n return {\n kind: reference.kind,\n uri: reference.uri,\n ...(reference.excerpt === undefined ? {} : { excerpt: reference.excerpt }),\n }\n })\n const fullRep: ExperimentRep = {\n rep: rep.rep ?? exp.reps.length,\n score: rep.score,\n timestamp: rep.timestamp ?? new Date(this.now()).toISOString(),\n ...(rep.runId === undefined ? {} : { runId: rep.runId }),\n ...(evidence === undefined ? {} : { evidence }),\n ...(rep.passed === undefined ? {} : { passed: rep.passed }),\n ...(rep.metrics === undefined ? {} : { metrics: { ...rep.metrics } }),\n }\n exp.reps.push(fullRep)\n exp.stats = computeExperimentStats(exp.reps, this.thresholds)\n const parent = exp.parentId ? experiments.find((e) => e.id === exp.parentId) : undefined\n exp.verdict = improvementVerdict(exp.stats, parent?.stats ?? null, this.thresholds).verdict\n await this.store.save(experiments)\n return structuredClone(exp)\n }\n\n async get(experimentId: string): Promise<Experiment | undefined> {\n const experiments = await this.store.load()\n const found = experiments.find((e) => e.id === experimentId)\n return found ? structuredClone(found) : undefined\n }\n\n async list(): Promise<Experiment[]> {\n return this.store.load()\n }\n\n /** Full verdict (not just the enum) for an experiment vs its parent. */\n async verdictFor(experimentId: string): Promise<ImprovementVerdictResult> {\n const experiments = await this.store.load()\n const exp = experiments.find((e) => e.id === experimentId)\n if (!exp)\n throw new ValidationError(`experiment-tracker: experiment \"${experimentId}\" not found`)\n const parent = exp.parentId ? experiments.find((e) => e.id === exp.parentId) : undefined\n return improvementVerdict(exp.stats, parent?.stats ?? null, this.thresholds)\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { b as CustomTokenPricing, g as CostReceiptInput } from "./cost-ledger-DbQdN3nO.js";
|
|
2
|
-
import { h as ChatResponse, m as ChatRequest } from "./types-
|
|
2
|
+
import { h as ChatResponse, m as ChatRequest } from "./types-DOhGq4S1.js";
|
|
3
3
|
//#region src/campaign/external-optimizer-contracts.d.ts
|
|
4
4
|
interface ExternalOptimizerProcessLimits {
|
|
5
5
|
/** Maximum serialized input written for the child process. */
|
|
@@ -162,4 +162,4 @@ interface ExternalOptimizerModelBudget {
|
|
|
162
162
|
}
|
|
163
163
|
//#endregion
|
|
164
164
|
export { ExternalTextEvaluationRequest as _, ExternalOptimizerEndpointFormat as a, ExternalOptimizerModelBudget as c, ExternalOptimizerModelCallResult as d, ExternalOptimizerModelExecutionObservation as f, ExternalTextCandidate as g, ExternalOptimizerRunnerCommand as h, ExternalOptimizerChatRequest as i, ExternalOptimizerModelCall as l, ExternalOptimizerResumeMode as m, DEFAULT_EXTERNAL_OPTIMIZER_PROCESS_LIMITS as n, ExternalOptimizerEvaluationObservation as o, ExternalOptimizerProcessLimits as p, ExternalOptimizerCallbackLimits as r, ExternalOptimizerEvaluationRefusalReason as s, DEFAULT_EXTERNAL_OPTIMIZER_CALLBACK_LIMITS as t, ExternalOptimizerModelCallRequest as u, resolveExternalOptimizerCallbackLimits as v, resolveExternalOptimizerProcessLimits as y };
|
|
165
|
-
//# sourceMappingURL=external-optimizer-contracts-
|
|
165
|
+
//# sourceMappingURL=external-optimizer-contracts-CSjDLLmr.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"external-optimizer-contracts-
|
|
1
|
+
{"version":3,"file":"external-optimizer-contracts-CSjDLLmr.d.ts","names":[],"sources":["../src/campaign/external-optimizer-contracts.ts"],"mappings":";;;UAWiB;;EAEf;;EAEA;;EAEA;;cAGW,2CAA2C,SAAS;UAOhD;;EAEf;;EAEA;;cAGW,4CAA4C,SAAS;UAMjD;EACf;EACA;EACA,MAAM,OAAO;;EAEb,SAAS,QAAQ;;KAGP;KAEA,iCAAiC;UAE5B;EACf,WAAW;EACX;;iBAUc,sCACd,OAAO,QAAQ,6CACf,iBACC;iBAmBa,uCACd,OAAO,QAAQ,8CACf,iBACC;KAkBE,aAAa,KAAK,eAAc,6BACjC,IACA,0BAA0B,gBACf,aAAa,OACtB,+BACc,WAAW,IAAI,aAAa,EAAE,SAC1C;;KAGI,+BAA+B,aACzC,KAAK;EAA0B;;KAGrB;;UAGK;;WAEN;;WAEA,SAAS;;WAET,iBAAiB;WACjB,QAAQ;;;KAIP;WAEG;;WAEA,UAAU;;;;;;;WAOV,SAPU;;WASV;;WAGA;;WAEA;;WAEA,SATkC;;WAWlC;;;;;;;;;;;;KAaH,8BACV,SAAS,sCACN,QAAQ;;KAGD;WAEG;WACA;WACA;WACA;WACA;WACA;WACA;WACA;;WAGA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;;KAGH;;;;;;KAUA;WAEG;WACA;WACA,WAAW;WACX;;WAGA;WACA;WACA,WAAW;WACX;WACA;;WAEA;WACA;;WAGA;WACA;WACA,QAAQ;WACR,YAAY;WACZ;WACA;;UAGE;;EAEf;;EAEA;;EAEA;;EAEA;;EAEA;;;;;;;;;;EAUA;;;;;;EAMA,UAAU;;EAEV"}
|
package/dist/{external-optimizer-process-DYNizz8W.js → external-optimizer-process-C4AyCcQd.js}
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { n as contentHash } from "./verdict-cache-mZf5FEiY.js";
|
|
2
2
|
import { m as tryAcquireAtomicFileLock, p as probeAtomicFileLock } from "./ledger-core-DTae9rv_.js";
|
|
3
|
-
import { _ as resolveExternalOptimizerCallbackLimits, a as closeServer, h as isRecord, m as isExternalTextCandidate, o as listenLocal, s as sendJson } from "./external-optimizer-subprocess-
|
|
3
|
+
import { _ as resolveExternalOptimizerCallbackLimits, a as closeServer, h as isRecord, m as isExternalTextCandidate, o as listenLocal, s as sendJson } from "./external-optimizer-subprocess-DU1KM8yV.js";
|
|
4
4
|
import { createServer } from "node:http";
|
|
5
5
|
//#region src/campaign/single-run-lock.ts
|
|
6
6
|
/**
|
|
@@ -298,4 +298,4 @@ function cloneCandidate(candidate) {
|
|
|
298
298
|
//#endregion
|
|
299
299
|
export { acquireSingleRunLock as n, startExternalOptimizerCallback as t };
|
|
300
300
|
|
|
301
|
-
//# sourceMappingURL=external-optimizer-process-
|
|
301
|
+
//# sourceMappingURL=external-optimizer-process-C4AyCcQd.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"external-optimizer-process-DYNizz8W.js","names":[],"sources":["../src/campaign/single-run-lock.ts","../src/campaign/external-optimizer-callback.ts"],"sourcesContent":["/**\n * Single-run lock for evaluations that share one mutable environment.\n *\n * Two concurrent runs against a shared stateful gym silently corrupt each\n * other: each resets/mutates environment state mid-cell of the other, and\n * every score from both becomes garbage that LOOKS like worker variance\n * (agent-lab R357 burned hours on flip-flopping scores before tracing them\n * to exactly this). The fix is a pid lockfile: refuse to start while a live\n * holder exists, reclaim stale locks whose pid is gone, release only if the\n * lock is still ours.\n *\n * `alsoCheck` exists because independent runners can guard the same shared\n * resource with differently named lockfiles; a runner must respect all of\n * them even though it writes only its own.\n */\n\nimport {\n type AtomicFileLockUnavailable,\n probeAtomicFileLock,\n tryAcquireAtomicFileLock,\n} from '../ledger-core/atomic-file-lock'\n\nexport interface SingleRunLockOptions {\n /** Lockfile this runner writes (and checks). */\n readonly lockPath: string\n /** Other runners' lockfiles guarding the same resource; checked, never written. */\n readonly alsoCheck?: readonly string[]\n /** Install a process 'exit' hook that releases the lock. Default true. */\n readonly releaseOnExit?: boolean\n /** Owner pid recorded in the lockfile metadata. Default process.pid. */\n readonly pid?: number\n}\n\nexport interface SingleRunLock {\n /** Remove the lockfile if this process still owns it. Idempotent. */\n release(): void\n}\n\nfunction assertAvailable(path: string): void {\n const unavailable = probeAtomicFileLock({ lockPath: path })\n if (unavailable) throw unavailableError(path, unavailable)\n}\n\nfunction unavailableError(path: string, unavailable: AtomicFileLockUnavailable): Error {\n if (unavailable.reason === 'recovery') {\n return new Error(\n `single-run lock recovery is already in progress (${path}); refusing a concurrent run`,\n )\n }\n return new Error(\n `single-run lock held by live pid ${unavailable.holder.pid} (${path}); refusing a concurrent run on the shared resource`,\n )\n}\n\n/**\n * Acquire the lock or throw naming the live holder. A stale lock (holder pid\n * no longer running) is reclaimed by one contender. An interrupted reclaim\n * leaves a marker that fails closed instead of admitting overlapping runs.\n */\nexport function acquireSingleRunLock(opts: SingleRunLockOptions): SingleRunLock {\n const pid = opts.pid ?? process.pid\n if (!Number.isSafeInteger(pid) || pid <= 0)\n throw new Error('single-run lock pid must be a positive integer')\n for (const path of opts.alsoCheck ?? []) assertAvailable(path)\n const acquisition = tryAcquireAtomicFileLock({\n lockPath: opts.lockPath,\n pid,\n })\n if (!acquisition.acquired) throw unavailableError(opts.lockPath, acquisition)\n const releaseOnExit = opts.releaseOnExit ?? true\n let released = false\n const release = (): void => {\n if (released) return\n released = true\n if (releaseOnExit) process.off('exit', release)\n try {\n acquisition.lock.release()\n } catch {\n // release is best-effort; a leftover stale lock is reclaimed on next acquire\n }\n }\n try {\n for (const path of opts.alsoCheck ?? []) assertAvailable(path)\n } catch (error) {\n release()\n throw error\n }\n if (releaseOnExit) process.on('exit', release)\n return { release }\n}\n","import { createServer, type IncomingMessage, type ServerResponse } from 'node:http'\nimport { contentHash } from '../verdict-cache'\nimport {\n type ExternalOptimizerCallback,\n type ExternalOptimizerCallbackLimits,\n type ExternalOptimizerEvaluationObservation,\n type ExternalTextCandidate,\n type ExternalTextEvaluationRequest,\n isExternalTextCandidate,\n isRecord,\n resolveExternalOptimizerCallbackLimits,\n} from './external-optimizer-contracts'\nimport { closeServer, listenLocal, sendJson } from './external-optimizer-http'\n\ntype UnsequencedObservation = ExternalOptimizerEvaluationObservation extends infer T\n ? T extends ExternalOptimizerEvaluationObservation\n ? Omit<T, 'sequence'>\n : never\n : never\n\nexport async function startExternalOptimizerCallback<TResponse>(args: {\n token: string\n maxEvaluations: number\n acceptEvaluation?: () => number | undefined\n evaluate: (request: ExternalTextEvaluationRequest, signal: AbortSignal) => Promise<TResponse>\n observe?: (observation: ExternalOptimizerEvaluationObservation) => void\n /** Loopback JSON byte limits. Omitted fields use finite defaults. */\n limits?: Partial<ExternalOptimizerCallbackLimits>\n signal?: AbortSignal\n}): Promise<ExternalOptimizerCallback> {\n assertCallbackConfig(args)\n const limits = resolveExternalOptimizerCallbackLimits(args.limits)\n args.signal?.throwIfAborted()\n let evaluations = 0\n let accepting = true\n let closePromise: Promise<void> | undefined\n const activeControllers = new Set<AbortController>()\n const activeHandlers = new Set<Promise<void>>()\n const proposedCandidateHashes = new Set<string>()\n let observationSequence = 0\n const server = createServer((request, response) => {\n if (!accepting) {\n sendJsonIfOpen(response, 503, { error: 'external optimizer callback is closing' })\n return\n }\n\n const controller = new AbortController()\n const abortRequest = (): void => {\n request.destroy()\n response.destroy()\n }\n activeControllers.add(controller)\n controller.signal.addEventListener('abort', abortRequest, { once: true })\n\n let handler!: Promise<void>\n handler = handleCallback(\n request,\n response,\n controller.signal,\n args,\n limits,\n () => {\n const accepted = args.acceptEvaluation ? args.acceptEvaluation() : evaluations + 1\n if (accepted === undefined) return undefined\n if (!Number.isSafeInteger(accepted) || accepted <= 0) {\n throw new Error('external optimizer callback: invalid accepted evaluation count')\n }\n if (accepted > args.maxEvaluations) return undefined\n evaluations += 1\n return accepted\n },\n (observation) => {\n if (!args.observe) return\n args.observe({ ...observation, sequence: ++observationSequence })\n },\n proposedCandidateHashes,\n ).finally(() => {\n controller.signal.removeEventListener('abort', abortRequest)\n activeControllers.delete(controller)\n activeHandlers.delete(handler)\n })\n activeHandlers.add(handler)\n void handler.catch(() => undefined)\n })\n const port = await listenLocal(server)\n const close = (): Promise<void> => {\n closePromise ??= closeCallbackServer()\n return closePromise\n }\n const onAbort = (): void => {\n void close().catch(() => undefined)\n }\n args.signal?.addEventListener('abort', onAbort, { once: true })\n if (args.signal?.aborted) onAbort()\n return {\n url: `http://127.0.0.1:${port}/evaluate`,\n token: args.token,\n evaluations: () => evaluations,\n close,\n }\n\n async function closeCallbackServer(): Promise<void> {\n args.signal?.removeEventListener('abort', onAbort)\n accepting = false\n const closingServer = closeServer(server)\n server.closeIdleConnections?.()\n for (const controller of activeControllers) controller.abort()\n const [serverResult] = await Promise.allSettled([\n closingServer,\n waitForActiveHandlers(activeHandlers),\n ])\n if (activeControllers.size !== 0 || activeHandlers.size !== 0) {\n throw new Error('external optimizer callback closed with active request work')\n }\n if (serverResult?.status === 'rejected') throw serverResult.reason\n }\n}\n\nasync function handleCallback<TResponse>(\n request: IncomingMessage,\n response: ServerResponse,\n signal: AbortSignal,\n args: {\n token: string\n maxEvaluations: number\n acceptEvaluation?: () => number | undefined\n evaluate: (request: ExternalTextEvaluationRequest, signal: AbortSignal) => Promise<TResponse>\n observe?: (observation: ExternalOptimizerEvaluationObservation) => void\n },\n limits: ExternalOptimizerCallbackLimits,\n nextEvaluation: () => number | undefined,\n observe: (observation: UnsequencedObservation) => void,\n proposedCandidateHashes: Set<string>,\n): Promise<void> {\n try {\n if (request.method !== 'POST' || request.url !== '/evaluate') {\n sendJsonIfOpen(response, 404, { error: 'not found' })\n return\n }\n if (request.headers.authorization !== `Bearer ${args.token}`) {\n sendJsonIfOpen(response, 401, { error: 'unauthorized' })\n return\n }\n let body: unknown\n try {\n body = await readJson(request, limits.maxRequestBytes)\n } catch {\n observe({ kind: 'refusal', reason: 'invalid-request' })\n sendJsonIfOpen(response, 400, { error: 'request body must be bounded valid JSON' })\n return\n }\n if (\n !isRecord(body) ||\n !isExternalTextCandidate(body.candidate) ||\n typeof body.exampleId !== 'string'\n ) {\n observe({ kind: 'refusal', reason: 'invalid-request' })\n sendJsonIfOpen(response, 400, { error: 'candidate and exampleId are required strings' })\n return\n }\n const candidate = cloneCandidate(body.candidate)\n const candidateHash = contentHash({ kind: 'external-text-candidate', candidate })\n if (!proposedCandidateHashes.has(candidateHash)) {\n observe({ kind: 'proposal', candidate, candidateHash })\n proposedCandidateHashes.add(candidateHash)\n }\n const count = nextEvaluation()\n if (count === undefined) {\n observe({\n kind: 'refusal',\n reason: 'evaluation-limit',\n candidate,\n candidateHash,\n exampleId: body.exampleId,\n })\n sendJsonIfOpen(response, 429, { error: 'evaluation limit reached' })\n return\n }\n let result: TResponse\n try {\n result = await args.evaluate({ candidate, exampleId: body.exampleId }, signal)\n } catch {\n observe({\n kind: 'refusal',\n reason: 'evaluation-failed',\n candidate,\n candidateHash,\n exampleId: body.exampleId,\n })\n sendJsonIfOpen(response, 500, { error: 'evaluation failed' })\n return\n }\n let encoded: string\n try {\n encoded = encodeJsonResponse(result)\n } catch {\n observe({\n kind: 'refusal',\n reason: 'evaluation-failed',\n candidate,\n candidateHash,\n exampleId: body.exampleId,\n })\n sendJsonIfOpen(response, 500, { error: 'evaluation response must be valid JSON' })\n return\n }\n if (Buffer.byteLength(encoded) > limits.maxResponseBytes) {\n observe({\n kind: 'refusal',\n reason: 'evaluation-failed',\n candidate,\n candidateHash,\n exampleId: body.exampleId,\n })\n sendJsonIfOpen(response, 413, { error: 'evaluation response too large' })\n return\n }\n observe({\n kind: 'evaluation',\n candidate,\n candidateHash,\n exampleId: body.exampleId,\n evaluationNumber: count,\n response: structuredClone(result),\n })\n sendEncodedJsonIfOpen(response, 200, encoded)\n } catch {\n sendJsonIfOpen(response, 500, { error: 'evaluation failed' })\n }\n}\n\nasync function waitForActiveHandlers(activeHandlers: Set<Promise<void>>): Promise<void> {\n while (activeHandlers.size > 0) {\n await Promise.allSettled([...activeHandlers])\n }\n}\n\nfunction sendJsonIfOpen(response: ServerResponse, status: number, body: unknown): void {\n if (response.destroyed || response.writableEnded) return\n sendJson(response, status, body)\n}\n\nfunction readJson(request: IncomingMessage, maxRequestBytes: number): Promise<unknown> {\n return new Promise((resolvePromise, reject) => {\n let size = 0\n const chunks: Buffer[] = []\n request.on('data', (chunk: Buffer) => {\n size += chunk.length\n if (size > maxRequestBytes) {\n reject(new Error('callback body too large'))\n request.destroy()\n return\n }\n chunks.push(chunk)\n })\n request.on('error', reject)\n request.on('end', () => {\n try {\n resolvePromise(JSON.parse(Buffer.concat(chunks).toString('utf8')))\n } catch (error) {\n reject(error)\n }\n })\n })\n}\n\nfunction encodeJsonResponse(value: unknown): string {\n const encoded = JSON.stringify(value)\n if (encoded === undefined) throw new Error('evaluation response must be JSON-serializable')\n return encoded\n}\n\nfunction sendEncodedJsonIfOpen(response: ServerResponse, status: number, encoded: string): void {\n if (response.destroyed || response.writableEnded) return\n response.writeHead(status, {\n 'content-type': 'application/json; charset=utf-8',\n 'content-length': String(Buffer.byteLength(encoded)),\n })\n response.end(encoded)\n}\n\nfunction assertCallbackConfig(args: {\n token: string\n maxEvaluations: number\n acceptEvaluation?: () => number | undefined\n evaluate: (request: ExternalTextEvaluationRequest, signal: AbortSignal) => Promise<unknown>\n observe?: (observation: ExternalOptimizerEvaluationObservation) => void\n limits?: Partial<ExternalOptimizerCallbackLimits>\n signal?: AbortSignal\n}): void {\n if (typeof args.token !== 'string' || !args.token.trim()) {\n throw new Error('external optimizer callback: token must be non-empty')\n }\n if (!Number.isSafeInteger(args.maxEvaluations) || args.maxEvaluations <= 0) {\n throw new Error('external optimizer callback: maxEvaluations must be a positive safe integer')\n }\n if (args.acceptEvaluation !== undefined && typeof args.acceptEvaluation !== 'function') {\n throw new Error('external optimizer callback: acceptEvaluation must be a function')\n }\n if (typeof args.evaluate !== 'function') {\n throw new Error('external optimizer callback: evaluate must be a function')\n }\n if (args.observe !== undefined && typeof args.observe !== 'function') {\n throw new Error('external optimizer callback: observe must be a function')\n }\n}\n\nfunction cloneCandidate(candidate: ExternalTextCandidate): ExternalTextCandidate {\n return typeof candidate === 'string' ? candidate : { ...candidate }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"external-optimizer-process-C4AyCcQd.js","names":[],"sources":["../src/campaign/single-run-lock.ts","../src/campaign/external-optimizer-callback.ts"],"sourcesContent":["/**\n * Single-run lock for evaluations that share one mutable environment.\n *\n * Two concurrent runs against a shared stateful gym silently corrupt each\n * other: each resets/mutates environment state mid-cell of the other, and\n * every score from both becomes garbage that LOOKS like worker variance\n * (agent-lab R357 burned hours on flip-flopping scores before tracing them\n * to exactly this). The fix is a pid lockfile: refuse to start while a live\n * holder exists, reclaim stale locks whose pid is gone, release only if the\n * lock is still ours.\n *\n * `alsoCheck` exists because independent runners can guard the same shared\n * resource with differently named lockfiles; a runner must respect all of\n * them even though it writes only its own.\n */\n\nimport {\n type AtomicFileLockUnavailable,\n probeAtomicFileLock,\n tryAcquireAtomicFileLock,\n} from '../ledger-core/atomic-file-lock'\n\nexport interface SingleRunLockOptions {\n /** Lockfile this runner writes (and checks). */\n readonly lockPath: string\n /** Other runners' lockfiles guarding the same resource; checked, never written. */\n readonly alsoCheck?: readonly string[]\n /** Install a process 'exit' hook that releases the lock. Default true. */\n readonly releaseOnExit?: boolean\n /** Owner pid recorded in the lockfile metadata. Default process.pid. */\n readonly pid?: number\n}\n\nexport interface SingleRunLock {\n /** Remove the lockfile if this process still owns it. Idempotent. */\n release(): void\n}\n\nfunction assertAvailable(path: string): void {\n const unavailable = probeAtomicFileLock({ lockPath: path })\n if (unavailable) throw unavailableError(path, unavailable)\n}\n\nfunction unavailableError(path: string, unavailable: AtomicFileLockUnavailable): Error {\n if (unavailable.reason === 'recovery') {\n return new Error(\n `single-run lock recovery is already in progress (${path}); refusing a concurrent run`,\n )\n }\n return new Error(\n `single-run lock held by live pid ${unavailable.holder.pid} (${path}); refusing a concurrent run on the shared resource`,\n )\n}\n\n/**\n * Acquire the lock or throw naming the live holder. A stale lock (holder pid\n * no longer running) is reclaimed by one contender. An interrupted reclaim\n * leaves a marker that fails closed instead of admitting overlapping runs.\n */\nexport function acquireSingleRunLock(opts: SingleRunLockOptions): SingleRunLock {\n const pid = opts.pid ?? process.pid\n if (!Number.isSafeInteger(pid) || pid <= 0)\n throw new Error('single-run lock pid must be a positive integer')\n for (const path of opts.alsoCheck ?? []) assertAvailable(path)\n const acquisition = tryAcquireAtomicFileLock({\n lockPath: opts.lockPath,\n pid,\n })\n if (!acquisition.acquired) throw unavailableError(opts.lockPath, acquisition)\n const releaseOnExit = opts.releaseOnExit ?? true\n let released = false\n const release = (): void => {\n if (released) return\n released = true\n if (releaseOnExit) process.off('exit', release)\n try {\n acquisition.lock.release()\n } catch {\n // release is best-effort; a leftover stale lock is reclaimed on next acquire\n }\n }\n try {\n for (const path of opts.alsoCheck ?? []) assertAvailable(path)\n } catch (error) {\n release()\n throw error\n }\n if (releaseOnExit) process.on('exit', release)\n return { release }\n}\n","import { createServer, type IncomingMessage, type ServerResponse } from 'node:http'\nimport { contentHash } from '../verdict-cache'\nimport {\n type ExternalOptimizerCallback,\n type ExternalOptimizerCallbackLimits,\n type ExternalOptimizerEvaluationObservation,\n type ExternalTextCandidate,\n type ExternalTextEvaluationRequest,\n isExternalTextCandidate,\n isRecord,\n resolveExternalOptimizerCallbackLimits,\n} from './external-optimizer-contracts'\nimport { closeServer, listenLocal, sendJson } from './external-optimizer-http'\n\ntype UnsequencedObservation = ExternalOptimizerEvaluationObservation extends infer T\n ? T extends ExternalOptimizerEvaluationObservation\n ? Omit<T, 'sequence'>\n : never\n : never\n\nexport async function startExternalOptimizerCallback<TResponse>(args: {\n token: string\n maxEvaluations: number\n acceptEvaluation?: () => number | undefined\n evaluate: (request: ExternalTextEvaluationRequest, signal: AbortSignal) => Promise<TResponse>\n observe?: (observation: ExternalOptimizerEvaluationObservation) => void\n /** Loopback JSON byte limits. Omitted fields use finite defaults. */\n limits?: Partial<ExternalOptimizerCallbackLimits>\n signal?: AbortSignal\n}): Promise<ExternalOptimizerCallback> {\n assertCallbackConfig(args)\n const limits = resolveExternalOptimizerCallbackLimits(args.limits)\n args.signal?.throwIfAborted()\n let evaluations = 0\n let accepting = true\n let closePromise: Promise<void> | undefined\n const activeControllers = new Set<AbortController>()\n const activeHandlers = new Set<Promise<void>>()\n const proposedCandidateHashes = new Set<string>()\n let observationSequence = 0\n const server = createServer((request, response) => {\n if (!accepting) {\n sendJsonIfOpen(response, 503, { error: 'external optimizer callback is closing' })\n return\n }\n\n const controller = new AbortController()\n const abortRequest = (): void => {\n request.destroy()\n response.destroy()\n }\n activeControllers.add(controller)\n controller.signal.addEventListener('abort', abortRequest, { once: true })\n\n let handler!: Promise<void>\n handler = handleCallback(\n request,\n response,\n controller.signal,\n args,\n limits,\n () => {\n const accepted = args.acceptEvaluation ? args.acceptEvaluation() : evaluations + 1\n if (accepted === undefined) return undefined\n if (!Number.isSafeInteger(accepted) || accepted <= 0) {\n throw new Error('external optimizer callback: invalid accepted evaluation count')\n }\n if (accepted > args.maxEvaluations) return undefined\n evaluations += 1\n return accepted\n },\n (observation) => {\n if (!args.observe) return\n args.observe({ ...observation, sequence: ++observationSequence })\n },\n proposedCandidateHashes,\n ).finally(() => {\n controller.signal.removeEventListener('abort', abortRequest)\n activeControllers.delete(controller)\n activeHandlers.delete(handler)\n })\n activeHandlers.add(handler)\n void handler.catch(() => undefined)\n })\n const port = await listenLocal(server)\n const close = (): Promise<void> => {\n closePromise ??= closeCallbackServer()\n return closePromise\n }\n const onAbort = (): void => {\n void close().catch(() => undefined)\n }\n args.signal?.addEventListener('abort', onAbort, { once: true })\n if (args.signal?.aborted) onAbort()\n return {\n url: `http://127.0.0.1:${port}/evaluate`,\n token: args.token,\n evaluations: () => evaluations,\n close,\n }\n\n async function closeCallbackServer(): Promise<void> {\n args.signal?.removeEventListener('abort', onAbort)\n accepting = false\n const closingServer = closeServer(server)\n server.closeIdleConnections?.()\n for (const controller of activeControllers) controller.abort()\n const [serverResult] = await Promise.allSettled([\n closingServer,\n waitForActiveHandlers(activeHandlers),\n ])\n if (activeControllers.size !== 0 || activeHandlers.size !== 0) {\n throw new Error('external optimizer callback closed with active request work')\n }\n if (serverResult?.status === 'rejected') throw serverResult.reason\n }\n}\n\nasync function handleCallback<TResponse>(\n request: IncomingMessage,\n response: ServerResponse,\n signal: AbortSignal,\n args: {\n token: string\n maxEvaluations: number\n acceptEvaluation?: () => number | undefined\n evaluate: (request: ExternalTextEvaluationRequest, signal: AbortSignal) => Promise<TResponse>\n observe?: (observation: ExternalOptimizerEvaluationObservation) => void\n },\n limits: ExternalOptimizerCallbackLimits,\n nextEvaluation: () => number | undefined,\n observe: (observation: UnsequencedObservation) => void,\n proposedCandidateHashes: Set<string>,\n): Promise<void> {\n try {\n if (request.method !== 'POST' || request.url !== '/evaluate') {\n sendJsonIfOpen(response, 404, { error: 'not found' })\n return\n }\n if (request.headers.authorization !== `Bearer ${args.token}`) {\n sendJsonIfOpen(response, 401, { error: 'unauthorized' })\n return\n }\n let body: unknown\n try {\n body = await readJson(request, limits.maxRequestBytes)\n } catch {\n observe({ kind: 'refusal', reason: 'invalid-request' })\n sendJsonIfOpen(response, 400, { error: 'request body must be bounded valid JSON' })\n return\n }\n if (\n !isRecord(body) ||\n !isExternalTextCandidate(body.candidate) ||\n typeof body.exampleId !== 'string'\n ) {\n observe({ kind: 'refusal', reason: 'invalid-request' })\n sendJsonIfOpen(response, 400, { error: 'candidate and exampleId are required strings' })\n return\n }\n const candidate = cloneCandidate(body.candidate)\n const candidateHash = contentHash({ kind: 'external-text-candidate', candidate })\n if (!proposedCandidateHashes.has(candidateHash)) {\n observe({ kind: 'proposal', candidate, candidateHash })\n proposedCandidateHashes.add(candidateHash)\n }\n const count = nextEvaluation()\n if (count === undefined) {\n observe({\n kind: 'refusal',\n reason: 'evaluation-limit',\n candidate,\n candidateHash,\n exampleId: body.exampleId,\n })\n sendJsonIfOpen(response, 429, { error: 'evaluation limit reached' })\n return\n }\n let result: TResponse\n try {\n result = await args.evaluate({ candidate, exampleId: body.exampleId }, signal)\n } catch {\n observe({\n kind: 'refusal',\n reason: 'evaluation-failed',\n candidate,\n candidateHash,\n exampleId: body.exampleId,\n })\n sendJsonIfOpen(response, 500, { error: 'evaluation failed' })\n return\n }\n let encoded: string\n try {\n encoded = encodeJsonResponse(result)\n } catch {\n observe({\n kind: 'refusal',\n reason: 'evaluation-failed',\n candidate,\n candidateHash,\n exampleId: body.exampleId,\n })\n sendJsonIfOpen(response, 500, { error: 'evaluation response must be valid JSON' })\n return\n }\n if (Buffer.byteLength(encoded) > limits.maxResponseBytes) {\n observe({\n kind: 'refusal',\n reason: 'evaluation-failed',\n candidate,\n candidateHash,\n exampleId: body.exampleId,\n })\n sendJsonIfOpen(response, 413, { error: 'evaluation response too large' })\n return\n }\n observe({\n kind: 'evaluation',\n candidate,\n candidateHash,\n exampleId: body.exampleId,\n evaluationNumber: count,\n response: structuredClone(result),\n })\n sendEncodedJsonIfOpen(response, 200, encoded)\n } catch {\n sendJsonIfOpen(response, 500, { error: 'evaluation failed' })\n }\n}\n\nasync function waitForActiveHandlers(activeHandlers: Set<Promise<void>>): Promise<void> {\n while (activeHandlers.size > 0) {\n await Promise.allSettled([...activeHandlers])\n }\n}\n\nfunction sendJsonIfOpen(response: ServerResponse, status: number, body: unknown): void {\n if (response.destroyed || response.writableEnded) return\n sendJson(response, status, body)\n}\n\nfunction readJson(request: IncomingMessage, maxRequestBytes: number): Promise<unknown> {\n return new Promise((resolvePromise, reject) => {\n let size = 0\n const chunks: Buffer[] = []\n request.on('data', (chunk: Buffer) => {\n size += chunk.length\n if (size > maxRequestBytes) {\n reject(new Error('callback body too large'))\n request.destroy()\n return\n }\n chunks.push(chunk)\n })\n request.on('error', reject)\n request.on('end', () => {\n try {\n resolvePromise(JSON.parse(Buffer.concat(chunks).toString('utf8')))\n } catch (error) {\n reject(error)\n }\n })\n })\n}\n\nfunction encodeJsonResponse(value: unknown): string {\n const encoded = JSON.stringify(value)\n if (encoded === undefined) throw new Error('evaluation response must be JSON-serializable')\n return encoded\n}\n\nfunction sendEncodedJsonIfOpen(response: ServerResponse, status: number, encoded: string): void {\n if (response.destroyed || response.writableEnded) return\n response.writeHead(status, {\n 'content-type': 'application/json; charset=utf-8',\n 'content-length': String(Buffer.byteLength(encoded)),\n })\n response.end(encoded)\n}\n\nfunction assertCallbackConfig(args: {\n token: string\n maxEvaluations: number\n acceptEvaluation?: () => number | undefined\n evaluate: (request: ExternalTextEvaluationRequest, signal: AbortSignal) => Promise<unknown>\n observe?: (observation: ExternalOptimizerEvaluationObservation) => void\n limits?: Partial<ExternalOptimizerCallbackLimits>\n signal?: AbortSignal\n}): void {\n if (typeof args.token !== 'string' || !args.token.trim()) {\n throw new Error('external optimizer callback: token must be non-empty')\n }\n if (!Number.isSafeInteger(args.maxEvaluations) || args.maxEvaluations <= 0) {\n throw new Error('external optimizer callback: maxEvaluations must be a positive safe integer')\n }\n if (args.acceptEvaluation !== undefined && typeof args.acceptEvaluation !== 'function') {\n throw new Error('external optimizer callback: acceptEvaluation must be a function')\n }\n if (typeof args.evaluate !== 'function') {\n throw new Error('external optimizer callback: evaluate must be a function')\n }\n if (args.observe !== undefined && typeof args.observe !== 'function') {\n throw new Error('external optimizer callback: observe must be a function')\n }\n}\n\nfunction cloneCandidate(candidate: ExternalTextCandidate): ExternalTextCandidate {\n return typeof candidate === 'string' ? candidate : { ...candidate }\n}\n"],"mappings":"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"}
|
package/dist/{external-optimizer-subprocess-r6dP9DAj.js → external-optimizer-subprocess-DU1KM8yV.js}
RENAMED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { s as ValidationError } from "./errors-Dngq5h35.js";
|
|
2
2
|
import { t as canonicalJson } from "./verdict-cache-mZf5FEiY.js";
|
|
3
|
-
import { c as costForTokenPricing, i as CostLedger } from "./cost-ledger-
|
|
3
|
+
import { c as costForTokenPricing, i as CostLedger } from "./cost-ledger-B1qx30B4.js";
|
|
4
4
|
import { a as appendLedgerLine, o as tryWithLedgerFileLock } from "./ledger-core-DTae9rv_.js";
|
|
5
|
-
import { h as ModelSubstitutionError, v as assertServedModel } from "./llm-client-
|
|
5
|
+
import { h as ModelSubstitutionError, v as assertServedModel } from "./llm-client-BMuxYoZy.js";
|
|
6
6
|
import { createRequire } from "node:module";
|
|
7
7
|
import { randomBytes } from "node:crypto";
|
|
8
8
|
import { isAbsolute, join, resolve } from "node:path";
|
|
@@ -1350,4 +1350,4 @@ function summarizeProcessOutput(capture, max = 4e3) {
|
|
|
1350
1350
|
//#endregion
|
|
1351
1351
|
export { SEARCH_LEDGER_FILE_CONTEXT as C, SearchLedgerIntegrityError as E, inMemoryCampaignStorage as S, SearchLedgerError as T, resolveExternalOptimizerCallbackLimits as _, closeServer as a, createRunCostLedger as b, DEFAULT_EXTERNAL_OPTIMIZER_CALLBACK_LIMITS as c, assertJsonValue as d, assertNoCredentialValues as f, removeCredentialEnvironment as g, isRecord as h, startExternalOptimizerModelProxy as i, DEFAULT_EXTERNAL_OPTIMIZER_PROCESS_LIMITS as l, isExternalTextCandidate as m, closeExternalOptimizerResources as n, listenLocal as o, isCandidateText as p, runWithCleanup as r, sendJson as s, runExternalOptimizerProcess as t, assertExternalOptimizerModelBudget as u, resolveExternalOptimizerProcessLimits as v, SearchLedgerConflictError as w, fsCampaignStorage as x, safePathComponent as y };
|
|
1352
1352
|
|
|
1353
|
-
//# sourceMappingURL=external-optimizer-subprocess-
|
|
1353
|
+
//# sourceMappingURL=external-optimizer-subprocess-DU1KM8yV.js.map
|