peeksafe 0.0.0-stage → 0.1.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 (66) hide show
  1. package/CHANGELOG.md +146 -0
  2. package/LICENSE +190 -0
  3. package/NOTICE +78 -0
  4. package/README.md +492 -2
  5. package/RESEARCH-NOTES.md +274 -0
  6. package/dist/baseline.d.ts +45 -0
  7. package/dist/baseline.d.ts.map +1 -0
  8. package/dist/baseline.js +49 -0
  9. package/dist/baseline.js.map +1 -0
  10. package/dist/check.d.ts +64 -0
  11. package/dist/check.d.ts.map +1 -0
  12. package/dist/check.js +172 -0
  13. package/dist/check.js.map +1 -0
  14. package/dist/cluster.d.ts +328 -0
  15. package/dist/cluster.d.ts.map +1 -0
  16. package/dist/cluster.js +598 -0
  17. package/dist/cluster.js.map +1 -0
  18. package/dist/errors.d.ts +87 -0
  19. package/dist/errors.d.ts.map +1 -0
  20. package/dist/errors.js +143 -0
  21. package/dist/errors.js.map +1 -0
  22. package/dist/evidence.d.ts +15 -0
  23. package/dist/evidence.d.ts.map +1 -0
  24. package/dist/evidence.js +30 -0
  25. package/dist/evidence.js.map +1 -0
  26. package/dist/frontier.d.ts +269 -0
  27. package/dist/frontier.d.ts.map +1 -0
  28. package/dist/frontier.js +460 -0
  29. package/dist/frontier.js.map +1 -0
  30. package/dist/gate.d.ts +173 -0
  31. package/dist/gate.d.ts.map +1 -0
  32. package/dist/gate.js +196 -0
  33. package/dist/gate.js.map +1 -0
  34. package/dist/index.d.ts +60 -0
  35. package/dist/index.d.ts.map +1 -0
  36. package/dist/index.js +79 -0
  37. package/dist/index.js.map +1 -0
  38. package/dist/plan.d.ts +248 -0
  39. package/dist/plan.d.ts.map +1 -0
  40. package/dist/plan.js +482 -0
  41. package/dist/plan.js.map +1 -0
  42. package/dist/rand.d.ts +17 -0
  43. package/dist/rand.d.ts.map +1 -0
  44. package/dist/rand.js +92 -0
  45. package/dist/rand.js.map +1 -0
  46. package/dist/stats.d.ts +397 -0
  47. package/dist/stats.d.ts.map +1 -0
  48. package/dist/stats.js +1245 -0
  49. package/dist/stats.js.map +1 -0
  50. package/dist/stop.d.ts +163 -0
  51. package/dist/stop.d.ts.map +1 -0
  52. package/dist/stop.js +262 -0
  53. package/dist/stop.js.map +1 -0
  54. package/package.json +64 -4
  55. package/src/baseline.ts +72 -0
  56. package/src/check.ts +238 -0
  57. package/src/cluster.ts +830 -0
  58. package/src/errors.ts +208 -0
  59. package/src/evidence.ts +62 -0
  60. package/src/frontier.ts +782 -0
  61. package/src/gate.ts +358 -0
  62. package/src/index.ts +206 -0
  63. package/src/plan.ts +778 -0
  64. package/src/rand.ts +121 -0
  65. package/src/stats.ts +1579 -0
  66. package/src/stop.ts +452 -0
