@tangle-network/agent-eval 0.189.0 → 0.190.1

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 (146) hide show
  1. package/CHANGELOG.md +94 -0
  2. package/README.md +3 -2
  3. package/dist/adapters/http.d.ts +10 -1
  4. package/dist/adapters/http.d.ts.map +1 -1
  5. package/dist/adapters/http.js +75 -7
  6. package/dist/adapters/http.js.map +1 -1
  7. package/dist/analyst/index.d.ts +66 -3
  8. package/dist/analyst/index.d.ts.map +1 -1
  9. package/dist/analyst/index.js +212 -7
  10. package/dist/analyst/index.js.map +1 -1
  11. package/dist/{benchmark-command-BhhAYstU.js → benchmark-command-BXIr_k8D.js} +12 -11
  12. package/dist/benchmark-command-BXIr_k8D.js.map +1 -0
  13. package/dist/benchmarks/index.d.ts +1 -1
  14. package/dist/benchmarks/index.js +3 -3
  15. package/dist/campaign/index.d.ts +4 -4
  16. package/dist/campaign/index.js +7 -7
  17. package/dist/{campaign-BWoSQPSU.js → campaign-B7q74uIh.js} +256 -11
  18. package/dist/campaign-B7q74uIh.js.map +1 -0
  19. package/dist/{campaign-evidence-CBlGJ3kC.js → campaign-evidence-D40-LHIL.js} +6 -5
  20. package/dist/campaign-evidence-D40-LHIL.js.map +1 -0
  21. package/dist/{chat-client-C4dg7Ng_.js → chat-client-B_ItsSBw.js} +2 -2
  22. package/dist/{chat-client-C4dg7Ng_.js.map → chat-client-B_ItsSBw.js.map} +1 -1
  23. package/dist/{chat-json-call-JVGbfx95.js → chat-json-call-CXHBvUz8.js} +2 -2
  24. package/dist/{chat-json-call-JVGbfx95.js.map → chat-json-call-CXHBvUz8.js.map} +1 -1
  25. package/dist/claim-BGOUqoMq.d.ts +38 -0
  26. package/dist/claim-BGOUqoMq.d.ts.map +1 -0
  27. package/dist/cli.js +3 -3
  28. package/dist/contract/index.d.ts +4 -4
  29. package/dist/contract/index.js +8 -8
  30. package/dist/{default-registry-m2jhbG6Q.js → default-registry-16I-Bxlf.js} +2 -2
  31. package/dist/{default-registry-m2jhbG6Q.js.map → default-registry-16I-Bxlf.js.map} +1 -1
  32. package/dist/{define-agent-eval-98sgUaC1.js → define-agent-eval-DPizhHfy.js} +4 -4
  33. package/dist/{define-agent-eval-98sgUaC1.js.map → define-agent-eval-DPizhHfy.js.map} +1 -1
  34. package/dist/{define-agent-eval-q6890HU4.d.ts → define-agent-eval-DblGedQk.d.ts} +4 -3
  35. package/dist/define-agent-eval-DblGedQk.d.ts.map +1 -0
  36. package/dist/diagnosis/index.d.ts +14 -2
  37. package/dist/diagnosis/index.d.ts.map +1 -1
  38. package/dist/diagnosis/index.js +11 -4
  39. package/dist/diagnosis/index.js.map +1 -1
  40. package/dist/{dspy-rlm-engine-DLYttKBm.js → dspy-rlm-engine-Cs5LzJ-f.js} +3 -3
  41. package/dist/{dspy-rlm-engine-DLYttKBm.js.map → dspy-rlm-engine-Cs5LzJ-f.js.map} +1 -1
  42. package/dist/{eval-campaign-C0Q1Eeo_.js → eval-campaign-CwsBn0Gm.js} +2 -2
  43. package/dist/{eval-campaign-C0Q1Eeo_.js.map → eval-campaign-CwsBn0Gm.js.map} +1 -1
  44. package/dist/experiment/index.d.ts +2 -1
  45. package/dist/experiment/index.d.ts.map +1 -1
  46. package/dist/experiment/index.js +1 -1
  47. package/dist/exporters-XMCYJlqT.d.ts +161 -0
  48. package/dist/exporters-XMCYJlqT.d.ts.map +1 -0
  49. package/dist/{external-optimizer-process-C3quNeKV.js → external-optimizer-process-BnSmrkgL.js} +3 -3
  50. package/dist/{external-optimizer-process-C3quNeKV.js.map → external-optimizer-process-BnSmrkgL.js.map} +1 -1
  51. package/dist/{external-optimizer-subprocess-BDwgKLO1.js → external-optimizer-subprocess-kbcPu5po.js} +3 -3
  52. package/dist/{external-optimizer-subprocess-BDwgKLO1.js.map → external-optimizer-subprocess-kbcPu5po.js.map} +1 -1
  53. package/dist/{feedback-trajectory-B3ZSkfAq.d.ts → feedback-trajectory-BYjh7NEM.d.ts} +2 -2
  54. package/dist/{feedback-trajectory-B3ZSkfAq.d.ts.map → feedback-trajectory-BYjh7NEM.d.ts.map} +1 -1
  55. package/dist/{index-CnJOPR_E.d.ts → index-CJv56rhX.d.ts} +673 -244
  56. package/dist/index-CJv56rhX.d.ts.map +1 -0
  57. package/dist/{index-Dk1dOUfm.d.ts → index-CWoIJHmy.d.ts} +4 -4
  58. package/dist/{index-Dk1dOUfm.d.ts.map → index-CWoIJHmy.d.ts.map} +1 -1
  59. package/dist/{index-Bcc9PkOz.d.ts → index-D4pC7Tvd.d.ts} +3 -2
  60. package/dist/index-D4pC7Tvd.d.ts.map +1 -0
  61. package/dist/{index-BqDJ6fUK.d.ts → index-I4UJGRno.d.ts} +74 -2
  62. package/dist/index-I4UJGRno.d.ts.map +1 -0
  63. package/dist/index.d.ts +66 -17
  64. package/dist/index.d.ts.map +1 -1
  65. package/dist/index.js +375 -31
  66. package/dist/index.js.map +1 -1
  67. package/dist/{journal-CDP0Vhx_.js → journal-c3qY0SDP.js} +246 -5
  68. package/dist/journal-c3qY0SDP.js.map +1 -0
  69. package/dist/{kind-factory-BGwN0nE6.js → kind-factory-ByZeXDqF.js} +2 -2
  70. package/dist/{kind-factory-BGwN0nE6.js.map → kind-factory-ByZeXDqF.js.map} +1 -1
  71. package/dist/ledger-core/index.d.ts +2 -2
  72. package/dist/ledger-core/index.js +2 -2
  73. package/dist/{llm-client-DF9bPNYA.js → llm-client-KYQBh9C8.js} +2 -2
  74. package/dist/{llm-client-DF9bPNYA.js.map → llm-client-KYQBh9C8.js.map} +1 -1
  75. package/dist/{llm-judge-M_l_WXw2.js → llm-judge-BnxAv7ed.js} +1892 -1378
  76. package/dist/llm-judge-BnxAv7ed.js.map +1 -0
  77. package/dist/mint-C9Lojt1V.d.ts +147 -0
  78. package/dist/mint-C9Lojt1V.d.ts.map +1 -0
  79. package/dist/openapi.json +1 -1
  80. package/dist/pipelines/index.d.ts +1 -1
  81. package/dist/pipelines/index.js +1 -1
  82. package/dist/pipelines/index.js.map +1 -1
  83. package/dist/{produced-state-BOY98IJO.js → produced-state-BXjXJHJT.js} +4 -4
  84. package/dist/{produced-state-BOY98IJO.js.map → produced-state-BXjXJHJT.js.map} +1 -1
  85. package/dist/{raw-provider-sink-C96CcqeG.js → raw-provider-sink-DYh4Bszw.js} +2 -2
  86. package/dist/{raw-provider-sink-C96CcqeG.js.map → raw-provider-sink-DYh4Bszw.js.map} +1 -1
  87. package/dist/{redact-DxwlUAvh.js → redact-B7rt9Zot.js} +130 -10
  88. package/dist/redact-B7rt9Zot.js.map +1 -0
  89. package/dist/{redact-DPoH1-OW.d.ts → redact-CopuMxll.d.ts} +7 -5
  90. package/dist/redact-CopuMxll.d.ts.map +1 -0
  91. package/dist/rl.d.ts +3 -2
  92. package/dist/rl.d.ts.map +1 -1
  93. package/dist/rl.js +1 -1
  94. package/dist/rollout/index.d.ts +3 -2
  95. package/dist/search-ledger-types-C9anU2DX.d.ts +489 -0
  96. package/dist/search-ledger-types-C9anU2DX.d.ts.map +1 -0
  97. package/dist/{semantic-concept-judge-Cm2K2wAo.js → semantic-concept-judge-ClB73cei.js} +6 -6
  98. package/dist/{semantic-concept-judge-Cm2K2wAo.js.map → semantic-concept-judge-ClB73cei.js.map} +1 -1
  99. package/dist/{server-C8XvqCg8.js → server-DtetGGoA.js} +2 -2
  100. package/dist/{server-C8XvqCg8.js.map → server-DtetGGoA.js.map} +1 -1
  101. package/dist/{skillopt-optimization-method-BVSB676o.js → skillopt-optimization-method-l2vDBtKp.js} +363 -18
  102. package/dist/skillopt-optimization-method-l2vDBtKp.js.map +1 -0
  103. package/dist/{spans-W0o8pbEg.d.ts → spans-BWtjk_9c.d.ts} +2 -2
  104. package/dist/{spans-W0o8pbEg.d.ts.map → spans-BWtjk_9c.d.ts.map} +1 -1
  105. package/dist/{statistical-heldout-plAHG82H.d.ts → statistical-heldout-CLpjYffJ.d.ts} +2 -36
  106. package/dist/statistical-heldout-CLpjYffJ.d.ts.map +1 -0
  107. package/dist/{store-otlp-D0AV4cvB.js → store-otlp-84DH0OEH.js} +2 -2
  108. package/dist/{store-otlp-D0AV4cvB.js.map → store-otlp-84DH0OEH.js.map} +1 -1
  109. package/dist/{store-tool-spans-8PAyhRqb.d.ts → store-tool-spans-BBXs8hDP.d.ts} +2 -2
  110. package/dist/{store-tool-spans-8PAyhRqb.d.ts.map → store-tool-spans-BBXs8hDP.d.ts.map} +1 -1
  111. package/dist/{store-tool-spans-B_0mXvYl.js → store-tool-spans-DUiqyHvR.js} +5 -5
  112. package/dist/{store-tool-spans-B_0mXvYl.js.map → store-tool-spans-DUiqyHvR.js.map} +1 -1
  113. package/dist/traces.d.ts +3 -63
  114. package/dist/traces.d.ts.map +1 -1
  115. package/dist/traces.js +6 -195
  116. package/dist/traces.js.map +1 -1
  117. package/dist/wire/index.d.ts +1 -1
  118. package/dist/wire/index.js +1 -1
  119. package/docs/adapters-observability.md +31 -27
  120. package/docs/charter.md +1 -1
  121. package/docs/design/mlbenchmarks-book-review.md +1 -1
  122. package/docs/distributed-driver.md +1 -5
  123. package/docs/experiment.md +15 -0
  124. package/docs/public-api.md +181 -71
  125. package/docs/redaction.md +7 -1
  126. package/docs/search-ledger.md +174 -0
  127. package/docs/trace-contracts.md +48 -3
  128. package/package.json +1 -1
  129. package/dist/benchmark-command-BhhAYstU.js.map +0 -1
  130. package/dist/campaign-BWoSQPSU.js.map +0 -1
  131. package/dist/campaign-evidence-CBlGJ3kC.js.map +0 -1
  132. package/dist/define-agent-eval-q6890HU4.d.ts.map +0 -1
  133. package/dist/index-Bcc9PkOz.d.ts.map +0 -1
  134. package/dist/index-BqDJ6fUK.d.ts.map +0 -1
  135. package/dist/index-CnJOPR_E.d.ts.map +0 -1
  136. package/dist/journal-CDP0Vhx_.js.map +0 -1
  137. package/dist/llm-judge-M_l_WXw2.js.map +0 -1
  138. package/dist/mint-DsS38v5c.d.ts +0 -305
  139. package/dist/mint-DsS38v5c.d.ts.map +0 -1
  140. package/dist/redact-DPoH1-OW.d.ts.map +0 -1
  141. package/dist/redact-DxwlUAvh.js.map +0 -1
  142. package/dist/search-ledger-types-D7KDVg-o.d.ts +0 -302
  143. package/dist/search-ledger-types-D7KDVg-o.d.ts.map +0 -1
  144. package/dist/skillopt-optimization-method-BVSB676o.js.map +0 -1
  145. package/dist/statistical-heldout-plAHG82H.d.ts.map +0 -1
  146. package/docs/search-history-receipts.md +0 -233
