@tangle-network/agent-runtime 0.194.0 → 0.195.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/dist/{activation-BQFIiyUG.js → activation-DtIbcFOX.js} +3 -3
  2. package/dist/{activation-BQFIiyUG.js.map → activation-DtIbcFOX.js.map} +1 -1
  3. package/dist/agent.d.ts +1 -1
  4. package/dist/agent.js +1 -1
  5. package/dist/candidate-execution/index.js +4 -4
  6. package/dist/{candidate-execution-B6CDW-fp.js → candidate-execution-nvqVIMyS.js} +5 -4
  7. package/dist/{candidate-execution-B6CDW-fp.js.map → candidate-execution-nvqVIMyS.js.map} +1 -1
  8. package/dist/durable.d.ts +1 -1
  9. package/dist/graph.d.ts +1 -1
  10. package/dist/{improve-COGzLCiY.d.ts → improve-7VTwse1c.d.ts} +4 -4
  11. package/dist/{improvement-cycle-DeS1ZC5B.js → improvement-cycle-bTBySunH.js} +19 -5
  12. package/dist/{improvement-cycle-DeS1ZC5B.js.map → improvement-cycle-bTBySunH.js.map} +1 -1
  13. package/dist/{index-CrBgLCIf.d.ts → index-CVD30soi.d.ts} +2 -2
  14. package/dist/{index-BEPjOPwH.d.ts → index-DNx0nWZH.d.ts} +9 -2
  15. package/dist/index.d.ts +6 -5
  16. package/dist/index.js +71 -25
  17. package/dist/index.js.map +1 -1
  18. package/dist/intelligence.d.ts +1 -1
  19. package/dist/intelligence.js +5 -4
  20. package/dist/intelligence.js.map +1 -1
  21. package/dist/kernel.d.ts +1 -1
  22. package/dist/kernel.js +2 -2
  23. package/dist/{knowledge-B5okOzBQ.js → knowledge-U8WJ5xCI.js} +6 -16
  24. package/dist/knowledge-U8WJ5xCI.js.map +1 -0
  25. package/dist/knowledge.d.ts +1 -1
  26. package/dist/knowledge.js +1 -1
  27. package/dist/{loop-runner-bin-U1J6x_UF.js → loop-runner-bin-BU2NACsF.js} +2 -2
  28. package/dist/{loop-runner-bin-U1J6x_UF.js.map → loop-runner-bin-BU2NACsF.js.map} +1 -1
  29. package/dist/{loop-runner-bin-Clc5IAwu.d.ts → loop-runner-bin-b4585v9Z.d.ts} +2 -2
  30. package/dist/loop-runner-bin.d.ts +1 -1
  31. package/dist/loop-runner-bin.js +1 -1
  32. package/dist/mcp/index.d.ts +1 -1
  33. package/dist/mcp/index.js +1 -1
  34. package/dist/{prepare-C29kNAon.js → prepare-DDGp0-rW.js} +4 -54
  35. package/dist/prepare-DDGp0-rW.js.map +1 -0
  36. package/dist/profiles.js +454 -1
  37. package/dist/profiles.js.map +1 -1
  38. package/dist/{protected-model-port-CKYND416.js → protected-model-port-DxFN8DLS.js} +3 -2
  39. package/dist/{protected-model-port-CKYND416.js.map → protected-model-port-DxFN8DLS.js.map} +1 -1
  40. package/dist/{protected-redaction--F3v1oo8.js → protected-redaction-wGo44k2K.js} +54 -3
  41. package/dist/protected-redaction-wGo44k2K.js.map +1 -0
  42. package/dist/{runtime-BVrqSu0-.js → runtime-CuNJ0opC.js} +133 -58
  43. package/dist/runtime-CuNJ0opC.js.map +1 -0
  44. package/dist/{structural-rollout-BcPXFzVb.js → structural-rollout-DxEQ77H7.js} +22 -9
  45. package/dist/structural-rollout-DxEQ77H7.js.map +1 -0
  46. package/dist/testing.d.ts +1 -1
  47. package/dist/testing.js +11 -10
  48. package/dist/testing.js.map +1 -1
  49. package/dist/tui/index.d.ts +1 -1
  50. package/dist/{workspace-archive-BCezkeIk.js → workspace-archive-Ybomp7AN.js} +3 -2
  51. package/dist/{workspace-archive-BCezkeIk.js.map → workspace-archive-Ybomp7AN.js.map} +1 -1
  52. package/package.json +4 -4
  53. package/skills/agent-graphs/SKILL.md +28 -123
  54. package/skills/agent-graphs/references/authoring.md +34 -0
  55. package/skills/agent-graphs/references/measurement.md +18 -0
  56. package/skills/build-with-agent-runtime/SKILL.md +31 -117
  57. package/skills/build-with-agent-runtime/references/improvement.md +32 -0
  58. package/skills/codemode/SKILL.md +22 -34
  59. package/skills/codemode/references/runtime-execution.md +14 -0
  60. package/skills/generate-eval/SKILL.md +2 -1
  61. package/skills/loop-writer/SKILL.md +30 -84
  62. package/skills/supervise/SKILL.md +43 -95
  63. package/skills/supervise/references/profile-authoring.md +19 -0
  64. package/dist/knowledge-B5okOzBQ.js.map +0 -1
  65. package/dist/prepare-C29kNAon.js.map +0 -1
  66. package/dist/protected-redaction--F3v1oo8.js.map +0 -1
  67. package/dist/researcher-Cp4JRbFp.js +0 -457
  68. package/dist/researcher-Cp4JRbFp.js.map +0 -1
  69. package/dist/runtime-BVrqSu0-.js.map +0 -1
  70. package/dist/structural-rollout-BcPXFzVb.js.map +0 -1
  71. package/skills/agent-graphs/IMPROVE.md +0 -58
