@tangle-network/agent-eval 0.120.4 → 0.122.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 (51) hide show
  1. package/CHANGELOG.md +4 -16
  2. package/dist/analyst/index.d.ts +1 -0
  3. package/dist/analyst/index.js +4 -4
  4. package/dist/belief-state/index.d.ts +43 -0
  5. package/dist/belief-state/index.js +48 -326
  6. package/dist/belief-state/index.js.map +1 -1
  7. package/dist/benchmarks/index.d.ts +5 -1
  8. package/dist/benchmarks/index.js +6 -6
  9. package/dist/campaign/index.d.ts +16 -18
  10. package/dist/campaign/index.js +7 -5
  11. package/dist/{chunk-SQQED7ZH.js → chunk-3A246TSA.js} +2 -2
  12. package/dist/{chunk-NMN4WGSJ.js → chunk-4I2E3LLO.js} +2 -2
  13. package/dist/chunk-7VYEGHWF.js +1425 -0
  14. package/dist/chunk-7VYEGHWF.js.map +1 -0
  15. package/dist/{chunk-ZMXDQ4K7.js → chunk-JHOJHHU7.js} +5 -8
  16. package/dist/{chunk-ZMXDQ4K7.js.map → chunk-JHOJHHU7.js.map} +1 -1
  17. package/dist/{chunk-3XH4Y2SS.js → chunk-P62I523A.js} +5 -3
  18. package/dist/{chunk-3XH4Y2SS.js.map → chunk-P62I523A.js.map} +1 -1
  19. package/dist/{chunk-CVJP5TMD.js → chunk-PICTDURQ.js} +2 -2
  20. package/dist/{chunk-5BYTIDZ7.js → chunk-QWMPPZ3X.js} +2 -2
  21. package/dist/{chunk-5CVUPHJ4.js → chunk-S5TT5R3L.js} +2 -2
  22. package/dist/{chunk-ZTJPIIVI.js → chunk-TDHX3BVA.js} +160 -7
  23. package/dist/chunk-TDHX3BVA.js.map +1 -0
  24. package/dist/{chunk-7QBFOJ3E.js → chunk-VZ6VKOJT.js} +32 -211
  25. package/dist/chunk-VZ6VKOJT.js.map +1 -0
  26. package/dist/{chunk-SYV364BL.js → chunk-XDIRG3TO.js} +2 -2
  27. package/dist/cli.js +2 -2
  28. package/dist/contract/index.d.ts +118 -29
  29. package/dist/contract/index.js +552 -502
  30. package/dist/contract/index.js.map +1 -1
  31. package/dist/fuzz.js +1 -1
  32. package/dist/index.d.ts +7 -19
  33. package/dist/index.js +13 -11
  34. package/dist/index.js.map +1 -1
  35. package/dist/openapi.json +1 -1
  36. package/dist/rl.d.ts +5 -1
  37. package/dist/{run-campaign-75RTPVV5.js → run-campaign-HNFPJET4.js} +3 -3
  38. package/dist/wire/index.js +2 -2
  39. package/docs/eval-surface-map.md +1 -1
  40. package/package.json +2 -2
  41. package/dist/chunk-7QBFOJ3E.js.map +0 -1
  42. package/dist/chunk-HKUCJ437.js +0 -787
  43. package/dist/chunk-HKUCJ437.js.map +0 -1
  44. package/dist/chunk-ZTJPIIVI.js.map +0 -1
  45. /package/dist/{chunk-SQQED7ZH.js.map → chunk-3A246TSA.js.map} +0 -0
  46. /package/dist/{chunk-NMN4WGSJ.js.map → chunk-4I2E3LLO.js.map} +0 -0
  47. /package/dist/{chunk-CVJP5TMD.js.map → chunk-PICTDURQ.js.map} +0 -0
  48. /package/dist/{chunk-5BYTIDZ7.js.map → chunk-QWMPPZ3X.js.map} +0 -0
  49. /package/dist/{chunk-5CVUPHJ4.js.map → chunk-S5TT5R3L.js.map} +0 -0
  50. /package/dist/{chunk-SYV364BL.js.map → chunk-XDIRG3TO.js.map} +0 -0
  51. /package/dist/{run-campaign-75RTPVV5.js.map → run-campaign-HNFPJET4.js.map} +0 -0
