@tangle-network/agent-eval 0.145.18 → 0.145.20

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.
package/dist/cli.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { o as runRolloutReleaseCli } from "./hf-dataset-XggBupCr.js";
3
- import { n as runAnalystBenchmarkCommand } from "./benchmark-command-CyqmP3uA.js";
3
+ import { n as runAnalystBenchmarkCommand } from "./benchmark-command-CkgLXHoN.js";
4
4
  import { a as runRpcBatch, o as runRpcOnce, p as handleVersion, r as startServerAsync, s as buildOpenApi } from "./server-ulsOdrTI.js";
5
5
  import { writeFileSync } from "node:fs";
6
6
  //#region src/cli-config.ts
@@ -0,0 +1,198 @@
1
+ import { t as DefaultVerdict } from "./verdict-E4eRNf7-.js";
2
+ import { p as CostProvenance } from "./cost-ledger-DbQdN3nO.js";
3
+ //#region src/matrix/cell-spend.d.ts
4
+ /**
5
+ * Spend carrier for a cell that fails after it has already spent money.
6
+ *
7
+ * `runCell` reports what a cell cost by returning a `CellResult`. A throw
8
+ * carries no result, so the runner cannot know what the cell spent before it
9
+ * failed: the cumulative sum the cost ceiling reads, and `totalCostUsd`, both
10
+ * miss that money. A throw that carries a `CellSpend` closes the gap — the
11
+ * runner bills the failed cell for the spend the carrier declares, and records
12
+ * a cell that declared nothing as `uncaptured` instead of a zero that reads
13
+ * like "this cell spent nothing".
14
+ *
15
+ * The carrier is read structurally, never by `instanceof`, so a throw that
16
+ * crosses a package or realm boundary still bills.
17
+ */
18
+ /** Money and wall time a cell consumed before it threw. */
19
+ interface CellSpend {
20
+ /** KNOWN subtotal in USD. When `kind` is `uncaptured` the cell spent this
21
+ * much AND an unknown amount more, so the value must not be read as the
22
+ * cell's total. */
23
+ costUsd: number;
24
+ /** Wall time the cell consumed before the throw, in milliseconds. */
25
+ durationMs: number;
26
+ /** `observed` = provider-reported amounts, `estimated` = computed from token
27
+ * prices, `uncaptured` = `costUsd` is a subtotal and part of the spend
28
+ * could not be measured. */
29
+ kind: 'observed' | 'estimated' | 'uncaptured';
30
+ }
31
+ /**
32
+ * Return `error` carrying `spend`, for a throw site inside `runCell`:
33
+ * `throw withCellSpend(err, { costUsd, durationMs, kind })`.
34
+ *
35
+ * A value that cannot hold the carrier — a thrown string or number, or a
36
+ * frozen, sealed, or otherwise non-extensible object — is wrapped in an
37
+ * `Error` that keeps the original as `cause`, so the spend is never dropped.
38
+ * A later call overwrites an earlier carrier — the outer frame knows more
39
+ * than the inner one.
40
+ *
41
+ * Throws `TypeError` on a non-finite or negative amount. A poisoned amount
42
+ * would reach `cumulativeCost` and disable the cost ceiling for the whole run,
43
+ * because `NaN >= ceiling` is false.
44
+ */
45
+ declare function withCellSpend(error: unknown, spend: CellSpend): unknown;
46
+ /** Read the spend a thrown value carries. `undefined` when the value carries
47
+ * none, or carries one that does not satisfy `CellSpend` — the runner records
48
+ * both as `uncaptured`. */
49
+ declare function readCellSpend(error: unknown): CellSpend | undefined;
50
+ //#endregion
51
+ //#region src/matrix/types.d.ts
52
+ /** One axis = one dimension to iterate. `V` is the value type — pass any
53
+ * substrate type (AgentProfile, Driver, Validator, rubric record). */
54
+ interface MatrixAxis<V> {
55
+ /** Axis name. Becomes the key in `MatrixResult.byAxis`. */
56
+ name: string;
57
+ /** Stable id per value. Used as the bucket key in aggregation. */
58
+ values: Array<{
59
+ id: string;
60
+ value: V;
61
+ }>;
62
+ /** Optional bucket label override. Receives the same `(value, id)` the
63
+ * runner stored on the cell; default label is `id`. */
64
+ label?: (value: V, id: string) => string;
65
+ }
66
+ /** A cell carries one picked value from each axis, keyed by axis name. */
67
+ interface MatrixCell {
68
+ axes: Record<string, {
69
+ id: string;
70
+ value: unknown;
71
+ }>;
72
+ /** 0-based replicate index within the same axis combination. */
73
+ rep: number;
74
+ /** Stable sort key — preserves cartesian order across concurrent execution. */
75
+ ordinal: number;
76
+ }
77
+ interface CellResult<Output> {
78
+ output: Output;
79
+ verdict: DefaultVerdict;
80
+ /** Known subtotal in USD. When `costProvenance.kind` is `uncaptured` the
81
+ * cell spent this much AND an unknown amount more, so the value must not be
82
+ * read as the cell's total. Counts toward `costCeiling` either way. */
83
+ costUsd: number;
84
+ durationMs: number;
85
+ runId?: string;
86
+ /** Origin of `costUsd`. Absent on a result `runCell` returned — that
87
+ * `costUsd` is measured by contract. The runner always sets it on a cell
88
+ * that threw, where a bare number cannot say whether `0` means "spent
89
+ * nothing" or "spend unknown".
90
+ *
91
+ * Converting to `RunRecord` needs one translation: a `RunRecord` rejects a
92
+ * numeric `costUsd` beside `uncaptured` provenance, so an uncaptured cell
93
+ * becomes `costUsd: null` there. A cell keeps the subtotal because a cost
94
+ * ceiling must charge the part it can see; a record drops it because a
95
+ * record must never read as a total. */
96
+ costProvenance?: CostProvenance;
97
+ /** Populated when `runCell` threw, or when it returned a cost the runner
98
+ * cannot bill. The cell contributes 0 to passRate AND meanScore regardless
99
+ * of `verdict`. */
100
+ error?: {
101
+ message: string;
102
+ kind: string;
103
+ };
104
+ }
105
+ interface AxisSummary {
106
+ axisName: string;
107
+ axisValue: string;
108
+ cells: number;
109
+ passRate: number;
110
+ meanScore: number;
111
+ p50Score: number;
112
+ p90Score: number;
113
+ /** Sum of the known cost subtotals in this bucket. Under-counts real spend
114
+ * by an unknown amount when `costUncapturedCells` is above 0. */
115
+ totalCostUsd: number;
116
+ /** Cells in this bucket whose cost is a subtotal, not a total. */
117
+ costUncapturedCells: number;
118
+ meanDurationMs: number;
119
+ }
120
+ interface MatrixResult<Output> {
121
+ cells: Array<{
122
+ cell: MatrixCell;
123
+ runs: CellResult<Output>[];
124
+ }>;
125
+ /** `byAxis[axisName][axisValueId] = summary`. Populated only for axes
126
+ * named in `aggregateBy` (default = every axis in `axes`). */
127
+ byAxis: Record<string, Record<string, AxisSummary>>;
128
+ summary: {
129
+ totalCells: number;
130
+ runsExecuted: number;
131
+ /** Cells removed by `filter` plus cells unscheduled after the cost
132
+ * ceiling or abort signal tripped. */
133
+ cellsSkipped: number;
134
+ overallPassRate: number;
135
+ overallMeanScore: number;
136
+ /** Sum of every cell's known cost subtotal. Read it together with
137
+ * `costUncapturedCells`: above 0, this number is a floor on real spend,
138
+ * and the cost ceiling stopped the run later than true spend deserved. */
139
+ totalCostUsd: number;
140
+ /** Cells whose cost is a subtotal rather than a total — a failure that
141
+ * reported no spend, a failure that reported a partial amount, or a
142
+ * result the runner could not bill. */
143
+ costUncapturedCells: number;
144
+ /** What the cost ceiling actually read. Equals `totalCostUsd` unless
145
+ * `maxCellCostUsd` was set and a cell's cost was a subtotal, in which case
146
+ * the ceiling charged the bound and this figure is higher. */
147
+ ceilingChargedUsd: number;
148
+ durationMs: number;
149
+ };
150
+ /** Stable id-like string generated at the end of the run. */
151
+ matrixId: string;
152
+ }
153
+ interface RunAgentMatrixOptions<Output> {
154
+ axes: MatrixAxis<unknown>[];
155
+ /** User-supplied cell executor. May throw; the matrix captures throws as
156
+ * `CellResult.error` and continues. A cell that spends money before it
157
+ * throws must declare that spend — `throw withCellSpend(err, spend)` — or
158
+ * the money is missing from `totalCostUsd` and from the sum `costCeiling`
159
+ * reads. */
160
+ runCell: (cell: MatrixCell) => Promise<CellResult<Output>>;
161
+ /** Replicates per cell. Default 1. */
162
+ reps?: number;
163
+ /** Prune cells from the cartesian BEFORE rep expansion. */
164
+ filter?: (cell: Omit<MatrixCell, 'rep' | 'ordinal'>) => boolean;
165
+ /** Axes to aggregate into `byAxis`. Default: every axis in `axes`. */
166
+ aggregateBy?: string[];
167
+ /** Max concurrent in-flight `runCell` invocations. Default 4. */
168
+ maxConcurrency?: number;
169
+ /** Cumulative-cost abort threshold (USD). When the running sum of
170
+ * `result.costUsd` crosses this value, no new cells are scheduled.
171
+ * In-flight cells finish. Failed cells count for the spend they declare.
172
+ * Default `Infinity`. */
173
+ costCeiling?: number;
174
+ /** Upper bound on what ONE cell can spend (USD). A cell whose cost is a
175
+ * subtotal — a failure that declared nothing, a partial amount, a result
176
+ * the runner could not bill — is charged this bound against `costCeiling`
177
+ * instead of its known subtotal, so hidden spend cannot walk the run past
178
+ * its budget.
179
+ *
180
+ * It changes only what the ceiling reads. `CellResult.costUsd` and
181
+ * `summary.totalCostUsd` keep reporting known spend, never a bound that was
182
+ * charged but not spent; `summary.ceilingChargedUsd` reports the
183
+ * conservative figure. Omit it and the ceiling stays fail-open for exactly
184
+ * the cells that hid their spend, with `costUncapturedCells` as the only
185
+ * signal. */
186
+ maxCellCostUsd?: number;
187
+ /** Fires once per executed cell, after its promise settles. */
188
+ onCellComplete?: (cell: MatrixCell, result: CellResult<Output>) => void;
189
+ /** External cancellation. Aborts in-flight cells via a forwarded signal
190
+ * and suppresses scheduling of new ones. */
191
+ signal?: AbortSignal;
192
+ }
193
+ //#endregion
194
+ //#region src/matrix/runner.d.ts
195
+ declare function runAgentMatrix<Output>(opts: RunAgentMatrixOptions<Output>): Promise<MatrixResult<Output>>;
196
+ //#endregion
197
+ export { MatrixCell as a, CellSpend as c, MatrixAxis as i, readCellSpend as l, AxisSummary as n, MatrixResult as o, CellResult as r, RunAgentMatrixOptions as s, runAgentMatrix as t, withCellSpend as u };
198
+ //# sourceMappingURL=index-D_P7Ye43.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-D_P7Ye43.d.ts","names":[],"sources":["../src/matrix/cell-spend.ts","../src/matrix/types.ts","../src/matrix/runner.ts"],"mappings":";;;;;;;;;;;;;;;;;;UAoBiB;;;;EAIf;;EAEA;;;;EAIA;;;;;;;;;;;;;;;;iBAiBc,cAAc,gBAAgB,OAAO;;;;iBA+CrC,cAAc,iBAAiB;;;;;UC5E9B,WAAW;;EAE1B;;EAEA,QAAQ;IAAQ;IAAY,OAAO;;;;EAGnC,SAAS,OAAO,GAAG;;;UAIJ;EACf,MAAM;IAAiB;IAAY;;;EAEnC;;EAEA;;UAGe,WAAW;EAC1B,QAAQ;EACR,SAAS;;;;EAIT;EACA;EACA;;;;;;;;;;;EAWA,iBAAiB;;;;EAIjB;IAAU;IAAiB;;;UAGZ;EACf;EACA;EACA;EACA;EACA;EACA;EACA;;;EAGA;;EAEA;EACA;;UAGe,aAAa;EAC5B,OAAO;IAAQ,MAAM;IAAY,MAAM,WAAW;;;;EAGlD,QAAQ,eAAe,eAAe;EACtC;IACE;IACA;;;IAGA;IACA;IACA;;;;IAIA;;;;IAIA;;;;IAIA;IACA;;;EAGF;;UAGe,sBAAsB;EACrC,MAAM;;;;;;EAMN,UAAU,MAAM,eAAe,QAAQ,WAAW;;EAElD;;EAEA,UAAU,MAAM,KAAK;;EAErB;;EAEA;;;;;EAKA;;;;;;;;;;;;;EAaA;;EAEA,kBAAkB,MAAM,YAAY,QAAQ,WAAW;;;EAGvD,SAAS;;;;iBC1BW,eAAe,QACnC,MAAM,sBAAsB,UAC3B,QAAQ,aAAa"}
@@ -1,3 +1,4 @@
1
1
  import { t as DefaultVerdict } from "../verdict-E4eRNf7-.js";