@@ -1,13 +1,14 @@
1
+ import { E as detachedFrozen } from "./materialization-vZssF9Nx.js";
1
2
  import { m as ValidationError, n as AnalystError, s as PlannerError } from "./errors-CDZ8XsVj.js";
2
3
  import "./stream-agent-turn-DOtEsvCV.js";
3
- import { i as redactProtectedValue, r as redactProtectedReason } from "./protected-redaction--F3v1oo8.js";
4
+ import { f as sha256Bytes, i as redactProtectedValue, o as canonicalCandidateDigest$1, r as redactProtectedReason, u as immutableCandidateValue } from "./protected-redaction-wGo44k2K.js";
4
5
  import { l as notifySandboxEventObserver } from "./sandbox-events-DWeQRWxg.js";
5
6
  import { a as executableAgentProfileSnapshot, i as writeAllBytes, n as parseCommittedJsonLines, o as executableAgentSpecSnapshot, r as prepareJsonlAppend, t as isNoEntError } from "./jsonl-file-Bh1Q9nt0.js";
6
7
  import { c as profileModelExecutionSettings, i as concreteModelId, l as profileProviderModel, o as enforceTokenLimits, t as assertExecutableAgentProfile } from "./model-policy-Wf2MxXJ9.js";
7
8
  import { C as settledToIteration, Ht as InMemorySpawnJournal, Vt as InMemoryResultBlobStore, Wt as insideCursorNamespace, Y as rollingDispatch, Zt as isTraceAnalysisStore, a as createSupervisor, an as runAgentRounds, bt as createPushTraceSource, dn as routerBrain, en as contentAddress, fn as runBrainLoop, ft as createWorktreeCliExecutor, h as withDriverExecutor, ln as assertBoxlessPromptOptions, lt as createExecutor, on as createSandboxLineage, pn as canonicalObservedModelParts, rn as defaultSelectWinner, sn as probeSandboxCapabilities, un as readPromptOptions, ut as createExecutorRegistry } from "./redact-BOU77QfQ.js";
8
9
  import { E as zeroSpend, _ as randomSuffix, b as sleep, l as chargedTokens, m as isAbortError, p as hasCompleteCacheBreakdown, s as addSpend, u as cloneSpend, x as stringifySafe } from "./environment-provider-Dr-wfnHg.js";
9
10
  import { i as notifyRuntimeHookEvent } from "./runtime-hooks-tXpAarhW.js";
10
- import { C as observe, O as strategyAuthorMethod, T as profileChatClient, b as sample, v as refine, x as sampleThenRefine, y as runAgentic } from "./structural-rollout-BcPXFzVb.js";
11
+ import { C as observe, O as strategyAuthorMethod, T as profileChatClient, b as sample, v as refine, x as sampleThenRefine, y as runAgentic } from "./structural-rollout-DxEQ77H7.js";
11
12
  import { b as mapExecutorResult, n as supervise, y as gateOnDeliverable } from "./supervise-C0V3pZXK.js";