@@ -1,7 +1,6 @@
1
1
  import {
2
2
  assertCampaignSplitIdentity,
3
3
  campaignCoverage,
4
- campaignSplitDigest,
5
4
  canonicalJson,
6
5
  contentHash,
7
6
  createRunCostLedger,
@@ -10,11 +9,11 @@ import {
10
9
  resolveRunDir,
11
10
  runCampaign,
12
11
  summarizeAgentReceiptIntegrity
13
- } from "./chunk-SYV364BL.js";
12
+ } from "./chunk-XDIRG3TO.js";
14
13
  import {
15
14
  clamp01,
16
15
  validatePolicyEditCandidateRecord
17
- } from "./chunk-5CVUPHJ4.js";
16
+ } from "./chunk-S5TT5R3L.js";
18
17
  import {
19
18
  detectRewardHacking
20
19
  } from "./chunk-ARU2PZFM.js";
@@ -26,15 +25,12 @@ import {
26
25
  stripFencedJson
27
26
  } from "./chunk-NJC7U437.js";
28
27
  import {
29
- mcnemar,
30
28
  pairedBootstrap,
31
- pairedRiskDifference,
32
- weightedComposite,
33
- wilcoxonSignedRank
29
+ weightedComposite
34
30
  } from "./chunk-PJQFMIOX.js";
35
31
  import {
36
32
  CostLedger
37
- } from "./chunk-ZMXDQ4K7.js";
33
+ } from "./chunk-JHOJHHU7.js";
38
34
  import {
39
35
  DEFAULT_REDACTION_RULES
40
36
  } from "./chunk-GGE4NNQT.js";
@@ -300,155 +296,6 @@ async function runJudgeChat(tc, input, judgeName, request) {
300
296
  return paid.value;
301
297
  }
302
298
 