@@ -0,0 +1,782 @@
1
+ /**
2
+ * frontier.ts: what *is* certifiable at coding-agent prices, and how.
3
+ *
4
+ * ## Why this module exists
5
+ *
6
+ * At $1 a run a 200-case suite at a 15-point MDE is $1,320 a pull request, so
7
+ * peeksafe is not a per-PR gate for a coding-agent benchmark at that size. That
8
+ * is true and it is half an answer. The other half, the one a
9
+ * buyer actually needs, is **which configurations *are* affordable**, and
10
+ * nobody had drawn it.
11
+ *
12
+ * A configuration is a point in five dimensions:
13
+ *
14
+ * suite size m × MDE δ × design × screening × baseline runs n_b
15
+ *
16
+ * and it is usable only if it is *both* affordable and **certifiable**. Those
17
+ * are different constraints, and a plan that conflates them quotes the wrong
18
+ * numbers. Cheap is easy: run fewer cases. Cheap *and able to decide anything* is
19
+ * the hard part, because `evidenceCeilingLogE` says a case whose unpaired
20
+ * ceiling sits under the e-BH bar cannot be certified at any budget, and the
21
+ * bar `m/q` moves with the suite size, so shrinking the suite raises the
22
+ * ceiling's odds *and* lowers the bar at the same time. That interaction is not
23
+ * something you can eyeball.
24
+ *
25
+ * ## The cost model, and the term the plan was missing
26
+ *
27
+ * `plan.ts` prices an observation at one number, `costPerRunUsd`. That is wrong
28
+ * in two ways at coding-agent prices, and both matter:
29
+ *
30
+ * 1. **Grading is not free.** An LLM judge is a model call; a coding-agent
31
+ * grader is a test suite in a container. So
32
+ *
33
+ * cost(observation) = costPerRunUsd + costPerGradeUsd
34
+ *
35
+ * and the second term is the *only* one a cheap proxy grader can reduce.
36
+ * When `costPerGradeUsd` is 0, which is the default,
37
+ * matching this package's own free graders, a proxy screen saves exactly
38
+ * nothing, and this module says so instead of offering it as an economy.
39
+ *
40
+ * 2. **The baseline is not free either, and it is not amortised over
41
+ * infinity.** The README calls the baseline "amortised, you pay it once on
42
+ * main". At $0.002 a run that is a rounding error. At $1 a run, a 200-case
43
+ * suite with a 240-run baseline is 48,000 runs, **$48,000**, and spread
44
+ * over a hundred pull requests it is still $480 each, which is larger than
45
+ * everything else in the bill put together. The unpaired design's evidence
46
+ * ceiling is bought with baseline runs, so *the amortised baseline is the
47
+ * dominant cost of the unpaired design at coding-agent prices*, and the
48
+ * paired design's headline advantage is not variance reduction. It is that
49
+ * it does not need to buy a ceiling.
50
+ *
51
+ * ## What this module will not do
52
+ *
53
+ * It will not recommend a screened configuration whose **recall cost has not
54
+ * been measured**. Screening is the largest cost lever available and it is paid
55
+ * for in missed regressions, which the caller supplies as `screenRecall`
56
+ * against planted ground truth, and until someone has, the honest price of a
57
+ * screened plan is unknown rather than low.
58
+ */
59
+
60
+ import {
61
+ PeeksafeError,
62
+ requireErrorRates,
63
+ requireOpenProbability,
64
+ requireProbability,
65
+ } from "./errors.js";
66
+ import { DEFAULT_PLAN } from "./plan.js";
67
+ import {
68
+ betaQuantile,
69
+ ebhSoloThreshold,
70
+ evidenceCeilingLogE,
71
+ mcnemarSamplesForEvidence,
72
+ samplesForEvidence,
73
+ sprtExpectedN,
74
+ } from "./stats.js";
75
+
76
+ export type FrontierDesign = "unpaired" | "paired";
77
+
78
+ /**
79
+ * What the screening pass grades with.
80
+ * - `none` every case goes straight to the sequential test
81
+ * - `expensive` the screen pays the real grader for its k runs per case
82
+ * - `proxy` the screen ranks on a cheap deterministic grader, so its runs
83
+ * cost `costPerRunUsd` and no grade. Sound, a screen chooses
84
+ * where to spend and cannot falsely certify, but it ranks on an
85
+ * effect attenuated by Youden's J, so it costs
86
+ * power, and the power is what has to be measured.
87
+ */
88
+ export type FrontierScreen = "none" | "expensive" | "proxy";
89
+
90
+ /**
91
+ * Which bill the budget is checked against. Three, because they are three
92
+ * genuinely different questions, and answering one while quoting another
93
+ * misprices the plan.
94
+ *
95
+ * `'typical'`, a pull request that changed nothing. Almost every pull request
96
+ * is this one. Budget from it and a genuine regression overruns and comes
97
+ * back uncertified, which is a survivable failure.
98
+ *
99
+ * `'certify-all'`, every case regressed by exactly the MDE and every one had
100
+ * to be certified. It was once called "the ceiling", and
101
+ * it is **not** an upper bound: at a large MDE against a sharp baseline,
102
+ * certifying a real regression is *cheaper* than clearing a case that did not
103
+ * move, so this bill can come in under the typical one. The arithmetic was
104
+ * never wrong; the word "ceiling" was.
105
+ *
106
+ * `'ceiling'`, every case the screen kept runs to the per-case cap
107
+ * (`maxTrials` observations). The gate cannot spend more than that by
108
+ * construction, so nothing can overrun it. This is the basis to use when the
109
+ * gate must return a verdict rather than a deferral, and it changes which
110
+ * *design* wins: paired costs two runs an observation and loses the typical
111
+ * basis by construction, while on the ceiling basis, and whenever the
112
+ * baseline cannot be amortised, it wins outright.
113
+ */
114
+ export type FrontierBasis = "typical" | "certify-all" | "ceiling";
115
+
116
+ export interface FrontierAxes {
117
+ cases: number[];
118
+ /** in probability units, e.g. 0.15 for 15 points */
119
+ mdes: number[];
120
+ baselineRuns: number[];
121
+ designs: FrontierDesign[];
122
+ screens: FrontierScreen[];
123
+ /** screening runs per case; only consulted for screens other than `none` */
124
+ screenRuns: number[];
125
+ }
126
+
127
+ export const DEFAULT_AXES: FrontierAxes = {
128
+ cases: [10, 20, 50, 100, 200],
129
+ mdes: [0.1, 0.15, 0.25, 0.35],
130
+ baselineRuns: [30, 60, 120, 240, 480],
131
+ designs: ["unpaired", "paired"],
132
+ screens: ["none", "expensive", "proxy"],
133
+ screenRuns: [4, 8],
134
+ };
135
+
136
+ export interface FrontierConfig {
137
+ /** the budget one pull request may spend */
138
+ budgetUsd: number;
139
+ /** which bill the budget is checked against */
140
+ basis: FrontierBasis;
141
+ /** USD to execute the agent once on one case */
142
+ costPerRunUsd: number;
143
+ /**
144
+ * USD to *grade* one output with the real grader. Zero for this package's own
145
+ * graders; a model call or a container run for anything real. This is the
146
+ * only term a proxy grader can reduce.
147
+ */
148
+ costPerGradeUsd: number;
149
+ /** the pass rate a typical case sits at, used for every power calculation */
150
+ baselineRate: number;
151
+ /** suite-level false discovery rate */
152
+ fdr: number;
153
+ /** measured pair coupling in [0,1] */
154
+ pairCoupling: number;
155
+ /**
156
+ * How many pull requests one recorded baseline is spread over before it is
157
+ * re-recorded. The README's "amortised" claim is exactly this number, and it
158
+ * had never been written down.
159
+ */
160
+ amortisePrs: number;
161
+ /**
162
+ * Baseline runs per case the *paired* design needs. The paired e-value's null
163
+ * is a point mass, so the stored baseline is not part of its validity and
164
+ * does not set a ceiling, it only feeds the SPRT stopping rule and the
165
+ * screen. A short one is enough, and that asymmetry is most of why the paired
166
+ * design wins at these prices.
167
+ */
168
+ pairedBaselineRuns: number;
169
+ /** fraction of cases a screen carries through to the expensive test */
170
+ screenKeepFraction: number;
171
+ /** past this many runs for one case, call it unaffordable regardless of budget */
172
+ runsPerCaseCeiling: number;
173
+ /**
174
+ * Measured recall of the screen, per screen kind. `null` means nobody has
175
+ * measured it, and a configuration using that screen will be reported but
176
+ * never *recommended*.
177
+ */
178
+ screenRecall: { expensive: number | null; proxy: number | null };
179
+ /** free text saying where `screenRecall` came from; printed next to it */
180
+ screenRecallSource: string;
181
+ /** the sequential design being priced; match the stopping rule you actually run */
182
+ alpha: number;
183
+ beta: number;
184
+ minTrials: number;
185
+ maxTrials: number;
186
+ batchSize: number;
187
+ nullQuantile: number;
188
+ }
189
+
190
+ export const DEFAULT_FRONTIER: FrontierConfig = {
191
+ budgetUsd: 100,
192
+ basis: "typical",
193
+ costPerRunUsd: 1,
194
+ costPerGradeUsd: 0,
195
+ baselineRate: 0.85,
196
+ fdr: 0.05,
197
+ pairCoupling: DEFAULT_PLAN.pairCoupling,
198
+ amortisePrs: 100,
199
+ pairedBaselineRuns: 20,
200
+ screenKeepFraction: 0.15,
201
+ runsPerCaseCeiling: DEFAULT_PLAN.runsPerCaseCeiling,
202
+ screenRecall: { expensive: null, proxy: null },
203
+ screenRecallSource: "not measured",
204
+ alpha: DEFAULT_PLAN.alpha,
205
+ beta: DEFAULT_PLAN.beta,
206
+ minTrials: DEFAULT_PLAN.minTrials,
207
+ maxTrials: DEFAULT_PLAN.maxTrials,
208
+ batchSize: DEFAULT_PLAN.batchSize,
209
+ nullQuantile: DEFAULT_PLAN.nullQuantile,
210
+ };
211
+
212
+ /** A cost broken into the three things a pull request actually pays for. */
213
+ export interface FrontierCost {
214
+ screenRuns: number;
215
+ screenUsd: number;
216
+ testRuns: number;
217
+ testUsd: number;
218
+ /** baseline runs charged to *this* pull request after amortisation */
219
+ baselineRunsAmortised: number;
220
+ baselineUsd: number;
221
+ totalUsd: number;
222
+ }
223
+
224
+ export interface FrontierPoint {
225
+ cases: number;
226
+ mde: number;
227
+ baselineRuns: number;
228
+ design: FrontierDesign;
229
+ screen: FrontierScreen;
230
+ /** 0 when `screen` is `none` */
231
+ screenRunsPerCase: number;
232
+ /** how many cases the screen carries through */
233
+ keep: number;
234
+ /** e-BH solo bar, in logs */
235
+ barLogE: number;
236
+ /** unpaired evidence ceiling at this baseline size, in logs. −∞ is not used;
237
+ * the paired design has no ceiling and this field is `null` for it. */
238
+ ceilingLogE: number | null;
239
+ feasible: boolean;
240
+ /** why not, when not. Never empty when `feasible` is false. */
241
+ infeasibleBecause: string | null;
242
+ /** observations per case to certify a case that really regressed */
243
+ certifyObservations: number;
244
+ /** observations per case on a pull request that changed nothing */
245
+ typicalObservations: number;
246
+ /**
247
+ * The per-case run cap this configuration needs. A `shouldStop` `maxTrials`
248
+ * below it stops cases short with reason `budget`, however much money is left.
249
+ */
250
+ requiresMaxRuns: number;
251
+ /** true when `requiresMaxRuns` exceeds the gate's configured cap */
252
+ exceedsGateCap: boolean;
253
+ /** a pull request that changed nothing, the number to budget from */
254
+ typical: FrontierCost;
255
+ /** every case regressed by exactly the MDE and had to be certified. A scenario, not a bound. */
256
+ certifyAll: FrontierCost;
257
+ /** every kept case ran to the per-case cap, the bill nothing can exceed */
258
+ ceiling: FrontierCost;
259
+ /** whichever of the three the configured `basis` selects, what the budget is checked against */
260
+ basisCostUsd: number;
261
+ withinBudget: boolean;
262
+ /** measured recall of this configuration's screen; null when unmeasured */
263
+ screenRecall: number | null;
264
+ /** true when this configuration may be *recommended*, not merely reported */
265
+ recommendable: boolean;
266
+ /** why it is reported but not recommendable */
267
+ caveat: string | null;
268
+ }
269
+
270
+ const RUNS_PER_OBS: Record<FrontierDesign, number> = { unpaired: 1, paired: 2 };
271
+
272
+ /** $1.00, but $0.0021 rather than $0.00, a per-run price rounds to nothing. */
273
+ export const fmtRate = (x: number): string =>
274
+ !Number.isFinite(x)
275
+ ? Number.isNaN(x)
276
+ ? "$?"
277
+ : "$∞"
278
+ : x >= 0.01 || x === 0
279
+ ? `$${x.toFixed(2)}`
280
+ : `$${x.toPrecision(2)}`;
281
+
282
+ /** Cost of `runs` runs, all of them graded by the real grader. */
283
+ const graded = (runs: number, cfg: FrontierConfig): number =>
284
+ runs * (cfg.costPerRunUsd + cfg.costPerGradeUsd);
285
+
286
+ /**
287
+ * Observations per case on a pull request where nothing moved, clamped onto the
288
+ * gate's own batch grid.
289
+ */
290
+ export function typicalObservationsPerCase(
291
+ rate: number,
292
+ mde: number,
293
+ cfg: FrontierConfig,
294
+ baselineRuns: number,
295
+ ): number {
296
+ // `makePlan` reaches this quantile through `baselineNullRate`, which refuses
297
+ // one outside (0,1). This handed it to `betaQuantile` directly, which answers
298
+ // 0 for a quantile at or below 0, 1 at or above 1, and about 0 for NaN, so the
299
+ // frontier priced the typical bill against a null rate nobody chose.
300
+ requireOpenProbability(cfg.nullQuantile, "nullQuantile", "typicalObservationsPerCase");
301
+ const s = Math.round(rate * baselineRuns);
302
+ const p0 = betaQuantile(1 + s, 1 + baselineRuns - s, cfg.nullQuantile);
303
+ const p1 = Math.max(0.005, p0 - mde);
304
+ const raw = sprtExpectedN(rate, p0, p1, cfg.alpha, cfg.beta);
305
+ const n =
306
+ Number.isFinite(raw) && raw > 0
307
+ ? Math.min(cfg.maxTrials, Math.max(cfg.minTrials, Math.ceil(raw)))
308
+ : cfg.maxTrials;
309
+ const batched =
310
+ cfg.minTrials + Math.ceil(Math.max(0, n - cfg.minTrials) / cfg.batchSize) * cfg.batchSize;
311
+ return Math.min(cfg.maxTrials, batched);
312
+ }
313
+
314
+ export function evaluatePoint(
315
+ cases: number,
316
+ mde: number,
317
+ baselineRuns: number,
318
+ design: FrontierDesign,
319
+ screen: FrontierScreen,
320
+ screenRunsPerCase: number,
321
+ cfg: FrontierConfig,
322
+ ): FrontierPoint {
323
+ // Strictly open: an MDE of 0 means "detect a zero-point drop", which every
324
+ // design correctly refuses, but it refuses with a message about the evidence
325
+ // ceiling, which sends the reader looking for a baseline problem that is not
326
+ // there. Same for a baseline rate of 0 or 1.
327
+ requireOpenProbability(mde, "mde", "evaluatePoint");
328
+ requireOpenProbability(cfg.baselineRate, "baselineRate", "evaluatePoint");
329
+ // `makePlan` refuses these two and this did not, so one options object was a
330
+ // refusal through the planner and a priced frontier through here. Both end up
331
+ // in `sprtExpectedN`, which answers NaN or Infinity outside (0,1), and
332
+ // `typicalObservationsPerCase` reads either as "cannot price this" and falls
333
+ // back to the run ceiling.
334
+ requireErrorRates(cfg.alpha, cfg.beta, "evaluatePoint");
335
+ requireProbability(cfg.pairCoupling, "pairCoupling", "evaluatePoint");
336
+ requireOpenProbability(cfg.nullQuantile, "nullQuantile", "evaluatePoint");
337
+ if (!Number.isInteger(cases) || cases < 1) {
338
+ throw new PeeksafeError(
339
+ "PEEKSAFE_E_CONFIG",
340
+ `frontier: cases must be a positive integer, got ${cases}`,
341
+ {
342
+ detail: { cases },
343
+ },
344
+ );
345
+ }
346
+ if (!Number.isInteger(baselineRuns) || baselineRuns < 1) {
347
+ throw new PeeksafeError(
348
+ "PEEKSAFE_E_CONFIG",
349
+ `frontier: baselineRuns must be a positive integer, got ${baselineRuns}`,
350
+ {
351
+ detail: { baselineRuns },
352
+ },
353
+ );
354
+ }
355
+ if (!Number.isInteger(cfg.maxTrials) || cfg.maxTrials < 1 || cfg.maxTrials < cfg.minTrials) {
356
+ throw new PeeksafeError(
357
+ "PEEKSAFE_E_CONFIG",
358
+ `frontier: maxTrials must be a positive integer ≥ minTrials, got ${cfg.maxTrials} vs ${cfg.minTrials}`,
359
+ {
360
+ detail: { maxTrials: cfg.maxTrials, minTrials: cfg.minTrials },
361
+ hint: "the ceiling bill is priced at this cap; a cap of zero prices a gate that never runs",
362
+ },
363
+ );
364
+ }
365
+ if (screen !== "none" && (!Number.isInteger(screenRunsPerCase) || screenRunsPerCase < 1)) {
366
+ throw new PeeksafeError(
367
+ "PEEKSAFE_E_CONFIG",
368
+ `frontier: a ${screen} screen needs at least one run per case, got ${screenRunsPerCase}`,
369
+ {
370
+ detail: { screen, screenRunsPerCase },
371
+ },
372
+ );
373
+ }
374
+
375
+ const rate = cfg.baselineRate;
376
+ const barLogE = Math.log(ebhSoloThreshold(cases, cfg.fdr));
377
+ // The baseline this design actually needs. The paired design's null is exact,
378
+ // so its stored baseline only tunes the stopping rule: a short one suffices,
379
+ // and pretending it needs the same n_b as the unpaired design would price a
380
+ // ceiling it never buys.
381
+ const effectiveBaselineRuns = design === "paired" ? cfg.pairedBaselineRuns : baselineRuns;
382
+ const s = Math.round(rate * effectiveBaselineRuns);
383
+
384
+ let ceilingLogE: number | null = null;
385
+ let certifyObservations: number;
386
+ let infeasibleBecause: string | null = null;
387
+
388
+ if (rate <= mde) {
389
+ infeasibleBecause =
390
+ `a case at ${(rate * 100).toFixed(0)}% cannot lose ${(mde * 100).toFixed(0)} points, ` +
391
+ "the effect is arithmetically impossible, not merely expensive";
392
+ certifyObservations = Infinity;
393
+ } else if (design === "unpaired") {
394
+ const pTrue = Math.max(1e-6, Math.min(1 - 1e-6, rate - mde));
395
+ ceilingLogE = evidenceCeilingLogE(pTrue, s, effectiveBaselineRuns, mde);
396
+ certifyObservations = samplesForEvidence(
397
+ pTrue,
398
+ s,
399
+ effectiveBaselineRuns,
400
+ mde,
401
+ barLogE,
402
+ cfg.runsPerCaseCeiling * 8,
403
+ );
404
+ if (!Number.isFinite(certifyObservations)) {
405
+ infeasibleBecause =
406
+ `unpaired evidence ceiling e^${ceilingLogE.toFixed(1)} is below the bar e^${barLogE.toFixed(1)} ` +
407
+ `at a ${effectiveBaselineRuns}-run baseline, no candidate budget certifies it`;
408
+ }
409
+ } else {
410
+ const pairs = mcnemarSamplesForEvidence(
411
+ rate,
412
+ mde,
413
+ cfg.pairCoupling,
414
+ barLogE,
415
+ cfg.runsPerCaseCeiling * 8,
416
+ );
417
+ certifyObservations = pairs;
418
+ if (!Number.isFinite(pairs)) {
419
+ infeasibleBecause = `paired: no number of pairs reaches the bar at ρ = ${cfg.pairCoupling.toFixed(2)}`;
420
+ }
421
+ }
422
+
423
+ const runsPerObs = RUNS_PER_OBS[design];
424
+ if (infeasibleBecause === null && certifyObservations * runsPerObs > cfg.runsPerCaseCeiling) {
425
+ infeasibleBecause =
426
+ `${Math.ceil(certifyObservations * runsPerObs)} runs for one case, past the ` +
427
+ `${cfg.runsPerCaseCeiling}-run per-case ceiling`;
428
+ }
429
+ const feasible = infeasibleBecause === null;
430
+
431
+ const typicalObservations = typicalObservationsPerCase(rate, mde, cfg, effectiveBaselineRuns);
432
+ const keep = screen === "none" ? cases : Math.max(1, Math.ceil(cases * cfg.screenKeepFraction));
433
+
434
+ // Screening runs are graded by whichever grader the screen uses. A proxy
435
+ // screen still *executes* the agent, it only skips the grade, so it saves
436
+ // `costPerGradeUsd` per screening run and not one cent more.
437
+ //
438
+ // And a screening *observation* costs `runsPerObs` runs, exactly as a test
439
+ // observation does, since a paired screen runs both arms too. Charging it one
440
+ // run an observation would understate it by 2×, in the direction that makes
441
+ // pairing look cheaper.
442
+ const screenRuns = screen === "none" ? 0 : cases * screenRunsPerCase * runsPerObs;
443
+ const screenUsd =
444
+ screen === "none"
445
+ ? 0
446
+ : screen === "proxy"
447
+ ? screenRuns * cfg.costPerRunUsd
448
+ : graded(screenRuns, cfg);
449
+
450
+ // The baseline. Unpaired buys its ceiling here; paired does not.
451
+ const baselineRunsTotal = cases * effectiveBaselineRuns;
452
+ const baselineRunsAmortised = baselineRunsTotal / Math.max(1, cfg.amortisePrs);
453
+ const baselineUsd = graded(baselineRunsAmortised, cfg);
454
+
455
+ const costFor = (obsPerCase: number): FrontierCost => {
456
+ const testRuns = Number.isFinite(obsPerCase) ? keep * obsPerCase * runsPerObs : Infinity;
457
+ const testUsd = Number.isFinite(testRuns) ? graded(testRuns, cfg) : Infinity;
458
+ return {
459
+ screenRuns,
460
+ screenUsd,
461
+ testRuns,
462
+ testUsd,
463
+ baselineRunsAmortised,
464
+ baselineUsd,
465
+ totalUsd: screenUsd + testUsd + baselineUsd,
466
+ };
467
+ };
468
+ const typical = costFor(typicalObservations);
469
+ const certifyAll = costFor(certifyObservations);
470
+ // The per-case cap this configuration would have to run under.
471
+ //
472
+ // `samplesForEvidence` can answer more runs than `cfg.maxTrials`, and a plan
473
+ // quoting those prices a design the configured cap never executes. So the cap
474
+ // is whatever this configuration *needs*, and `requiresMaxRuns` says so.
475
+ const capObservations = Number.isFinite(certifyObservations)
476
+ ? Math.max(cfg.maxTrials, Math.ceil(certifyObservations))
477
+ : cfg.maxTrials;
478
+ // The gate stops paying for a case at that cap, so this is a real upper
479
+ // bound rather than a scenario, and scenarios do not bound anything.
480
+ const ceiling = costFor(capObservations);
481
+
482
+ const screenRecall =
483
+ screen === "none"
484
+ ? 1
485
+ : screen === "proxy"
486
+ ? cfg.screenRecall.proxy
487
+ : cfg.screenRecall.expensive;
488
+
489
+ // A lookup, not a `?:` chain with `typical` on the else branch. A typo'd
490
+ // basis silently selecting the cheapest bill is precisely the
491
+ // malformed-input-becomes-the-most-permissive-result failure this codebase
492
+ // keeps finding in itself.
493
+ const BILLS: Record<FrontierBasis, FrontierCost> = {
494
+ typical,
495
+ "certify-all": certifyAll,
496
+ ceiling,
497
+ };
498
+ const basisCost = BILLS[cfg.basis];
499
+ if (basisCost === undefined) {
500
+ throw new PeeksafeError(
501
+ "PEEKSAFE_E_CONFIG",
502
+ `frontier: basis must be one of ${Object.keys(BILLS).join(", ")}, got "${String(cfg.basis)}"`,
503
+ {
504
+ detail: { basis: cfg.basis },
505
+ hint: "an unrecognised basis silently defaulting to the cheaper bill is how a budget becomes fiction",
506
+ },
507
+ );
508
+ }
509
+ const withinBudget = feasible && basisCost.totalUsd <= cfg.budgetUsd;
510
+
511
+ // Reportable and recommendable are different. A screen whose recall nobody
512
+ // measured is cheap in a way we cannot price, and a proxy screen at zero
513
+ // grading cost is cheaper than nothing at all, which is to say, it is not.
514
+ let caveat: string | null = null;
515
+ if (screen !== "none" && screenRecall === null) {
516
+ caveat = `the ${screen} screen's recall cost is unmeasured, it drops regressions at an unknown rate`;
517
+ } else if (screen === "proxy" && cfg.costPerGradeUsd <= 0) {
518
+ caveat =
519
+ "a proxy screen saves only grading cost, and grading here is free, it buys nothing and costs recall";
520
+ }
521
+
522
+ return {
523
+ cases,
524
+ mde,
525
+ baselineRuns,
526
+ design,
527
+ screen,
528
+ screenRunsPerCase: screen === "none" ? 0 : screenRunsPerCase,
529
+ keep,
530
+ barLogE,
531
+ ceilingLogE,
532
+ feasible,
533
+ infeasibleBecause,
534
+ certifyObservations,
535
+ typicalObservations,
536
+ requiresMaxRuns: capObservations,
537
+ exceedsGateCap: capObservations > cfg.maxTrials,
538
+ typical,
539
+ certifyAll,
540
+ ceiling,
541
+ basisCostUsd: basisCost.totalUsd,
542
+ withinBudget,
543
+ screenRecall,
544
+ recommendable: withinBudget && caveat === null,
545
+ caveat,
546
+ };
547
+ }
548
+
549
+ /** Every point in the swept space, feasible or not. */
550
+ export function enumerateFrontier(
551
+ cfg: FrontierConfig,
552
+ axes: FrontierAxes = DEFAULT_AXES,
553
+ ): FrontierPoint[] {
554
+ if (!(cfg.budgetUsd >= 0) || !(cfg.costPerRunUsd >= 0) || !(cfg.costPerGradeUsd >= 0)) {
555
+ throw new PeeksafeError(
556
+ "PEEKSAFE_E_CONFIG",
557
+ "frontier: budget and costs must be ≥ 0 and not NaN",
558
+ {
559
+ detail: {
560
+ budgetUsd: cfg.budgetUsd,
561
+ costPerRunUsd: cfg.costPerRunUsd,
562
+ costPerGradeUsd: cfg.costPerGradeUsd,
563
+ },
564
+ },
565
+ );
566
+ }
567
+ if (!(cfg.screenKeepFraction > 0) || !(cfg.screenKeepFraction <= 1)) {
568
+ throw new PeeksafeError(
569
+ "PEEKSAFE_E_CONFIG",
570
+ `frontier: screenKeepFraction must be in (0,1], got ${cfg.screenKeepFraction}`,
571
+ {
572
+ detail: { screenKeepFraction: cfg.screenKeepFraction },
573
+ },
574
+ );
575
+ }
576
+ if (!Number.isInteger(cfg.amortisePrs) || cfg.amortisePrs < 1) {
577
+ throw new PeeksafeError(
578
+ "PEEKSAFE_E_CONFIG",
579
+ `frontier: amortisePrs must be a positive integer, got ${cfg.amortisePrs}`,
580
+ {
581
+ detail: { amortisePrs: cfg.amortisePrs },
582
+ hint: 'a baseline spread over "infinity" pull requests is how the baseline cost disappears from a plan',
583
+ },
584
+ );
585
+ }
586
+ for (const [name, xs] of Object.entries(axes) as Array<[string, unknown[]]>) {
587
+ if (!Array.isArray(xs) || xs.length === 0) {
588
+ throw new PeeksafeError(
589
+ "PEEKSAFE_E_CONFIG",
590
+ `frontier: axis "${name}" is empty, nothing to sweep`,
591
+ {
592
+ detail: { axis: name },
593
+ },
594
+ );
595
+ }
596
+ }
597
+ const out: FrontierPoint[] = [];
598
+ for (const m of axes.cases) {
599
+ for (const mde of axes.mdes) {
600
+ for (const design of axes.designs) {
601
+ // The baseline axis is real for the unpaired design and a fiction for
602
+ // the paired one, which uses `pairedBaselineRuns` whatever this says.
603
+ // Sweeping it anyway would emit five identical paired rows and make the
604
+ // frontier look like it had five times the evidence it has.
605
+ const baselines = design === "paired" ? [cfg.pairedBaselineRuns] : axes.baselineRuns;
606
+ for (const nb of baselines) {
607
+ for (const screen of axes.screens) {
608
+ const ks = screen === "none" ? [0] : axes.screenRuns;
609
+ for (const k of ks) out.push(evaluatePoint(m, mde, nb, design, screen, k, cfg));
610
+ }
611
+ }
612
+ }
613
+ }
614
+ }
615
+ return out;
616
+ }
617
+
618
+ export interface FrontierCell {
619
+ cases: number;
620
+ mde: number;
621
+ /** the cheapest recommendable configuration that certifies this cell */
622
+ best: FrontierPoint;
623
+ /** the cheapest configuration ignoring the recommendable rule, when it differs */
624
+ cheapestReported: FrontierPoint | null;
625
+ }
626
+
627
+ export interface FrontierResult {
628
+ config: FrontierConfig;
629
+ axes: FrontierAxes;
630
+ /** everything swept */
631
+ points: FrontierPoint[];
632
+ /** feasible, within budget, and recommendable */
633
+ affordable: FrontierPoint[];
634
+ /**
635
+ * The frontier proper: the (cases, mde) cells that are achievable within
636
+ * budget and not dominated by another achievable cell, i.e. no other cell
637
+ * has at least as many cases *and* an MDE at least as tight.
638
+ */
639
+ frontier: FrontierCell[];
640
+ /** cheapest feasible configuration overall, whether or not it fits */
641
+ cheapestFeasible: FrontierPoint | null;
642
+ /** the smallest budget at which anything at all becomes recommendable */
643
+ minimumViableBudgetUsd: number | null;
644
+ headline: string;
645
+ }
646
+
647
+ /**
648
+ * A cell (m, δ) dominates (m', δ') when it covers at least as many cases and
649
+ * detects at least as small a drop, and is strictly better on one of them. The
650
+ * frontier is what survives.
651
+ */
652
+ function paretoCells(cells: FrontierCell[]): FrontierCell[] {
653
+ return cells.filter(
654
+ (a) =>
655
+ !cells.some(
656
+ (b) =>
657
+ b !== a && b.cases >= a.cases && b.mde <= a.mde && (b.cases > a.cases || b.mde < a.mde),
658
+ ),
659
+ );
660
+ }
661
+
662
+ export function computeFrontier(
663
+ cfg: FrontierConfig,
664
+ axes: FrontierAxes = DEFAULT_AXES,
665
+ ): FrontierResult {
666
+ const points = enumerateFrontier(cfg, axes);
667
+ const feasible = points.filter((p) => p.feasible);
668
+ const affordable = points.filter((p) => p.recommendable);
669
+
670
+ const cheaper = (a: FrontierPoint, b: FrontierPoint) =>
671
+ a.basisCostUsd <= b.basisCostUsd ? a : b;
672
+ const byCell = new Map<string, FrontierCell>();
673
+ for (const p of affordable) {
674
+ const key = `${p.cases}|${p.mde}`;
675
+ const cur = byCell.get(key);
676
+ if (!cur) byCell.set(key, { cases: p.cases, mde: p.mde, best: p, cheapestReported: null });
677
+ else cur.best = cheaper(cur.best, p);
678
+ }
679
+ // For each cell on the frontier, also name the cheapest *reported* option, so
680
+ // an operator can see what the "unmeasured recall" rule cost them.
681
+ for (const cell of byCell.values()) {
682
+ const reported = points
683
+ .filter((p) => p.cases === cell.cases && p.mde === cell.mde && p.withinBudget)
684
+ .reduce<FrontierPoint | null>((best, p) => (best === null ? p : cheaper(best, p)), null);
685
+ cell.cheapestReported =
686
+ reported && reported.basisCostUsd < cell.best.basisCostUsd ? reported : null;
687
+ }
688
+
689
+ const frontier = paretoCells([...byCell.values()]).sort(
690
+ (a, b) => b.cases - a.cases || a.mde - b.mde,
691
+ );
692
+
693
+ const cheapestFeasible = feasible.reduce<FrontierPoint | null>(
694
+ (best, p) => (best === null || p.basisCostUsd < best.basisCostUsd ? p : best),
695
+ null,
696
+ );
697
+ // The smallest budget at which *something* becomes recommendable. `caveat`
698
+ // is exactly the recommendable rule minus the budget test, so reusing it here
699
+ // means the headline and the recommendation cannot disagree about what counts.
700
+ const cleanFeasible = feasible.filter((p) => p.caveat === null);
701
+ const minimumViableBudgetUsd =
702
+ cleanFeasible.length === 0 ? null : Math.min(...cleanFeasible.map((p) => p.basisCostUsd));
703
+
704
+ const headline =
705
+ frontier.length === 0
706
+ ? minimumViableBudgetUsd === null
707
+ ? `nothing in the swept space is certifiable at ${(cfg.baselineRate * 100).toFixed(0)}% baseline rate, ` +
708
+ "every configuration is either arithmetically impossible or past the per-case run ceiling"
709
+ : `nothing fits $${cfg.budgetUsd.toFixed(2)} at ${fmtRate(cfg.costPerRunUsd)}/run on the ${cfg.basis} bill. ` +
710
+ `The cheapest certifiable configuration is $${minimumViableBudgetUsd.toFixed(2)} per pull request` +
711
+ (cheapestFeasible
712
+ ? `, ${cheapestFeasible.cases} cases at ${(cheapestFeasible.mde * 100).toFixed(0)} points, ${cheapestFeasible.design}.`
713
+ : ".")
714
+ : (() => {
715
+ const widest = frontier[0]!;
716
+ const tightest = [...frontier].sort((a, b) => a.mde - b.mde)[0]!;
717
+ return (
718
+ `at ${fmtRate(cfg.costPerRunUsd)}/run and $${cfg.budgetUsd.toFixed(2)} a pull request (${cfg.basis} bill) you can certify ` +
719
+ `${widest.cases} cases at ${(widest.mde * 100).toFixed(0)} points ` +
720
+ `($${widest.best.basisCostUsd.toFixed(2)}, ${widest.best.design})` +
721
+ (tightest !== widest
722
+ ? `, or ${tightest.cases} cases at ${(tightest.mde * 100).toFixed(0)} points ` +
723
+ `($${tightest.best.basisCostUsd.toFixed(2)}, ${tightest.best.design})`
724
+ : "") +
725
+ "."
726
+ );
727
+ })();
728
+
729
+ return {
730
+ config: cfg,
731
+ axes,
732
+ points,
733
+ affordable,
734
+ frontier,
735
+ cheapestFeasible,
736
+ minimumViableBudgetUsd,
737
+ headline,
738
+ };
739
+ }
740
+
741
+ /**
742
+ * Where the money goes, for one configuration. Printed under the frontier
743
+ * because the shares are the actual finding: at coding-agent prices the
744
+ * unpaired design's amortised baseline is usually the largest line, and it is
745
+ * the one the README used to call free.
746
+ */
747
+ export function costShares(
748
+ p: FrontierPoint,
749
+ basis: FrontierBasis = "typical",
750
+ ): { screen: number; test: number; baseline: number } {
751
+ // A lookup and a refusal, for the same reason `evaluatePoint` uses one: this
752
+ // was a `?:` chain with `p.typical` on the else branch, so any basis it did
753
+ // not recognise was reported as the typical bill. `FrontierPoint` names the
754
+ // field `certifyAll` and the basis `certify-all`, so reaching for the field
755
+ // name is the obvious slip, and it put the baseline at 6.6% of the money
756
+ // where the certify-all bill puts it at 1.1%.
757
+ const BILLS: Record<FrontierBasis, FrontierCost> = {
758
+ typical: p.typical,
759
+ "certify-all": p.certifyAll,
760
+ ceiling: p.ceiling,
761
+ };
762
+ // `hasOwn` rather than an `undefined` check: `BILLS['toString']` is inherited
763
+ // from Object.prototype, so it is not undefined and would slip through one.
764
+ if (!Object.hasOwn(BILLS, basis)) {
765
+ throw new PeeksafeError(
766
+ "PEEKSAFE_E_CONFIG",
767
+ `costShares: basis must be one of ${Object.keys(BILLS).join(", ")}, got "${String(basis)}"`,
768
+ {
769
+ detail: { basis },
770
+ hint: "an unrecognised basis silently reporting the typical bill is how a cost breakdown describes a different plan than the one you asked about",
771
+ },
772
+ );
773
+ }
774
+ const cost = BILLS[basis];
775
+ const t = cost.totalUsd;
776
+ if (!(t > 0) || !Number.isFinite(t)) return { screen: 0, test: 0, baseline: 0 };
777
+ return {
778
+ screen: cost.screenUsd / t,
779
+ test: cost.testUsd / t,
780
+ baseline: cost.baselineUsd / t,
781
+ };
782
+ }