12
13
  import "./coordination-driver-iSN-m3VX.js";
13
14
  import "./run-layout-B8I_LXN-.js";
@@ -27,6 +28,7 @@ import { tmpdir } from "node:os";
27
28
  import { createAgentRunOutcomeTracker } from "@tangle-network/sandbox/runtime";
28
29
  import { collectAgentResponseText } from "@tangle-network/sandbox";
29
30
  import { createInterface } from "node:readline";
31
+ import { pathToFileURL } from "node:url";
30
32
  import { gzipSync } from "node:zlib";
31
33
  import { createContext, runInContext } from "node:vm";
32
34
  import { stuckLoopView, toolWasteView } from "@tangle-network/agent-eval/pipelines";
@@ -2696,23 +2698,25 @@ function applyFilter(records, filter) {
2696
2698
  var InMemoryCorpus = class {
2697
2699
  byId = /* @__PURE__ */ new Map();
2698
2700
  async append(record) {
2701
+ let snapshot;
2699
2702
  try {
2700
2703
  assertCorpusRecord(record, "append: record");
2704
+ snapshot = detachedFrozen(record);
2701
2705
  } catch (err) {
2702
2706
  return {
2703
2707
  succeeded: false,
2704
2708
  error: err instanceof Error ? err.message : String(err)
2705
2709
  };
2706
2710
  }
2707
- const existing = this.byId.get(record.id);
2711
+ const existing = this.byId.get(snapshot.id);
2708
2712
  if (existing) {
2709
- if (recordsEqual(existing, record)) return { succeeded: true };
2713
+ if (recordsEqual(existing, snapshot)) return { succeeded: true };
2710
2714
  return {
2711
2715
  succeeded: false,
2712
2716
  error: `corpus conflict: id '${record.id}' is already stored with a different record; a learned fact is append-only — re-mint the id or reconcile before re-appending`
2713
2717
  };
2714
2718
  }
2715
- this.byId.set(record.id, freeze(record));
2719
+ this.byId.set(snapshot.id, snapshot);
2716
2720
  return { succeeded: true };
2717
2721
  }
2718
2722
  async query(filter) {
@@ -2737,40 +2741,51 @@ var FileCorpus = class {
2737
2741
  async append(record) {
2738
2742
  try {
2739
2743
  assertCorpusRecord(record, "append: record");
2744
+ const snapshot = detachedFrozen(record);
2745
+ const fs = await import("node:fs/promises");
2746
+ const { dirname } = await import("node:path");
2747
+ const { tryAcquireAtomicFileLock } = await import("@tangle-network/agent-eval/ledger-core");
2748
+ await fs.mkdir(dirname(this.path), { recursive: true });
2749
+ await (await fs.open(this.path, "a")).close();
2750
+ const canonicalPath = await fs.realpath(this.path);
2751
+ const deadline = Date.now() + 5e3;
2752
+ for (;;) {
2753
+ const acquisition = tryAcquireAtomicFileLock({ lockPath: `${canonicalPath}.lock` });
2754
+ if (!acquisition.acquired) {
2755
+ if (Date.now() >= deadline) throw new Error(`corpus append lock unavailable after 5000ms: ${canonicalPath}`);
2756
+ await new Promise((resolve) => setTimeout(resolve, 25));
2757
+ continue;
2758
+ }
2759
+ try {
2760
+ const existing = (await this.load(canonicalPath)).get(snapshot.id);
2761
+ if (existing) {
2762
+ if (recordsEqual(existing, snapshot)) return { succeeded: true };
2763
+ return {
2764
+ succeeded: false,
2765
+ error: `corpus conflict: id '${snapshot.id}' is already stored in ${canonicalPath} with a different record; a learned fact is append-only — re-mint the id or reconcile before re-appending`
2766
+ };
2767
+ }
2768
+ await this.appendLine(canonicalPath, snapshot);
2769
+ return { succeeded: true };
2770
+ } finally {
2771
+ acquisition.lock.release();
2772
+ }
2773
+ }
2740
2774
  } catch (err) {
2741
2775
  return {
2742
2776
  succeeded: false,
2743
2777
  error: err instanceof Error ? err.message : String(err)
2744
2778
  };
2745
2779
  }
2746
- let stored;
2747
- try {
2748
- stored = await this.load();
2749
- } catch (err) {
2750
- return {
2751
- succeeded: false,
2752
- error: err instanceof Error ? err.message : String(err)
2753
- };
2754
- }
2755
- const existing = stored.get(record.id);
2756
- if (existing) {
2757
- if (recordsEqual(existing, record)) return { succeeded: true };
2758
- return {
2759
- succeeded: false,
2760
- error: `corpus conflict: id '${record.id}' is already stored in ${this.path} with a different record; a learned fact is append-only — re-mint the id or reconcile before re-appending`
2761
- };
2762
- }
2763
- await this.appendLine(record);
2764
- return { succeeded: true };
2765
2780
  }
2766
2781
  async query(filter) {
2767
2782
  return applyFilter([...(await this.load()).values()], filter);
2768
2783
  }
2769
- async load() {
2784
+ async load(path = this.path) {
2770
2785
  const fs = await import("node:fs/promises");
2771
2786
  let text;
2772
2787
  try {
2773
- text = await fs.readFile(this.path, "utf8");
2788
+ text = await fs.readFile(path, "utf8");
2774
2789
  } catch (err) {
2775
2790
  if (isNoEntError(err)) return /* @__PURE__ */ new Map();
2776
2791
  throw err;
@@ -2782,16 +2797,14 @@ var FileCorpus = class {
2782
2797
  assertCorpusRecord(parsed, `corpus ${this.path} line ${i + 1}`);
2783
2798
  const existing = byId.get(parsed.id);
2784
2799
  if (existing && !recordsEqual(existing, parsed)) throw new Error(`corpus corrupted: ${this.path} has two different records for id '${parsed.id}'; an append-only corpus must never hold a conflicting re-append under one id`);
2785
- byId.set(parsed.id, freeze(parsed));
2800
+ byId.set(parsed.id, detachedFrozen(parsed));
2786
2801
  }
2787
2802
  return byId;
2788
2803
  }
2789
- async appendLine(record) {
2804
+ async appendLine(path, record) {
2790
2805
  const fs = await import("node:fs/promises");
2791
- const path = await import("node:path");
2792
- await fs.mkdir(path.dirname(this.path), { recursive: true });
2793
- const needsSeparator = await prepareJsonlAppend(this.path);
2794
- const fh = await fs.open(this.path, "a");
2806
+ const needsSeparator = await prepareJsonlAppend(path);
2807
+ const fh = await fs.open(path, "a");
2795
2808
  try {
2796
2809
  await writeAllBytes(fh, `${needsSeparator ? "\n" : ""}${JSON.stringify(record)}\n`);
2797
2810
  await fh.sync();
@@ -2843,9 +2856,6 @@ async function renderCorpusToInstructions(opts) {
2843
2856
  function renderLine(record) {
2844
2857
  return record.rationale ? `${record.claim} (${record.rationale})` : record.claim;
2845
2858
  }
2846
- function freeze(record) {
2847
- return Object.freeze({ ...record });
2848
- }
2849
2859
  //#endregion
2850
2860
  //#region src/runtime/personify/registry.ts
2851
2861
  /**
@@ -4029,9 +4039,10 @@ function errorMessage(error) {
4029
4039
  * optimization strategy as code; the caller gates it like any human-built candidate
4030
4040
  * (runBenchmark + a frozen holdout).
4031
4041
  *
4032
- * Structurally safe by construction: the authored body composes shot()/critique() and
4033
- * spends through the Supervisor's conserved pool it can be wrong, but it cannot
4034
- * Goodhart the check (it never sees the verifiers) and it cannot win by overspending.
4042
+ * Brokered shot()/critique() calls spend through the Supervisor's conserved pool.
4043
+ * Source validation checks obvious forbidden operations; it is not an execution sandbox.
4044
+ * Code that uses other execution paths can access state or spend outside that pool.
4045
+ * Callers must provide isolation when authored code requires an enforced boundary.
4035
4046
  *
4036
4047
  * The authored module is written to `outDir` and dynamically imported — run under a
4037
4048
  * TS-capable loader (tsx) since models often emit type annotations.
@@ -4041,16 +4052,20 @@ const strategyAuthorContract = `
4041
4052
  You author an OPTIMIZATION STRATEGY for an agentic loop system. A strategy decides how to
4042
4053
  spend a compute budget to beat a task's deployable check. You compose exactly two steps:
4043
4054
 
4044
- shot(spec?: { handle?, messages?, steer?, persona?, tools? }): Promise<ShotResult | null>
4055
+ shot(spec?: { handle?, messages?, steer?, profile?, tools? }): Promise<ShotResult | null>
4045
4056
  Runs ONE worker attempt (a bounded tool loop) over an artifact.
4046
4057
  - omit handle => the shot opens its OWN fresh artifact and closes it after (a sample).
4047
4058
  - pass handle => the shot CONTINUES that artifact (state accumulates across shots).
4048
4059
  - messages => the carried conversation (pass the previous ShotResult.messages to continue).
4049
4060
  - steer => a corrective instruction injected before the shot.
4050
- - persona => { systemPrompt?, model? } — give THIS shot its own role and/or model
4051
- (multi-agent strategies: a researcher shot then an engineer shot, a panel of k
4052
- personas over one budget). On a fresh shot the systemPrompt replaces the task's; on
4053
- a carried conversation it arrives as a hand-off message. Same conserved budget.
4061
+ - profile => a complete AgentProfile — give THIS shot its own instructions,
4062
+ model, skills, tools, hooks, and subagents. Include name, harness, and
4063
+ model: { provider, default }; put standing instructions in prompt.systemPrompt.
4064
+ For example: { ...opts.workerProfile, name: 'researcher',
4065
+ prompt: { ...opts.workerProfile.prompt,
4066
+ systemPrompt: 'Inspect the evidence before proposing a change.' } }.
4067
+ Choose an available model from the current execution setup. Omit profile to use
4068
+ the worker's exact profile. Every shot spends from the same conserved budget.
4054
4069
  - tools => string[] — restrict THIS shot to a subset of the task's tools by
4055
4070
  name (focus an explore shot on read-only tools, an execute shot on write tools).
4056
4071
  Restriction-only; unknown names make the shot fail. ALWAYS select from
@@ -4088,7 +4103,7 @@ Rules:
4088
4103
  - The module must be EXACTLY this shape (no other imports, no commentary outside code):
4089
4104
 
4090
4105
  import { defineStrategy } from '@tangle-network/agent-runtime/kernel'
4091
- export default defineStrategy('your-strategy-name', async ({ surface, task, budget, shot, critique, listTools }) => {
4106
+ export default defineStrategy('your-strategy-name', async ({ surface, task, opts, budget, shot, critique, listTools }) => {
4092
4107
  // your composition (listTools comes from the destructured context — it is NOT a global)
4093
4108
  })
4094
4109
  `;
@@ -4282,23 +4297,66 @@ async function runStrategyEvolution(cfg) {
4282
4297
  const epsilon = cfg.championEpsilon ?? (cfg.objective === "cost" ? cfg.scoreTolerance ?? .05 : .01);
4283
4298
  const byName = new Map(baselines.map((s) => [s.name, s]));
4284
4299
  const codeByName = /* @__PURE__ */ new Map();
4285
- const fingerprint = {
4300
+ for (const [label, count] of Object.entries({
4301
+ trainN: cfg.trainN,
4302
+ holdoutN: cfg.holdoutN
4303
+ })) if (!Number.isSafeInteger(count) || count < 1) throw new Error(`evolution: ${label} must be a positive integer`);
4304
+ const holdoutOffset = cfg.holdoutOffset ?? 0;
4305
+ if (!Number.isSafeInteger(holdoutOffset) || holdoutOffset < 0) throw new Error("evolution: holdoutOffset must be a non-negative integer");
4306
+ if (baselines.length === 0 || byName.size !== baselines.length) throw new Error("evolution: baselines must have non-empty, unique names");
4307
+ if (cfg.checkpoint && !/^sha256:[0-9a-f]{64}$/.test(cfg.checkpoint.executionRef)) throw new Error("evolution checkpoint: executionRef must be a lowercase sha256:<64 hex> digest");
4308
+ const fingerprint = cfg.checkpoint ? canonicalCandidateDigest$1({
4309
+ schemaVersion: 2,
4310
+ executionRef: cfg.checkpoint?.executionRef ?? null,
4311
+ environment: cfg.environment.name,
4286
4312
  trainN: cfg.trainN,
4287
4313
  holdoutN: cfg.holdoutN,
4314
+ holdoutOffset,
4288
4315
  budget,
4316
+ concurrency,
4289
4317
  generations,
4290
- populationSize
4291
- };
4318
+ populationSize,
4319
+ baselines: baselines.map((baseline) => baseline.name),
4320
+ objective: cfg.objective ?? "score",
4321
+ scoreTolerance: cfg.scoreTolerance ?? .05,
4322
+ champion: policy,
4323
+ championEpsilon: epsilon,
4324
+ minPairedTasks: cfg.minPairedTasks ?? null,
4325
+ band: cfg.band ?? null,
4326
+ lossesDetail: cfg.lossesDetail ?? "exact",
4327
+ reproducerCheck: cfg.reproducerCheck ?? null,
4328
+ modelPreflight: cfg.modelPreflight !== false,
4329
+ modelPreflightTimeoutMs: cfg.modelPreflightTimeoutMs ?? null,
4330
+ worker: {
4331
+ routerBaseUrl: cfg.worker.routerBaseUrl,
4332
+ profile: cfg.worker.workerProfile,
4333
+ analystProfile: cfg.worker.analystProfile ?? cfg.worker.workerProfile,
4334
+ corpusTags: cfg.worker.corpusTags ?? [],
4335
+ corpusReadback: cfg.worker.corpusReadback ?? null
4336
+ },
4337
+ author: {
4338
+ profile: cfg.author.profile,
4339
+ fallbackProfile: cfg.author.fallbackProfile ?? null,
4340
+ executorBackend: cfg.author.executor.backend
4341
+ },
4342
+ authorContract: strategyAuthorContract
4343
+ }) : void 0;
4292
4344
  let ckpt;
4293
4345
  if (cfg.checkpoint?.resume && existsSync(cfg.checkpoint.path)) {
4294
4346
  const raw = JSON.parse(readFileSync(cfg.checkpoint.path, "utf8"));
4295
- if (JSON.stringify(raw.fingerprint) !== JSON.stringify(fingerprint)) throw new Error(`evolution resume: checkpoint design mismatch checkpoint ${JSON.stringify(raw.fingerprint)} vs config ${JSON.stringify(fingerprint)}; delete ${cfg.checkpoint.path} or match the config`);
4347
+ if (raw.fingerprint !== fingerprint) throw new Error(`evolution resume: checkpoint design mismatch at ${cfg.checkpoint.path}; use a new checkpoint or restore the original execution dependencies`);
4296
4348
  ckpt = raw;
4297
4349
  }
4350
+ const train = checkedTaskSlice(await cfg.tasks(0, cfg.trainN), cfg.trainN, "train", !!cfg.checkpoint);
4351
+ const trainDigest = cfg.checkpoint ? canonicalCandidateDigest$1(train) : void 0;
4352
+ if (ckpt && ckpt.trainDigest !== trainDigest) throw new Error("evolution resume: train task payloads changed");
4353
+ let holdoutPoolDigest;
4298
4354
  const save = (state) => {
4299
4355
  if (cfg.checkpoint) writeFileSync(cfg.checkpoint.path, JSON.stringify({
4300
4356
  ...state,
4301
- fingerprint
4357
+ fingerprint,
4358
+ trainDigest,
4359
+ holdoutPoolDigest
4302
4360
  }, null, 1));
4303
4361
  };
4304
4362
  let modelsPreflighted = false;
@@ -4319,7 +4377,6 @@ async function runStrategyEvolution(cfg) {
4319
4377
  modelsPreflighted = true;
4320
4378
  return report;
4321
4379
  };
4322
- const train = await cfg.tasks(0, cfg.trainN);
4323
4380
  const probeTask = train[0];
4324
4381
  if (!probeTask) throw new Error("runStrategyEvolution: empty train slice");
4325
4382
  const probe = await cfg.environment.open(probeTask);
@@ -4346,11 +4403,16 @@ async function runStrategyEvolution(cfg) {
4346
4403
  usd: gen0Champion.usd
4347
4404
  }];
4348
4405
  for (const row of generationRows) for (const c of row.candidates) {
4349
- if (!c.file || c.error) continue;
4350
- const mod = await import(`file://${c.file}`);
4406
+ if (c.error) continue;
4407
+ if (!c.file || !c.sourceSha256) throw new Error(`evolution resume: missing source identity for '${c.name}'`);
4408
+ const bytes = readFileSync(c.file);
4409
+ if (sha256Bytes(bytes) !== c.sourceSha256) throw new Error(`evolution resume: authored source changed for '${c.name}' (${c.file})`);
4410
+ const sourceUrl = pathToFileURL(c.file);
4411
+ sourceUrl.searchParams.set("sha256", c.sourceSha256);
4412
+ const mod = await import(sourceUrl.href);
4351
4413
  if (!mod.default || typeof mod.default.driver !== "function") throw new Error(`evolution resume: ${c.file} no longer exports a Strategy — cannot restore "${c.name}"`);
4352
4414
  byName.set(c.name, renameStrategy(mod.default, c.name));
4353
- codeByName.set(c.name, readFileSync(c.file, "utf8"));
4415
+ codeByName.set(c.name, bytes.toString("utf8"));
4354
4416
  }
4355
4417
  let authoredOk = generationRows.reduce((n, row) => n + row.candidates.filter((c) => !c.error).length, 0);
4356
4418
  const lastRow = generationRows[generationRows.length - 1];
@@ -4398,6 +4460,7 @@ async function runStrategyEvolution(cfg) {
4398
4460
  candidates.push({
4399
4461
  name: unique,
4400
4462
  file: authored.file,
4463
+ sourceSha256: sha256Bytes(Buffer.from(authored.code)),
4401
4464
  gzipBits: gzipSync(Buffer.from(authored.code)).length * 8,
4402
4465
  codeChars: authored.code.length
4403
4466
  });
@@ -4445,13 +4508,17 @@ async function runStrategyEvolution(cfg) {
4445
4508
  });
4446
4509
  }
4447
4510
  if (authoredOk === 0) throw new Error("runStrategyEvolution: every author attempt failed across all generations — no search happened; see the candidates[].error entries");
4448
- const holdoutOffset = cfg.trainN + (cfg.holdoutOffset ?? 0);
4511
+ const poolN = cfg.band?.holdoutPoolN ?? cfg.holdoutN;
4512
+ const pool = checkedTaskSlice(await cfg.tasks(cfg.trainN + holdoutOffset, poolN), poolN, "holdout", !!cfg.checkpoint);
4513
+ const trainIds = new Set(train.map((task) => task.id));
4514
+ if (pool.some((task) => trainIds.has(task.id))) throw new Error("evolution: train and holdout task IDs must be disjoint");
4515
+ holdoutPoolDigest = cfg.checkpoint ? canonicalCandidateDigest$1(pool) : void 0;
4516
+ if (ckpt?.holdout && ckpt.holdoutPoolDigest !== holdoutPoolDigest) throw new Error("evolution resume: holdout task payloads changed");
4449
4517
  let holdoutTasks = [];
4450
4518
  let bandInfo;
4451
4519
  if (ckpt?.holdout && ckpt.verdict) {
4452
4520
  bandInfo = ckpt.band;
4453
4521
  if (cfg.reproducerCheck && codeByName.has(incumbent.name)) {
4454
- const pool = await cfg.tasks(holdoutOffset, cfg.band?.holdoutPoolN ?? cfg.holdoutN);
4455
4522
  const gateIds = new Set(ckpt.holdout.perTask.map((r) => r.taskId));
4456
4523
  holdoutTasks = pool.filter((t) => gateIds.has(t.id));
4457
4524
  }
@@ -4459,7 +4526,6 @@ async function runStrategyEvolution(cfg) {
4459
4526
  const maxRef = cfg.band.maxRefScore ?? .99;
4460
4527
  const reference = baselines[0];
4461
4528
  if (!reference) throw new Error("evolution band: baselines[0] required as the screening reference");
4462
- const pool = await cfg.tasks(holdoutOffset, cfg.band.holdoutPoolN);
4463
4529
  const refScores = (await bench("band-screen", pool, [reference])).perTask.filter((r) => r.cells?.[reference.name]).map((r) => ({
4464
4530
  taskId: r.taskId,
4465
4531
  score: r.cells?.[reference.name]?.score ?? 0
@@ -4473,7 +4539,7 @@ async function runStrategyEvolution(cfg) {
4473
4539
  inBand: kept.length,
4474
4540
  refScores
4475
4541
  };
4476
- } else holdoutTasks = await cfg.tasks(holdoutOffset, cfg.holdoutN);
4542
+ } else holdoutTasks = pool;
4477
4543
  let holdout;
4478
4544
  let verdict;
4479
4545
  if (ckpt?.holdout && ckpt.verdict) {
@@ -4573,6 +4639,15 @@ async function runStrategyEvolution(cfg) {
4573
4639
  trajectory
4574
4640
  };
4575
4641
  }
4642
+ function checkedTaskSlice(tasks, count, label, snapshot) {
4643
+ if (!Number.isSafeInteger(count) || count < 1 || tasks.length !== count) throw new Error(`evolution: ${label} must supply exactly ${count} tasks; received ${tasks.length}`);
4644
+ const ids = /* @__PURE__ */ new Set();
4645
+ for (const task of tasks) {
4646
+ if (typeof task.id !== "string" || !task.id.trim() || ids.has(task.id)) throw new Error(`evolution: ${label} task IDs must be non-empty and unique`);
4647
+ ids.add(task.id);
4648
+ }
4649
+ return snapshot ? immutableCandidateValue(tasks) : tasks;
4650
+ }
4576
4651
  //#endregion
4577
4652
  //#region src/runtime/supervise/chat-transport-executor.ts
4578
4653
  /**
@@ -6361,4 +6436,4 @@ function tail(s) {
6361
6436
  //#endregion
6362
6437
  export { InMemoryCorpus as $, chatWorkerSeam as A, renderLeaderboardSvg as At, SandboxRunAbortError as B, mcpSecretEnvMetadataKey as Bt, withUntrackedArtifacts as C, deterministicCompletion as Ct, codeModeSupervisorTools as D, pairwiseSignificance as Dt, runCoderChecks as E, leaderboard as Et, selectChampion as F, connectStdioMcp as Ft, equalKOnCost as G, printBenchmarkReport as H, resolveSecretEnv as Ht, assertStrategyContract as I, materializeLocalMcp as It, runPersonified as J, trajectoryReport as K, authorStrategy as L, createMcpEnvironment as Lt, discriminatingMeans as M, auditIntent as Mt, pickChampion as N, defaultAuditorInstruction as Nt, unsafeInProcessRunner as O, renderLeaderboardHtml as Ot, runStrategyEvolution as P, McpSpawnFault as Pt, FileCorpus as Q, strategyAuthorContract as R, sanitizeMcpToolSchema as Rt, copyUntrackedIntoClone as S, completionAuthorizes as St, patchDelivered as T, stopSentinel as Tt, runBenchmark as U, secretEnvOfMcpServer as Ut, openSandboxRun as V, resolveMcpServerLaunch as Vt, promotionGate as W, createShapeRegistry as X, builtinShapes as Y, registerShape as Z, NOTE_MAX_CHARS as _, localSandboxClient as _t, localShell as a, pipeline as at, composeWorkerEvidence as b, loopDispatch as bt, createVerifierEnvironment as c, widen as ct, harvestSurfaceDiffs as d, createScopeAnalyst as dt, renderCorpusToInstructions as et, analystsFromRegistry as f, registryScopeAnalyst as ft, EVIDENCE_MAX_CHARS as g, resolveSandboxClient as gt, worktreeFanout as h, defineLeaderboard as ht, jjWorkspace as i, panel as it, createChatSessionStore as j, renderPairwiseMarkdown as jt, chatTransportExecutor as k, renderLeaderboardMarkdown as kt, boxSurfaceReader as l, assertTraceDerivedFindings as lt, superviseSurface as m, harvestCorpus as mt, makeFinding$1 as n, flatWidenGate as nt, runInWorkspace as o, selectValidWinner as ot, failuresAnalyst as p, inProcessSandboxClient as pt, definePersona as q, gitWorkspace as r, loopUntil as rt, createWaterfallCollector as s, verify as st, computeFindingId$1 as t, fanout as tt, fsSurfaceReader as u, buildSteerContext as ut, VERIFY_TAIL_CHARS as v, inlineSandboxClient as vt, analyzeTrace as w, sentinelCompletion as wt, settledWorkerOut as x, superviseDispatch as xt, closingWorkerNote as y, loopCampaignDispatch as yt, strategyAuthorSystemPrompt as z, envKeyProvider as zt };
6363
6438
 
6364
- //# sourceMappingURL=runtime-BVrqSu0-.js.map
6439
+ //# sourceMappingURL=runtime-CuNJ0opC.js.map