textopt 0.0.0 → 0.2.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 (65) hide show
  1. package/README.md +65 -25
  2. package/dist/bootstrap-search/index.cjs +159 -73
  3. package/dist/bootstrap-search/index.d.cts +32 -10
  4. package/dist/bootstrap-search/index.d.mts +32 -10
  5. package/dist/bootstrap-search/index.mjs +150 -66
  6. package/dist/demos-9v5ts7F3.cjs +244 -0
  7. package/dist/{demos-B0pVQjYC.d.mts → demos-ASsSXYXA.d.mts} +10 -3
  8. package/dist/demos-Brobjfuc.mjs +215 -0
  9. package/dist/{demos-BTuzFNsp.d.cts → demos-ByaLZy-Z.d.cts} +10 -3
  10. package/dist/file-cache.cjs +27 -8
  11. package/dist/file-cache.d.cts +13 -0
  12. package/dist/file-cache.d.mts +13 -0
  13. package/dist/file-cache.mjs +27 -8
  14. package/dist/gepa/index.cjs +128 -80
  15. package/dist/gepa/index.d.cts +15 -7
  16. package/dist/gepa/index.d.mts +15 -7
  17. package/dist/gepa/index.mjs +101 -55
  18. package/dist/index.cjs +157 -30
  19. package/dist/index.d.cts +177 -7
  20. package/dist/index.d.mts +177 -7
  21. package/dist/index.mjs +139 -18
  22. package/dist/{math-COOofUyv.cjs → math-BhlziRPc.cjs} +60 -9
  23. package/dist/math-Dqme4rYz.mjs +123 -0
  24. package/dist/mipro/index.cjs +104 -70
  25. package/dist/mipro/index.d.cts +17 -14
  26. package/dist/mipro/index.d.mts +17 -14
  27. package/dist/mipro/index.mjs +90 -58
  28. package/dist/opro/index.cjs +136 -51
  29. package/dist/opro/index.d.cts +17 -9
  30. package/dist/opro/index.d.mts +17 -9
  31. package/dist/opro/index.mjs +121 -38
  32. package/dist/{optimizer-B7SpRwl7.d.cts → optimizer-4Zv-Zt2t.d.cts} +90 -5
  33. package/dist/{optimizer-DqCoth_w.d.mts → optimizer-Ds5mzYjz.d.mts} +90 -5
  34. package/dist/random-search/index.cjs +99 -49
  35. package/dist/random-search/index.d.cts +15 -13
  36. package/dist/random-search/index.d.mts +15 -13
  37. package/dist/random-search/index.mjs +89 -41
  38. package/dist/{reflection-Cr_upzU0.d.mts → reflection-CMezGu6u.d.mts} +38 -14
  39. package/dist/{reflection-CQToe-5B.d.cts → reflection-D0A7eahD.d.cts} +38 -14
  40. package/dist/reporting-bq007_2z.d.cts +294 -0
  41. package/dist/reporting-bq007_2z.d.mts +294 -0
  42. package/dist/simba/index.cjs +216 -83
  43. package/dist/simba/index.d.cts +53 -13
  44. package/dist/simba/index.d.mts +53 -13
  45. package/dist/simba/index.mjs +206 -75
  46. package/dist/testing.cjs +1 -0
  47. package/dist/testing.d.cts +5 -3
  48. package/dist/testing.d.mts +5 -3
  49. package/dist/testing.mjs +1 -1
  50. package/dist/{evaluation-OZOp6TB7.cjs → warnings-CWRJF-jA.cjs} +228 -5
  51. package/dist/{evaluation-BV0nSZVx.mjs → warnings-OxvDi9kN.mjs} +175 -6
  52. package/docs/adapters.md +169 -0
  53. package/docs/benchmark.md +90 -0
  54. package/docs/data-prep.md +113 -0
  55. package/docs/distillation.md +128 -0
  56. package/docs/evaluation.md +87 -0
  57. package/docs/metric-preflight.md +132 -0
  58. package/docs/optimizers.md +293 -0
  59. package/docs/tuning.md +130 -0
  60. package/package.json +6 -4
  61. package/dist/demos-B9BJiNKz.cjs +0 -143
  62. package/dist/demos-Degx6UmP.mjs +0 -126
  63. package/dist/math-DhrDmpFS.mjs +0 -78
  64. package/dist/types-CWv4IQFF.d.cts +0 -129
  65. package/dist/types-CWv4IQFF.d.mts +0 -129
@@ -12,20 +12,33 @@ import { dirname } from "node:path";
12
12
  * Append-only rather than rewritten: a score is never invalidated (the key
13
13
  * names the candidate, the instance, and the environment), and a log survives
14
14
  * a process killed mid-write, which a file rewritten in place does not.
15
+ *
16
+ * `namespace` is what makes that invariant true. A cached score measures a
17
+ * whole system, not a candidate, and this log outlives every part of that
18
+ * system a run does not pass through the key: the model id behind an alias the
19
+ * provider upgraded, the decoding settings, the scorer's own version. It is
20
+ * required rather than optional because the failure it prevents is silent —
21
+ * scores from one system served to a run of another, with a normal-looking
22
+ * result and no way to read afterwards that it happened.
15
23
  */