@@ -1,11 +1,12 @@
1
+ import { a as hashCanonical } from "./canonical-BsZVgBhW.js";
1
2
  import { a as heldoutSignificance, o as pairHoldout } from "./statistical-heldout-GcLIPxk4.js";
2
3
  import { n as contentHash, t as canonicalJson } from "./verdict-cache-BQEsVy9n.js";
3
- import { A as openSearchLedger, X as runCampaign, b as recordCandidatePopulationSearch, d as combineComparisonCosts, f as costFromLedgerSummary, l as optimizationTokenUsageFromSummary, m as readGepaCandidatePopulationArtifact, p as assertGepaCandidatePopulationSummary, t as llmJudge } from "./llm-judge-M_l_WXw2.js";
4
- import { x as campaignBreakdown, z as surfaceContentHash } from "./campaign-evidence-CBlGJ3kC.js";
4
+ import { _ as SearchRecorder, b as surfaceDiff, d as combineComparisonCosts, f as costFromLedgerSummary, j as openSearchLedger, l as optimizationTokenUsageFromSummary, m as readGepaCandidatePopulationArtifact, ot as runCampaign, p as assertGepaCandidatePopulationSummary, t as llmJudge, v as developmentClaim, x as surfaceNode } from "./llm-judge-BnxAv7ed.js";
5
+ import { B as surfaceContentHash, x as campaignBreakdown } from "./campaign-evidence-D40-LHIL.js";
5
6
  import { t as deepFreezeCanonicalJson } from "./deep-freeze-CurcOQg3.js";
