@mark1russell7/rigor-bench 0.2.13 → 0.2.15

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/build/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { a as checkPairedTime, i as caseRatios, n as CaseRatio, o as firstArm, r as PairedTime, t as Arm } from "./paired.js";
2
- import { BootstrapOptions, Comparison, Interval } from "@mark1russell7/rigor-statistics";
2
+ import { BootstrapOptions, Comparison as Comparison$1, Interval } from "@mark1russell7/rigor-statistics";
3
3
  /** One value of one build on one case. The value is finite and 0 or more. */
4
4
  interface BudgetRound {
5
5
  /** The name of the case: one input of the bench. */
@@ -124,239 +124,6 @@ export declare function budgetLookSpend(looks: readonly BudgetLook[]): number;
124
124
  * - The field `fails` is true only for the outcome `beyond`. Tell a final `cannot decide` to the reader of the run.
125
125
  */
126
126
  export declare function budgetLooksVerdict(rounds: readonly BudgetRound[], aa: readonly BudgetRound[], options: BudgetLooksOptions): BudgetLooksVerdict;
127
- /** One time of the control in one group. */
128
- interface ControlRow {
129
- /** The name of the group: a run, or a shard of one run. */
130
- readonly group: string;
131
- /** The name of a class of work. The same key in two groups names equal work, so a ratio of the two measures the load. */
132
- readonly key: string;
133
- /** The time. It is finite and more than 0. */
134
- readonly value: number;
135
- /** This field is true when the run stopped the case at `value`. Thus the real time is at least `value`. */
136
- readonly censored?: boolean;
137
- }
138
- /** The options of `controlFactor`. */
139
- interface ControlOptions {
140
- /** The group that the factors compare with. Without it, the base of each key is the median of that key over the groups. */
141
- readonly base?: string;
142
- /** The least number of keys in a factor. A group with fewer keys has no factor. The default is 5. */
143
- readonly minPairs?: number;
144
- }
145
- /** The counts of one group, with or without a factor. */
146
- interface GroupCounts {
147
- readonly group: string;
148
- /** The number of keys that the factor reads. */
149
- readonly pairs: number;
150
- /** The number of keys that this function left out because a time of the key was censored. The factor reads low when this count is not 0. */
151
- readonly censored: number;
152
- /** The number of keys of this group that have no time to compare with, so no ratio reads them. */
153
- readonly unshared: number;
154
- }
155
- /** The factor of one group. */
156
- interface MeasuredFactor extends GroupCounts {
157
- /** The median ratio of the times of this group over the base. A factor of 1.6 means that this group took 1.6 times as long. */
158
- readonly factor: number;
159
- /** The quartiles of the ratios. A wide spread means that one factor does not explain the load. */
160
- readonly low: number;
161
- readonly high: number;
162
- }
163
- /** A group with too few usable keys. It has no factor, and the other groups keep theirs. */
164
- interface NoFactor extends GroupCounts {
165
- readonly factor: undefined;
166
- /** The reason that this group has no factor. */
167
- readonly reason: string;
168
- }
169
- /** The result of one group. Read `factor` first: a group with too few usable keys has no factor. */
170
- type GroupFactor = MeasuredFactor | NoFactor;
171
- /** The factors of a run, with the base that they use. */
172
- interface ControlFactors {
173
- /** The base group, or undefined when the base of each key is its median over the groups. */
174
- readonly base: string | undefined;
175
- readonly factors: readonly GroupFactor[];
176
- }
177
- /**
178
- * This function gives the load factor of each group from the times of a control.
179
- *
180
- * With `base`, a factor compares the keys that a group shares with that group. Without it, a factor compares each time with the median of its key over the groups.
181
- * A key names a class of work, so equal keys in two groups mean equal work. Each group has at most one row for a key.
182
- *
183
- * A censored time is only a lower limit, so no ratio reads it, and the result counts those keys. A run stops its slowest cases, so a factor reads low when `censored` is not 0.
184
- *
185
- * A group with too few usable keys gets an entry with no factor and its reason, so the other groups keep their factors. This function refuses a result where no group has a factor.
186
- */
187
- export declare function controlFactor(rows: readonly ControlRow[], options?: ControlOptions): ControlFactors;
188
- /** The format name of a ladder. It changes when a reader of an older form cannot read the data. */
189
- export declare const LADDER_FORMAT = "rigor-ladder/1";
190
- /** One dimension of a ladder, for example tenants or nodes. */
191
- interface LadderDimension {
192
- readonly name: string;
193
- /** What one unit of the dimension is, in plain words. */
194
- readonly describe: string;
195
- }
196
- /** A budget on the median of each case, for example the time of a read. A record gives rounds and an A/A arm. */
197
- interface MedianBudget {
198
- readonly kind: "median";
199
- readonly measure: string;
200
- /** The unit of the limit and of the values. */
201
- readonly unit: string;
202
- /** The largest median that the budget permits. */
203
- readonly limit: number;
204
- /** The largest difference between the medians of the two arms. A larger difference makes the run too noisy. */
205
- readonly maxDifference: number;
206
- /** The level of the interval of each median. The default is 0.95. */
207
- readonly caseLevel?: number;
208
- }
209
- /** A budget on the share of failed trials, for example failed requests. A record gives failures and trials. */
210
- interface RateBudget {
211
- readonly kind: "rate";
212
- readonly measure: string;
213
- /** The largest share of failures that the budget permits, from 0 to 1. */
214
- readonly limit: number;
215
- }
216
- /** A budget on the largest value of a set of drills, for example the writes that a restore lost. One bad drill is `beyond`. */
217
- interface WorstBudget {
218
- readonly kind: "worst";
219
- readonly measure: string;
220
- readonly unit: string;
221
- /** The largest value that the budget permits in any drill. */
222
- readonly limit: number;
223
- /** The number of drills that a verdict needs, 1 or more. With fewer, the budget is `cannot decide`. */
224
- readonly minDrills: number;
225
- }
226
- /**
227
- * A budget on a high quantile, for example the p99 of a read. A record gives the values. The verdict is the distribution-free
228
- * interval of the quantile against the limit. A p99 needs 368 independent values at the level 0.95: refer to `quantileSamples`.
229
- * Successive times of one run can follow each other. Space them apart, or give one value for each run.
230
- *
231
- * The evidence can also hold `censored`: a lower bound for each arrival with no reply, and for each arrival that was not
232
- * sent. The bound is the time that the arrival waited. The true value is that bound or more, with no upper limit. Thus the
233
- * low end of the interval reads the bounds, and the high end reads each censored value as `Infinity`. A `beyond` stays
234
- * provable from the bounds alone. A `within` needs real replies up to the upper rank of the interval.
235
- */
236
- interface QuantileBudget {
237
- readonly kind: "quantile";
238
- readonly measure: string;
239
- /** The unit of the limit and of the values. */
240
- readonly unit: string;
241
- /** The quantile, more than 0 and less than 1, for example 0.99. */
242
- readonly quantile: number;
243
- /** The largest quantile that the budget permits. */
244
- readonly limit: number;
245
- /** The level of the interval. The default is 0.95. */
246
- readonly level?: number;
247
- }
248
- /** One budget of a rung. */
249
- type RungBudget = MedianBudget | QuantileBudget | RateBudget | WorstBudget;
250
- /** One rung of a ladder. */
251
- interface Rung {
252
- /** The name of the rung, unique in the ladder. */
253
- readonly name: string;
254
- /** The size of the rung in each dimension that it names. */
255
- readonly at: Readonly<Record<string, number>>;
256
- readonly budgets: readonly RungBudget[];
257
- /** The name of the automatic test that holds the rung. */
258
- readonly test: string;
259
- /** True when a gate holds the rung: the verdict fails when the rung is not `within`. */
260
- readonly locked?: boolean;
261
- }
262
- /** The ladder of one subject. The rungs go from the smallest to the largest. */
263
- interface Ladder {
264
- readonly format: typeof LADDER_FORMAT;
265
- /** The product or the service that the ladder is for. */
266
- readonly subject: string;
267
- readonly dimensions: readonly LadderDimension[];
268
- readonly rungs: readonly Rung[];
269
- }
270
- /** The measured evidence for one budget. Its `kind` is the kind of the budget. */
271
- type RungEvidence = {
272
- readonly kind: "median";
273
- readonly measure: string;
274
- readonly rounds: readonly BudgetRound[];
275
- readonly aa: readonly BudgetRound[];
276
- } | {
277
- readonly kind: "quantile";
278
- readonly measure: string;
279
- readonly values: readonly number[];
280
- readonly censored?: readonly number[];
281
- } | {
282
- readonly kind: "rate";
283
- readonly measure: string;
284
- readonly failures: number;
285
- readonly trials: number;
286
- } | {
287
- readonly kind: "worst";
288
- readonly measure: string;
289
- readonly values: readonly number[];
290
- };
291
- /** One run of the test of a rung. */
292
- interface RungRecord {
293
- /** The name of the rung. */
294
- readonly rung: string;
295
- /** The commit that the run measured. */
296
- readonly commit: string;
297
- /** The time of the run, as an ISO 8601 string. */
298
- readonly at: string;
299
- /** What the run did for real, for example "2 processes" or "a restore from a real backup". */
300
- readonly real: readonly string[];
301
- /** What the run made up, for example "90 % of the tenants as data at rest". An empty list states that nothing was synthetic. */
302
- readonly synthetic: readonly string[];
303
- readonly evidence: readonly RungEvidence[];
304
- }
305
- /** The verdict of one budget of a rung. */
306
- interface BudgetResult {
307
- readonly measure: string;
308
- readonly outcome: BudgetOutcome;
309
- /** The reason of the outcome, in one sentence, with the numbers. */
310
- readonly reason: string;
311
- }
312
- /** The verdict of one rung. */
313
- interface RungVerdict {
314
- readonly rung: string;
315
- readonly test: string;
316
- readonly locked: boolean;
317
- readonly outcome: BudgetOutcome;
318
- /** The reason of the outcome, in one sentence. */
319
- readonly reason: string;
320
- readonly budgets: readonly BudgetResult[];
321
- /** The commit of the record, or undefined when the rung has no record. */
322
- readonly commit: string | undefined;
323
- readonly real: readonly string[];
324
- readonly synthetic: readonly string[];
325
- }
326
- /** The verdict of a ladder. */
327
- interface LadderVerdict {
328
- readonly subject: string;
329
- /** The highest rung with each rung up to it `within`, or undefined when the first rung is not `within`. */
330
- readonly held: string | undefined;
331
- /** The first rung that is not `within`, or undefined when each rung is `within`. */
332
- readonly next: string | undefined;
333
- /** True when a locked rung is not `within`. A rung with no result is not held, so `cannot decide` fails too. */
334
- readonly failed: boolean;
335
- /** The reason of `failed`, in one sentence. */
336
- readonly reason: string;
337
- readonly rungs: readonly RungVerdict[];
338
- }
339
- /** The options of a ladder verdict. */
340
- interface LadderOptions {
341
- /** The time of the verdict, as an ISO 8601 string. It is an input, so that a verdict is the same at each read. */
342
- readonly now: string;
343
- /** The largest age of a record, in days. An older record gives `cannot decide`. The default accepts any age. */
344
- readonly maxAgeDays?: number;
345
- }
346
- /**
347
- * This function gives each problem of a ladder as data, or an empty list. A ladder needs a subject, one dimension or more,
348
- * and one rung or more. Names are unique. Each rung names a test and has budgets. From one rung to the next, each dimension
349
- * that the two rungs name grows.
350
- */
351
- export declare function checkLadder(ladder: Ladder): readonly string[];
352
- /** This function gives the verdict of one rung from its record. With no record, the rung is `cannot decide`. */
353
- export declare function rungVerdict(rung: Rung, record: RungRecord | undefined, options: LadderOptions): RungVerdict;
354
- /**
355
- * This function gives the verdict of a ladder from the records of its rungs. It uses the newest record of each rung, so an
356
- * older pass does not hide a newer failure. A rung high up does not count when a rung below it is not `within`. It throws
357
- * a `RangeError` for a ladder with problems, because a verdict on a bad ladder has no meaning. See `checkLadder`.
358
- */
359
- export declare function ladderVerdict(ladder: Ladder, records: readonly RungRecord[], options: LadderOptions): LadderVerdict;
360
127
  /**
361
128
  * The two kinds of an A/A band.
362
129
  * - The band `case` holds the ratio of one A/A case. It is wide, so it finds only a large change.
@@ -498,7 +265,7 @@ interface TimeVerdict {
498
265
  * The counts of the cases out of the band, or undefined without a band.
499
266
  * The comparison uses the value `1 + log(ratio)` of each case and the noise of the band, so its two sides are the ends of the band.
500
267
  */
501
- readonly comparison: Comparison | undefined;
268
+ readonly comparison: Comparison$1 | undefined;
502
269
  /** The facts of the pooled band. The verdict has this field only with the option `pool`. */
503
270
  readonly pool?: PoolFacts;
504
271
  /** The noise cap. The verdict has this field only with the option `noiseCap`. */
@@ -698,6 +465,551 @@ interface RunPairs {
698
465
  * It balances the records of each pair with `balanceOrders` first. It refuses an `aaPair` that the run does not have.
699
466
  */
700
467
  export declare function armVerdicts(run: RunPairs, aaPair: string, options?: VerdictOptions): Record<string, TimeVerdict>;
468
+ /** The three results of a gate. */
469
+ type GateOutcome = "pass" | "block" | "no read";
470
+ /** The fields of a case that a gate reads. The cases of `limitVerdict`, `budgetVerdict` and the verdict of this file have them. */
471
+ interface GateCaseOutcome {
472
+ readonly case: string;
473
+ readonly outcome: LimitOutcome;
474
+ }
475
+ /** The result of a gate, with the cases that make it. */
476
+ interface Gate {
477
+ readonly outcome: GateOutcome;
478
+ /** The reason of the result, in one sentence. */
479
+ readonly reason: string;
480
+ /** The cases with the outcome `beyond`. */
481
+ readonly blocks: readonly string[];
482
+ /** The cases with the outcome `cannot decide`. */
483
+ readonly noRead: readonly string[];
484
+ }
485
+ /**
486
+ * This function gives the gate of a list of case outcomes.
487
+ * - The result is "block" when a case is `beyond`.
488
+ * - The result is "pass" when each case is `within`.
489
+ * - Each other result is "no read", and so is a list with no cases. A caller does not count "no read" as a pass.
490
+ */
491
+ export declare function gateOf(cases: readonly GateCaseOutcome[]): Gate;
492
+ /** The word of a case for the claim "not slower by more than the margin". The word "not slower" is apart from `same` of `timeVerdict`. */
493
+ type NotSlowerRead = "not slower" | "slower" | "no read";
494
+ /** The looks of `notSlowerVerdict`: the rounds in each job. The level of the family has an equal share at each look. */
495
+ export declare const GATE_LOOKS: readonly number[];
496
+ /** The options of `notSlowerVerdict`. */
497
+ interface NotSlowerOptions {
498
+ /** The margin of each case on a log scale: a number, or a function of the name of the case. */
499
+ readonly margin: number | ((name: string) => number);
500
+ /** The chance of a false "not slower", and apart from it the chance of a false "slower", over the family and all looks. The default is 0.05. */
501
+ readonly level?: number;
502
+ /** The looks: even whole numbers in rising order. The default is `GATE_LOOKS`. */
503
+ readonly looks?: readonly number[];
504
+ /** The count of jobs that each need the bound. The default is 2, because more rounds do not remove a difference between jobs. */
505
+ readonly jobs?: number;
506
+ }
507
+ /** The read of one case in one job, at one look. */
508
+ interface GateJobRead {
509
+ readonly job: string;
510
+ /** The pairs of rounds that the look uses. Below the rounds of the look, the job has not reached the look. */
511
+ readonly rounds: number;
512
+ /** The count of pairs with a difference below the margin. */
513
+ readonly below: number;
514
+ /** The count of pairs with a difference above the margin. */
515
+ readonly above: number;
516
+ /** The one-sided p of the sign test of the claim "the median difference is below the margin". */
517
+ readonly notSlower: number;
518
+ /** The one-sided p of the sign test of the claim "the median difference is above the margin". */
519
+ readonly slower: number;
520
+ /** The median of the differences, or undefined when the job has not reached the look. */
521
+ readonly centre: number | undefined;
522
+ }
523
+ /** The verdict of one case. */
524
+ interface CaseGate extends GateCaseOutcome {
525
+ readonly read: NotSlowerRead;
526
+ readonly margin: number;
527
+ /** The rounds of the look that decides the case, or undefined when the case has no outcome. */
528
+ readonly look: number | undefined;
529
+ /** The reads of each job, at the look that decides the case, or else at the last look that a job reached. */
530
+ readonly jobs: readonly GateJobRead[];
531
+ /** The reason of the outcome, in one sentence. */
532
+ readonly reason: string;
533
+ }
534
+ /** The gate of the claim "not slower by more than the margin", with the facts that it uses. */
535
+ interface NotSlowerVerdict extends Gate {
536
+ readonly level: number;
537
+ readonly looks: readonly number[];
538
+ /** The count of jobs that each need the bound. */
539
+ readonly need: number;
540
+ readonly cases: readonly CaseGate[];
541
+ /** The cases with no outcome that can have another look. The list is empty when the verdict is final. */
542
+ readonly more: readonly BudgetMore[];
543
+ }
544
+ /**
545
+ * This function gives the gate of the claim "the candidate is not slower than the A/A arm by more than the margin" for each
546
+ * case. A one-sided bound answers the claim. Thus a case with its whole interval under the margin reads "not slower", also
547
+ * when its interval holds 1.
548
+ *
549
+ * - In each job, the sign test compares the median of the differences with the margin. It uses no random numbers.
550
+ * - A case reads in `jobs` jobs or more: `partialConjunction` joins the p of each job, with no condition on how they depend.
551
+ * - The level is for the family. Each look has `level / looks` of it, and `holm` corrects each look over all cases.
552
+ * - The first look with an outcome decides a case. Later rounds do not change it. Each look uses the first rounds of a job.
553
+ * - The result is "block" when a case reads "slower", and "pass" when each case reads "not slower".
554
+ * - Each other result is "no read". The field `more` gives the next look of each case. After the last look, the caller adds jobs.
555
+ *
556
+ * The level needs independent rounds. Rounds with a shared cause, for example a slow computer for one job, do not have it.
557
+ * A job that a caller adds after the last look is one more look, and the level does not count it.
558
+ */
559
+ export declare function notSlowerVerdict(jobs: readonly JobRecords[], options: NotSlowerOptions): NotSlowerVerdict;
560
+ /** One time of the control in one group. */
561
+ interface ControlRow {
562
+ /** The name of the group: a run, or a shard of one run. */
563
+ readonly group: string;
564
+ /** The name of a class of work. The same key in two groups names equal work, so a ratio of the two measures the load. */
565
+ readonly key: string;
566
+ /** The time. It is finite and more than 0. */
567
+ readonly value: number;
568
+ /** This field is true when the run stopped the case at `value`. Thus the real time is at least `value`. */
569
+ readonly censored?: boolean;
570
+ }
571
+ /** The options of `controlFactor`. */
572
+ interface ControlOptions {
573
+ /** The group that the factors compare with. Without it, the base of each key is the median of that key over the groups. */
574
+ readonly base?: string;
575
+ /** The least number of keys in a factor. A group with fewer keys has no factor. The default is 5. */
576
+ readonly minPairs?: number;
577
+ }
578
+ /** The counts of one group, with or without a factor. */
579
+ interface GroupCounts {
580
+ readonly group: string;
581
+ /** The number of keys that the factor reads. */
582
+ readonly pairs: number;
583
+ /** The number of keys that this function left out because a time of the key was censored. The factor reads low when this count is not 0. */
584
+ readonly censored: number;
585
+ /** The number of keys of this group that have no time to compare with, so no ratio reads them. */
586
+ readonly unshared: number;
587
+ }
588
+ /** The factor of one group. */
589
+ interface MeasuredFactor extends GroupCounts {
590
+ /** The median ratio of the times of this group over the base. A factor of 1.6 means that this group took 1.6 times as long. */
591
+ readonly factor: number;
592
+ /** The quartiles of the ratios. A wide spread means that one factor does not explain the load. */
593
+ readonly low: number;
594
+ readonly high: number;
595
+ }
596
+ /** A group with too few usable keys. It has no factor, and the other groups keep theirs. */
597
+ interface NoFactor extends GroupCounts {
598
+ readonly factor: undefined;
599
+ /** The reason that this group has no factor. */
600
+ readonly reason: string;
601
+ }
602
+ /** The result of one group. Read `factor` first: a group with too few usable keys has no factor. */
603
+ type GroupFactor = MeasuredFactor | NoFactor;
604
+ /** The factors of a run, with the base that they use. */
605
+ interface ControlFactors {
606
+ /** The base group, or undefined when the base of each key is its median over the groups. */
607
+ readonly base: string | undefined;
608
+ readonly factors: readonly GroupFactor[];
609
+ }
610
+ /**
611
+ * This function gives the load factor of each group from the times of a control.
612
+ *
613
+ * With `base`, a factor compares the keys that a group shares with that group. Without it, a factor compares each time with the median of its key over the groups.
614
+ * A key names a class of work, so equal keys in two groups mean equal work. Each group has at most one row for a key.
615
+ *
616
+ * A censored time is only a lower limit, so no ratio reads it, and the result counts those keys. A run stops its slowest cases, so a factor reads low when `censored` is not 0.
617
+ *
618
+ * A group with too few usable keys gets an entry with no factor and its reason, so the other groups keep their factors. This function refuses a result where no group has a factor.
619
+ */
620
+ export declare function controlFactor(rows: readonly ControlRow[], options?: ControlOptions): ControlFactors;
621
+ /** The format name of a ladder. It changes when a reader of an older form cannot read the data. */
622
+ export declare const LADDER_FORMAT = "rigor-ladder/1";
623
+ /** One dimension of a ladder, for example tenants or nodes. */
624
+ interface LadderDimension {
625
+ readonly name: string;
626
+ /** What one unit of the dimension is, in plain words. */
627
+ readonly describe: string;
628
+ }
629
+ /** A budget on the median of each case, for example the time of a read. A record gives rounds and an A/A arm. */
630
+ interface MedianBudget {
631
+ readonly kind: "median";
632
+ readonly measure: string;
633
+ /** The unit of the limit and of the values. */
634
+ readonly unit: string;
635
+ /** The largest median that the budget permits. */
636
+ readonly limit: number;
637
+ /** The largest difference between the medians of the two arms. A larger difference makes the run too noisy. */
638
+ readonly maxDifference: number;
639
+ /** The level of the interval of each median. The default is 0.95. */
640
+ readonly caseLevel?: number;
641
+ }
642
+ /** A budget on the share of failed trials, for example failed requests. A record gives failures and trials. */
643
+ interface RateBudget {
644
+ readonly kind: "rate";
645
+ readonly measure: string;
646
+ /** The largest share of failures that the budget permits, from 0 to 1. */
647
+ readonly limit: number;
648
+ }
649
+ /** A budget on the largest value of a set of drills, for example the writes that a restore lost. One bad drill is `beyond`. */
650
+ interface WorstBudget {
651
+ readonly kind: "worst";
652
+ readonly measure: string;
653
+ readonly unit: string;
654
+ /** The largest value that the budget permits in any drill. */
655
+ readonly limit: number;
656
+ /** The number of drills that a verdict needs, 1 or more. With fewer, the budget is `cannot decide`. */
657
+ readonly minDrills: number;
658
+ }
659
+ /**
660
+ * A budget on a high quantile, for example the p99 of a read. A record gives the values. The verdict is the distribution-free
661
+ * interval of the quantile against the limit. A p99 needs 368 independent values at the level 0.95: refer to `quantileSamples`.
662
+ * Successive times of one run can follow each other. Space them apart, or give one value for each run.
663
+ *
664
+ * The evidence can also hold `censored`: a lower bound for each arrival with no reply, and for each arrival that was not
665
+ * sent. The bound is the time that the arrival waited. The true value is that bound or more, with no upper limit. Thus the
666
+ * low end of the interval reads the bounds, and the high end reads each censored value as `Infinity`. A `beyond` stays
667
+ * provable from the bounds alone. A `within` needs real replies up to the upper rank of the interval.
668
+ */
669
+ interface QuantileBudget {
670
+ readonly kind: "quantile";
671
+ readonly measure: string;
672
+ /** The unit of the limit and of the values. */
673
+ readonly unit: string;
674
+ /** The quantile, more than 0 and less than 1, for example 0.99. */
675
+ readonly quantile: number;
676
+ /** The largest quantile that the budget permits. */
677
+ readonly limit: number;
678
+ /** The level of the interval. The default is 0.95. */
679
+ readonly level?: number;
680
+ }
681
+ /** One budget of a rung. */
682
+ type RungBudget = MedianBudget | QuantileBudget | RateBudget | WorstBudget;
683
+ /** One rung of a ladder. */
684
+ interface Rung {
685
+ /** The name of the rung, unique in the ladder. */
686
+ readonly name: string;
687
+ /** The size of the rung in each dimension that it names. */
688
+ readonly at: Readonly<Record<string, number>>;
689
+ readonly budgets: readonly RungBudget[];
690
+ /** The name of the automatic test that holds the rung. */
691
+ readonly test: string;
692
+ /** True when a gate holds the rung: the verdict fails when the rung is not `within`. */
693
+ readonly locked?: boolean;
694
+ }
695
+ /** The ladder of one subject. The rungs go from the smallest to the largest. */
696
+ interface Ladder {
697
+ readonly format: typeof LADDER_FORMAT;
698
+ /** The product or the service that the ladder is for. */
699
+ readonly subject: string;
700
+ readonly dimensions: readonly LadderDimension[];
701
+ readonly rungs: readonly Rung[];
702
+ }
703
+ /** The measured evidence for one budget. Its `kind` is the kind of the budget. */
704
+ type RungEvidence = {
705
+ readonly kind: "median";
706
+ readonly measure: string;
707
+ readonly rounds: readonly BudgetRound[];
708
+ readonly aa: readonly BudgetRound[];
709
+ } | {
710
+ readonly kind: "quantile";
711
+ readonly measure: string;
712
+ readonly values: readonly number[];
713
+ readonly censored?: readonly number[];
714
+ } | {
715
+ readonly kind: "rate";
716
+ readonly measure: string;
717
+ readonly failures: number;
718
+ readonly trials: number;
719
+ } | {
720
+ readonly kind: "worst";
721
+ readonly measure: string;
722
+ readonly values: readonly number[];
723
+ };
724
+ /** One run of the test of a rung. */
725
+ interface RungRecord {
726
+ /** The name of the rung. */
727
+ readonly rung: string;
728
+ /** The commit that the run measured. */
729
+ readonly commit: string;
730
+ /** The time of the run, as an ISO 8601 string. */
731
+ readonly at: string;
732
+ /** What the run did for real, for example "2 processes" or "a restore from a real backup". */
733
+ readonly real: readonly string[];
734
+ /** What the run made up, for example "90 % of the tenants as data at rest". An empty list states that nothing was synthetic. */
735
+ readonly synthetic: readonly string[];
736
+ readonly evidence: readonly RungEvidence[];
737
+ }
738
+ /** The verdict of one budget of a rung. */
739
+ interface BudgetResult {
740
+ readonly measure: string;
741
+ readonly outcome: BudgetOutcome;
742
+ /** The reason of the outcome, in one sentence, with the numbers. */
743
+ readonly reason: string;
744
+ }
745
+ /** The verdict of one rung. */
746
+ interface RungVerdict {
747
+ readonly rung: string;
748
+ readonly test: string;
749
+ readonly locked: boolean;
750
+ readonly outcome: BudgetOutcome;
751
+ /** The reason of the outcome, in one sentence. */
752
+ readonly reason: string;
753
+ readonly budgets: readonly BudgetResult[];
754
+ /** The commit of the record, or undefined when the rung has no record. */
755
+ readonly commit: string | undefined;
756
+ readonly real: readonly string[];
757
+ readonly synthetic: readonly string[];
758
+ }
759
+ /** The verdict of a ladder. */
760
+ interface LadderVerdict {
761
+ readonly subject: string;
762
+ /** The highest rung with each rung up to it `within`, or undefined when the first rung is not `within`. */
763
+ readonly held: string | undefined;
764
+ /** The first rung that is not `within`, or undefined when each rung is `within`. */
765
+ readonly next: string | undefined;
766
+ /** True when a locked rung is not `within`. A rung with no result is not held, so `cannot decide` fails too. */
767
+ readonly failed: boolean;
768
+ /** The reason of `failed`, in one sentence. */
769
+ readonly reason: string;
770
+ readonly rungs: readonly RungVerdict[];
771
+ }
772
+ /** The options of a ladder verdict. */
773
+ interface LadderOptions {
774
+ /** The time of the verdict, as an ISO 8601 string. It is an input, so that a verdict is the same at each read. */
775
+ readonly now: string;
776
+ /** The largest age of a record, in days. An older record gives `cannot decide`. The default accepts any age. */
777
+ readonly maxAgeDays?: number;
778
+ }
779
+ /**
780
+ * This function gives each problem of a ladder as data, or an empty list. A ladder needs a subject, one dimension or more,
781
+ * and one rung or more. Names are unique. Each rung names a test and has budgets. From one rung to the next, each dimension
782
+ * that the two rungs name grows.
783
+ */
784
+ export declare function checkLadder(ladder: Ladder): readonly string[];
785
+ /** This function gives the verdict of one rung from its record. With no record, the rung is `cannot decide`. */
786
+ export declare function rungVerdict(rung: Rung, record: RungRecord | undefined, options: LadderOptions): RungVerdict;
787
+ /**
788
+ * This function gives the verdict of a ladder from the records of its rungs. It uses the newest record of each rung, so an
789
+ * older pass does not hide a newer failure. A rung high up does not count when a rung below it is not `within`. It throws
790
+ * a `RangeError` for a ladder with problems, because a verdict on a bad ladder has no meaning. See `checkLadder`.
791
+ */
792
+ export declare function ladderVerdict(ladder: Ladder, records: readonly RungRecord[], options: LadderOptions): LadderVerdict;
793
+ /** One value of one measure, for one entry and one input. */
794
+ interface MeasureRow {
795
+ /** The name of the measure. */
796
+ readonly measure: string;
797
+ /** The name of the entry: a real strategy or a control. */
798
+ readonly group: string;
799
+ /** The name of the input. Equal keys in two groups name equal work, so the two values make a pair. */
800
+ readonly key: string;
801
+ /** The value. It is finite. No test reads the value of a censored row. */
802
+ readonly value: number;
803
+ /** This field is true when the entry did not finish this input, for example over its budget. */
804
+ readonly censored?: boolean;
805
+ /** The way that the value was made, for example a sample or a full count. Two ways in one measure do not compare. */
806
+ readonly method?: string;
807
+ /** The family of the input. A key has one stratum in all its rows. Rows without a stratum make one group. */
808
+ readonly stratum?: string;
809
+ }
810
+ /** A measure with no control yet: the reason and the date of the control. */
811
+ interface NoControl {
812
+ /** The reason that the measure has no control at this time. */
813
+ readonly because: string;
814
+ /** The date of the control, as `YYYY-MM-DD`. A date before `asOf` gives the finding `control-late`. */
815
+ readonly until: string;
816
+ }
817
+ /** The rule of one measure. */
818
+ interface MeasureRule {
819
+ readonly measure: string;
820
+ /** The direction of a better value. */
821
+ readonly sense: "higher" | "lower";
822
+ /** The controls made to win this measure. Each one is in `controls` of the options. */
823
+ readonly controls: readonly string[];
824
+ /** The measures that a control of this measure is to lose. Each one has its own rule. */
825
+ readonly partners: readonly string[];
826
+ /** The smallest median paired difference that counts. Without it, only the test decides, and the output says so. It has no default. */
827
+ readonly resolution?: number;
828
+ /** The reason and the date, for a rule with no controls. */
829
+ readonly noControl?: NoControl;
830
+ }
831
+ /** The options of `checkMeasures`. */
832
+ interface MeasureCheckOptions {
833
+ readonly rules: readonly MeasureRule[];
834
+ /** Each group that is a control. Each other group is a real entry. */
835
+ readonly controls: readonly string[];
836
+ /** The date of the check, as `YYYY-MM-DD`. The caller gives it, so the function stays pure. */
837
+ readonly asOf: string;
838
+ /** The level of each family of tests. The default is 0.05. */
839
+ readonly alpha?: number;
840
+ }
841
+ /** One test: `better` beats `other` on the keys that the two finished. */
842
+ interface Comparison {
843
+ readonly better: string;
844
+ readonly other: string;
845
+ readonly stratum: string | undefined;
846
+ /** The keys that both finished. */
847
+ readonly shared: number;
848
+ /** The shared keys with different values. The test reads only these. */
849
+ readonly n: number;
850
+ readonly ties: number;
851
+ /** The keys where `better` has the better value. */
852
+ readonly wins: number;
853
+ /** The keys where `other` has the better value. */
854
+ readonly losses: number;
855
+ /** The median paired difference over the shared keys, with ties. A positive value favours `better`. */
856
+ readonly medianDifference: number;
857
+ /** The p of the sign test. */
858
+ readonly p: number;
859
+ /** The p after the Holm correction. */
860
+ readonly adjusted: number;
861
+ /** The size of the Holm family. */
862
+ readonly family: number;
863
+ /** The least count of untied keys with the power to pass in this family. */
864
+ readonly needs: number;
865
+ /** This field is true when `n` is under `needs`. Such a test beats nothing. */
866
+ readonly tooFew: boolean;
867
+ /** This field is true when the shared keys reach `needs` and ties took them under it. So the two read as equal, not as unread. */
868
+ readonly tied: boolean;
869
+ /** The test passes, and the median difference is over the resolution when the measure has one. */
870
+ readonly beats: boolean;
871
+ }
872
+ /** The read of one control on one measure and one stratum. */
873
+ interface ControlRead {
874
+ readonly measure: string;
875
+ readonly control: string;
876
+ readonly stratum: string | undefined;
877
+ /**
878
+ * The state of the read. `wins`: no real entry with enough pairs beats the control. `beaten`: a real entry beats it.
879
+ * `too-few`: no real entry has enough shared keys. `no-rows`: no real entry shares a finished key with it.
880
+ */
881
+ readonly status: "wins" | "beaten" | "too-few" | "no-rows";
882
+ /** The real entries with fewer winning keys than the control. It is a plain count with no test. */
883
+ readonly aheadOf: number;
884
+ /** One test for each real entry: `better` is the real entry, and `other` is the control. */
885
+ readonly comparisons: readonly Comparison[];
886
+ /** The real entries that the control beats by test on this stratum. */
887
+ readonly beatsEntries: number;
888
+ /** The tests of the control against the real entries that have power on this stratum. */
889
+ readonly of: number;
890
+ /** One test for each real entry: `better` is the control, and `other` is the real entry. This family is apart from `comparisons`. */
891
+ readonly against: readonly Comparison[];
892
+ }
893
+ /** The counts of one entry on one measure and one stratum. */
894
+ interface EntryCount {
895
+ readonly group: string;
896
+ readonly stratum: string | undefined;
897
+ readonly finished: number;
898
+ readonly censored: number;
899
+ }
900
+ /** The read of the spread of one measure on one stratum, over the pairs of real entries. */
901
+ interface SpreadRead {
902
+ readonly stratum: string | undefined;
903
+ /** The pairs of real entries that share a finished key. */
904
+ readonly pairs: number;
905
+ /** The pairs with a test that passes in one direction. */
906
+ readonly separated: number;
907
+ /** The pairs with too few shared keys for the test. A pair that ties on enough keys does not count here. */
908
+ readonly tooFew: number;
909
+ /** The largest absolute median paired difference of a pair. */
910
+ readonly widest: number | undefined;
911
+ }
912
+ /** The result of one control and one partner on one stratum. */
913
+ interface PartnerRead {
914
+ readonly partner: string;
915
+ /**
916
+ * `lost`: a real entry beats the control at the level divided by the count of partners. Each partner is one more chance to clear the control.
917
+ * `not-lost`: no real entry does. `too-few`: no test has the power at that level. `no-rows`: nothing to read.
918
+ */
919
+ readonly status: "lost" | "not-lost" | "too-few" | "no-rows";
920
+ }
921
+ /** The result of one control on its measure and one stratum, with its partners. */
922
+ interface GuardRead {
923
+ readonly control: string;
924
+ readonly stratum: string | undefined;
925
+ readonly status: ControlRead["status"];
926
+ readonly partners: readonly PartnerRead[];
927
+ }
928
+ /** The read of one measure. */
929
+ interface MeasureCheck {
930
+ readonly measure: string;
931
+ readonly sense: "higher" | "lower";
932
+ /** `test only`: a measure with no resolution. `test and resolution`: a measure with one. */
933
+ readonly basis: "test only" | "test and resolution";
934
+ /** The only method of the rows. It is undefined when the rows give none. */
935
+ readonly method: string | undefined;
936
+ /** This field is true when the rows mix methods. The check then has no read of the measure. */
937
+ readonly mixed: boolean;
938
+ readonly guards: readonly GuardRead[];
939
+ readonly spread: readonly SpreadRead[];
940
+ readonly entries: readonly EntryCount[];
941
+ /** The partners that the rule names. */
942
+ readonly partners: readonly string[];
943
+ /** The reason and the date, for a measure with no control. */
944
+ readonly open: NoControl | undefined;
945
+ }
946
+ /** The kind of a finding. Each finding fails a gate. */
947
+ type MeasureFindingKind = "uncaught" | "weak-control" | "censored-win" | "no-spread" | "too-few" | "mixed-method" | "no-rule" | "no-rows" | "no-control" | "control-late";
948
+ /** One finding of the check, with the numbers behind it. */
949
+ interface MeasureFinding {
950
+ readonly kind: MeasureFindingKind;
951
+ readonly measure: string;
952
+ readonly stratum?: string | undefined;
953
+ readonly control?: string;
954
+ /** The count of the partners of the rule, for a finding about the partners of a control. */
955
+ readonly partners?: number;
956
+ /** The finding in plain words, with its numbers. */
957
+ readonly text: string;
958
+ /** The tests behind the finding. */
959
+ readonly comparisons: readonly Comparison[];
960
+ }
961
+ /** The result of `checkMeasures`. */
962
+ interface MeasureChecks {
963
+ /** The level of each family of tests. */
964
+ readonly alpha: number;
965
+ readonly measures: readonly MeasureCheck[];
966
+ /** Each read of a control, on its own measures and on their partners. */
967
+ readonly reads: readonly ControlRead[];
968
+ readonly findings: readonly MeasureFinding[];
969
+ }
970
+ /** What a page says about the win of one entry on one measure. */
971
+ interface WinClaim {
972
+ /** This field is true only when a control was read on this measure and this entry beats each control on it. A win by another entry does not count. */
973
+ readonly alone: boolean;
974
+ /** The partners that a winning control loses. When this entry does not beat a control that does not win, or with no read of a control, all partners of the rule. */
975
+ readonly show: readonly string[];
976
+ /** This field is true when this entry does not beat a control on this measure and beats it on no partner. The win then reads the same as the trick. The status of the control does not change this. */
977
+ readonly likeControl: boolean;
978
+ /** The censored keys of this entry and of each control that it does not beat. A page shows them beside the win. */
979
+ readonly censored: {
980
+ readonly entry: number;
981
+ readonly controls: readonly {
982
+ readonly control: string;
983
+ readonly censored: number;
984
+ }[];
985
+ };
986
+ /** The reason and the date, for a measure with no control. */
987
+ readonly open: NoControl | undefined;
988
+ }
989
+ /**
990
+ * This function reads the controls and the spread of each measure of a bench.
991
+ *
992
+ * - A control wins a measure when no real entry beats it on the keys that both finished. A tie counts for the control.
993
+ * - A real entry beats a control when the Holm-corrected sign test passes and the median paired difference is over the resolution.
994
+ * - One Holm family holds the tests of one control on one measure over all real entries and all strata.
995
+ * - One more Holm family holds the tests of one control against the real entries, with the same need and resolution. A control that beats none of them is weak.
996
+ * - One Holm family holds the tests of the spread of one measure over all pairs of real entries and all strata.
997
+ * - A test with fewer untied keys than `signTestPower` needs for that family reads `tooFew` and beats nothing.
998
+ * - A test with enough shared keys and too few untied keys is `tied`. The two entries read as equal, so a constant measure is `no-spread` and not `too-few`.
999
+ * - A control loses a partner only at the level divided by the count of its partners. One passed partner clears `uncaught`, so each partner is one more chance.
1000
+ *
1001
+ * The function throws a `RangeError` for a value that is not finite, a repeat of measure, group and key, or a key in two strata.
1002
+ * It also throws one for rules that contradict each other.
1003
+ * The rules, the controls and the date are stated, so the result depends only on the arguments.
1004
+ */
1005
+ export declare function checkMeasures(rows: readonly MeasureRow[], options: MeasureCheckOptions): MeasureChecks;
1006
+ /**
1007
+ * This function tells what a page says about the win of one real entry on one measure.
1008
+ * The claim is about this entry: only this entry beating the control, on this measure or on a partner, clears the entry. A win by another entry clears nothing.
1009
+ * With a stratum, the function reads that stratum. Without one, it reads the rows with no stratum.
1010
+ * The function throws a `RangeError` for a measure with no read and for an entry that the rows do not hold.
1011
+ */
1012
+ export declare function winClaim(check: MeasureChecks, measure: string, entry: string, stratum?: string): WinClaim;
701
1013
  /** The options of a power test. */
702
1014
  interface PowerOptions {
703
1015
  /** The count of the cases of the candidate and of the A/A arm. */
@@ -760,5 +1072,5 @@ interface Rounds {
760
1072
  * keeps the work.
761
1073
  */
762
1074
  export declare function timeRounds(arms: Readonly<Record<Arm, () => number>>, options: RoundsOptions): Rounds;
763
- export { type Arm, type Balanced, type Band, type BandKind, type BandOptions, type BudgetLook, type BudgetLooksOptions, type BudgetLooksVerdict, type BudgetMore, type BudgetOptions, type BudgetOutcome, type BudgetResult, type BudgetRound, type BudgetVerdict, type CaseBudget, type CaseInterval, type CaseLimit, type CaseRatio, type ControlFactors, type ControlOptions, type ControlRow, type GroupCounts, type GroupFactor, type JobLimitVerdict, type JobRecords, type JobVerdict, type Ladder, type LadderDimension, type LadderOptions, type LadderVerdict, type LimitOptions, type LimitOutcome, type LimitVerdict, type MeasuredFactor, type MedianBudget, type NoFactor, type NoiseCheck, type PairedTime, type PoolFacts, type PoolOptions, type PooledJob, type PooledLimitVerdict, type PooledRecords, type PooledVerdict, type Power, type PowerOptions, type QuantileBudget, type RateBudget, type Rounds, type RoundsOptions, type RunPairs, type Rung, type RungBudget, type RungEvidence, type RungRecord, type RungVerdict, type TimeOutcome, type TimeVerdict, type VerdictOptions, type VerdictRule, type WorstBudget, caseRatios, checkPairedTime, firstArm };
1075
+ export { type Arm, type Balanced, type Band, type BandKind, type BandOptions, type BudgetLook, type BudgetLooksOptions, type BudgetLooksVerdict, type BudgetMore, type BudgetOptions, type BudgetOutcome, type BudgetResult, type BudgetRound, type BudgetVerdict, type CaseBudget, type CaseGate, type CaseInterval, type CaseLimit, type CaseRatio, type Comparison, type ControlFactors, type ControlOptions, type ControlRead, type ControlRow, type EntryCount, type Gate, type GateCaseOutcome, type GateJobRead, type GateOutcome, type GroupCounts, type GroupFactor, type GuardRead, type JobLimitVerdict, type JobRecords, type JobVerdict, type Ladder, type LadderDimension, type LadderOptions, type LadderVerdict, type LimitOptions, type LimitOutcome, type LimitVerdict, type MeasureCheck, type MeasureCheckOptions, type MeasureChecks, type MeasureFinding, type MeasureFindingKind, type MeasureRow, type MeasureRule, type MeasuredFactor, type MedianBudget, type NoControl, type NoFactor, type NoiseCheck, type NotSlowerOptions, type NotSlowerRead, type NotSlowerVerdict, type PairedTime, type PartnerRead, type PoolFacts, type PoolOptions, type PooledJob, type PooledLimitVerdict, type PooledRecords, type PooledVerdict, type Power, type PowerOptions, type QuantileBudget, type RateBudget, type Rounds, type RoundsOptions, type RunPairs, type Rung, type RungBudget, type RungEvidence, type RungRecord, type RungVerdict, type SpreadRead, type TimeOutcome, type TimeVerdict, type VerdictOptions, type VerdictRule, type WinClaim, type WorstBudget, caseRatios, checkPairedTime, firstArm };
764
1076
  //# sourceMappingURL=index.d.ts.map