@mark1russell7/rigor-bench 0.2.14 → 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/README.md CHANGED
@@ -42,6 +42,8 @@ v.comparison; // the cases that gain and dro
42
42
  | `pooledBand(pool, level)` | The pooled band: the larger of the floor and the A/A spread of the records of earlier runs. |
43
43
  | `caseIntervals(records, level)` | The ratio of each case with a distribution-free interval of its median over the rounds. The level 0.95 needs 6 rounds or more. |
44
44
  | `limitVerdict(candidate, aa, options)` | The verdict of the claim "the ratio of each case is at most `limit`": `within`, `beyond` or `cannot decide`. |
45
+ | `gateOf(cases)` | The gate of a list of case outcomes: `pass`, `block` or `no read`. |
46
+ | `notSlowerVerdict(jobs, options)` | The gate of the claim "not slower by more than the margin", with looks and a family level. |
45
47
  | `budgetVerdict(rounds, aa, options)` | The verdict of the claim "the median of each case is at most `limit`", for one build: `within`, `beyond` or `cannot decide`. |
46
48
  | `budgetLooksVerdict(rounds, aa, options)` | The budget verdict of a run that adds rounds to the cases with no outcome, up to a stated budget. |
47
49
  | `budgetLookSpend(looks)` | The chance of error that a list of looks spends. |
@@ -78,6 +80,31 @@ v.cases; // the interval, the bound and
78
80
 
79
81
  The verdict has no correction for many cases. Each case has its own interval at the level `caseLevel`. Thus with many cases, a verdict `beyond` can come from noise only. Set `caseLevel` higher when a bench has many cases. A correction of Holm is an option for a later version.
80
82
 
83
+ ## A gate that can fail
84
+
85
+ A check that blocks a merge needs a result that can fail. `gateOf` reads the case outcomes of a verdict, and `notSlowerVerdict` gives the claim of a speed gate.
86
+
87
+ ```ts
88
+ const gate = notSlowerVerdict(jobs, { margin: Math.log(1.015) });
89
+
90
+ gate.outcome; // "pass", "block" or "no read"
91
+ gate.cases; // "not slower", "slower" or "no read" for each case, with the facts of each job
92
+ gate.more; // the next look of each case with no outcome
93
+ ```
94
+
95
+ - The claim is "not slower by more than the margin". A one-sided bound answers it, thus a case can read `not slower` when its interval holds 1. The word `same` of `timeVerdict` asks for more.
96
+ - The outcome of each case uses the words of `LimitOutcome`: `within` is `not slower`, `beyond` is `slower`, and `cannot decide` is `no read`. Thus `gateOf` also reads `limitVerdict` and `budgetVerdict`.
97
+ - A case needs its bound in each of `jobs` jobs, by default 2. More rounds do not remove a difference between jobs.
98
+ - The claim "the bound holds in at least `r` of `J` jobs" is a partial conjunction. Its p is `(J - r + 1)` times the `r`-th smallest p of the jobs (Benjamini and Heller, 2008). With 2 jobs of 2, this p is the larger p.
99
+ - The sign test compares the median difference with the margin in each job. It uses no random numbers.
100
+ - A pair holds two records with the same first arm. A runner can give the two arms opposite orders in one round, and a difference of two orders holds the effect of the order.
101
+ - The `level` is for the family. `holm` corrects each look over all cases. Each look has an equal share of the level.
102
+ - The first look with an outcome decides a case. `GATE_LOOKS` is 12, 24 and 48 rounds.
103
+ - Take 16 cases and the default looks. The first test of a family at 12 rounds needs 12 of 12 pairs below the margin in both jobs. Thus a noisy case needs more rounds, or it stays `no read`.
104
+ - `no read` is not a pass. A caller adds the rounds of `more`, then more jobs. A job that it adds after the last look is one more look, and the level does not count it.
105
+
106
+ The level needs independent rounds. Rounds with a shared cause, for example a slow computer for one job, do not have it.
107
+
81
108
  ## A claim with a budget