6
- import { S as fsCampaignStorage, _ as removeCredentialEnvironment, b as safePathComponent, d as assertExternalOptimizerModelBudget, f as assertJsonValue, g as isRecord, h as isExternalTextCandidate, i as startExternalOptimizerModelProxy, m as isCandidateText, n as closeExternalOptimizerResources, p as assertNoCredentialValues, r as runWithCleanup, t as runExternalOptimizerProcess, v as resolveExternalOptimizerCallbackLimits, x as createRunCostLedger, y as resolveExternalOptimizerProcessLimits } from "./external-optimizer-subprocess-BDwgKLO1.js";
7
- import { g as assertServedModelPolicy } from "./llm-client-DF9bPNYA.js";
8
- import { n as acquireSingleRunLock, t as startExternalOptimizerCallback } from "./external-optimizer-process-C3quNeKV.js";
7
+ import { S as fsCampaignStorage, _ as removeCredentialEnvironment, b as safePathComponent, d as assertExternalOptimizerModelBudget, f as assertJsonValue, g as isRecord, h as isExternalTextCandidate, i as startExternalOptimizerModelProxy, m as isCandidateText, n as closeExternalOptimizerResources, p as assertNoCredentialValues, r as runWithCleanup, t as runExternalOptimizerProcess, v as resolveExternalOptimizerCallbackLimits, x as createRunCostLedger, y as resolveExternalOptimizerProcessLimits } from "./external-optimizer-subprocess-kbcPu5po.js";
8
+ import { g as assertServedModelPolicy } from "./llm-client-KYQBh9C8.js";
9
+ import { n as acquireSingleRunLock, t as startExternalOptimizerCallback } from "./external-optimizer-process-BnSmrkgL.js";
9
10
  import { createHash, randomBytes } from "node:crypto";
