@tangle-network/agent-eval 0.79.0 → 0.81.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 (107) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +101 -169
  3. package/dist/adapters/http.d.ts +2 -2
  4. package/dist/adapters/langchain.d.ts +2 -2
  5. package/dist/adapters/otel.d.ts +4 -4
  6. package/dist/{agent-profile-aSEaJ9Pl.d.ts → agent-profile-D0PBIWlV.d.ts} +14 -2
  7. package/dist/analyst/index.d.ts +10 -10
  8. package/dist/analyst/index.js +3 -3
  9. package/dist/{analyst-t7zZS3TV.d.ts → analyst-C8HHvfJp.d.ts} +1 -1
  10. package/dist/belief-state/index.d.ts +524 -0
  11. package/dist/belief-state/index.js +1862 -0
  12. package/dist/belief-state/index.js.map +1 -0
  13. package/dist/benchmarks/index.d.ts +2 -2
  14. package/dist/calibration-Cpr3WaX3.d.ts +101 -0
  15. package/dist/campaign/index.d.ts +40 -120
  16. package/dist/campaign/index.js +129 -238
  17. package/dist/campaign/index.js.map +1 -1
  18. package/dist/chunk-4DIJWVUT.js +131 -0
  19. package/dist/chunk-4DIJWVUT.js.map +1 -0
  20. package/dist/{chunk-RPLZ4OIB.js → chunk-BABOZOSN.js} +7 -4
  21. package/dist/{chunk-RPLZ4OIB.js.map → chunk-BABOZOSN.js.map} +1 -1
  22. package/dist/{chunk-IHDHUN2X.js → chunk-CVVHBFGN.js} +3 -3
  23. package/dist/chunk-CVVHBFGN.js.map +1 -0
  24. package/dist/{chunk-B26KI423.js → chunk-FZWAFVAA.js} +2 -2
  25. package/dist/{chunk-ITBRCT73.js → chunk-IDVBLYCY.js} +2 -10
  26. package/dist/chunk-IDVBLYCY.js.map +1 -0
  27. package/dist/{chunk-5LVWPNS5.js → chunk-L5G7OUKD.js} +4 -4
  28. package/dist/{chunk-5LVWPNS5.js.map → chunk-L5G7OUKD.js.map} +1 -1
  29. package/dist/chunk-NPCTHQIO.js +91 -0
  30. package/dist/chunk-NPCTHQIO.js.map +1 -0
  31. package/dist/{chunk-GXHLRXDI.js → chunk-OTYQPHPL.js} +4 -4
  32. package/dist/{chunk-6REHLN5J.js → chunk-QS3RBQPI.js} +2 -2
  33. package/dist/{chunk-GWGO2K6Y.js → chunk-RBNA5AZT.js} +2 -2
  34. package/dist/chunk-S42AWHMP.js +697 -0
  35. package/dist/chunk-S42AWHMP.js.map +1 -0
  36. package/dist/chunk-VI2UW6B6.js +162 -0
  37. package/dist/chunk-VI2UW6B6.js.map +1 -0
  38. package/dist/{chunk-CF67I6QY.js → chunk-VIDQF3F5.js} +2 -2
  39. package/dist/{chunk-XXNIODOM.js → chunk-WJL2NJXN.js} +3 -3
  40. package/dist/{chunk-LB2UOI5F.js → chunk-YGYXHNAQ.js} +47 -160
  41. package/dist/chunk-YGYXHNAQ.js.map +1 -0
  42. package/dist/{chunk-KX6F6NCG.js → chunk-Z7VFTS2J.js} +2 -2
  43. package/dist/{chunk-ZPSKPT3V.js → chunk-ZZ2HOPME.js} +5 -2
  44. package/dist/chunk-ZZ2HOPME.js.map +1 -0
  45. package/dist/cli.js +2 -2
  46. package/dist/code-agent-session-BRXmavYv.d.ts +80 -0
  47. package/dist/contract/index.d.ts +132 -18
  48. package/dist/contract/index.js +139 -6
  49. package/dist/contract/index.js.map +1 -1
  50. package/dist/{control-CehLtoET.d.ts → control-GeE8OhpN.d.ts} +1 -1
  51. package/dist/control.d.ts +2 -2
  52. package/dist/governance/index.d.ts +1 -1
  53. package/dist/hosted/index.d.ts +4 -4
  54. package/dist/{index-B1RKber3.d.ts → index-DE3RXAXD.d.ts} +1 -1
  55. package/dist/index.d.ts +79 -288
  56. package/dist/index.js +87 -410
  57. package/dist/index.js.map +1 -1
  58. package/dist/{insight-report-dlpEzQDi.d.ts → insight-report-3ADTfClO.d.ts} +1 -1
  59. package/dist/{kind-factory-DqV2t1Xk.d.ts → kind-factory-CVecZZG_.d.ts} +2 -2
  60. package/dist/{llm-client-DbjLfz-K.d.ts → llm-client-CuUg2Mn3.d.ts} +1 -1
  61. package/dist/meta-eval/index.d.ts +6 -99
  62. package/dist/meta-eval/index.js +7 -76
  63. package/dist/meta-eval/index.js.map +1 -1
  64. package/dist/off-policy-DiwuKKg7.d.ts +132 -0
  65. package/dist/openapi.json +1 -1
  66. package/dist/{outcome-store-D6KWmYvj.d.ts → outcome-store-rnXLEqSn.d.ts} +1 -1
  67. package/dist/pipelines/index.js +2 -2
  68. package/dist/{provenance-CEAJI9rm.d.ts → provenance-B9Q4886D.d.ts} +4 -4
  69. package/dist/{registry-BmEuU94S.d.ts → registry-DrEQ3Luj.d.ts} +2 -2
  70. package/dist/{release-report-CXXZlR8g.d.ts → release-report-hlNtD12q.d.ts} +2 -2
  71. package/dist/reporting.d.ts +6 -6
  72. package/dist/reporting.js +3 -3
  73. package/dist/{researcher-rInLj9De.d.ts → researcher-BLPHBbNV.d.ts} +3 -3
  74. package/dist/rl.d.ts +11 -141
  75. package/dist/rl.js +10 -124
  76. package/dist/rl.js.map +1 -1
  77. package/dist/{rubric-predictive-validity-CWyWWLBg.d.ts → rubric-predictive-validity-CnEl9Jc8.d.ts} +2 -2
  78. package/dist/{run-campaign-OVEZF24D.js → run-campaign-4Y5V5CN3.js} +3 -3
  79. package/dist/{run-improvement-loop-Bgu4C59E.d.ts → run-improvement-loop-D6PZOoQL.d.ts} +2 -2
  80. package/dist/{run-record-sItO5ftF.d.ts → run-record-De9VarXR.d.ts} +1 -1
  81. package/dist/{semantic-concept-judge-Du4ZVyef.d.ts → semantic-concept-judge-DIEgr_6v.d.ts} +6 -6
  82. package/dist/{statistics-B7yCbi9i.d.ts → statistics-CnC1FMbx.d.ts} +3 -7
  83. package/dist/{store-GmBE2pZZ.d.ts → store-C1YxJDEK.d.ts} +1 -1
  84. package/dist/{summary-report-BTaXq1TS.d.ts → summary-report-Db0dDSWP.d.ts} +1 -1
  85. package/dist/traces.d.ts +5 -5
  86. package/dist/{types-DRvV0zRo.d.ts → types-Cu3u_x59.d.ts} +3 -3
  87. package/dist/{types-QHG0KnkF.d.ts → types-D7lLRYe9.d.ts} +2 -2
  88. package/dist/wire/index.js +2 -2
  89. package/dist/workflow/index.d.ts +7 -7
  90. package/dist/workflow/index.js +1 -1
  91. package/docs/concepts.md +1 -0
  92. package/docs/research/belief-state-agent-eval-roadmap.md +590 -0
  93. package/docs/research/research-roadmap.md +1 -0
  94. package/docs/self-improvement-map.md +111 -0
  95. package/package.json +7 -2
  96. package/dist/chunk-IHDHUN2X.js.map +0 -1
  97. package/dist/chunk-ITBRCT73.js.map +0 -1
  98. package/dist/chunk-LB2UOI5F.js.map +0 -1
  99. package/dist/chunk-ZPSKPT3V.js.map +0 -1
  100. /package/dist/{chunk-B26KI423.js.map → chunk-FZWAFVAA.js.map} +0 -0
  101. /package/dist/{chunk-GXHLRXDI.js.map → chunk-OTYQPHPL.js.map} +0 -0
  102. /package/dist/{chunk-6REHLN5J.js.map → chunk-QS3RBQPI.js.map} +0 -0
  103. /package/dist/{chunk-GWGO2K6Y.js.map → chunk-RBNA5AZT.js.map} +0 -0
  104. /package/dist/{chunk-CF67I6QY.js.map → chunk-VIDQF3F5.js.map} +0 -0
  105. /package/dist/{chunk-XXNIODOM.js.map → chunk-WJL2NJXN.js.map} +0 -0
  106. /package/dist/{chunk-KX6F6NCG.js.map → chunk-Z7VFTS2J.js.map} +0 -0
  107. /package/dist/{run-campaign-OVEZF24D.js.map → run-campaign-4Y5V5CN3.js.map} +0 -0