2
- import { a as MatrixCell, i as MatrixAxis, n as AxisSummary, o as MatrixResult, r as CellResult, s as RunAgentMatrixOptions, t as runAgentMatrix } from "../index-CvjYbU0D.js";
3
- export { type AxisSummary, type CellResult, type DefaultVerdict, type MatrixAxis, type MatrixCell, type MatrixResult, type RunAgentMatrixOptions, runAgentMatrix };
2
+ import { p as CostProvenance } from "../cost-ledger-DbQdN3nO.js";
3
+ import { a as MatrixCell, c as CellSpend, i as MatrixAxis, l as readCellSpend, n as AxisSummary, o as MatrixResult, r as CellResult, s as RunAgentMatrixOptions, t as runAgentMatrix, u as withCellSpend } from "../index-D_P7Ye43.js";
4
+ export { type AxisSummary, type CellResult, type CellSpend, type CostProvenance, type DefaultVerdict, type MatrixAxis, type MatrixCell, type MatrixResult, type RunAgentMatrixOptions, readCellSpend, runAgentMatrix, withCellSpend };
@@ -1,2 +1,2 @@
1
- import { t as runAgentMatrix } from "../matrix-BzQnu2S6.js";
2
- export { runAgentMatrix };
1
+ import { n as readCellSpend, r as withCellSpend, t as runAgentMatrix } from "../matrix-pWinRMPl.js";
2
+ export { readCellSpend, runAgentMatrix, withCellSpend };
@@ -1,3 +1,94 @@
1
+ //#region src/matrix/cell-spend.ts
2
+ /**
3
+ * Spend carrier for a cell that fails after it has already spent money.
4
+ *
5
+ * `runCell` reports what a cell cost by returning a `CellResult`. A throw
6
+ * carries no result, so the runner cannot know what the cell spent before it
7
+ * failed: the cumulative sum the cost ceiling reads, and `totalCostUsd`, both
8
+ * miss that money. A throw that carries a `CellSpend` closes the gap — the
9
+ * runner bills the failed cell for the spend the carrier declares, and records
10
+ * a cell that declared nothing as `uncaptured` instead of a zero that reads
11
+ * like "this cell spent nothing".
12
+ *
13
+ * The carrier is read structurally, never by `instanceof`, so a throw that
14
+ * crosses a package or realm boundary still bills.
15
+ */
16
+ /** Property key the carrier occupies on a thrown object. Stable across
17
+ * versions — two copies of this package must agree on it. */
18
+ const CELL_SPEND_KEY = "__agentEvalCellSpend";
19
+ /**
20
+ * Return `error` carrying `spend`, for a throw site inside `runCell`:
21
+ * `throw withCellSpend(err, { costUsd, durationMs, kind })`.
22
+ *
23
+ * A value that cannot hold the carrier — a thrown string or number, or a
24
+ * frozen, sealed, or otherwise non-extensible object — is wrapped in an
25
+ * `Error` that keeps the original as `cause`, so the spend is never dropped.
26
+ * A later call overwrites an earlier carrier — the outer frame knows more
27
+ * than the inner one.
28
+ *
29
+ * Throws `TypeError` on a non-finite or negative amount. A poisoned amount
30
+ * would reach `cumulativeCost` and disable the cost ceiling for the whole run,
31
+ * because `NaN >= ceiling` is false.
32
+ */
33
+ function withCellSpend(error, spend) {
34
+ assertAmount(spend.costUsd, "costUsd");
35
+ assertAmount(spend.durationMs, "durationMs");
36
+ if (spend.kind !== "observed" && spend.kind !== "estimated" && spend.kind !== "uncaptured") throw new TypeError(`withCellSpend: kind must be observed, estimated or uncaptured, received ${String(spend.kind)}`);
37
+ const carrier = {
38
+ costUsd: spend.costUsd,
39
+ durationMs: spend.durationMs,
40
+ kind: spend.kind
41
+ };
42
+ if (typeof error === "object" && error !== null && attach(error, carrier)) return error;
43
+ const wrapper = new Error(`cell failed: ${messageOf(error)}`, { cause: error });
44
+ attach(wrapper, carrier);
45
+ return wrapper;
46
+ }
47
+ /** True when the carrier landed. `defineProperty` throws on a non-extensible
48
+ * target, so the caller must be able to fall back. */
49
+ function attach(target, carrier) {
50
+ try {
51
+ Object.defineProperty(target, CELL_SPEND_KEY, {
52
+ value: carrier,
53
+ enumerable: false,
54
+ configurable: true,
55
+ writable: true
56
+ });
57
+ return true;
58
+ } catch {
59
+ return false;
60
+ }
61
+ }
62
+ function messageOf(error) {
63
+ if (error instanceof Error) return error.message;
64
+ return String(error);
65
+ }
66
+ /** Read the spend a thrown value carries. `undefined` when the value carries
67
+ * none, or carries one that does not satisfy `CellSpend` — the runner records
68
+ * both as `uncaptured`. */
69
+ function readCellSpend(error) {
70
+ if (typeof error !== "object" || error === null) return void 0;
71
+ const raw = error[CELL_SPEND_KEY];
72
+ if (typeof raw !== "object" || raw === null) return void 0;
73
+ const candidate = raw;
74
+ if (!isAmount(candidate.costUsd) || !isAmount(candidate.durationMs)) return void 0;
75
+ const kind = candidate.kind;
76
+ if (kind !== "observed" && kind !== "estimated" && kind !== "uncaptured") return void 0;
77
+ return {
78
+ costUsd: candidate.costUsd,
79
+ durationMs: candidate.durationMs,
80
+ kind
81
+ };
82
+ }
83
+ /** A number the matrix can add to a running cost or duration: finite and not
84
+ * negative. Anything else would poison a sum the cost ceiling reads. */
85
+ function isAmount(value) {
86
+ return typeof value === "number" && Number.isFinite(value) && value >= 0;
87
+ }
88
+ function assertAmount(value, field) {
89
+ if (!isAmount(value)) throw new TypeError(`withCellSpend: ${field} must be a finite number >= 0, received ${String(value)}`);
90
+ }
91
+ //#endregion
1
92
  //#region src/matrix/aggregation.ts