10
11
  import { z } from "zod";
11
12
  import { mkdir } from "node:fs/promises";
@@ -1409,6 +1410,346 @@ function isGepaCandidate(value, maxChars) {
1409
1410
  return (typeof value === "string" ? value.length : JSON.stringify(value).length) <= maxChars;
1410
1411
  }
1411
1412
  //#endregion
1413
+ //#region src/campaign/gepa-search-import.ts
1414
+ /**
1415
+ * Import an optimizer's own record into a search ledger.
1416
+ *
1417
+ * GEPA searches inside its own process. Its candidate population names each
1418
+ * candidate's parents by index, and the evaluation callback's observation log
1419
+ * holds every candidate it evaluated. The importer turns both into ledger
1420
+ * events: one node per distinct candidate, one `correlated` edge per population
1421
+ * entry (joined by content digest from GEPA's own parent record), and one cell
1422
+ * per evaluation. Nothing is inferred from timing or order: a candidate GEPA
1423
+ * evaluated but kept out of its population has no parent record, so its edge
1424
+ * is `unknown` and has no parents.
1425
+ */
1426
+ const NO_GEPA_RATIONALE = { unknown: "GEPA records no rationale per candidate; its reflection attaches to the proposer operation" };
1427
+ /**
1428
+ * Register GEPA's population as nodes and its parent indices as `correlated`
1429
+ * edges. A parentless entry (GEPA's seed) gets a seed edge unless its node is
1430
+ * already in the tree, for example the root the caller seeded.
1431
+ */
1432
+ async function importGepaPopulation(input) {
1433
+ const { recorder, population } = input;
1434
+ const node = input.node ?? ((candidate) => surfaceNode(recorder, externalSurface(candidate.candidate)));
1435
+ const diff = input.diff ?? ((parent, child) => surfaceDiff(recorder, externalSurface(parent.candidate), externalSurface(child.candidate)));
1436
+ const nodeIds = /* @__PURE__ */ new Map();
1437
+ const byIndex = new Map(population.candidates.map((candidate) => [candidate.index, candidate]));
1438
+ const seenNodes = /* @__PURE__ */ new Set();
1439
+ let edges = 0;
1440
+ let collapsedDuplicates = 0;
1441
+ let unchangedProposals = 0;
1442
+ for (const candidate of population.candidates) {
1443
+ const { nodeId } = await recorder.registerNode(node(candidate));
1444
+ if (seenNodes.has(nodeId)) collapsedDuplicates += 1;
1445
+ seenNodes.add(nodeId);
1446
+ nodeIds.set(candidate.index, nodeId);
1447
+ const parentIndices = [...new Set(candidate.parentIndices.filter((index) => index !== null))];
1448
+ const parents = [];
1449
+ for (const index of parentIndices) {
1450
+ const parentNodeId = nodeIds.get(index);
1451
+ const parent = byIndex.get(index);
1452
+ if (parentNodeId === void 0 || parent === void 0) throw new Error(`GEPA candidate ${candidate.index} names parent ${index}, which precedes no population entry`);
1453
+ if (parentNodeId === nodeId) continue;
1454
+ if (!parents.some((known) => known.nodeId === parentNodeId)) parents.push({
1455
+ nodeId: parentNodeId,
1456
+ candidate: parent
1457
+ });
1458
+ }
1459
+ if (parentIndices.length > 0 && parents.length === 0) {
1460
+ unchangedProposals += 1;
1461
+ continue;
1462
+ }
1463
+ if (parents.length === 0) {
1464
+ if (((await recorder.state()).node(nodeId)?.edgeIds.length ?? 0) > 0) continue;
1465
+ await recorder.recordEdge({
1466
+ childNodeId: nodeId,
1467
+ parents: [],
1468
+ operator: "seed",
1469
+ attribution: "correlated",
1470
+ proposer: null,
1471
+ proposalKey: `gepa:${population.runId}:${candidate.index}`,
1472
+ rationale: NO_GEPA_RATIONALE,
1473
+ diffs: [],
1474
+ label: `GEPA seed candidate ${candidate.index}`
1475
+ });
1476
+ edges += 1;
1477
+ continue;
1478
+ }
1479
+ await recorder.recordEdge({
1480
+ childNodeId: nodeId,
1481
+ parents: parents.map((parent) => parent.nodeId),
1482
+ operator: parents.length > 1 ? "merge" : "improve",
1483
+ attribution: "correlated",
1484
+ proposer: input.proposer,
1485
+ proposalKey: `gepa:${population.runId}:${candidate.index}`,
1486
+ rationale: NO_GEPA_RATIONALE,
1487
+ diffs: parents.map((parent) => diff(parent.candidate, candidate)),
1488
+ label: `GEPA candidate ${candidate.index}`
1489
+ });
1490
+ edges += 1;
1491
+ }
1492
+ return {
1493
+ nodeIds,
1494
+ nodes: seenNodes.size,
1495
+ edges,
1496
+ collapsedDuplicates,
1497
+ unchangedProposals
1498
+ };
1499
+ }
1500
+ /**
1501
+ * Record every evaluation in the callback's observation log as an `external`
1502
+ * cell attempt. A candidate that is not yet a node (GEPA evaluated it on a
1503
+ * minibatch and discarded it) is registered with an `unknown` edge.
1504
+ */
1505
+ async function importExternalEvaluations(input) {
1506
+ const { recorder } = input;
1507
+ const reps = /* @__PURE__ */ new Map();
1508
+ const unrecorded = [];
1509
+ let cells = 0;
1510
+ for (const observation of input.observations.observations) {
1511
+ if (!(observation.kind === "evaluation" || observation.kind === "refusal" && observation.reason === "evaluation-failed") || observation.candidate === void 0 || observation.exampleId === void 0) continue;
1512
+ const candidateHash = observation.candidateHash;
1513
+ const surface = externalSurface(observation.candidate);
1514
+ const registered = await recorder.registerNode(surfaceNode(recorder, surface));
1515
+ if (((await recorder.state()).node(registered.nodeId)?.edgeIds.length ?? 0) === 0) {
1516
+ await recorder.recordEdge({
1517
+ childNodeId: registered.nodeId,
1518
+ parents: [],
1519
+ operator: "improve",
1520
+ attribution: "unknown",
1521
+ proposer: input.proposer,
1522
+ proposalKey: `gepa-evaluated:${candidateHash}`,
1523
+ rationale: NO_GEPA_RATIONALE,
1524
+ diffs: [],
1525
+ label: "GEPA proposal outside its population"
1526
+ });
1527
+ unrecorded.push(registered.nodeId);
1528
+ }
1529
+ const split = input.splitOf(observation.exampleId);
1530
+ const repKey = `${registered.nodeId}\u0000${observation.exampleId}`;
1531
+ const rep = reps.get(repKey) ?? 0;
1532
+ reps.set(repKey, rep + 1);
1533
+ const cellId = await recorder.allocateCell({
1534
+ nodeId: registered.nodeId,
1535
+ taskId: observation.exampleId,
1536
+ split,
1537
+ rep,
1538
+ stage: "external"
1539
+ });
1540
+ await recorder.settleCell({
1541
+ cellId,
1542
+ attempt: 1,
1543
+ outcome: observation.kind === "evaluation" ? evaluationOutcome(observation.response) : {
1544
+ status: "errored",
1545
+ metrics: {},
1546
+ error: {
1547
+ code: "evaluation-failed",
1548
+ message: "the evaluation callback failed before a score",
1549
+ retryable: false
1550
+ }
1551
+ },
1552
+ accounting: {
1553
+ tokens: {
1554
+ status: "unknown",
1555
+ reason: "the evaluation callback meters tokens per run"
1556
+ },
1557
+ cost: {
1558
+ status: "unknown",
1559
+ knownLowerBoundUsd: 0,
1560
+ reason: "the evaluation callback meters cost per run, not per evaluation"
1561
+ }
1562
+ },
1563
+ identity: input.identity
1564
+ });
1565
+ cells += 1;
1566
+ }
1567
+ return {
1568
+ cells,
1569
+ unrecordedParentNodeIds: unrecorded
1570
+ };
1571
+ }
1572
+ /** GEPA's callback response. A `failed` evaluation carries a penalty score for
1573
+ * the optimizer that is not a measurement, so the cell is unscored. */
1574
+ function evaluationOutcome(response) {
1575
+ const record = response ?? {};
1576
+ if (record.info?.status === "scored" && typeof record.score === "number" && Number.isFinite(record.score)) return {
1577
+ status: "passed",
1578
+ score: record.score,
1579
+ metrics: { score: record.score }
1580
+ };
1581
+ return {
1582
+ status: "errored",
1583
+ metrics: {},
1584
+ error: {
1585
+ code: "evaluation-failed",
1586
+ message: typeof record.info?.notes === "string" && record.info.notes.trim().length > 0 ? record.info.notes.trim() : "the evaluation produced no score",
1587
+ retryable: false
1588
+ }
1589
+ };
1590
+ }
1591
+ /** An optimizer candidate as the mutable surface it represents. */
1592
+ function externalSurface(candidate) {
1593
+ return typeof candidate === "string" ? candidate : {
1594
+ kind: "components",
1595
+ components: candidate
1596
+ };
1597
+ }
1598
+ /**
1599
+ * Write GEPA's finished search into its ledger: the baseline as the seeded
1600
+ * root, the population as nodes with `correlated` edges, every callback
1601
+ * evaluation as an `external` cell, GEPA's proposer spend as one operation,
1602
+ * GEPA's choice as the selected node, and the close. GEPA's own selection is a
1603
+ * budget decision, so the ledger carries no claim; the final comparison runs
1604
+ * outside this search.
1605
+ */
1606
+ async function recordGepaSearch(input) {
1607
+ const { identity, population } = input;
1608
+ const tasks = (scenarios) => scenarios.map((scenario) => ({
1609
+ taskId: scenario.id,
1610
+ unitId: scenario.id,
1611
+ source: {
1612
+ uri: `scenario://${scenario.id}`,
1613
+ revision: hashCanonical(scenario)
1614
+ }
1615
+ }));
1616
+ const train = tasks(input.trainScenarios);
1617
+ const selection = tasks(input.selectionScenarios);
1618
+ const taskSet = hashCanonical({
1619
+ train,
1620
+ selection
1621
+ });
1622
+ const recorder = await SearchRecorder.open({
1623
+ ledger: openSearchLedger({
1624
+ path: input.path,
1625
+ searchId: input.searchId
1626
+ }),
1627
+ storage: input.storage
1628
+ }, {
1629
+ subject: identity.subject ?? input.name,
1630
+ process: {
1631
+ name: input.name,
1632
+ executionRef: identity.search
1633
+ },
1634
+ artifactKind: "prompt",
1635
+ objective: {
1636
+ metric: "score",
1637
+ direction: "maximize",
1638
+ judge: identity.judge ?? { unknown: "the evaluation callback judges through caller functions without a pinned source" },
1639
+ claim: identity.claim ?? developmentClaim(taskSet)
1640
+ },
1641
+ splits: {
1642
+ train,
1643
+ selection,
1644
+ test: [],
1645
+ heldOutUnits: true
1646
+ },
1647
+ policy: {
1648
+ expansion: "gepa",
1649
+ allocation: "gepa",
1650
+ seed: input.seed
1651
+ },
1652
+ budget: {
1653
+ maxUsd: null,
1654
+ maxCells: input.evaluationLimit,
1655
+ maxNodes: null,
1656
+ deadline: null,
1657
+ maxConcurrency: null,
1658
+ reservedClaimUsd: 0
1659
+ },
1660
+ containment: null,
1661
+ derivedFrom: null,
1662
+ identity: {
1663
+ model: identity.model,
1664
+ agent: identity.agent,
1665
+ benchmark: {
1666
+ uri: `optimizer://${input.name}`,
1667
+ revision: taskSet
1668
+ }
1669
+ }
1670
+ });
1671
+ const root = await recorder.registerNode(surfaceNode(recorder, input.baselineSurface));
1672
+ await recorder.recordEdge({
1673
+ childNodeId: root.nodeId,
1674
+ parents: [],
1675
+ operator: "seed",
1676
+ attribution: "explicit",
1677
+ proposer: null,
1678
+ proposalKey: "baseline",
1679
+ rationale: { unknown: "the baseline is the caller-supplied starting surface" },
1680
+ diffs: [],
1681
+ label: "baseline"
1682
+ });
1683
+ const operationId = "gepa-proposals";
1684
+ await recorder.startOperation({
1685
+ operationId,
1686
+ operationKind: "candidate-generation"
1687
+ });
1688
+ const proposer = {
1689
+ kind: "optimizer",
1690
+ name: input.name,
1691
+ operationId,
1692
+ source: identity.proposer.source
1693
+ };
1694
+ const imported = await importGepaPopulation({
1695
+ recorder,
1696
+ population,
1697
+ proposer
1698
+ });
1699
+ const trainIds = new Set(train.map((task) => task.taskId));
1700
+ const evaluations = await importExternalEvaluations({
1701
+ recorder,
1702
+ observations: input.observations,
1703
+ proposer,
1704
+ identity: {
1705
+ model: identity.model,
1706
+ agent: identity.agent,
1707
+ benchmark: {
1708
+ uri: `optimizer://${input.name}`,
1709
+ revision: taskSet
1710
+ }
1711
+ },
1712
+ splitOf: (exampleId) => trainIds.has(exampleId) ? "train" : "selection"
1713
+ });
1714
+ await recorder.recordOperation({
1715
+ operationId,
1716
+ operationKind: "candidate-generation",
1717
+ execution: identity.proposer,
1718
+ outcome: { status: "completed" },
1719
+ accounting: input.generationAccounting
1720
+ });
1721
+ const best = imported.nodeIds.get(population.bestIndex);
1722
+ const state = await recorder.state();
1723
+ const nodes = state.nodes();
1724
+ const bestScored = best !== void 0 && state.cells({ nodeId: best }).some((cell) => cell.score !== null);
1725
+ for (const node of nodes) if (node.nodeId === best && bestScored) await recorder.decideNode({
1726
+ nodeId: node.nodeId,
1727
+ decision: { status: "selected" },
1728
+ rule: "gepa-best-aggregate",
1729
+ reason: "GEPA chose this candidate by its aggregate selection score"
1730
+ });
1731
+ else if (evaluations.unrecordedParentNodeIds.includes(node.nodeId)) await recorder.decideNode({
1732
+ nodeId: node.nodeId,
1733
+ decision: { status: "pruned" },
1734
+ rule: "gepa-population",
1735
+ reason: "GEPA evaluated the candidate and kept it out of its population"
1736
+ });
1737
+ else await recorder.decideNode({
1738
+ nodeId: node.nodeId,
1739
+ decision: node.nodeId === best ? { status: "invalid" } : { status: "rejected" },
1740
+ rule: "gepa-best-aggregate",
1741
+ reason: node.nodeId === best ? "GEPA chose this candidate, but no evaluation of it was scored" : "GEPA chose another candidate"
1742
+ });
1743
+ await recorder.close({
1744
+ reason: "budget",
1745
+ claim: null
1746
+ });
1747
+ return recorder.receipt({
1748
+ producerId: input.name,
1749
+ runId: input.searchId
1750
+ });
1751
+ }
1752
+ //#endregion
1412
1753
  //#region src/campaign/gepa-optimization-method.ts