@@ -0,0 +1,131 @@
1
+ import {
2
+ ValidationError
3
+ } from "./chunk-3BFEG2F6.js";
4
+
5
+ // src/rl/off-policy.ts
6
+ function inverseProbabilityWeighting(trajectories, opts = {}) {
7
+ const cap = opts.weightCap ?? Infinity;
8
+ const clip = opts.rewardClip ?? { low: 0, high: 1 };
9
+ if (trajectories.length === 0) {
10
+ return zeroEstimate();
11
+ }
12
+ const weights = [];
13
+ const weightedRewards = [];
14
+ let maxW = 0;
15
+ for (const t of trajectories) {
16
+ if (t.behaviorProb <= 0) {
17
+ throw new ValidationError(
18
+ `inverseProbabilityWeighting: behaviorProb must be > 0 (runId=${t.runId})`
19
+ );
20
+ }
21
+ const w = Math.min(cap, t.targetProb / t.behaviorProb);
22
+ const r = clamp(t.reward, clip.low, clip.high);
23
+ weights.push(w);
24
+ weightedRewards.push(w * r);
25
+ if (w > maxW) maxW = w;
26
+ }
27
+ const n = weights.length;
28
+ const value = weightedRewards.reduce((s, x) => s + x, 0) / n;
29
+ const variance = weightedRewards.reduce((s, x) => s + (x - value) ** 2, 0) / Math.max(1, n - 1);
30
+ const sumW = weights.reduce((s, w) => s + w, 0);
31
+ const sumW2 = weights.reduce((s, w) => s + w * w, 0);
32
+ const effN = sumW === 0 ? 0 : sumW * sumW / sumW2;
33
+ return {
34
+ value,
35
+ standardError: Math.sqrt(variance / n),
36
+ effectiveSampleSize: effN,
37
+ n,
38
+ maxImportanceWeight: maxW
39
+ };
40
+ }
41
+ function selfNormalizedImportanceWeighting(trajectories, opts = {}) {
42
+ const cap = opts.weightCap ?? Infinity;
43
+ const clip = opts.rewardClip ?? { low: 0, high: 1 };
44
+ if (trajectories.length === 0) return zeroEstimate();
45
+ const weights = [];
46
+ const rewards = [];
47
+ let maxW = 0;
48
+ for (const t of trajectories) {
49
+ if (t.behaviorProb <= 0) {
50
+ throw new ValidationError(
51
+ `selfNormalizedImportanceWeighting: behaviorProb must be > 0 (runId=${t.runId})`
52
+ );
53
+ }
54
+ const w = Math.min(cap, t.targetProb / t.behaviorProb);
55
+ weights.push(w);
56
+ rewards.push(clamp(t.reward, clip.low, clip.high));
57
+ if (w > maxW) maxW = w;
58
+ }
59
+ const sumW = weights.reduce((s, w) => s + w, 0);
60
+ const sumWR = weights.reduce((s, w, i) => s + w * rewards[i], 0);
61
+ const value = sumW === 0 ? 0 : sumWR / sumW;
62
+ const sumW2 = weights.reduce((s, w) => s + w * w, 0);
63
+ const effN = sumW === 0 ? 0 : sumW * sumW / sumW2;
64
+ const phi = weights.map((w, i) => w * (rewards[i] - value));
65
+ const variance = phi.reduce((s, x) => s + x * x, 0) / Math.max(1, sumW * sumW);
66
+ return {
67
+ value,
68
+ standardError: Math.sqrt(variance),
69
+ effectiveSampleSize: effN,
70
+ n: trajectories.length,
71
+ maxImportanceWeight: maxW
72
+ };
73
+ }
74
+ function doublyRobust(trajectories, opts = {}) {
75
+ const cap = opts.weightCap ?? Infinity;
76
+ const clip = opts.rewardClip ?? { low: 0, high: 1 };
77
+ if (trajectories.length === 0) return zeroEstimate();
78
+ const contributions = [];
79
+ let maxW = 0;
80
+ let sumW = 0;
81
+ let sumW2 = 0;
82
+ for (const t of trajectories) {
83
+ if (t.behaviorProb <= 0) {
84
+ throw new ValidationError(`doublyRobust: behaviorProb must be > 0 (runId=${t.runId})`);
85
+ }
86
+ const w = Math.min(cap, t.targetProb / t.behaviorProb);
87
+ const r = clamp(t.reward, clip.low, clip.high);
88
+ const q = typeof t.qHat === "number" && Number.isFinite(t.qHat) ? clamp(t.qHat, clip.low, clip.high) : null;
89
+ if (q === null) {
90
+ contributions.push(w * r);
91
+ } else {
92
+ contributions.push(q + w * (r - q));
93
+ }
94
+ if (w > maxW) maxW = w;
95
+ sumW += w;
96
+ sumW2 += w * w;
97
+ }
98
+ const n = contributions.length;
99
+ const value = contributions.reduce((s, x) => s + x, 0) / n;
100
+ const variance = contributions.reduce((s, x) => s + (x - value) ** 2, 0) / Math.max(1, n - 1);
101
+ const effN = sumW === 0 ? 0 : sumW * sumW / sumW2;
102
+ return {
103
+ value,
104
+ standardError: Math.sqrt(variance / n),
105
+ effectiveSampleSize: effN,
106
+ n,
107
+ maxImportanceWeight: maxW
108
+ };
109
+ }
110
+ function offPolicyEstimateAll(trajectories, opts = {}) {
111
+ return {
112
+ ips: inverseProbabilityWeighting(trajectories, opts),
113
+ snips: selfNormalizedImportanceWeighting(trajectories, opts),
114
+ dr: doublyRobust(trajectories, opts)
115
+ };
116
+ }
117
+ function zeroEstimate() {
118
+ return { value: 0, standardError: 0, effectiveSampleSize: 0, n: 0, maxImportanceWeight: 0 };
119
+ }
120
+ function clamp(x, lo, hi) {
121
+ if (!Number.isFinite(x)) return lo;
122
+ return Math.max(lo, Math.min(hi, x));
123
+ }
124
+
125
+ export {
126
+ inverseProbabilityWeighting,
127
+ selfNormalizedImportanceWeighting,
128
+ doublyRobust,
129
+ offPolicyEstimateAll
130
+ };
131
+ //# sourceMappingURL=chunk-4DIJWVUT.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/rl/off-policy.ts"],"sourcesContent":["/**\n * Off-policy evaluation primitives.\n *\n * Standard inverse-probability-weighted (IPS), self-normalized\n * importance-weighted (SNIPS), and doubly-robust (DR) estimators for the\n * value of a *target* policy given trajectories collected under a\n * *behavior* policy. This is the canonical RL eval task: \"we have last\n * week's runs, we changed the policy — how would the new one do without\n * re-running?\"\n *\n * The math here is textbook (Dudík, Langford, Li 2011 for DR; Swaminathan\n * & Joachims 2015 for SNIPS) but the *application* to LLM-agent\n * evaluation needs care:\n *\n * - The \"policy\" is the (prompt, tool config, model snapshot) triple.\n * Two policies have the same probability over an action *iff* their\n * LLM call would emit the same token with the same probability —\n * which is generally unknowable without the model log-probs.\n * - For LLM agents, propensity scores must be supplied by the caller\n * (logged in the trace, recovered from token log-probs, or estimated\n * via a learned propensity model). We do NOT estimate propensity here.\n * - Doubly-robust requires a Q-function (model-based reward predictor).\n * We accept any callable; consumers pass either a tabular average,\n * a regression fit, or a learned reward model.\n *\n * Bias / variance tradeoffs:\n * - IPS: unbiased; high variance for small overlap, infinite variance\n * when target has support outside behavior.\n * - SNIPS: lower variance, slight bias; usually preferred in practice.\n * - DR: doubly-robust — unbiased if either propensity OR Q-function is\n * correct. Lowest practical variance when Q is decent. Use this.\n *\n * Caveat the panel will land: on the LLM-agent setting, propensity scores\n * recovered from token log-probs are noisy, the action space is enormous,\n * and overlap is often poor. These estimators are useful but not magic;\n * complement with `replayCampaign` (exact replay where the request hashes\n * match) for high-confidence answers and OPE for the gap.\n */\n\nimport { ValidationError } from '../errors'\n\nexport interface OffPolicyTrajectory {\n /** Stable id, for traceability through the dataset. */\n runId: string\n /** Reward observed under the behavior policy (the realized outcome). */\n reward: number\n /**\n * Behavior-policy probability of the action that was taken. For LLM\n * agents this is typically `exp(sum(token_log_probs))` over the chosen\n * trajectory. Must be in (0, 1].\n */\n behaviorProb: number\n /**\n * Target-policy probability of the same action. For replay-style\n * counterfactual evaluation this is what the *new* policy would have\n * assigned to the *old* trajectory. Must be in [0, 1].\n */\n targetProb: number\n /**\n * Optional model-based reward prediction at the same context. Used by\n * `doublyRobust`. Set to `null` for IPS-only evaluation.\n */\n qHat?: number | null\n}\n\nexport interface OffPolicyEstimate {\n /** Estimated value of the target policy. */\n value: number\n /** Standard error of the estimate. */\n standardError: number\n /** Effective sample size (Kong 1992). Lower = more reliance on a few high-weight samples. */\n effectiveSampleSize: number\n /** Number of trajectories used. */\n n: number\n /**\n * Diagnostic: maximum importance weight observed. Large values (>>10x\n * mean) are a red flag — variance is dominated by a few outliers.\n */\n maxImportanceWeight: number\n}\n\nexport interface OffPolicyOptions {\n /**\n * Cap importance weights at this value (Ionides 2008 truncated IS) to\n * trade unbiasedness for variance reduction. Default `Infinity` (no cap).\n * Set e.g. `10` for stable estimates when the policies are close.\n */\n weightCap?: number\n /** Reward clipping range. Default `[0, 1]`. */\n rewardClip?: { low: number; high: number }\n}\n\n/**\n * Inverse Probability Weighting (Horvitz-Thompson). Unbiased estimator\n * of E[reward under target policy]. Variance scales with the spread of\n * target/behavior ratios.\n */\nexport function inverseProbabilityWeighting(\n trajectories: OffPolicyTrajectory[],\n opts: OffPolicyOptions = {},\n): OffPolicyEstimate {\n const cap = opts.weightCap ?? Infinity\n const clip = opts.rewardClip ?? { low: 0, high: 1 }\n\n if (trajectories.length === 0) {\n return zeroEstimate()\n }\n\n const weights: number[] = []\n const weightedRewards: number[] = []\n let maxW = 0\n for (const t of trajectories) {\n if (t.behaviorProb <= 0) {\n throw new ValidationError(\n `inverseProbabilityWeighting: behaviorProb must be > 0 (runId=${t.runId})`,\n )\n }\n const w = Math.min(cap, t.targetProb / t.behaviorProb)\n const r = clamp(t.reward, clip.low, clip.high)\n weights.push(w)\n weightedRewards.push(w * r)\n if (w > maxW) maxW = w\n }\n const n = weights.length\n const value = weightedRewards.reduce((s, x) => s + x, 0) / n\n const variance = weightedRewards.reduce((s, x) => s + (x - value) ** 2, 0) / Math.max(1, n - 1)\n const sumW = weights.reduce((s, w) => s + w, 0)\n const sumW2 = weights.reduce((s, w) => s + w * w, 0)\n const effN = sumW === 0 ? 0 : (sumW * sumW) / sumW2\n\n return {\n value,\n standardError: Math.sqrt(variance / n),\n effectiveSampleSize: effN,\n n,\n maxImportanceWeight: maxW,\n }\n}\n\n/**\n * Self-Normalized Importance Sampling. Lower variance than vanilla IPS at\n * the cost of small bias (vanishing as N grows). The right default for\n * LLM-agent evaluation where overlap is often poor.\n */\nexport function selfNormalizedImportanceWeighting(\n trajectories: OffPolicyTrajectory[],\n opts: OffPolicyOptions = {},\n): OffPolicyEstimate {\n const cap = opts.weightCap ?? Infinity\n const clip = opts.rewardClip ?? { low: 0, high: 1 }\n if (trajectories.length === 0) return zeroEstimate()\n\n const weights: number[] = []\n const rewards: number[] = []\n let maxW = 0\n for (const t of trajectories) {\n if (t.behaviorProb <= 0) {\n throw new ValidationError(\n `selfNormalizedImportanceWeighting: behaviorProb must be > 0 (runId=${t.runId})`,\n )\n }\n const w = Math.min(cap, t.targetProb / t.behaviorProb)\n weights.push(w)\n rewards.push(clamp(t.reward, clip.low, clip.high))\n if (w > maxW) maxW = w\n }\n const sumW = weights.reduce((s, w) => s + w, 0)\n const sumWR = weights.reduce((s, w, i) => s + w * rewards[i]!, 0)\n const value = sumW === 0 ? 0 : sumWR / sumW\n const sumW2 = weights.reduce((s, w) => s + w * w, 0)\n const effN = sumW === 0 ? 0 : (sumW * sumW) / sumW2\n // Influence-function-based SE for SNIPS (Owen 2013, Ch. 9).\n const phi = weights.map((w, i) => w * (rewards[i]! - value))\n const variance = phi.reduce((s, x) => s + x * x, 0) / Math.max(1, sumW * sumW)\n return {\n value,\n standardError: Math.sqrt(variance),\n effectiveSampleSize: effN,\n n: trajectories.length,\n maxImportanceWeight: maxW,\n }\n}\n\n/**\n * Doubly-robust off-policy estimator (Dudík, Langford, Li 2011).\n *\n * V_DR = (1/N) * sum_i [ q_hat_i + (target_prob_i / behavior_prob_i) * (r_i - q_hat_i) ]\n *\n * Unbiased if EITHER:\n * - the importance ratios are correct (IPS-style validity), OR\n * - the Q-hat function is correct (model-based validity).\n *\n * In practice both are imperfect, but the residual bias is the *product*\n * of both errors — much smaller than either alone. This is why DR is the\n * default in production OPE pipelines.\n *\n * Requires `qHat` on every trajectory. If any are `null`, the estimator\n * falls back to SNIPS for those entries (loud-fallback behavior; the\n * report's `n` reflects the full set but `effectiveSampleSize` accounts\n * for the lost variance reduction).\n */\nexport function doublyRobust(\n trajectories: OffPolicyTrajectory[],\n opts: OffPolicyOptions = {},\n): OffPolicyEstimate {\n const cap = opts.weightCap ?? Infinity\n const clip = opts.rewardClip ?? { low: 0, high: 1 }\n if (trajectories.length === 0) return zeroEstimate()\n\n const contributions: number[] = []\n let maxW = 0\n let sumW = 0\n let sumW2 = 0\n for (const t of trajectories) {\n if (t.behaviorProb <= 0) {\n throw new ValidationError(`doublyRobust: behaviorProb must be > 0 (runId=${t.runId})`)\n }\n const w = Math.min(cap, t.targetProb / t.behaviorProb)\n const r = clamp(t.reward, clip.low, clip.high)\n const q =\n typeof t.qHat === 'number' && Number.isFinite(t.qHat)\n ? clamp(t.qHat, clip.low, clip.high)\n : null\n if (q === null) {\n contributions.push(w * r) // fallback: IPS for this entry\n } else {\n contributions.push(q + w * (r - q))\n }\n if (w > maxW) maxW = w\n sumW += w\n sumW2 += w * w\n }\n const n = contributions.length\n const value = contributions.reduce((s, x) => s + x, 0) / n\n const variance = contributions.reduce((s, x) => s + (x - value) ** 2, 0) / Math.max(1, n - 1)\n const effN = sumW === 0 ? 0 : (sumW * sumW) / sumW2\n return {\n value,\n standardError: Math.sqrt(variance / n),\n effectiveSampleSize: effN,\n n,\n maxImportanceWeight: maxW,\n }\n}\n\n/**\n * Convenience: run all three estimators and return them side-by-side.\n * The recommended diagnostic — agreement across estimators is a much\n * stronger signal than any single one.\n */\nexport function offPolicyEstimateAll(\n trajectories: OffPolicyTrajectory[],\n opts: OffPolicyOptions = {},\n): { ips: OffPolicyEstimate; snips: OffPolicyEstimate; dr: OffPolicyEstimate } {\n return {\n ips: inverseProbabilityWeighting(trajectories, opts),\n snips: selfNormalizedImportanceWeighting(trajectories, opts),\n dr: doublyRobust(trajectories, opts),\n }\n}\n\n// ── Helpers ──────────────────────────────────────────────────────────────\n\nfunction zeroEstimate(): OffPolicyEstimate {\n return { value: 0, standardError: 0, effectiveSampleSize: 0, n: 0, maxImportanceWeight: 0 }\n}\n\nfunction clamp(x: number, lo: number, hi: number): number {\n if (!Number.isFinite(x)) return lo\n return Math.max(lo, Math.min(hi, x))\n}\n"],"mappings":"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","names":[]}
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  runCampaign,
3
3
  summarizeBackendIntegrity