303
- // src/paired-arms.ts
304
- function pairArms(rows, opts) {
305
- const { baselineArm, treatmentArm } = opts;
306
- if (baselineArm === treatmentArm) {
307
- throw new ValidationError(
308
- `pairArms: baselineArm and treatmentArm are both '${baselineArm}' \u2014 an arm cannot be compared to itself`
309
- );
310
- }
311
- const byArm = /* @__PURE__ */ new Map();
312
- const armsSeen = /* @__PURE__ */ new Set();
313
- for (const row of rows) {
314
- armsSeen.add(row.arm);
315
- if (row.arm !== baselineArm && row.arm !== treatmentArm) continue;
316
- const byKey = byArm.get(row.arm) ?? /* @__PURE__ */ new Map();
317
- const group = byKey.get(row.pairKey) ?? [];
318
- group.push(row);
319
- byKey.set(row.pairKey, group);
320
- byArm.set(row.arm, byKey);
321
- }
322
- for (const arm of [baselineArm, treatmentArm]) {
323
- if (!byArm.has(arm)) {
324
- const seen = [...armsSeen].sort().join(", ") || "<none>";
325
- throw new ValidationError(`pairArms: no rows for arm '${arm}' (arms present: ${seen})`);
326
- }
327
- }
328
- const baselineByKey = byArm.get(baselineArm);
329
- const treatmentByKey = byArm.get(treatmentArm);
330
- const allKeys = [.../* @__PURE__ */ new Set([...baselineByKey.keys(), ...treatmentByKey.keys()])].sort();
331
- const pairs = [];
332
- const unpairedBaseline = [];
333
- const unpairedTreatment = [];
334
- for (const pairKey of allKeys) {
335
- const b = baselineByKey.get(pairKey) ?? [];
336
- const t = treatmentByKey.get(pairKey) ?? [];
337
- if (b.length <= 1 && t.length <= 1) {
338
- if (b.length === 1 && t.length === 1) {
339
- pairs.push({ pairKey, repIndex: 0, baseline: b[0], treatment: t[0] });
340
- } else {
341
- unpairedBaseline.push(...b);
342
- unpairedTreatment.push(...t);
343
- }
344
- continue;
345
- }
346
- const bByRep = indexByRepKey(b, pairKey, baselineArm);
347
- const tByRep = indexByRepKey(t, pairKey, treatmentArm);
348
- const repKeys = [.../* @__PURE__ */ new Set([...bByRep.keys(), ...tByRep.keys()])].sort();
349
- let repIndex = 0;
350
- for (const repKey of repKeys) {
351
- const baseline = bByRep.get(repKey);
352
- const treatment = tByRep.get(repKey);
353
- if (baseline !== void 0 && treatment !== void 0) {
354
- pairs.push({ pairKey, repIndex: repIndex++, baseline, treatment });
355
- } else if (baseline !== void 0) {
356
- unpairedBaseline.push(baseline);
357
- } else if (treatment !== void 0) {
358
- unpairedTreatment.push(treatment);
359
- }
360
- }
361
- }
362
- return { pairs, unpairedBaseline, unpairedTreatment };
363
- }
364
- function indexByRepKey(group, pairKey, arm) {
365
- const byRep = /* @__PURE__ */ new Map();
366
- for (const row of group) {
367
- if (row.repKey === void 0) {
368
- throw new ValidationError(
369
- `pairArms: pairKey '${pairKey}' has multiple reps in an arm, but a row in arm '${arm}' is missing repKey \u2014 multi-rep items require an explicit repKey on every row so reps pair by identity (pairing reps by outcome or by index would bias the paired statistics)`
370
- );
371
- }
372
- if (byRep.has(row.repKey)) {
373
- throw new ValidationError(
374
- `pairArms: duplicate repKey '${row.repKey}' for pairKey '${pairKey}' in arm '${arm}' \u2014 (pairKey, repKey) must uniquely identify a rep within an arm`
375
- );
376
- }
377
- byRep.set(row.repKey, row);
378
- }
379
- return byRep;
380
- }
381
- function comparePairedArms(rows, opts) {
382
- const { pairs, unpairedBaseline, unpairedTreatment } = pairArms(rows, opts);
383
- let correctness = null;
384
- const baselinePass = [];
385
- const treatmentPass = [];
386
- for (const pair of pairs) {
387
- if (pair.baseline.pass === void 0 || pair.treatment.pass === void 0) continue;
388
- baselinePass.push(pair.baseline.pass ? 1 : 0);
389
- treatmentPass.push(pair.treatment.pass ? 1 : 0);
390
- }
391
- if (baselinePass.length > 0) {
392
- const mc = mcnemar(baselinePass, treatmentPass);
393
- correctness = {
394
- b10: mc.b,
395
- b01: mc.c,
396
- mcnemar: mc,
397
- riskDifference: pairedRiskDifference(baselinePass, treatmentPass)
398
- };
399
- }
400
- const metricNames = opts.metricNames ?? [
401
- ...new Set(
402
- pairs.flatMap((p) => [
403
- ...Object.keys(p.baseline.metrics ?? {}),
404
- ...Object.keys(p.treatment.metrics ?? {})
405
- ])
406
- )
407
- ].sort();
408
- const metricDeltas = metricNames.map((name) => {
409
- const before = [];
410
- const after = [];
411
- let nMissing = 0;
412
- for (const pair of pairs) {
413
- const b = metricValue(pair.baseline, name);
414
- const t = metricValue(pair.treatment, name);
415
- if (b === void 0 || t === void 0) {
416
- nMissing++;
417
- continue;
418
- }
419
- before.push(b);
420
- after.push(t);
421
- }
422
- const bootstrapCi = before.length === 0 ? null : pairedBootstrap(before, after, opts.bootstrap);
423
- return {
424
- name,
425
- n: before.length,
426
- nMissing,
427
- medianDelta: bootstrapCi === null ? Number.NaN : bootstrapCi.median,
428
- meanDelta: bootstrapCi === null ? Number.NaN : bootstrapCi.mean,
429
- bootstrapCi,
430
- wilcoxon: before.length === 0 ? null : wilcoxonSignedRank(before, after)
431
- };
432
- });
433
- return {
434
- nPairs: pairs.length,
435
- nUnpairedBaseline: unpairedBaseline.length,
436
- nUnpairedTreatment: unpairedTreatment.length,
437
- correctness,
438
- metricDeltas
439
- };
440
- }
441
- function metricValue(row, name) {
442
- const v = row.metrics?.[name];
443
- if (v === void 0) return void 0;
444
- if (!Number.isFinite(v)) {
445
- throw new ValidationError(
446
- `comparePairedArms: non-finite value for metric '${name}' on pairKey '${row.pairKey}' (arm '${row.arm}'): ${v}`
447
- );
448
- }
449
- return v;
450
- }
451
-
452
299
  // src/pareto.ts