1413
1754
  /**
1414
1755
  * Turn an optional GEPA installation into an `OptimizationMethod`.
@@ -1675,19 +2016,23 @@ function gepaOptimizationMethod(config) {
1675
2016
  candidate: result.bestCandidate
1676
2017
  });
1677
2018
  if (selected?.candidateHash !== selectedHash) throw new Error(`${name}: GEPA candidate population identifies a different winner`);
1678
- if (config.searchLedger) searchHistory = await recordCandidatePopulationSearch({
1679
- ledger: openSearchLedger({
1680
- path: config.searchLedger.path ?? `${runDir}/search-ledger.jsonl`,
1681
- campaignId: runId
1682
- }),
1683
- storage,
1684
- runDir,
2019
+ if (config.searchLedger) searchHistory = await recordGepaSearch({
2020
+ name,
2021
+ path: config.searchLedger.path ?? `${runDir}/search-ledger.jsonl`,
2022
+ searchId: runId,
1685
2023
  identity: config.searchLedger.identity,
2024
+ storage,
2025
+ seed: input.seed,
2026
+ baselineSurface: input.baselineSurface,
2027
+ trainScenarios: input.trainScenarios,
2028
+ selectionScenarios: input.selectionScenarios,
2029
+ evaluationLimit,
1686
2030
  population,
1687
- scenarios: input.selectionScenarios,
1688
- generationAccounting: optimizerAccounting(result.tokenUsage, result.proposerCostUsd),
1689
- producerId: name,
1690
- runId
2031
+ observations: readExternalOptimizerObservationArtifact({
2032
+ summary: observationLog.summary(),
2033
+ storage
2034
+ }),
2035
+ generationAccounting: optimizerAccounting(result.tokenUsage, result.proposerCostUsd)
1691
2036
  });
1692
2037
  }
1693
2038
  const evaluationCost = costFromLedgerSummary(costLedger.summary({
@@ -2139,6 +2484,6 @@ function skillOptOptimizationMethod(config) {
2139
2484
  };
2140
2485
  }
2141
2486
  //#endregion
2142
- export { externalTextOptimizationMethod as a, REFERENCE_EQUIVALENCE_INPUT_LIMITS as c, runReferenceEquivalenceJudge as d, composeGate as i, REFERENCE_EQUIVALENCE_JUDGE_VERSION as l, gepaOptimizationMethod as n, decodeExternalTextCandidate as o, heldOutGate as r, readExternalOptimizerObservationArtifact as s, skillOptOptimizationMethod as t, createReferenceEquivalenceJudge as u };
2487
+ export { importGepaPopulation as a, composeGate as c, readExternalOptimizerObservationArtifact as d, REFERENCE_EQUIVALENCE_INPUT_LIMITS as f, runReferenceEquivalenceJudge as h, importExternalEvaluations as i, externalTextOptimizationMethod as l, createReferenceEquivalenceJudge as m, gepaOptimizationMethod as n, recordGepaSearch as o, REFERENCE_EQUIVALENCE_JUDGE_VERSION as p, externalSurface as r, heldOutGate as s, skillOptOptimizationMethod as t, decodeExternalTextCandidate as u };
2143
2488
 
2144
- //# sourceMappingURL=skillopt-optimization-method-BVSB676o.js.map
2489
+ //# sourceMappingURL=skillopt-optimization-method-l2vDBtKp.js.map