16
24
  function createFileCache(args) {
17
- const { path, maxEntries = 1e6 } = args;
25
+ const { path, namespace, maxEntries = 1e6 } = args;
26
+ if (namespace.trim() === "") throw new Error("createFileCache requires a non-empty namespace naming the system these scores measure");
18
27
  mkdirSync(dirname(path), { recursive: true });
19
- const entries = readLog(path);
28
+ const log = readLog(path);
29
+ const entries = log.entries;
30
+ const scope = (key) => `${namespace}\u0000${key}`;
31
+ if (log.unterminated) appendFileSync(path, "\n");
20
32
  return {
21
- get: (key) => entries.get(key),
33
+ get: (key) => entries.get(scope(key)),
22
34
  set: (key, cached) => {
23
- if (entries.size >= maxEntries && !entries.has(key)) {
35
+ const scoped = scope(key);
36
+ if (entries.size >= maxEntries && !entries.has(scoped)) {
24
37
  const oldest = entries.keys().next();
25
38
  if (!oldest.done) entries.delete(oldest.value);
26
39
  }
27
- entries.set(key, cached);
28
- appendFileSync(path, `${JSON.stringify([key, cached])}\n`);
40
+ entries.set(scoped, cached);
41
+ appendFileSync(path, `${JSON.stringify([scoped, cached])}\n`);
29
42
  }
30
43
  };
31
44
  }
@@ -41,14 +54,20 @@ function readLog(path) {
41
54
  try {
42
55
  contents = readFileSync(path, "utf8");
43
56
  } catch {
44
- return entries;
57
+ return {
58
+ entries,
59
+ unterminated: false
60
+ };
45
61
  }
46
62
  for (const line of contents.split("\n")) {
47
63
  if (line.length === 0) continue;
48
64
  const entry = parseEntry(line);
49
65
  if (entry !== void 0) entries.set(entry[0], entry[1]);
50
66
  }
51
- return entries;
67
+ return {
68
+ entries,
69
+ unterminated: contents.length > 0 && !contents.endsWith("\n")
70
+ };
52
71
  }
53
72
  function parseEntry(line) {
54
73
  let parsed;
@@ -1,8 +1,8 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_evaluation = require("../evaluation-OZOp6TB7.cjs");
2
+ const require_warnings = require("../warnings-CWRJF-jA.cjs");
3
3
  const require_concurrency = require("../concurrency-C-cFzWW2.cjs");
4
- const require_math = require("../math-COOofUyv.cjs");
5
- const require_demos = require("../demos-B9BJiNKz.cjs");
4
+ const require_math = require("../math-BhlziRPc.cjs");
5
+ const require_demos = require("../demos-9v5ts7F3.cjs");
6
6
  const require_rng = require("../rng-DbA_rPIo.cjs");
7
7
  const require_reflection = require("../reflection-DRfbk6hu.cjs");
8
8
  const require_sampling = require("../sampling-Dars7ctR.cjs");
@@ -334,7 +334,7 @@ function isEligibleAncestor(args) {
334
334
  */
335
335
  function hasComplementaryComponent(args) {
336
336
  const { ancestor, left, right } = args;
337
- return require_evaluation.componentNames(ancestor).some((name) => {
337
+ return require_warnings.componentNames(ancestor).some((name) => {
338
338
  const base = ancestor[name];
339
339
  return (base === left[name] || base === right[name]) && left[name] !== right[name];
340
340
  });
@@ -347,7 +347,7 @@ function mergeComponents(args) {
347
347
  const rightRecord = records[rightId];
348
348
  const candidate = { ...ancestor };
349
349
  const sources = [];
350
- for (const name of require_evaluation.componentNames(ancestor)) {
350
+ for (const name of require_warnings.componentNames(ancestor)) {
351
351
  const base = ancestor[name];
352
352
  const leftText = leftRecord.candidate[name];
353
353
  const rightText = rightRecord.candidate[name];
@@ -391,7 +391,7 @@ function buildAncestries(records) {
391
391
  return ancestries;
392
392
  }
393
393
  function fingerprint(candidate) {
394
- return JSON.stringify(require_evaluation.componentNames(candidate).sort().map((name) => [name, candidate[name]]));
394
+ return JSON.stringify(require_warnings.componentNames(candidate).sort().map((name) => [name, candidate[name]]));
395
395
  }
396
396
  //#endregion
397
397
  //#region src/gepa/pareto.ts
@@ -513,7 +513,9 @@ function hasSurvivor(args) {
513
513
  * `frontier` chooses what the fronts are taken over. "instance" is GEPA as
514
514
  * published. "objective" tracks candidates leading each named objective the
515
515
  * adapter reports, and "hybrid" pools both — a candidate then earns selection
516
- * weight for every instance it wins *and* every objective it leads.
516
+ * weight for every instance it wins *and* every objective it leads. The
517
+ * objectives are whatever the adapter put in `objectiveScores`, which for a
518
+ * judge is every criterion it graded, including any at `weight: 0`.
517
519
  */
518
520
  function paretoSelector(args = {}) {
519
521
  const { epsilon = 0, frontier = "instance" } = args;
@@ -628,14 +630,14 @@ function subsampledEvaluationPolicy(args) {
628
630
  */
629
631
  function roundRobinComponentSelector() {
630
632
  return ({ candidate, cursor }) => {
631
- const names = require_evaluation.componentNames(candidate);
633
+ const names = require_warnings.componentNames(candidate);
632
634
  if (names.length === 0) throw new Error("Candidate has no components to update");
633
635
  return [names[cursor % names.length]];
634
636
  };
635
637
  }
636
638
  /** Update every component in a single reflection call. */
637
639
  function allComponentsSelector() {
638
- return ({ candidate }) => require_evaluation.componentNames(candidate);
640
+ return ({ candidate }) => require_warnings.componentNames(candidate);
639
641
  }
640
642
  /**
641
643
  * Accept a mutation only when it beats its parent on the same minibatch. Cheap
@@ -660,7 +662,8 @@ function improvementAcceptance(args = {}) {
660
662
  */
661
663
  function pairedPermutationAcceptance(args = {}) {
662
664
  const { alpha = .2, maxExact = 16 } = args;
663
- return ({ parentScores, childScores }) => {
665
+ if (!Number.isFinite(alpha) || alpha <= 0 || alpha > 1) throw new Error(`alpha must be greater than 0 and at most 1, received ${alpha}`);
666
+ const policy = ({ parentScores, childScores }) => {
664
667
  const differences = [];
665
668
  for (let index = 0; index < parentScores.length; index += 1) differences.push(childScores[index] - parentScores[index]);
666
669
  const observed = require_math.sum(differences);
@@ -671,6 +674,33 @@ function pairedPermutationAcceptance(args = {}) {
671
674
  maxExact
672
675
  }) <= alpha;
673
676
  };
677
+ policy.minimumPairs = smallestAcceptableBatch({
678
+ alpha,
679
+ maxExact
680
+ });
681
+ return policy;
682
+ }
683
+ /**
684
+ * Smallest paired batch on which a sign-flip test at `alpha` could return a
685
+ * verdict of "accept" at all.
686
+ *
687
+ * Enumerating n non-zero differences gives 2^n equally likely sign
688
+ * assignments, so the smallest attainable p-value is 2^-n and no batch below
689
+ * `log2(1/alpha)` pairs can clear the bar. Past `maxExact` the p-value comes
690
+ * from a normal approximation, which has no such floor — so when the exact
691
+ * requirement is out of that regime's reach, the first batch that leaves the
692
+ * regime is the honest answer rather than an exact size that never applies.
693
+ */
694
+ function smallestAcceptableBatch(args) {
695
+ const { alpha, maxExact } = args;
696
+ let pairs = 1;
697
+ let smallestPValue = .5;
698
+ while (smallestPValue > alpha) {
699
+ pairs += 1;
700
+ smallestPValue /= 2;
701
+ if (pairs > maxExact) return maxExact + 1;
702
+ }
703
+ return pairs;
674
704
  }
675
705
  /**
676
706
  * Highest mean over the instances it was scored on, with wider coverage
@@ -739,18 +769,26 @@ var GepaOptimizer = class {
739
769
  this.#config = config;
740
770
  }
741
771
  async optimize(task) {
742
- return runGepa({
743
- config: this.#config,
744
- task
745
- });
772
+ try {
773
+ return await runGepa({
774
+ config: this.#config,
775
+ task
776
+ });
777
+ } finally {
778
+ await require_warnings.flushReporters(task.reporters ?? []);
779
+ }
746
780
  }
747
781
  };
748
782
  async function runGepa(args) {
749
783
  const { config, task } = args;
750
784
  const { minibatchSize = DEFAULT_MINIBATCH_SIZE, maxIterations = Number.POSITIVE_INFINITY, seed = 0, candidateSelector = paretoSelector(), acceptance = improvementAcceptance(), merge, skipPerfectScore = true, perfectScore = 1, rejectedProposalMemory = DEFAULT_REJECTED_PROPOSAL_MEMORY, proposals, reflection, checkpointCache = true, trackBestOutputs = false, raiseOnError = true } = config;
751
- const { seedCandidate, trainingSet, validationSet = trainingSet, testSet, adapter, reflect, maxMetricCalls, componentSelector = roundRobinComponentSelector(), batchSampler = require_sampling.createEpochShuffledSampler({ minibatchSize }), valEvaluationPolicy = fullEvaluationPolicy(), cache, cacheNamespace, retry, maxCostUsd, maxWallClockMs, instanceId = defaultInstanceId, onEvent, onCheckpoint, resumeFrom, signal } = task;
752
- const deadline = require_evaluation.createDeadline({ maxWallClockMs });
753
- const seedComponents = require_evaluation.componentNames(seedCandidate);
785
+ const { seedCandidate, trainingSet, validationSet: requestedValidationSet, testSet, adapter, reflect, maxMetricCalls, componentSelector = roundRobinComponentSelector(), batchSampler = require_sampling.createEpochShuffledSampler({ minibatchSize }), valEvaluationPolicy = fullEvaluationPolicy(), cache, cacheNamespace, retry, maxCostUsd, maxWallClockMs, instanceId = require_warnings.defaultInstanceId, reporters = [], onCheckpoint, resumeFrom, signal } = task;
786
+ const { validationSet, warnings } = require_warnings.resolveValidationSet({
787
+ validationSet: requestedValidationSet,
788
+ trainingSet
789
+ });
790
+ const deadline = require_warnings.createDeadline({ maxWallClockMs });
791
+ const seedComponents = require_warnings.componentNames(seedCandidate);
754
792
  const mergeConfig = {
755
793
  enabled: merge?.enabled ?? seedComponents.length > 1,
756
794
  maxInvocations: merge?.maxInvocations ?? DEFAULT_MAX_MERGES,
@@ -763,7 +801,7 @@ async function runGepa(args) {
763
801
  if (validationSet.length === 0) throw new Error("optimize requires a non-empty validationSet; the Pareto frontier is tracked over validation instances");
764
802
  if (seedComponents.length === 0) throw new Error("optimize requires a seed candidate with at least one component");
765
803
  if (testSet !== void 0 && testSet.length === 0) throw new Error("optimize requires a non-empty testSet when one is given; omit it to skip held-out evaluation");
766
- const evaluationCache = cache === false ? void 0 : cache ?? require_evaluation.createMemoryCache();
804
+ const evaluationCache = cache === false ? void 0 : cache ?? require_warnings.createMemoryCache();
767
805
  const propose = adapter.proposeNewTexts?.bind(adapter) ?? require_reflection.createDefaultProposer({
768
806
  ...reflection?.buildPrompt === void 0 ? {} : { buildPrompt: reflection.buildPrompt },
769
807
  ...reflection?.strategies === void 0 ? {} : { strategies: reflection.strategies },
@@ -784,19 +822,19 @@ async function runGepa(args) {
784
822
  datum,
785
823
  index
786
824
  })) ?? [];
787
- const fingerprint = require_evaluation.runFingerprint({
825
+ const fingerprint = require_warnings.runFingerprint({
788
826
  seedCandidate,
789
827
  trainingIds,
790
828
  validationIds,
791
829
  seed,
792
830
  ...cacheNamespace === void 0 ? {} : { cacheNamespace }
793
831
  });
794
- require_evaluation.assertResumable({
832
+ require_warnings.assertResumable({
795
833
  fingerprint,
796
834
  ...resumeFrom === void 0 ? {} : { snapshot: resumeFrom }
797
835
  });
798
836
  const rng = require_rng.createSeededRng(seed, resumeFrom?.rngState);
799
- const budget = require_evaluation.createBudget({
837
+ const budget = require_warnings.createBudget({
800
838
  maxMetricCalls,
801
839
  spent: resumeFrom?.metricCalls ?? 0
802
840
  });
@@ -816,7 +854,7 @@ async function runGepa(args) {
816
854
  records: resumeFrom?.records ?? [],
817
855
  seedCandidate
818
856
  });
819
- const seenCandidates = new Set(records.map((record) => require_evaluation.candidateFingerprint(record.candidate)));
857
+ const seenCandidates = new Set(records.map((record) => require_warnings.candidateFingerprint(record.candidate)));
820
858
  const outputsByCandidate = /* @__PURE__ */ new Map();
821
859
  const rejectedProposals = restoreRejections({
822
860
  rejections: resumeFrom?.rejectedProposals ?? {},
@@ -828,8 +866,26 @@ async function runGepa(args) {
828
866
  let mergesDue = resumeFrom?.merge.due ?? 0;
829
867
  let totalMergesTested = resumeFrom?.merge.tested ?? 0;
830
868
  let lastIterationAccepted = resumeFrom?.merge.lastIterationAccepted ?? false;
831
- function emit(event) {
832
- onEvent?.(event);
869
+ const emit = require_warnings.createEmitter(reporters);
870
+ /**
871
+ * Everything an acceptance means, in one event: the text, the aggregate, and
872
+ * the row it put on the frontier. Emitted from one place because the merge
873
+ * path and the mutation path accept candidates separately, and a payload
874
+ * assembled twice is a payload that drifts.
875
+ */
876
+ function emitAccepted(record) {
877
+ const outputs = outputsByCandidate.get(record.id);
878
+ emit({
879
+ type: "candidateAccepted",
880
+ iteration,
881
+ candidateId: record.id,
882
+ parentIds: record.parentIds,
883
+ aggregateScore: record.aggregateScore,
884
+ source: record.source,
885
+ candidate: record.candidate,
886
+ instanceScores: record.instanceScores,
887
+ ...outputs === void 0 ? {} : { outputs }
888
+ });
833
889
  }
834
890
  /**
835
891
  * Copies everything mutable: a snapshot handed to `onCheckpoint` is a record
@@ -846,6 +902,7 @@ async function runGepa(args) {
846
902
  metricCalls: budget.spent(),
847
903
  reflectionCalls,
848
904
  cacheHits: evaluator.cacheHits(),
905
+ usage: evaluator.usage(),
849
906
  ...samplerState === void 0 ? {} : { sampler: samplerState },
850
907
  rejectedProposals: snapshotRejections({
851
908
  rejections: rejectedProposals,
@@ -866,7 +923,7 @@ async function runGepa(args) {
866
923
  if (onCheckpoint === void 0) return;
867
924
  await onCheckpoint(takeSnapshot());
868
925
  }
869
- const evaluator = require_evaluation.createEvaluator({
926
+ const evaluator = require_warnings.createEvaluator({
870
927
  adapter,
871
928
  budget,
872
929
  ...retry === void 0 ? {} : { retry },
@@ -874,6 +931,7 @@ async function runGepa(args) {
874
931
  ...evaluationCache === void 0 ? {} : { cache: evaluationCache },
875
932
  trackOutputs: trackBestOutputs,
876
933
  cacheHits: resumeFrom?.cacheHits ?? 0,
934
+ ...resumeFrom?.usage === void 0 ? {} : { usage: resumeFrom.usage },
877
935
  ...signal === void 0 ? {} : { signal },
878
936
  onEvaluation: (event) => emit({
879
937
  type: "evaluation",
@@ -953,7 +1011,7 @@ async function runGepa(args) {
953
1011
  componentCursor: inheritedCursor(args.parentIds)
954
1012
  };
955
1013
  records.push(record);
956
- seenCandidates.add(require_evaluation.candidateFingerprint(args.candidate));
1014
+ seenCandidates.add(require_warnings.candidateFingerprint(args.candidate));
957
1015
  if (trackBestOutputs) outputsByCandidate.set(record.id, args.evaluation.outputs);
958
1016
  if (args.source !== "merge") {
959
1017
  lastIterationAccepted = true;
@@ -965,7 +1023,7 @@ async function runGepa(args) {
965
1023
  function rememberRejection(args) {
966
1024
  const { proposed, parentScore, childScore } = args;
967
1025
  if (rejectedProposalMemory <= 0) return;
968
- for (const component of require_evaluation.componentNames(proposed)) {
1026
+ for (const component of require_warnings.componentNames(proposed)) {
969
1027
  const text = proposed[component];
970
1028
  if (text === void 0) continue;
971
1029
  const history = rejectedProposals[component] ?? [];
@@ -993,18 +1051,23 @@ async function runGepa(args) {
993
1051
  if (records.length === 0) {
994
1052
  const seedInstances = selectValInstances(seedCandidate);
995
1053
  if (!budget.canAfford(seedInstances.length)) throw new Error(`maxMetricCalls (${maxMetricCalls}) is smaller than the ${seedInstances.length} validation instances selected for scoring; the seed candidate cannot be scored`);
996
- addCandidate({
1054
+ const seedEvaluation = await evaluateValidation({
1055
+ candidate: seedCandidate,
1056
+ instances: seedInstances,
1057
+ phase: "seed",
1058
+ candidateId: 0
1059
+ });
1060
+ emitAccepted(addCandidate({
997
1061
  candidate: seedCandidate,
998
1062
  parentIds: [],
999
- evaluation: await evaluateValidation({
1000
- candidate: seedCandidate,
1001
- instances: seedInstances,
1002
- phase: "seed",
1003
- candidateId: 0
1004
- }),
1063
+ evaluation: seedEvaluation,
1005
1064
  source: "seed",
1006
1065
  updatedComponents: []
1007
- });
1066
+ }));
1067
+ warnings.push(...require_warnings.seedScoreWarnings({
1068
+ scores: seedEvaluation.scores,
1069
+ perfectScore
1070
+ }));
1008
1071
  lastIterationAccepted = false;
1009
1072
  mergesDue = 0;
1010
1073
  await checkpoint();
@@ -1091,18 +1154,11 @@ async function runGepa(args) {
1091
1154
  parentIds: [...proposal.parentIds],
1092
1155
  evaluation,
1093
1156
  source: "merge",
1094
- updatedComponents: require_evaluation.componentNames(proposal.candidate).filter((name) => proposal.candidate[name] !== ancestor.candidate[name])
1157
+ updatedComponents: require_warnings.componentNames(proposal.candidate).filter((name) => proposal.candidate[name] !== ancestor.candidate[name])
1095
1158
  });
1096
1159
  mergesDue -= 1;
1097
1160
  totalMergesTested += 1;
1098
- emit({
1099
- type: "candidateAccepted",
1100
- iteration,
1101
- candidateId: record.id,
1102
- parentIds: record.parentIds,
1103
- aggregateScore: record.aggregateScore,
1104
- source: "merge"
1105
- });
1161
+ emitAccepted(record);
1106
1162
  return "attempted";
1107
1163
  }
1108
1164
  /**
@@ -1141,7 +1197,7 @@ async function runGepa(args) {
1141
1197
  candidate: parent.candidate,
1142
1198
  source: "componentSelector"
1143
1199
  });
1144
- parent.componentCursor = (parent.componentCursor + 1) % Math.max(1, require_evaluation.componentNames(parent.candidate).length);
1200
+ parent.componentCursor = (parent.componentCursor + 1) % Math.max(1, require_warnings.componentNames(parent.candidate).length);
1145
1201
  plans.push({
1146
1202
  parent,
1147
1203
  batch: batchIndices.map((index) => trainingSet[index]),
@@ -1191,7 +1247,7 @@ async function runGepa(args) {
1191
1247
  throw err;
1192
1248
  }
1193
1249
  assertComponents({
1194
- names: require_evaluation.componentNames(proposed),
1250
+ names: require_warnings.componentNames(proposed),
1195
1251
  candidate: parent.candidate,
1196
1252
  source: "proposeNewTexts"
1197
1253
  });
@@ -1199,7 +1255,7 @@ async function runGepa(args) {
1199
1255
  ...parent.candidate,
1200
1256
  ...proposed
1201
1257
  };
1202
- const changed = require_evaluation.componentNames(proposed).length > 0 && !seenCandidates.has(require_evaluation.candidateFingerprint(child));
1258
+ const changed = require_warnings.componentNames(proposed).length > 0 && !seenCandidates.has(require_warnings.candidateFingerprint(child));
1203
1259
  emit({
1204
1260
  type: "proposal",
1205
1261
  iteration,
@@ -1219,7 +1275,7 @@ async function runGepa(args) {
1219
1275
  candidateId: null
1220
1276
  });
1221
1277
  } catch (err) {
1222
- if (err instanceof require_evaluation.BudgetExhausted) return { status: "budgetExhausted" };
1278
+ if (err instanceof require_warnings.BudgetExhausted) return { status: "budgetExhausted" };
1223
1279
  throw err;
1224
1280
  }
1225
1281
  const screened = pairMeasured({
@@ -1262,7 +1318,7 @@ async function runGepa(args) {
1262
1318
  stop ??= "reflectionBudgetExhausted";
1263
1319
  continue;
1264
1320
  }
1265
- const fingerprint = require_evaluation.candidateFingerprint(outcome.child);
1321
+ const fingerprint = require_warnings.candidateFingerprint(outcome.child);
1266
1322
  if (claimed.has(fingerprint)) continue;
1267
1323
  claimed.add(fingerprint);
1268
1324
  if (!outcome.accepted) {
@@ -1334,7 +1390,7 @@ async function runGepa(args) {
1334
1390
  })
1335
1391
  };
1336
1392
  } catch (err) {
1337
- if (err instanceof require_evaluation.BudgetExhausted) return {
1393
+ if (err instanceof require_warnings.BudgetExhausted) return {
1338
1394
  item,
1339
1395
  evaluation: void 0
1340
1396
  };
@@ -1347,21 +1403,13 @@ async function runGepa(args) {
1347
1403
  stop ??= "budgetExhausted";
1348
1404
  break;
1349
1405
  }
1350
- const record = addCandidate({
1406
+ emitAccepted(addCandidate({
1351
1407
  candidate: item.outcome.child,
1352
1408
  parentIds: [item.outcome.plan.parent.id],
1353
1409
  evaluation,
1354
1410
  source: "mutation",
1355
- updatedComponents: require_evaluation.componentNames(item.outcome.proposed)
1356
- });
1357
- emit({
1358
- type: "candidateAccepted",
1359
- iteration,
1360
- candidateId: record.id,
1361
- parentIds: record.parentIds,
1362
- aggregateScore: record.aggregateScore,
1363
- source: "mutation"
1364
- });
1411
+ updatedComponents: require_warnings.componentNames(item.outcome.proposed)
1412
+ }));
1365
1413
  }
1366
1414
  return stop;
1367
1415
  }
@@ -1378,7 +1426,7 @@ async function runGepa(args) {
1378
1426
  stopReason = "aborted";
1379
1427
  break;
1380
1428
  }
1381
- if (require_evaluation.costExhausted({
1429
+ if (require_warnings.costExhausted({
1382
1430
  usage: evaluator.usage(),
1383
1431
  maxCostUsd
1384
1432
  })) {
@@ -1425,7 +1473,7 @@ async function runGepa(args) {
1425
1473
  stopReason = "aborted";
1426
1474
  break;
1427
1475
  }
1428
- if (err instanceof require_evaluation.BudgetExhausted) {
1476
+ if (err instanceof require_warnings.BudgetExhausted) {
1429
1477
  stopReason = "budgetExhausted";
1430
1478
  break;
1431
1479
  }
@@ -1445,7 +1493,7 @@ async function runGepa(args) {
1445
1493
  }
1446
1494
  const bestCandidateId = valEvaluationPolicy.bestCandidate(records);
1447
1495
  const best = records[bestCandidateId];
1448
- const testScore = testSet === void 0 ? void 0 : require_evaluation.measuredMean(await evaluateCached({
1496
+ const heldOut = testSet === void 0 ? void 0 : await evaluateCached({
1449
1497
  candidate: best.candidate,
1450
1498
  batch: testSet,
1451
1499
  ids: testIds,
@@ -1453,13 +1501,18 @@ async function runGepa(args) {
1453
1501
  phase: "test",
1454
1502
  candidateId: bestCandidateId,
1455
1503
  charge: false
1456
- }));
1504
+ });
1505
+ const testScore = heldOut === void 0 ? void 0 : require_warnings.measuredMean(heldOut);
1457
1506
  emit({
1458
1507
  type: "finish",
1459
1508
  reason: stopReason,
1509
+ warnings,
1460
1510
  bestCandidateId,
1511
+ bestScore: best.aggregateScore,
1461
1512
  metricCalls: budget.spent(),
1462
- ...testScore === void 0 ? {} : { testScore }
1513
+ ...testScore === void 0 ? {} : { testScore },
1514
+ ...heldOut === void 0 ? {} : { testInstanceScores: require_warnings.instanceRow(heldOut) },
1515
+ ...heldOut === void 0 || !trackBestOutputs ? {} : { testOutputs: heldOut.outputs }
1463
1516
  });
1464
1517
  const perObjectiveBest = collectPerObjectiveBest(records);
1465
1518
  const bestOutputs = outputsByCandidate.get(bestCandidateId);
@@ -1470,7 +1523,8 @@ async function runGepa(args) {
1470
1523
  bestCandidateId,
1471
1524
  ...testScore === void 0 ? {} : {
1472
1525
  testScore,
1473
- testMetricCalls: evaluator.unchargedCalls()
1526
+ testMetricCalls: evaluator.unchargedCalls(),
1527
+ testUsage: evaluator.unchargedUsage()
1474
1528
  },
1475
1529
  ...bestOutputs === void 0 ? {} : { bestOutputs },
1476
1530
  candidates: records,
@@ -1481,6 +1535,7 @@ async function runGepa(args) {
1481
1535
  reflectionCalls,
1482
1536
  cacheHits: evaluator.cacheHits(),
1483
1537
  iterations: iteration,
1538
+ warnings,
1484
1539
  stopReason,
1485
1540
  snapshot: takeSnapshot()
1486
1541
  };
@@ -1493,13 +1548,15 @@ async function runGepa(args) {
1493
1548
  function assertGepaConfig(config) {
1494
1549
  if (config.reflection?.buildPrompt !== void 0 && config.reflection.strategies !== void 0) throw new Error("reflection takes buildPrompt or strategies, not both");
1495
1550
  if (config.reflection?.strategies?.length === 0) throw new Error("reflection.strategies must not be empty");
1496
- const { minibatchSize = DEFAULT_MINIBATCH_SIZE, maxIterations = Number.POSITIVE_INFINITY, perfectScore = 1, rejectedProposalMemory = DEFAULT_REJECTED_PROPOSAL_MEMORY, proposals } = config;
1551
+ const { minibatchSize = DEFAULT_MINIBATCH_SIZE, maxIterations = Number.POSITIVE_INFINITY, acceptance, perfectScore = 1, rejectedProposalMemory = DEFAULT_REJECTED_PROPOSAL_MEMORY, proposals } = config;
1497
1552
  const proposalsPerIteration = proposals?.perIteration ?? 1;
1498
1553
  const proposalConcurrency = proposals?.concurrency ?? 1;
1499
1554
  if (!Number.isInteger(proposalsPerIteration) || proposalsPerIteration < 1) throw new Error(`proposals.perIteration must be a positive integer, received ${proposalsPerIteration}`);
1500
1555
  if (!Number.isInteger(proposalConcurrency) || proposalConcurrency < 1) throw new Error(`proposals.concurrency must be a positive integer, received ${proposalConcurrency}`);
1501
1556
  keepCount(proposals?.selection ?? "all");
1502
1557
  if (!Number.isInteger(minibatchSize) || minibatchSize < 1) throw new Error(`minibatchSize must be a positive integer, received ${minibatchSize}`);
1558
+ const minimumPairs = acceptance?.minimumPairs;
1559
+ if (minimumPairs !== void 0 && minibatchSize < minimumPairs) throw new Error(`this acceptance policy cannot accept anything on fewer than ${minimumPairs} instances, but minibatchSize is ${minibatchSize}; raise minibatchSize or loosen the policy`);
1503
1560
  if (!Number.isFinite(perfectScore)) throw new Error(`perfectScore must be a finite number, received ${perfectScore}`);
1504
1561
  if (!Number.isInteger(rejectedProposalMemory) || rejectedProposalMemory < 0) throw new Error(`rejectedProposalMemory must be a non-negative integer, received ${rejectedProposalMemory}`);
1505
1562
  if (maxIterations !== Number.POSITIVE_INFINITY && (!Number.isInteger(maxIterations) || maxIterations < 0)) throw new Error(`maxIterations must be a non-negative integer or Infinity, received ${maxIterations}`);
@@ -1513,7 +1570,7 @@ function assertGepaConfig(config) {
1513
1570
  */
1514
1571
  function restoreRecords(args) {
1515
1572
  const { records, seedCandidate } = args;
1516
- const known = new Set(require_evaluation.componentNames(seedCandidate));
1573
+ const known = new Set(require_warnings.componentNames(seedCandidate));
1517
1574
  for (const record of records) {
1518
1575
  const named = [...Object.keys(record.candidate), ...record.updatedComponents];
1519
1576
  for (const name of named) if (!known.has(name)) throw new Error(`checkpoint names the component "${name}", which the seed candidate does not have (${[...known].join(", ")})`);
@@ -1618,17 +1675,6 @@ function collectDominatorIds(records) {
1618
1675
  return [...ids].sort((a, b) => a - b);
1619
1676
  }
1620
1677
  /**
1621
- * Names an instance by a hash of its content rather than by the content
1622
- * itself: the id ends up inside every cache key and inside the checkpoint
1623
- * fingerprint, and embedding whole examples there costs memory proportional to
1624
- * the dataset for no benefit. Data that will not serialize falls back to its
1625
- * position, which is stable for as long as the dataset order is.
1626
- */
1627
- function defaultInstanceId(args) {
1628
- const hash = require_evaluation.stableHash(args.datum);
1629
- return hash === "" ? String(args.index) : hash;
1630
- }
1631
- /**
1632
1678
  * The two rollout sets restricted to the instances both of them measured.
1633
1679
  *
1634
1680
  * Screening is a paired comparison over one minibatch: a transient row is a
@@ -1663,6 +1709,8 @@ exports.diverseReflectionStrategies = require_reflection.diverseReflectionStrate
1663
1709
  exports.epsilonGreedySelector = epsilonGreedySelector;
1664
1710
  exports.fullEvaluationPolicy = fullEvaluationPolicy;
1665
1711
  exports.improvementAcceptance = improvementAcceptance;
1712
+ exports.isCandidateAccepted = require_warnings.isCandidateAccepted;
1713
+ exports.isRunFinished = require_warnings.isRunFinished;
1666
1714
  exports.lowerBoundEvaluationPolicy = lowerBoundEvaluationPolicy;
1667
1715
  exports.pairedPermutationAcceptance = pairedPermutationAcceptance;
1668
1716
  exports.paretoSelector = paretoSelector;
@@ -1,8 +1,8 @@
1
- import { l as ScoreResult, u as TextModel } from "../types-CWv4IQFF.cjs";
1
+ import { a as RunFinished, b as ScoreResult, i as Reporter, n as OptimizerEvent, o as isCandidateAccepted, r as ReportableEvent, s as isRunFinished, t as CandidateAccepted, x as TextModel } from "../reporting-bq007_2z.cjs";
2
2
  import { n as EvaluationCache } from "../cache-CuSo0NJ8.cjs";
3
- import { r as DemoRenderer } from "../demos-BTuzFNsp.cjs";
4
- import { n as OptimizerResult, r as OptimizerTask, t as Optimizer } from "../optimizer-B7SpRwl7.cjs";
5
- import { C as RejectedProposal, S as ReflectiveRecord, T as ValEvaluationPolicy, _ as GepaStopReason, a as buildRewritePrompt, b as ProposeArgs, c as AcceptancePolicy, d as CandidateSource, f as ComponentPatch, g as GepaSnapshot, h as GepaEvent, i as buildReflectionPrompt, l as CandidateRecord, m as GepaAdapter, n as ReflectionPromptBuilder, o as buildSimplifyPrompt, p as ComponentSelector, r as buildGeneralizePrompt, s as diverseReflectionStrategies, t as ReflectionPromptArgs, u as CandidateSelector, v as MakeReflectiveDatasetArgs, w as SelectionState, x as ReflectiveDataset, y as ParetoFrontier } from "../reflection-CQToe-5B.cjs";
3
+ import { r as DemoRenderer } from "../demos-ByaLZy-Z.cjs";
4
+ import { n as OptimizerResult, r as OptimizerTask, t as Optimizer } from "../optimizer-4Zv-Zt2t.cjs";
5
+ import { C as ReflectiveRecord, E as ValEvaluationPolicy, S as ReflectiveDataset, T as SelectionState, _ as GepaStopReason, a as buildRewritePrompt, b as ProposeArgs, c as AcceptancePolicy, d as CandidateSource, f as ComponentPatch, g as GepaSnapshot, h as GepaEvent, i as buildReflectionPrompt, l as CandidateRecord, m as GepaAdapter, n as ReflectionPromptBuilder, o as buildSimplifyPrompt, p as ComponentSelector, r as buildGeneralizePrompt, s as diverseReflectionStrategies, t as ReflectionPromptArgs, u as CandidateSelector, v as MakeReflectiveDatasetArgs, w as RejectedProposal, x as ReflectiveBatch, y as ParetoFrontier } from "../reflection-D0A7eahD.cjs";
6
6
  import { t as BatchSampler } from "../sampling-axOwfZf5.cjs";
7
7
  //#region src/gepa/demos.d.ts
8
8
  /**
@@ -246,7 +246,13 @@ interface GepaTask<Datum, Trajectory = unknown, Output = unknown, K extends stri
246
246
  * counts against a reference run directly.
247
247
  */
248
248
  cache?: EvaluationCache | false;
249
- onEvent?: (event: GepaEvent<NoInfer<K>>) => void;
249
+ /**
250
+ * Where the run's events go. An array because a run usually has more than
251
+ * one audience — a progress line on the terminal and a permanent record
252
+ * somewhere else — and teeing one callback by hand is how one of them ends
253
+ * up silently dropped.
254
+ */
255
+ reporters?: readonly Reporter<GepaEvent<NoInfer<K>>>[];
250
256
  /**
251
257
  * Called with a resumable snapshot after the seed is scored and after every
252
258
  * iteration. Persist it and a killed run costs the last iteration, not all
@@ -299,7 +305,9 @@ declare class GepaOptimizer implements Optimizer<GepaStopReason> {
299
305
  * `frontier` chooses what the fronts are taken over. "instance" is GEPA as
300
306
  * published. "objective" tracks candidates leading each named objective the
301
307
  * adapter reports, and "hybrid" pools both — a candidate then earns selection
302
- * weight for every instance it wins *and* every objective it leads.
308
+ * weight for every instance it wins *and* every objective it leads. The
309
+ * objectives are whatever the adapter put in `objectiveScores`, which for a
310
+ * judge is every criterion it graded, including any at `weight: 0`.
303
311
  */
304
312
  declare function paretoSelector(args?: {
305
313
  epsilon?: number;
@@ -382,4 +390,4 @@ declare function pairedPermutationAcceptance(args?: {
382
390
  maxExact?: number;
383
391
  }): AcceptancePolicy;
384
392
  //#endregion
385
- export { type AcceptancePolicy, type CandidateRecord, type CandidateSelector, type CandidateSource, type ComponentPatch, type ComponentSelector, type GepaAdapter, type GepaConfig, type GepaEvent, GepaOptimizer, type GepaResult, type GepaSnapshot, type GepaStopReason, type GepaTask, type MakeReflectiveDatasetArgs, type PipelineModule, type PipelineStep, type PipelineTrace, type ProposeArgs, type ReflectionPromptArgs, type ReflectionPromptBuilder, type ReflectiveDataset, type ReflectiveRecord, type RejectedProposal, type SelectionState, type ValEvaluationPolicy, allComponentsSelector, buildGeneralizePrompt, buildReflectionPrompt, buildRewritePrompt, buildSimplifyPrompt, createDemoProposer, createPipelineAdapter, currentBestSelector, diverseReflectionStrategies, epsilonGreedySelector, fullEvaluationPolicy, improvementAcceptance, lowerBoundEvaluationPolicy, pairedPermutationAcceptance, paretoSelector, roundRobinComponentSelector, subsampledEvaluationPolicy, topKParetoSelector };
393
+ export { type AcceptancePolicy, type CandidateAccepted, type CandidateRecord, type CandidateSelector, type CandidateSource, type ComponentPatch, type ComponentSelector, type GepaAdapter, type GepaConfig, type GepaEvent, GepaOptimizer, type GepaResult, type GepaSnapshot, type GepaStopReason, type GepaTask, type MakeReflectiveDatasetArgs, type OptimizerEvent, type PipelineModule, type PipelineStep, type PipelineTrace, type ProposeArgs, type ReflectionPromptArgs, type ReflectionPromptBuilder, type ReflectiveBatch, type ReflectiveDataset, type ReflectiveRecord, type RejectedProposal, type ReportableEvent, type Reporter, type RunFinished, type SelectionState, type ValEvaluationPolicy, allComponentsSelector, buildGeneralizePrompt, buildReflectionPrompt, buildRewritePrompt, buildSimplifyPrompt, createDemoProposer, createPipelineAdapter, currentBestSelector, diverseReflectionStrategies, epsilonGreedySelector, fullEvaluationPolicy, improvementAcceptance, isCandidateAccepted, isRunFinished, lowerBoundEvaluationPolicy, pairedPermutationAcceptance, paretoSelector, roundRobinComponentSelector, subsampledEvaluationPolicy, topKParetoSelector };
@@ -1,8 +1,8 @@
1
- import { l as ScoreResult, u as TextModel } from "../types-CWv4IQFF.mjs";
1
+ import { a as RunFinished, b as ScoreResult, i as Reporter, n as OptimizerEvent, o as isCandidateAccepted, r as ReportableEvent, s as isRunFinished, t as CandidateAccepted, x as TextModel } from "../reporting-bq007_2z.mjs";
2
2
  import { n as EvaluationCache } from "../cache-CuSo0NJ8.mjs";
3
- import { r as DemoRenderer } from "../demos-B0pVQjYC.mjs";
4
- import { n as OptimizerResult, r as OptimizerTask, t as Optimizer } from "../optimizer-DqCoth_w.mjs";
5
- import { C as RejectedProposal, S as ReflectiveRecord, T as ValEvaluationPolicy, _ as GepaStopReason, a as buildRewritePrompt, b as ProposeArgs, c as AcceptancePolicy, d as CandidateSource, f as ComponentPatch, g as GepaSnapshot, h as GepaEvent, i as buildReflectionPrompt, l as CandidateRecord, m as GepaAdapter, n as ReflectionPromptBuilder, o as buildSimplifyPrompt, p as ComponentSelector, r as buildGeneralizePrompt, s as diverseReflectionStrategies, t as ReflectionPromptArgs, u as CandidateSelector, v as MakeReflectiveDatasetArgs, w as SelectionState, x as ReflectiveDataset, y as ParetoFrontier } from "../reflection-Cr_upzU0.mjs";
3
+ import { r as DemoRenderer } from "../demos-ASsSXYXA.mjs";
4
+ import { n as OptimizerResult, r as OptimizerTask, t as Optimizer } from "../optimizer-Ds5mzYjz.mjs";
5
+ import { C as ReflectiveRecord, E as ValEvaluationPolicy, S as ReflectiveDataset, T as SelectionState, _ as GepaStopReason, a as buildRewritePrompt, b as ProposeArgs, c as AcceptancePolicy, d as CandidateSource, f as ComponentPatch, g as GepaSnapshot, h as GepaEvent, i as buildReflectionPrompt, l as CandidateRecord, m as GepaAdapter, n as ReflectionPromptBuilder, o as buildSimplifyPrompt, p as ComponentSelector, r as buildGeneralizePrompt, s as diverseReflectionStrategies, t as ReflectionPromptArgs, u as CandidateSelector, v as MakeReflectiveDatasetArgs, w as RejectedProposal, x as ReflectiveBatch, y as ParetoFrontier } from "../reflection-CMezGu6u.mjs";
6
6
  import { t as BatchSampler } from "../sampling-DFo_7RNJ.mjs";
7
7
  //#region src/gepa/demos.d.ts
8
8
  /**
@@ -246,7 +246,13 @@ interface GepaTask<Datum, Trajectory = unknown, Output = unknown, K extends stri
246
246
  * counts against a reference run directly.
247
247
  */
248
248
  cache?: EvaluationCache | false;
249
- onEvent?: (event: GepaEvent<NoInfer<K>>) => void;
249
+ /**
250
+ * Where the run's events go. An array because a run usually has more than
251
+ * one audience — a progress line on the terminal and a permanent record
252
+ * somewhere else — and teeing one callback by hand is how one of them ends
253
+ * up silently dropped.
254
+ */
255
+ reporters?: readonly Reporter<GepaEvent<NoInfer<K>>>[];
250
256
  /**
251
257
  * Called with a resumable snapshot after the seed is scored and after every
252
258
  * iteration. Persist it and a killed run costs the last iteration, not all
@@ -299,7 +305,9 @@ declare class GepaOptimizer implements Optimizer<GepaStopReason> {
299
305
  * `frontier` chooses what the fronts are taken over. "instance" is GEPA as
300
306
  * published. "objective" tracks candidates leading each named objective the
301
307
  * adapter reports, and "hybrid" pools both — a candidate then earns selection
302
- * weight for every instance it wins *and* every objective it leads.
308
+ * weight for every instance it wins *and* every objective it leads. The
309
+ * objectives are whatever the adapter put in `objectiveScores`, which for a
310
+ * judge is every criterion it graded, including any at `weight: 0`.
303
311
  */
304
312
  declare function paretoSelector(args?: {
305
313
  epsilon?: number;
@@ -382,4 +390,4 @@ declare function pairedPermutationAcceptance(args?: {
382
390
  maxExact?: number;
383
391
  }): AcceptancePolicy;
384
392
  //#endregion
385
- export { type AcceptancePolicy, type CandidateRecord, type CandidateSelector, type CandidateSource, type ComponentPatch, type ComponentSelector, type GepaAdapter, type GepaConfig, type GepaEvent, GepaOptimizer, type GepaResult, type GepaSnapshot, type GepaStopReason, type GepaTask, type MakeReflectiveDatasetArgs, type PipelineModule, type PipelineStep, type PipelineTrace, type ProposeArgs, type ReflectionPromptArgs, type ReflectionPromptBuilder, type ReflectiveDataset, type ReflectiveRecord, type RejectedProposal, type SelectionState, type ValEvaluationPolicy, allComponentsSelector, buildGeneralizePrompt, buildReflectionPrompt, buildRewritePrompt, buildSimplifyPrompt, createDemoProposer, createPipelineAdapter, currentBestSelector, diverseReflectionStrategies, epsilonGreedySelector, fullEvaluationPolicy, improvementAcceptance, lowerBoundEvaluationPolicy, pairedPermutationAcceptance, paretoSelector, roundRobinComponentSelector, subsampledEvaluationPolicy, topKParetoSelector };
393
+ export { type AcceptancePolicy, type CandidateAccepted, type CandidateRecord, type CandidateSelector, type CandidateSource, type ComponentPatch, type ComponentSelector, type GepaAdapter, type GepaConfig, type GepaEvent, GepaOptimizer, type GepaResult, type GepaSnapshot, type GepaStopReason, type GepaTask, type MakeReflectiveDatasetArgs, type OptimizerEvent, type PipelineModule, type PipelineStep, type PipelineTrace, type ProposeArgs, type ReflectionPromptArgs, type ReflectionPromptBuilder, type ReflectiveBatch, type ReflectiveDataset, type ReflectiveRecord, type RejectedProposal, type ReportableEvent, type Reporter, type RunFinished, type SelectionState, type ValEvaluationPolicy, allComponentsSelector, buildGeneralizePrompt, buildReflectionPrompt, buildRewritePrompt, buildSimplifyPrompt, createDemoProposer, createPipelineAdapter, currentBestSelector, diverseReflectionStrategies, epsilonGreedySelector, fullEvaluationPolicy, improvementAcceptance, isCandidateAccepted, isRunFinished, lowerBoundEvaluationPolicy, pairedPermutationAcceptance, paretoSelector, roundRobinComponentSelector, subsampledEvaluationPolicy, topKParetoSelector };