82
109
 
83
110
  `limitVerdict` judges a ratio of two arms. A budget is an absolute limit on one build. An example is "the median blocking time of this page is at most 450 ms". A budget needs `budgetVerdict`:
package/build/index.d.ts CHANGED
@@ -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.
@@ -698,6 +465,331 @@ 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;
701
793
  /** One value of one measure, for one entry and one input. */
702
794
  interface MeasureRow {
703
795
  /** The name of the measure. */
@@ -980,5 +1072,5 @@ interface Rounds {
980
1072
  * keeps the work.
981
1073
  */
982
1074
  export declare function timeRounds(arms: Readonly<Record<Arm, () => number>>, options: RoundsOptions): Rounds;
983
- 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 Comparison, type ControlFactors, type ControlOptions, type ControlRead, type ControlRow, type EntryCount, 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 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 };
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 };
984
1076
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":["Comparison"],"sources":["../src/budget.ts","../src/control.ts","../src/ladder.ts","../src/verdict.ts","../src/limit.ts","../src/merge.ts","../src/measures.ts","../src/power.ts","../src/rounds.ts"],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","names":["Comparison"],"sources":["../src/budget.ts","../src/verdict.ts","../src/limit.ts","../src/merge.ts","../src/gate.ts","../src/control.ts","../src/ladder.ts","../src/measures.ts","../src/power.ts","../src/rounds.ts"],"mappings":";;;UAQiB;;WAEN;;WAEA;WACA;;;KAIC;;UAGK;;WAEN;;WAEA;;WAEA;;;UAIM;WACN;;WAEA;;WAEA;WACA;;WAEA;;WAEA;;WAEA;WACA;;WAEA;WACA,SAAS;;WAET;;;UAIM;WACN,SAAS;;WAET;WACA;WACA;WACA;WACA,gBAAgB;;;;;;;;;;;;wBAyDX,cAAc,iBAAiB,eAAe,aAAa,eAAe,SAAS,gBAAgB;;UAyBlG;WACN;WACA;;;;;;qBAOE,uBAAuB;;UAOnB;;WAEN;;WAEA;;WAEA,iBAAiB;;WAEjB;;;UAIM;WACN;WACA;;;UAIM,2BAA2B;;WAEjC;;WAEA,eAAe;;WAEf;;;;;;wBAOK,gBAAgB,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;wBAoDhC,mBAAmB,iBAAiB,eAAe,aAAa,eAAe,SAAS,qBAAqB;;;;;;KCnOjH;;UAGK;;WAEN,OAAO;;WAEP;;WAEA;;WAEA,YAAY;;;UAIN;;WAEN;WACA,MAAM;;;;;;WAMN;;WAEA;WACA;;WAEA;;;wBAIK,OAAO,aAAa,cAAc,UAAS,cAAmB;;;;;wBAoB9D,SAAS,aAAa,cAAc;;UAWnC;;WAEN,kBAAkB;;WAElB;;WAEA;;;;;WAKA,OAAO,QAAQ;;;UAIT;;WAEN;;WAEA;;WAEA;WACA;;WAEA;;;;;;;;wBASK,WAAW,MAAM,aAAa,iBAAc;;KAmBhD;;;;;;;KAQA;;UAGK,uBAAuB;;WAE7B,OAAO;;;;;WAKP;;;;;;WAMA;;WAEA;;;;;WAKA,OAAO;;;UAID;;WAEN;WACA;;WAEA;;WAEA;;;;;WAKA;;;UAIM;WACN,SAAS;;WAET;WACA,gBAAgB;WAChB,MAAM;;;;;;;WAON,UAAU;;WAEV,MAAM;;;;;WAKN,YAAYA;;WAEZ,OAAO;;WAEP,QAAQ;;;;;;;;;;;;;;wBAeH,YAAY,oBAAoB,cAAc,aAAa,cAAc,UAAS,iBAAsB;;;;;;;wBA+CxG,cAAc,UAAS;;UChQtB,qBAAqB;;WAE3B;WACA;;WAEA;;;;;;wBAOK,cAAc,kBAAkB,cAAc,iBAAe;;KAcjE;;UAGK,qBAAqB;;WAE3B;;WAEA;;;;;WAKA;;;UAIM,kBAAkB;;WAExB;;WAEA;WACA,SAAS;;;UAIH;WACN,SAAS;;WAET;WACA;WACA,gBAAgB;;WAEhB,MAAM;;WAEN;;WAEA;;;;;;;;;;wBAWK,aAAa,oBAAoB,cAAc,aAAa,cAAc,SAAS,eAAe;;UCzEjG,SAAS,UAAU;WACzB,SAAS;;WAET;;;;;;;wBAQK,cAAc,UAAU,YAAY,kBAAkB,MAAM,SAAS;;UAkBpE;;WAEN;WACA,oBAAoB;WACpB,aAAa;;WAEb;aAA8B;;;;UAIxB;WACN;WACA,WAAW;WACX,IAAI;;;UAIE;;WAEN,WAAW;;WAEX,IAAI;;WAEJ,eAAe;;WAEf;;WAEA;;;;;;;;wBASK,YAAY,eAAe,eAAe;;UAsEzC;WACN;WACA,SAAS;;;UAIH;;WAEN,SAAS;;WAET,QAAQ;;WAER,eAAe;;WAEf;;WAEA;;WAEA;;WAEA;;;;;;;;wBAWK,cAAc,eAAe,cAAc,UAAS,iBAAsB;;UASzE;WACN;WACA,SAAS;;;UAIH;;WAEN,SAAS;;WAET,QAAQ;;WAER,eAAe;;WAEf;;WAEA;;WAEA;;WAEA;;;;;;;;wBAWK,mBAAmB,eAAe,cAAc,SAAS,eAAe;;UASvE;WACN,OAAO,SAAS,wBAAwB;;;;;;wBAOnC,YAAY,KAAK,UAAU,gBAAgB,UAAS,iBAAsB,eAAe;;KC7N7F;;UAGK;WACN;WACA,SAAS;;;UAIH;WACN,SAAS;;WAET;;WAEA;;WAEA;;;;;;;;wBASK,OAAO,gBAAgB,oBAAoB;;KAW/C;;qBAKC;;UAGI;;WAEN,mBAAmB;;WAEnB;;WAEA;;WAEA;;;UAIM;WACN;;WAEA;;WAEA;;WAEA;;WAEA;;WAEA;;WAEA;;;UAIM,iBAAiB;WACvB,MAAM;WACN;;WAEA;;WAEA,eAAe;;WAEf;;;UAIM,yBAAyB;WAC/B;WACA;;WAEA;WACA,gBAAgB;;WAEhB,eAAe;;;;;;;;;;;;;;;;;wBA8EV,iBAAiB,eAAe,cAAc,SAAS,mBAAmB;;UC7KzE;;WAEN;;WAEA;;WAEA;;WAEA;;;UAIM;;WAEN;;WAEA;;;UAIM;WACN;;WAEA;;WAEA;;WAEA;;;UAIM,uBAAuB;;WAE7B;;WAEA;WACA;;;UAIM,iBAAiB;WACvB;;WAEA;;;KAIC,cAAc,iBAAiB;;UAG1B;;WAEN;WACA,kBAAkB;;;;;;;;;;;;wBAuFb,cAAc,eAAe,cAAc,UAAS,iBAAsB;;qBC3I7E;;UAGI;WACN;;WAEA;;;UAIM;WACN;WACA;;WAEA;;WAEA;;WAEA;;WAEA;;;UAIM;WACN;WACA;;WAEA;;;UAIM;WACN;WACA;WACA;;WAEA;;WAEA;;;;;;;;;;;;UAaM;WACN;WACA;;WAEA;;WAEA;;WAEA;;WAEA;;;KAIC,aAAa,eAAe,iBAAiB,aAAa;;UAGrD;;WAEN;;WAEA,IAAI,SAAS;WACb,kBAAkB;;WAElB;;WAEA;;;UAIM;WACN,eAAe;;WAEf;WACA,qBAAqB;WACrB,gBAAgB;;;KAIf;WACG;WAAyB;WAA0B,iBAAiB;WAAwB,aAAa;;WACzG;WAA2B;WAA0B;WAAoC;;WACzF;WAAuB;WAA0B;WAA2B;;WAC5E;WAAwB;WAA0B;;;UAGhD;;WAEN;;WAEA;;WAEA;;WAEA;;WAEA;WACA,mBAAmB;;;UAIb;WACN;WACA,SAAS;;WAET;;;UAIM;WACN;WACA;WACA;WACA,SAAS;;WAET;WACA,kBAAkB;;WAElB;WACA;WACA;;;UAIM;WACN;;WAEA;;WAEA;;WAEA;;WAEA;WACA,gBAAgB;;;UAIV;;WAEN;;WAEA;;;;;;;wBAkDK,YAAY,QAAQ;;wBAyFpB,YAAY,MAAM,MAAM,QAAQ,wBAAwB,SAAS,gBAAgB;;;;;;wBA6BjF,cAAc,QAAQ,QAAQ,kBAAkB,cAAc,SAAS,gBAAgB;;UC/TtF;;WAEN;;WAEA;;WAEA;;WAEA;;WAEA;;WAEA;;WAEA;;;UAIM;;WAEN;;WAEA;;;UAIM;WACN;;WAEA;;WAEA;;WAEA;;WAEA;;WAEA,YAAY;;;UAIN;WACN,gBAAgB;;WAEhB;;WAEA;;WAEA;;;UAIM;WACN;WACA;WACA;;WAEA;;WAEA;WACA;;WAEA;;WAEA;;WAEA;;WAEA;;WAEA;;WAEA;;WAEA;;WAEA;;WAEA;;WAEA;;;UAIM;WACN;WACA;WACA;;;;;WAKA;;WAEA;;WAEA,sBAAsB;;WAEtB;;WAEA;;WAEA,kBAAkB;;;UAIZ;WACN;WACA;WACA;WACA;;;UAIM;WACN;;WAEA;;WAEA;;WAEA;;WAEA;;;UAIM;WACN;;;;;WAKA;;;UAIM;WACN;WACA;WACA,QAAQ;WACR,mBAAmB;;;UAIb;WACN;WACA;;WAEA;;WAEA;;WAEA;WACA,iBAAiB;WACjB,iBAAiB;WACjB,kBAAkB;;WAElB;;WAEA,MAAM;;;KAIL;;UAGK;WACN,MAAM;WACN;WACA;WACA;;WAEA;;WAEA;;WAEA,sBAAsB;;;UAIhB;;WAEN;WACA,mBAAmB;;WAEnB,gBAAgB;WAChB,mBAAmB;;;UAIb;;WAEN;;WAEA;;WAEA;;WAEA;aAAqB;aAAwB;eAA8B;eAA0B;;;;WAErG,MAAM;;;;;;;;;;;;;;;;;;wBAuUD,cAAc,eAAe,cAAc,SAAS,sBAAsB;;;;;;;wBAgC1E,SAAS,OAAO,eAAe,iBAAiB,eAAe,mBAAmB;;UCnjBjF;;WAEN;;WAEA;;WAEA;;WAEA;;WAEA;;WAEA;;WAEA,UAAU;;;UAIJ;WACN;WACA,UAAU,SAAS,OAAO;;;;;;WAM1B;;;;;;wBAOK,aAAa,SAAS,eAAe;;UClCpC;;WAEN;;WAEA;;WAEA;;WAEA;;WAEA;;WAEA;;;UAIM;WACN,SAAS;;WAET;;WAEA;;;;;;;wBAQK,WAAW,MAAM,SAAS,OAAO,qBAAqB,SAAS,gBAAgB"}