2
93
  function flattenRuns(cells) {
3
94
  const rows = [];
@@ -27,12 +118,14 @@ function summariseRows(rows, axisName, axisValue) {
27
118
  p50Score: 0,
28
119
  p90Score: 0,
29
120
  totalCostUsd: 0,
121
+ costUncapturedCells: 0,
30
122
  meanDurationMs: 0
31
123
  };
32
124
  let pass = 0;
33
125
  let scoreSum = 0;
34
126
  let costSum = 0;
35
127
  let durSum = 0;
128
+ let costUncapturedCells = 0;
36
129
  const scores = [];
37
130
  for (const { result } of rows) {
38
131
  const errored = result.error !== void 0;
@@ -42,6 +135,7 @@ function summariseRows(rows, axisName, axisValue) {
42
135
  scores.push(score);
43
136
  costSum += result.costUsd;
44
137
  durSum += result.durationMs;
138
+ if (result.costProvenance?.kind === "uncaptured") costUncapturedCells++;
45
139
  }
46
140
  scores.sort((a, b) => a - b);
47
141
  return {
@@ -53,6 +147,7 @@ function summariseRows(rows, axisName, axisValue) {
53
147
  p50Score: quantile(scores, .5),
54
148
  p90Score: quantile(scores, .9),
55
149
  totalCostUsd: costSum,
150
+ costUncapturedCells,
56
151
  meanDurationMs: durSum / rows.length
57
152
  };
58
153
  }
@@ -139,28 +234,62 @@ function makeMatrixId() {
139
234
  for (let i = 0; i < 8; i++) r += Math.floor(Math.random() * 16).toString(16);
140
235
  return `mtx_${t}_${r}`;
141
236
  }
237
+ /** Fresh per result — a shared object would let one consumer's mutation reach
238
+ * every other cell in the run. */
239
+ function uncaptured() {
240
+ return {
241
+ kind: "uncaptured",
242
+ usd: null
243
+ };
244
+ }
142
245
  function makeErrorResult(err) {
143
246
  const e = err;
247
+ const spend = readCellSpend(err);
144
248
  return {
145
249
  output: void 0,
146
250
  verdict: {
147
251
  valid: false,
148
252
  score: 0
149
253
  },
150
- costUsd: 0,
151
- durationMs: 0,
254
+ costUsd: spend?.costUsd ?? 0,
255
+ durationMs: spend?.durationMs ?? 0,
256
+ costProvenance: spend === void 0 || spend.kind === "uncaptured" ? uncaptured() : {
257
+ kind: spend.kind,
258
+ usd: spend.costUsd
259
+ },
152
260
  error: {
153
261
  message: typeof e?.message === "string" ? e.message : String(err),
154
262
  kind: typeof e?.name === "string" ? e.name : "Error"
155
263
  }
156
264
  };
157
265
  }
266
+ /** Make a result safe to sum.
267
+ *
268
+ * A `costUsd` that cannot be summed fails the cell: `NaN` in `cumulativeCost`
269
+ * makes `>= costCeiling` false forever, so one bad cell would disable the
270
+ * ceiling for every cell after it.
271
+ *
272
+ * A bad `durationMs` reaches only `meanDurationMs`, never the ceiling, so it
273
+ * cannot justify throwing away a real verdict and a real cost. It is reported
274
+ * as 0 and warned about, and the rest of the result stands. A wall clock that
275
+ * steps back mid-cell makes `Date.now() - startedAt` negative, so this is a
276
+ * reachable state, not only a caller bug. */
277
+ function billableResult(result, onBadDuration) {
278
+ if (!isAmount(result.costUsd)) return makeErrorResult(/* @__PURE__ */ new RangeError(`runCell reported costUsd=${String(result.costUsd)}; a cell cost must be a finite number >= 0 so the cost ceiling stays enforceable`));
279
+ if (isAmount(result.durationMs)) return result;
280
+ onBadDuration(result.durationMs);
281
+ return {
282
+ ...result,
283
+ durationMs: 0
284
+ };
285
+ }
158
286
  async function runAgentMatrix(opts) {
159
287
  const startedAt = Date.now();
160
288
  const reps = Math.max(1, opts.reps ?? 1);
161
289
  const maxConcurrency = Math.max(1, opts.maxConcurrency ?? 4);
162
290
  const costCeiling = opts.costCeiling ?? Number.POSITIVE_INFINITY;
163
291
  const aggregateBy = opts.aggregateBy ?? opts.axes.map((a) => a.name);
292
+ if (opts.maxCellCostUsd !== void 0 && !isAmount(opts.maxCellCostUsd)) throw new RangeError(`runAgentMatrix: maxCellCostUsd must be a finite number >= 0, received ${String(opts.maxCellCostUsd)}`);
164
293
  const base = cartesian(opts.axes);
165
294
  const filtered = opts.filter ? base.filter((c) => opts.filter(c)) : base;
166
295
  const filteredOut = base.length - filtered.length;
@@ -175,6 +304,8 @@ async function runAgentMatrix(opts) {
175
304
  let costCeilingReached = false;
176
305
  let runsExecuted = 0;
177
306
  let cellsUnscheduled = 0;
307
+ let costUncapturedCells = 0;
308
+ let badDurationCells = 0;
178
309
  const aborted = () => opts.signal?.aborted === true;
179
310
  let inFlight = 0;
180
311
  let cursor = 0;
@@ -203,10 +334,19 @@ async function runAgentMatrix(opts) {
203
334
  } catch (err) {
204
335
  return makeErrorResult(err);
205
336
  }
206
- })().then((result) => {
337
+ })().then((settled) => {
338
+ const result = billableResult(settled, (reported) => {
339
+ badDurationCells++;
340
+ if (badDurationCells === 1) console.warn(`[matrix] a cell reported durationMs=${String(reported)}; recorded as 0 — meanDurationMs under-reports this run`);
341
+ });
207
342
  record.runs.push(result);
208
343
  runsExecuted++;
209
- cumulativeCost += result.costUsd;
344
+ const uncapturedCost = result.costProvenance?.kind === "uncaptured";
345
+ cumulativeCost += uncapturedCost && opts.maxCellCostUsd !== void 0 ? Math.max(result.costUsd, opts.maxCellCostUsd) : result.costUsd;
346
+ if (uncapturedCost) {
347
+ costUncapturedCells++;
348
+ if (costUncapturedCells === 1) console.warn("[matrix] a cell's cost is a subtotal, not a total — totalCostUsd and the cost ceiling under-count this run");
349
+ }
210
350
  if (cumulativeCost >= costCeiling && !costCeilingReached) {
211
351
  costCeilingReached = true;
212
352
  console.warn("[matrix] cost ceiling reached");
@@ -259,12 +399,14 @@ async function runAgentMatrix(opts) {
259
399
  overallPassRate: runCount === 0 ? 0 : pass / runCount,
260
400
  overallMeanScore: runCount === 0 ? 0 : scoreSum / runCount,
261
401
  totalCostUsd: totalCost,
402
+ costUncapturedCells,
403
+ ceilingChargedUsd: cumulativeCost,
262
404
  durationMs: Date.now() - startedAt
263
405
  },
264
406
  matrixId: makeMatrixId()
265
407
  };
266
408
  }
267
409
  //#endregion
268
- export { runAgentMatrix as t };
410
+ export { readCellSpend as n, withCellSpend as r, runAgentMatrix as t };
269
411
 
270
- //# sourceMappingURL=matrix-BzQnu2S6.js.map
412
+ //# sourceMappingURL=matrix-pWinRMPl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"matrix-pWinRMPl.js","names":[],"sources":["../src/matrix/cell-spend.ts","../src/matrix/aggregation.ts","../src/matrix/runner.ts"],"sourcesContent":["/**\n * Spend carrier for a cell that fails after it has already spent money.\n *\n * `runCell` reports what a cell cost by returning a `CellResult`. A throw\n * carries no result, so the runner cannot know what the cell spent before it\n * failed: the cumulative sum the cost ceiling reads, and `totalCostUsd`, both\n * miss that money. A throw that carries a `CellSpend` closes the gap — the\n * runner bills the failed cell for the spend the carrier declares, and records\n * a cell that declared nothing as `uncaptured` instead of a zero that reads\n * like \"this cell spent nothing\".\n *\n * The carrier is read structurally, never by `instanceof`, so a throw that\n * crosses a package or realm boundary still bills.\n */\n\n/** Property key the carrier occupies on a thrown object. Stable across\n * versions — two copies of this package must agree on it. */\nconst CELL_SPEND_KEY = '__agentEvalCellSpend'\n\n/** Money and wall time a cell consumed before it threw. */\nexport interface CellSpend {\n /** KNOWN subtotal in USD. When `kind` is `uncaptured` the cell spent this\n * much AND an unknown amount more, so the value must not be read as the\n * cell's total. */\n costUsd: number\n /** Wall time the cell consumed before the throw, in milliseconds. */\n durationMs: number\n /** `observed` = provider-reported amounts, `estimated` = computed from token\n * prices, `uncaptured` = `costUsd` is a subtotal and part of the spend\n * could not be measured. */\n kind: 'observed' | 'estimated' | 'uncaptured'\n}\n\n/**\n * Return `error` carrying `spend`, for a throw site inside `runCell`:\n * `throw withCellSpend(err, { costUsd, durationMs, kind })`.\n *\n * A value that cannot hold the carrier — a thrown string or number, or a\n * frozen, sealed, or otherwise non-extensible object — is wrapped in an\n * `Error` that keeps the original as `cause`, so the spend is never dropped.\n * A later call overwrites an earlier carrier — the outer frame knows more\n * than the inner one.\n *\n * Throws `TypeError` on a non-finite or negative amount. A poisoned amount\n * would reach `cumulativeCost` and disable the cost ceiling for the whole run,\n * because `NaN >= ceiling` is false.\n */\nexport function withCellSpend(error: unknown, spend: CellSpend): unknown {\n assertAmount(spend.costUsd, 'costUsd')\n assertAmount(spend.durationMs, 'durationMs')\n if (spend.kind !== 'observed' && spend.kind !== 'estimated' && spend.kind !== 'uncaptured') {\n throw new TypeError(\n `withCellSpend: kind must be observed, estimated or uncaptured, received ${String(spend.kind)}`,\n )\n }\n const carrier: CellSpend = {\n costUsd: spend.costUsd,\n durationMs: spend.durationMs,\n kind: spend.kind,\n }\n if (typeof error === 'object' && error !== null && attach(error, carrier)) return error\n // A primitive cannot hold a property, and a frozen or sealed object refuses\n // one. Carry the spend on a fresh Error that keeps the original as `cause`\n // rather than lose it — a dropped carrier bills the cell as uncaptured,\n // which is the under-billing this module exists to prevent.\n const wrapper = new Error(`cell failed: ${messageOf(error)}`, { cause: error })\n attach(wrapper, carrier)\n return wrapper\n}\n\n/** True when the carrier landed. `defineProperty` throws on a non-extensible\n * target, so the caller must be able to fall back. */\nfunction attach(target: object, carrier: CellSpend): boolean {\n try {\n Object.defineProperty(target, CELL_SPEND_KEY, {\n value: carrier,\n enumerable: false,\n configurable: true,\n writable: true,\n })\n return true\n } catch {\n return false\n }\n}\n\nfunction messageOf(error: unknown): string {\n if (error instanceof Error) return error.message\n return String(error)\n}\n\n/** Read the spend a thrown value carries. `undefined` when the value carries\n * none, or carries one that does not satisfy `CellSpend` — the runner records\n * both as `uncaptured`. */\nexport function readCellSpend(error: unknown): CellSpend | undefined {\n if (typeof error !== 'object' || error === null) return undefined\n const raw = (error as Record<string, unknown>)[CELL_SPEND_KEY]\n if (typeof raw !== 'object' || raw === null) return undefined\n const candidate = raw as Record<string, unknown>\n if (!isAmount(candidate.costUsd) || !isAmount(candidate.durationMs)) return undefined\n const kind = candidate.kind\n if (kind !== 'observed' && kind !== 'estimated' && kind !== 'uncaptured') return undefined\n return { costUsd: candidate.costUsd, durationMs: candidate.durationMs, kind }\n}\n\n/** A number the matrix can add to a running cost or duration: finite and not\n * negative. Anything else would poison a sum the cost ceiling reads. */\nexport function isAmount(value: unknown): value is number {\n return typeof value === 'number' && Number.isFinite(value) && value >= 0\n}\n\nfunction assertAmount(value: number, field: string): void {\n if (!isAmount(value)) {\n throw new TypeError(\n `withCellSpend: ${field} must be a finite number >= 0, received ${String(value)}`,\n )\n }\n}\n","/**\n * Per-axis aggregation of cell runs into `AxisSummary` rows.\n *\n * Pure: consumes the final `cells: [{cell, runs}]` array and returns the\n * `byAxis` table. Error runs contribute 0 to passRate and meanScore. Cost and\n * duration always count — the budget was spent regardless. A run whose cost is\n * a subtotal rather than a total raises `costUncapturedCells` for its bucket,\n * so a per-axis cost row says when it under-counts.\n */\n\nimport type { AxisSummary, CellResult, MatrixAxis, MatrixCell, MatrixResult } from './types'\n\ninterface Row<Output> {\n cell: MatrixCell\n result: CellResult<Output>\n}\n\nfunction flattenRuns<Output>(cells: MatrixResult<Output>['cells']): Row<Output>[] {\n const rows: Row<Output>[] = []\n for (const { cell, runs } of cells) {\n for (const result of runs) rows.push({ cell, result })\n }\n return rows\n}\n\nfunction quantile(sorted: number[], q: number): number {\n if (sorted.length === 0) return 0\n if (sorted.length === 1) return sorted[0] as number\n const pos = (sorted.length - 1) * q\n const lo = Math.floor(pos)\n const hi = Math.ceil(pos)\n if (lo === hi) return sorted[lo] as number\n const frac = pos - lo\n return (sorted[lo] as number) * (1 - frac) + (sorted[hi] as number) * frac\n}\n\nexport function summariseRows<Output>(\n rows: Row<Output>[],\n axisName: string,\n axisValue: string,\n): AxisSummary {\n if (rows.length === 0) {\n return {\n axisName,\n axisValue,\n cells: 0,\n passRate: 0,\n meanScore: 0,\n p50Score: 0,\n p90Score: 0,\n totalCostUsd: 0,\n costUncapturedCells: 0,\n meanDurationMs: 0,\n }\n }\n let pass = 0\n let scoreSum = 0\n let costSum = 0\n let durSum = 0\n let costUncapturedCells = 0\n const scores: number[] = []\n for (const { result } of rows) {\n const errored = result.error !== undefined\n const score = errored ? 0 : result.verdict.score\n const valid = !errored && result.verdict.valid\n if (valid) pass++\n scoreSum += score\n scores.push(score)\n costSum += result.costUsd\n durSum += result.durationMs\n if (result.costProvenance?.kind === 'uncaptured') costUncapturedCells++\n }\n scores.sort((a, b) => a - b)\n return {\n axisName,\n axisValue,\n cells: rows.length,\n passRate: pass / rows.length,\n meanScore: scoreSum / rows.length,\n p50Score: quantile(scores, 0.5),\n p90Score: quantile(scores, 0.9),\n totalCostUsd: costSum,\n costUncapturedCells,\n meanDurationMs: durSum / rows.length,\n }\n}\n\nfunction bucketBy<Output>(\n rows: Row<Output>[],\n axisName: string,\n labelFor: (id: string) => string,\n): Record<string, AxisSummary> {\n const buckets = new Map<string, Row<Output>[]>()\n for (const row of rows) {\n const slot = row.cell.axes[axisName]\n if (!slot) continue\n const id = slot.id\n let arr = buckets.get(id)\n if (!arr) {\n arr = []\n buckets.set(id, arr)\n }\n arr.push(row)\n }\n const out: Record<string, AxisSummary> = {}\n // Sorted keys for deterministic JSON serialisation.\n for (const id of [...buckets.keys()].sort()) {\n out[id] = summariseRows(buckets.get(id) as Row<Output>[], axisName, labelFor(id))\n }\n return out\n}\n\nexport function buildByAxis<Output>(\n cells: MatrixResult<Output>['cells'],\n axes: MatrixAxis<unknown>[],\n aggregateBy: string[],\n): Record<string, Record<string, AxisSummary>> {\n const rows = flattenRuns(cells)\n const byName = new Map(axes.map((a) => [a.name, a]))\n const byAxis: Record<string, Record<string, AxisSummary>> = {}\n for (const name of aggregateBy) {\n const axis = byName.get(name)\n const labelFor = (id: string): string => {\n if (!axis?.label) return id\n const found = axis.values.find((v) => v.id === id)\n if (!found) return id\n return axis.label(found.value, id)\n }\n byAxis[name] = bucketBy(rows, name, labelFor)\n }\n return byAxis\n}\n","/**\n * N-axis cartesian runner.\n *\n * Expansion order: cartesian over `axes` in declared order, then `reps` as the\n * inner-most dim → `ordinal = (cartIdx * reps) + rep`. The returned\n * `cells[]` is sorted by `ordinal` so concurrent execution does not reorder\n * the output.\n *\n * Scheduling is a sliding window of in-flight promises capped at\n * `maxConcurrency`. The window stops admitting new cells when the cost\n * ceiling trips or the abort signal fires; in-flight cells finish.\n */\n\nimport { buildByAxis } from './aggregation'\nimport { isAmount, readCellSpend } from './cell-spend'\nimport type {\n CellResult,\n CostProvenance,\n MatrixAxis,\n MatrixCell,\n MatrixResult,\n RunAgentMatrixOptions,\n} from './types'\n\ninterface BaseCell {\n axes: Record<string, { id: string; value: unknown }>\n}\n\nfunction cartesian(axes: MatrixAxis<unknown>[]): BaseCell[] {\n // Empty axes (`values=[]`) collapse the whole product to zero cells. An\n // empty `axes` array yields a single empty-axes cell — degenerate but\n // valid (caller is iterating only reps).\n if (axes.length === 0) return [{ axes: {} }]\n for (const a of axes) if (a.values.length === 0) return []\n const out: BaseCell[] = []\n const idx = new Array(axes.length).fill(0)\n while (true) {\n const slot: Record<string, { id: string; value: unknown }> = {}\n for (let i = 0; i < axes.length; i++) {\n const axis = axes[i] as MatrixAxis<unknown>\n const v = axis.values[idx[i] as number] as { id: string; value: unknown }\n slot[axis.name] = { id: v.id, value: v.value }\n }\n out.push({ axes: slot })\n // Increment like an odometer, left-most axis is fastest.\n let i = 0\n while (i < axes.length) {\n const next = (idx[i] as number) + 1\n const axis = axes[i] as MatrixAxis<unknown>\n if (next < axis.values.length) {\n idx[i] = next\n break\n }\n idx[i] = 0\n i++\n }\n if (i === axes.length) break\n }\n return out\n}\n\nfunction makeMatrixId(): string {\n // Stable id-like string: time + 8 random hex chars. Avoids node:crypto\n // import to keep the matrix dep-free.\n const t = Date.now().toString(36)\n let r = ''\n for (let i = 0; i < 8; i++) r += Math.floor(Math.random() * 16).toString(16)\n return `mtx_${t}_${r}`\n}\n\n/** Fresh per result — a shared object would let one consumer's mutation reach\n * every other cell in the run. */\nfunction uncaptured(): CostProvenance {\n return { kind: 'uncaptured', usd: null }\n}\n\nfunction makeErrorResult<Output>(err: unknown): CellResult<Output> {\n const e = err as { message?: string; name?: string }\n const spend = readCellSpend(err)\n return {\n output: undefined as unknown as Output,\n verdict: { valid: false, score: 0 },\n costUsd: spend?.costUsd ?? 0,\n durationMs: spend?.durationMs ?? 0,\n costProvenance:\n spend === undefined || spend.kind === 'uncaptured'\n ? uncaptured()\n : { kind: spend.kind, usd: spend.costUsd },\n error: {\n message: typeof e?.message === 'string' ? e.message : String(err),\n kind: typeof e?.name === 'string' ? e.name : 'Error',\n },\n }\n}\n\n/** Make a result safe to sum.\n *\n * A `costUsd` that cannot be summed fails the cell: `NaN` in `cumulativeCost`\n * makes `>= costCeiling` false forever, so one bad cell would disable the\n * ceiling for every cell after it.\n *\n * A bad `durationMs` reaches only `meanDurationMs`, never the ceiling, so it\n * cannot justify throwing away a real verdict and a real cost. It is reported\n * as 0 and warned about, and the rest of the result stands. A wall clock that\n * steps back mid-cell makes `Date.now() - startedAt` negative, so this is a\n * reachable state, not only a caller bug. */\nfunction billableResult<Output>(\n result: CellResult<Output>,\n onBadDuration: (reported: unknown) => void,\n): CellResult<Output> {\n if (!isAmount(result.costUsd)) {\n return makeErrorResult<Output>(\n new RangeError(\n `runCell reported costUsd=${String(result.costUsd)}; a cell cost must be a finite number >= 0 so the cost ceiling stays enforceable`,\n ),\n )\n }\n if (isAmount(result.durationMs)) return result\n onBadDuration(result.durationMs)\n return { ...result, durationMs: 0 }\n}\n\nexport async function runAgentMatrix<Output>(\n opts: RunAgentMatrixOptions<Output>,\n): Promise<MatrixResult<Output>> {\n const startedAt = Date.now()\n const reps = Math.max(1, opts.reps ?? 1)\n const maxConcurrency = Math.max(1, opts.maxConcurrency ?? 4)\n const costCeiling = opts.costCeiling ?? Number.POSITIVE_INFINITY\n const aggregateBy = opts.aggregateBy ?? opts.axes.map((a) => a.name)\n if (opts.maxCellCostUsd !== undefined && !isAmount(opts.maxCellCostUsd)) {\n throw new RangeError(\n `runAgentMatrix: maxCellCostUsd must be a finite number >= 0, received ${String(opts.maxCellCostUsd)}`,\n )\n }\n\n const base = cartesian(opts.axes)\n const filtered = opts.filter\n ? base.filter((c) => (opts.filter as (b: BaseCell) => boolean)(c))\n : base\n const filteredOut = base.length - filtered.length\n\n const planned: MatrixCell[] = []\n for (let i = 0; i < filtered.length; i++) {\n for (let r = 0; r < reps; r++) {\n planned.push({\n axes: (filtered[i] as BaseCell).axes,\n rep: r,\n ordinal: i * reps + r,\n })\n }\n }\n\n const cellRecords: Array<{ cell: MatrixCell; runs: CellResult<Output>[] }> = []\n // What the ceiling reads. It runs ahead of the reported total whenever a\n // cell's cost is a subtotal and `maxCellCostUsd` bounds what it could have\n // been — a budget must assume the worst about spend it cannot see.\n let cumulativeCost = 0\n let costCeilingReached = false\n let runsExecuted = 0\n let cellsUnscheduled = 0\n let costUncapturedCells = 0\n let badDurationCells = 0\n\n const aborted = (): boolean => opts.signal?.aborted === true\n\n // Per-run abort controller forwards the external signal so cell executors\n // see cancellation. We don't expose it on `MatrixCell` — the signature on\n // `runCell` per the public API is `(cell) => Promise<...>`. Executors that\n // need cancellation use the external signal directly via closure.\n\n let inFlight = 0\n let cursor = 0\n let resolveAll: (() => void) | undefined\n const done = new Promise<void>((res) => {\n resolveAll = res\n })\n\n const pump = (): void => {\n while (inFlight < maxConcurrency && cursor < planned.length) {\n if (aborted() || costCeilingReached) {\n // Drain remaining as unscheduled.\n const left = planned.length - cursor\n cellsUnscheduled += left\n cursor = planned.length\n break\n }\n const cell = planned[cursor++] as MatrixCell\n inFlight++\n // Lazily allocate the record so cells appear in `cells[]` in any\n // arrival order; we sort by ordinal at the end.\n const record = { cell, runs: [] as CellResult<Output>[] }\n cellRecords.push(record)\n const promise: Promise<CellResult<Output>> = (async () => {\n try {\n return await opts.runCell(cell)\n } catch (err) {\n return makeErrorResult<Output>(err)\n }\n })()\n promise.then((settled) => {\n const result = billableResult(settled, (reported) => {\n badDurationCells++\n if (badDurationCells === 1) {\n // eslint-disable-next-line no-console\n console.warn(\n `[matrix] a cell reported durationMs=${String(reported)}; recorded as 0 — meanDurationMs under-reports this run`,\n )\n }\n })\n record.runs.push(result)\n runsExecuted++\n const uncapturedCost = result.costProvenance?.kind === 'uncaptured'\n cumulativeCost +=\n uncapturedCost && opts.maxCellCostUsd !== undefined\n ? Math.max(result.costUsd, opts.maxCellCostUsd)\n : result.costUsd\n if (uncapturedCost) {\n costUncapturedCells++\n if (costUncapturedCells === 1) {\n // eslint-disable-next-line no-console\n console.warn(\n \"[matrix] a cell's cost is a subtotal, not a total — totalCostUsd and the cost ceiling under-count this run\",\n )\n }\n }\n if (cumulativeCost >= costCeiling && !costCeilingReached) {\n costCeilingReached = true\n // eslint-disable-next-line no-console\n console.warn('[matrix] cost ceiling reached')\n }\n try {\n opts.onCellComplete?.(cell, result)\n } catch {\n // onCellComplete is observational — swallow throws so a noisy\n // callback can't tank the run.\n }\n inFlight--\n if (cursor < planned.length) {\n pump()\n } else if (inFlight === 0) {\n resolveAll?.()\n }\n })\n }\n if (cursor >= planned.length && inFlight === 0) resolveAll?.()\n }\n\n const onAbort = (): void => {\n // External abort: stop scheduling. In-flight cells finish; their\n // executors observe `opts.signal.aborted` directly via closure.\n if (cursor < planned.length) {\n cellsUnscheduled += planned.length - cursor\n cursor = planned.length\n }\n if (inFlight === 0) resolveAll?.()\n }\n if (opts.signal) {\n if (opts.signal.aborted) {\n cellsUnscheduled = planned.length\n cursor = planned.length\n resolveAll?.()\n } else {\n opts.signal.addEventListener('abort', onAbort, { once: true })\n }\n }\n\n if (planned.length === 0) {\n resolveAll?.()\n } else {\n pump()\n }\n\n await done\n if (opts.signal) opts.signal.removeEventListener('abort', onAbort)\n\n cellRecords.sort((a, b) => a.cell.ordinal - b.cell.ordinal)\n\n let pass = 0\n let scoreSum = 0\n let totalCost = 0\n let runCount = 0\n for (const { runs } of cellRecords) {\n for (const r of runs) {\n runCount++\n const errored = r.error !== undefined\n if (!errored && r.verdict.valid) pass++\n scoreSum += errored ? 0 : r.verdict.score\n totalCost += r.costUsd\n }\n }\n\n const byAxis = buildByAxis(cellRecords, opts.axes, aggregateBy)\n\n return {\n cells: cellRecords,\n byAxis,\n summary: {\n totalCells: planned.length,\n runsExecuted,\n cellsSkipped: cellsUnscheduled + filteredOut * reps,\n overallPassRate: runCount === 0 ? 0 : pass / runCount,\n overallMeanScore: runCount === 0 ? 0 : scoreSum / runCount,\n totalCostUsd: totalCost,\n costUncapturedCells,\n ceilingChargedUsd: cumulativeCost,\n durationMs: Date.now() - startedAt,\n },\n matrixId: makeMatrixId(),\n }\n}\n"],"mappings":"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"}