453
300
  function dominates(a, b, objectives) {
454
301
  let strictlyBetter = false;
@@ -2257,6 +2104,7 @@ function recoverFrom(slice) {
2257
2104
  }
2258
2105
 
2259
2106
  // src/reflective-mutation.ts
2107
+ var EMITTED_EVIDENCE_MAX_CHARS = 2e3;
2260
2108
  var DEFAULT_MUTATION_PRIMITIVES = [
2261
2109
  'Strengthen an imperative ("should" \u2192 "must")',
2262
2110
  "Add a concrete example pulled from a missed-golden phrase",
@@ -2288,7 +2136,7 @@ function buildReflectionPrompt(ctx) {
2288
2136
  );
2289
2137
  if (trial.failureNote) {
2290
2138
  sections.push("");
2291
- sections.push(`**Why it scored low:** ${truncate(trial.failureNote, 600)}`);
2139
+ sections.push(`**Why it scored low:** ${truncate(trial.failureNote, 1500)}`);
2292
2140
  }
2293
2141
  const missed = (trial.expectations ?? []).filter((e) => !e.matched);
2294
2142
  if (missed.length > 0) {
@@ -2302,7 +2150,7 @@ function buildReflectionPrompt(ctx) {
2302
2150
  sections.push("");
2303
2151
  sections.push("**What the agent emitted:**");
2304
2152
  sections.push("```");
2305
- sections.push(truncate(trial.emitted, 600));
2153
+ sections.push(truncate(trial.emitted, EMITTED_EVIDENCE_MAX_CHARS));
2306
2154
  sections.push("```");
2307
2155
  }
2308
2156
  sections.push("");
@@ -2713,7 +2561,11 @@ function buildEvidence(ctx, evidenceK, baseTarget) {
2713
2561
  score: s.composite,
2714
2562
  // The judge's "why it scored low" — grounds the reflection on real failure
2715
2563
  // patterns instead of blind rephrasing. Generalizable by the judge contract.
2716
- ...s.notes ? { failureNote: s.notes } : {}
2564
+ ...s.notes ? { failureNote: s.notes } : {},
2565
+ // The candidate's raw output for the scenario — buildReflectionPrompt
2566
+ // renders it as the "what the agent emitted" block, so the reflection sees
2567
+ // the actual wrong output, not just the score.
2568
+ ...s.emitted ? { emitted: s.emitted } : {}
2717
2569
  });
2718
2570
  const top = byScore.slice(0, evidenceK).map(toTrace);
2719
2571
  const bottom = byScore.slice(-evidenceK).reverse().map(toTrace);
@@ -2738,6 +2590,7 @@ function campaignBreakdown(campaign) {
2738
2590
  const dimCounts = {};
2739
2591
  const byScenario = /* @__PURE__ */ new Map();
2740
2592
  const notesByScenario = /* @__PURE__ */ new Map();
2593
+ const emittedByScenario = /* @__PURE__ */ new Map();
2741
2594
  for (const cell of campaign.cells) {
2742
2595
  const judgeScores = Object.values(cell.judgeScores).filter(
2743
2596
  (score) => score.failed !== true && Number.isFinite(score.composite)
@@ -2747,6 +2600,15 @@ function campaignBreakdown(campaign) {
2747
2600
  const arr = byScenario.get(cell.scenarioId) ?? [];
2748
2601
  arr.push(cellComposite);
2749
2602
  byScenario.set(cell.scenarioId, arr);
2603
+ if (typeof cell.artifact === "string" && cell.artifact.trim().length > 0) {
2604
+ const prev = emittedByScenario.get(cell.scenarioId);
2605
+ if (!prev || cellComposite < prev.composite) {
2606
+ emittedByScenario.set(cell.scenarioId, {
2607
+ composite: cellComposite,
2608
+ text: cell.artifact.slice(0, EMITTED_EVIDENCE_MAX_CHARS)
2609
+ });
2610
+ }
2611
+ }
2750
2612
  for (const s of judgeScores) {
2751
2613
  if (s.notes?.trim()) {
2752
2614
  const set = notesByScenario.get(cell.scenarioId) ?? /* @__PURE__ */ new Set();
@@ -2770,10 +2632,12 @@ function campaignBreakdown(campaign) {
2770
2632
  const scenarios = [...byScenario.entries()].map(([scenarioId, comps]) => {
2771
2633
  const notesSet = notesByScenario.get(scenarioId);
2772
2634
  const notes = notesSet && notesSet.size > 0 ? [...notesSet].join(" | ") : void 0;
2635
+ const emitted = emittedByScenario.get(scenarioId)?.text;
2773
2636
  return {
2774
2637
  scenarioId,
2775
2638
  composite: comps.reduce((a, b) => a + b, 0) / comps.length,
2776
- ...notes ? { notes } : {}
2639
+ ...notes ? { notes } : {},
2640
+ ...emitted ? { emitted } : {}
2777
2641
  };
2778
2642
  });
2779
2643
  return { dimensions, scenarios };
@@ -2797,32 +2661,23 @@ async function runOptimization(opts) {
2797
2661
  "runOptimization: promoteTopK must be 1 because the loop has one global incumbent"
2798
2662
  );
2799
2663
  }
2800
- const requireJudgeScore = (opts.judges?.length ?? 0) > 0;
2801
- const reps = opts.reps ?? 1;
2802
- const premeasuredBaseline = opts.premeasuredBaseline;
2803
- const baselineCampaign = premeasuredBaseline ? validatedPremeasuredBaseline({
2804
- input: premeasuredBaseline,
2805
- baselineSurface: opts.baselineSurface,
2806
- scenarios: opts.scenarios,
2807
- reps,
2808
- seed: opts.seed ?? 42
2809
- }) : await runCampaign({
2664
+ const baselineCampaign = await runCampaign({
2810
2665
  ...opts,
2811
2666
  costLedger,
2812
2667
  costPhase: "search.baseline",
2813
2668
  dispatch: (scenario, ctx) => opts.dispatchWithSurface(opts.baselineSurface, scenario, ctx),
2814
2669
  runDir: `${opts.runDir}/baseline`
2815
2670
  });
2671
+ const requireJudgeScore = (opts.judges?.length ?? 0) > 0;
2816
2672
  const baselineCoverage = campaignCoverage(
2817
2673
  baselineCampaign.cells,
2818
2674
  opts.scenarios,
2819
- reps,
2675
+ opts.reps ?? 1,
2820
2676
  requireJudgeScore
2821
2677
  );
2822
2678
  if (!baselineCoverage.complete) {
2823
- const label = opts.premeasuredBaseline ? "premeasured baseline" : "baseline";
2824
2679
  throw new Error(
2825
- `runOptimization: ${label} is incomplete (${baselineCoverage.scorableCellIds.length}/${baselineCoverage.expectedCellIds.length} designed cells scorable) \u2014 ${formatCoverageFailures(baselineCoverage)}. Refusing to optimize against an incomplete incumbent.`
2680
+ `runOptimization: baseline is incomplete (${baselineCoverage.scorableCellIds.length}/${baselineCoverage.expectedCellIds.length} designed cells scorable) \u2014 ${formatCoverageFailures(baselineCoverage)}. Refusing to optimize against an incomplete incumbent.`
2826
2681
  );
2827
2682
  }
2828
2683
  const generations = [];
@@ -2846,7 +2701,7 @@ async function runOptimization(opts) {
2846
2701
  if (opts.analyzeGeneration && opts.maxGenerations > 0 && baselineCampaign.cells.length > 0) {
2847
2702
  const fresh = await opts.analyzeGeneration({
2848
2703
  generation: -1,
2849
- runDir: baselineCampaign.runDir,
2704
+ runDir: `${opts.runDir}/baseline`,
2850
2705
  candidates: [
2851
2706
  { surfaceHash: winnerSurfaceHash, campaign: baselineCampaign, composite: winnerComposite }
2852
2707
  ],
@@ -2997,38 +2852,6 @@ async function runOptimization(opts) {
2997
2852
  cost: costLedger.summary()
2998
2853
  };
2999
2854
  }
3000
- function validatedPremeasuredBaseline(args) {
3001
- const { input } = args;
3002
- if (input.surfaceHash !== surfaceHash(args.baselineSurface)) {
3003
- throw new Error(
3004
- "runOptimization: premeasured baseline surface hash does not match baselineSurface"
3005
- );
3006
- }
3007
- const campaign = input.campaign;
3008
- if (campaign.reps !== args.reps) {
3009
- throw new Error(
3010
- `runOptimization: premeasured baseline reps ${campaign.reps} do not match requested reps ${args.reps}`
3011
- );
3012
- }
3013
- if (campaign.seed !== args.seed) {
3014
- throw new Error(
3015
- `runOptimization: premeasured baseline seed ${campaign.seed} does not match requested seed ${args.seed}`
3016
- );
3017
- }
3018
- try {
3019
- assertCampaignSplitIdentity(campaign.scenarios, campaign.reps, campaign.splitDigest);
3020
- } catch (error) {
3021
- throw new Error(
3022
- `runOptimization: premeasured baseline has an invalid retained split identity \u2014 ${error instanceof Error ? error.message : String(error)}`
3023
- );
3024
- }
3025
- if (campaign.splitDigest !== campaignSplitDigest(args.scenarios, args.reps)) {
3026
- throw new Error(
3027
- "runOptimization: premeasured baseline split does not match the requested scenarios"
3028
- );
3029
- }
3030
- return campaign;
3031
- }
3032
2855
  function toParetoParent(surface, hash, campaign, generation, label, rationale) {
3033
2856
  const objectives = {};
3034
2857
  for (const { scenarioId, composite } of campaignBreakdown(campaign).scenarios) {
@@ -3123,7 +2946,7 @@ async function runImprovementLoop(opts) {
3123
2946
  const dispatchTimeoutMs = opts.dispatchTimeoutMs ?? DEFAULT_DISPATCH_TIMEOUT_MS;
3124
2947
  const optimization = await runOptimization({ ...opts, dispatchTimeoutMs, costLedger });
3125
2948
  const winnerIsBaseline = optimization.winnerSurfaceHash === surfaceHash(opts.baselineSurface);
3126
- const { runCampaign: runCampaign2 } = await import("./run-campaign-75RTPVV5.js");
2949
+ const { runCampaign: runCampaign2 } = await import("./run-campaign-HNFPJET4.js");
3127
2950
  const baselineOnHoldout = await runCampaign2({
3128
2951
  ...opts,
3129
2952
  costLedger,
@@ -3853,8 +3676,6 @@ export {
3853
3676
  adversarialJudge,
3854
3677
  createCustomJudge,
3855
3678
  defaultJudges,
3856
- pairArms,
3857
- comparePairedArms,
3858
3679
  recoverTruncatedJson,
3859
3680
  dominates,
3860
3681
  paretoFrontier,
@@ -3917,4 +3738,4 @@ export {
3917
3738
  provenanceSpansPath,
3918
3739
  emitLoopProvenance
3919
3740
  };
3920
- //# sourceMappingURL=chunk-7QBFOJ3E.js.map
3741
+ //# sourceMappingURL=chunk-VZ6VKOJT.js.map