4
- } from "./chunk-ZPSKPT3V.js";
4
+ } from "./chunk-ZZ2HOPME.js";
5
5
  import {
6
6
  callLlm
7
- } from "./chunk-IHDHUN2X.js";
7
+ } from "./chunk-CVVHBFGN.js";
8
8
  import {
9
9
  DEFAULT_REDACTION_RULES
10
10
  } from "./chunk-GGE4NNQT.js";
@@ -1252,6 +1252,9 @@ function labelTrustRank(trust) {
1252
1252
  import { createHash } from "crypto";
1253
1253
  async function runOptimization(opts) {
1254
1254
  const promoteTopK = opts.promoteTopK ?? 2;
1255
+ if (typeof opts.runDir !== "string" || opts.runDir.trim().length === 0) {
1256
+ throw new Error("runOptimization: runDir is required and must be a non-empty string");
1257
+ }
1255
1258
  const baselineCampaign = await runCampaign({
1256
1259
  ...opts,
1257
1260
  dispatch: (scenario, ctx) => opts.dispatchWithSurface(opts.baselineSurface, scenario, ctx),
@@ -1440,7 +1443,7 @@ async function runImprovementLoop(opts) {
1440
1443
  const dispatchTimeoutMs = opts.dispatchTimeoutMs ?? DEFAULT_DISPATCH_TIMEOUT_MS;
1441
1444
  const optimization = await runOptimization({ ...opts, dispatchTimeoutMs });
1442
1445
  const winnerIsBaseline = optimization.winnerSurfaceHash === surfaceHash(opts.baselineSurface);
1443
- const { runCampaign: runCampaign2 } = await import("./run-campaign-OVEZF24D.js");
1446
+ const { runCampaign: runCampaign2 } = await import("./run-campaign-4Y5V5CN3.js");
1444
1447
  const baselineOnHoldout = await runCampaign2({
1445
1448
  ...opts,
1446
1449
  dispatchTimeoutMs,
@@ -1841,4 +1844,4 @@ export {
1841
1844
  provenanceSpansPath,
1842
1845
  emitLoopProvenance
1843
1846
  };
1844
- //# sourceMappingURL=chunk-RPLZ4OIB.js.map
1847
+ //# sourceMappingURL=chunk-BABOZOSN.js.map