@mark1russell7/rigor-bench 0.2.22 → 0.2.24

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
@@ -345,6 +345,21 @@ Each finding fails a gate, and each one carries its tests with `n`, `ties`, `p`
345
345
  | `no-control` | A rule has no control and no `noControl`. |
346
346
  | `control-late` | The date of `noControl` is before `asOf`. |
347
347
 
348
+ ### A narrow spread
349
+
350
+ The finding `no-spread` reads "no pair separates". One entry far from the others stops that finding, but the measure does not separate the others. Each row of `spread` in a `MeasureCheck` thus has a report of how many entries carry the separated pairs.
351
+
352
+ | Field | Meaning |
353
+ | --- | --- |
354
+ | `entries` | The real entries with at least one pair that has a read. |
355
+ | `share` | The median, over these entries, of the share of the other entries that a test separates from the entry. A pair with no read does not count. |
356
+ | `apart` | The entries that a test separates from more than half of the others that they have a read with. |
357
+ | `narrow` | Some pair separates and `share` is under `NARROW_SPREAD_SHARE`. |
358
+
359
+ - `narrow` is a report. It gives no finding, and it fails no gate.
360
+ - `NARROW_SPREAD_SHARE` is 0.1. This value is a fitted default from a gap in the rows of one project, and it is not a gate limit.
361
+ - One Holm family holds all pairs of all strata. Thus more strata in one call give fewer separated pairs and a lower `share`. Compare a `share` only with a `share` from the same strata.
362
+
348
363
  `winClaim(check, measure, entry, stratum)` gives `alone`, `show`, `likeControl`, `censored` and `open`. The fields are about this entry. The field `likeControl` is true when this entry does not beat a control on the measure and beats it on no partner. A win by another entry clears nothing. The field `alone` is true only when this entry itself beats each control on the measure, so a measure with no control is not `alone`.
349
364
 
350
365
  `jointClaim(check, measures, entry, stratum)` reads a set of measures together, because one measure cannot call a win when each control wins a measure and loses a partner:
@@ -402,6 +417,32 @@ A run of many jobs sets `roundOffset` to `job * rounds`. Then the merged records
402
417
 
403
418
  A rotation of N arms turns the order of two arms only when they are N/2 apart in the rotation. For 4 arms, two arms 1 apart come in the order 3:1 over 4 rounds. Thus each pair of `freshRun` has its own two children, and the order of each pair turns each round.
404
419
 
420
+ ## A result that changes on purpose
421
+
422
+ A bench compares two arms, and two arms with different results do not do the same work. So a difference stops the merge. A pull request can change a result on purpose. Without a stated path, its author edits the case, and no gate reads that edit. A row in the diff gives that path, and it names the exact change.
423
+
424
+ ```ts
425
+ import { resultRows, resultVerdict } from "@mark1russell7/rigor-bench";
426
+
427
+ const verdict = resultVerdict(
428
+ [{ case: "facts of a tree", base: "9f3a", head: "c81e" }], // the hash of the result of each case in the two arms
429
+ { base: resultRows(rowsOfTheBase), head: resultRows(rowsOfTheHead) }, // the parsed file of rows in each arm
430
+ );
431
+
432
+ verdict.outcome; // "pass" or "fail"
433
+ verdict.lines; // the lines that the check prints
434
+ ```
435
+
436
+ A row has four fields: `case`, `base`, `head` and `reason`. The fields `base` and `head` are hashes that the caller makes, so a large result stays out of the file. A reviewer can read a row against the run. A refused line prints the row to add. These rules stop the reuse of a row:
437
+
438
+ - **The hashes bind the row to one change.** The same row against one other result reads `refused`, and the line says which side moved: the base, the head or both. The fields have an order, so a row of a change does not accept its revert.
439
+ - **A row counts only if it is new.** A row that the base also has is spent and accepts nothing, even on the same change. The verdict keeps the array `spent`, and it prints one line with the count.
440
+ - **A new row that accepts nothing fails the verdict.** A row of a case with one result reads `unused`. Otherwise it merges and is spent, and a later true change is refused.
441
+ - **A row of a case with no result fails the verdict.** It reads `absent`, because a missing read is no pass. The case can be skipped or filtered out, so the line does not tell the author to delete the row.
442
+ - **A change that comes again needs two pull requests.** The first one deletes the spent row, and the second one adds it. A revert can delete the row in the same pull request.
443
+
444
+ **Time.** The verdict reads results only. An accepted result buys no time reading. Keep the accepted case in `freshRun`, so it gets its head and A/A pairs and its normal time verdict. The time of the new result counts. The hash rule of `freshRun` is per arm, so two arms with different hashes run. The test "refuses two hashes of one arm on one case, and permits other hashes for other arms" pins this rule.
445
+
405
446
  ## The stamp of the code of a run
406
447
 
407
448
  The entry `@mark1russell7/rigor-bench/code-stamp` is for Node only. It uses the optional peer `esbuild`. Add `esbuild` to the dependencies of the caller, so that its lock file pins the version.
package/build/index.d.ts CHANGED
@@ -1147,7 +1147,20 @@ interface SpreadRead {
1147
1147
  readonly tooFew: number;
1148
1148
  /** The largest absolute median paired difference of a pair. */
1149
1149
  readonly widest: number | undefined;
1150
+ /** The real entries with at least one pair that has a read. */
1151
+ readonly entries: number;
1152
+ /** The median, over these entries, of the share of the other entries that a test separates from the entry. A pair with no read does not count in a share. It is undefined with no such entry. */
1153
+ readonly share: number | undefined;
1154
+ /** The entries that a test separates from more than half of the others that they have a read with. */
1155
+ readonly apart: readonly string[];
1156
+ /** Some pair separates and `share` is under `NARROW_SPREAD_SHARE`. A few entries then carry the separated pairs. This field is a report, and no finding reads it. */
1157
+ readonly narrow: boolean;
1150
1158
  }
1159
+ /**
1160
+ * The limit of `SpreadRead.narrow`. This value is a fitted default and not a limit of a gate.
1161
+ * It comes from a gap in the rows of one project, and it has no test on rows that had no part in its choice.
1162
+ */
1163
+ export declare const NARROW_SPREAD_SHARE = .1;
1151
1164
  /** The result of one control and one partner on one stratum. */
1152
1165
  interface PartnerRead {
1153
1166
  readonly partner: string;
@@ -1335,6 +1348,71 @@ interface Power {
1335
1348
  * Each arm of each round adds a normal noise of `sigma` to the log time.
1336
1349
  */
1337
1350
  export declare function verdictPower(options: PowerOptions): Power;
1351
+ /**
1352
+ * The rows that accept a changed result of a bench case. A bench compares two arms, and two arms with different results do not do the same work.
1353
+ * So a difference stops the merge. A pull request can change a result on purpose, and without a stated path its author edits the case, and no gate reads that edit.
1354
+ * A row is that stated path. It names the case and the hash of each result, and it gives a reason. A reviewer can read the row against the run.
1355
+ *
1356
+ * Three rules stop the reuse of a row. The fields `base` and `head` bind the row to one change in one direction. A row counts only if it is new: the rows of the base are spent.
1357
+ * A new row that accepts nothing is a fault. These rules read results only, so the time of an accepted case stays with the time verdict of the bench.
1358
+ */
1359
+ /**
1360
+ * One row: a statement that the result of one case changes on purpose.
1361
+ * The caller uses one hash function for the row and for the run. Two hash functions give a refused line on each row, and each line reads "both sides moved".
1362
+ */
1363
+ interface ResultRow {
1364
+ readonly case: string;
1365
+ /** The hash of the result of the base arm. The caller makes the hash, so a large result stays out of the file of rows. */
1366
+ readonly base: string;
1367
+ /** The hash of the result of the head arm. */
1368
+ readonly head: string;
1369
+ /** The reason for the change, in plain words. The verdict prints it. */
1370
+ readonly reason: string;
1371
+ }
1372
+ /** The hash of the result of one case in each arm. The hashes come from the same function as the hashes of the rows. */
1373
+ interface CaseResults {
1374
+ readonly case: string;
1375
+ readonly base: string;
1376
+ readonly head: string;
1377
+ }
1378
+ /** The rows of the base and of the head. A row of the head that the base also has is spent. */
1379
+ interface ResultRows {
1380
+ readonly base: readonly ResultRow[];
1381
+ readonly head: readonly ResultRow[];
1382
+ }
1383
+ /** The read of one case with two different results. */
1384
+ interface ResultRead extends CaseResults {
1385
+ readonly outcome: "accepted" | "refused";
1386
+ /** The line that the check prints. A refused line gives the path through. */
1387
+ readonly line: string;
1388
+ }
1389
+ /** The read of one new row that accepted nothing. */
1390
+ interface RowRead {
1391
+ readonly row: ResultRow;
1392
+ readonly line: string;
1393
+ }
1394
+ /** A verdict over the results of a run and the rows. */
1395
+ interface ResultVerdict {
1396
+ /** The value "fail" means a refused case, or a new row that accepted nothing. */
1397
+ readonly outcome: "pass" | "fail";
1398
+ /** The cases with two different results. */
1399
+ readonly cases: readonly ResultRead[];
1400
+ /** The new rows of a case with one result, or with another change. Each one fails the verdict. */
1401
+ readonly unused: readonly RowRead[];
1402
+ /** The new rows of a case with no result in this run. The case can be skipped or filtered out. A missing read is no pass, so each one fails the verdict. */
1403
+ readonly absent: readonly RowRead[];
1404
+ /** The rows of the base that the head keeps. They accept nothing, and they do not fail the verdict. */
1405
+ readonly spent: readonly ResultRow[];
1406
+ /** The lines of `cases`, `unused` and `absent`, then one line with the count of `spent`. */
1407
+ readonly lines: readonly string[];
1408
+ }
1409
+ /** This function checks the parsed content of a file of rows. A row with an empty field, or the same row two times, stops the read with an error. */
1410
+ export declare function resultRows(content: unknown): ResultRow[];
1411
+ /**
1412
+ * This function gives the verdict over the results of a run. A case with two different results passes only with a new row of its exact hashes.
1413
+ * The verdict reads results only, so an accepted case still needs its time verdict.
1414
+ */
1415
+ export declare function resultVerdict(results: readonly CaseResults[], rows: ResultRows): ResultVerdict;
1338
1416
  /** The options of the timed rounds of one case. */
1339
1417
  interface RoundsOptions {
1340
1418
  /** The name of the case. */
@@ -1364,5 +1442,5 @@ interface Rounds {
1364
1442
  * keeps the work.
1365
1443
  */
1366
1444
  export declare function timeRounds(arms: Readonly<Record<Arm, () => number>>, options: RoundsOptions): Rounds;
1367
- export { type Arm, type ArmModels, type ArmPair, 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 CaseTail, type CaseTailLimit, 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 JointClaim, type JointControl, type JointMeasure, type JointVerdict, type Ladder, type LadderDimension, type LadderOptions, type LadderVerdict, type LimitOnModel, 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 ModelLimits, type ModelRead, type ModelRow, type ModelStatus, type ModelTest, type ModelTestOptions, type NoControl, type NoFactor, type NoiseCheck, type NotSlowerOptions, type NotSlowerRead, type NotSlowerVerdict, type OrderSize, 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 TailFalseFails, type TailGainCase, type TailLimit, type TailLimitOptions, type TailLimitVerdict, type TailRuleOptions, type TimeOutcome, type TimeVerdict, type VerdictOptions, type VerdictRule, type VisibleShift, type WinClaim, type WorstBudget, armOrder, caseRatios, checkPairedTime, firstArm, orderSize };
1445
+ export { type Arm, type ArmModels, type ArmPair, 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 CaseResults, type CaseTail, type CaseTailLimit, 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 JointClaim, type JointControl, type JointMeasure, type JointVerdict, type Ladder, type LadderDimension, type LadderOptions, type LadderVerdict, type LimitOnModel, 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 ModelLimits, type ModelRead, type ModelRow, type ModelStatus, type ModelTest, type ModelTestOptions, type NoControl, type NoFactor, type NoiseCheck, type NotSlowerOptions, type NotSlowerRead, type NotSlowerVerdict, type OrderSize, 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 ResultRead, type ResultRow, type ResultRows, type ResultVerdict, type Rounds, type RoundsOptions, type RowRead, type RunPairs, type Rung, type RungBudget, type RungEvidence, type RungRecord, type RungVerdict, type SpreadRead, type TailFalseFails, type TailGainCase, type TailLimit, type TailLimitOptions, type TailLimitVerdict, type TailRuleOptions, type TimeOutcome, type TimeVerdict, type VerdictOptions, type VerdictRule, type VisibleShift, type WinClaim, type WorstBudget, armOrder, caseRatios, checkPairedTime, firstArm, orderSize };
1368
1446
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
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/model.ts","../src/tail.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/model.ts","../src/tail.ts","../src/measures.ts","../src/power.ts","../src/results.ts","../src/rounds.ts"],"mappings":"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"}
package/build/index.js CHANGED
@@ -1706,6 +1706,11 @@ function armVerdicts(run, aaPair, options = {}) {
1706
1706
  * from one family of inputs, so they are not independent draws. The p of a test holds only under the sign test's own null: each
1707
1707
  * untied key is a fair coin. A result is about these keys, and this check claims nothing about other inputs.
1708
1708
  */
1709
+ /**
1710
+ * The limit of `SpreadRead.narrow`. This value is a fitted default and not a limit of a gate.
1711
+ * It comes from a gap in the rows of one project, and it has no test on rows that had no part in its choice.
1712
+ */
1713
+ const NARROW_SPREAD_SHARE = .1;
1709
1714
  const DEFAULT_ALPHA = .05;
1710
1715
  const DATE = /^\d{4}-\d{2}-\d{2}$/;
1711
1716
  function checkedDate(name, date) {
@@ -1850,6 +1855,23 @@ function controlReads(measure, control, data, rule, real, alpha) {
1850
1855
  };
1851
1856
  });
1852
1857
  }
1858
+ /** This function reads how many entries carry the separated pairs of one stratum. */
1859
+ function shareRead(here, real) {
1860
+ const shares = real.flatMap((entry) => {
1861
+ const own = here.filter((c) => !unread(c) && (c.better === entry || c.other === entry));
1862
+ return own.length === 0 ? [] : [{
1863
+ entry,
1864
+ share: own.filter((c) => c.beats).length / own.length
1865
+ }];
1866
+ });
1867
+ const share = shares.length === 0 ? void 0 : median(shares.map((s) => s.share));
1868
+ return {
1869
+ entries: shares.length,
1870
+ share,
1871
+ apart: shares.filter((s) => s.share > .5).map((s) => s.entry),
1872
+ narrow: share !== void 0 && share < .1 && here.some((c) => c.beats)
1873
+ };
1874
+ }
1853
1875
  /** The read of the spread of one measure: one family over all pairs of real entries and all strata. */
1854
1876
  function spreadReads(data, rule, real, alpha) {
1855
1877
  const comparisons = corrected([...data].flatMap(([stratum, groups]) => real.flatMap((entry, i) => real.slice(i + 1).flatMap((other) => rawTest(entry, other, stratum, groups, rule.sense) ?? []))), 2, alpha, rule);
@@ -1862,7 +1884,8 @@ function spreadReads(data, rule, real, alpha) {
1862
1884
  pairs: here.length,
1863
1885
  separated: here.filter((c) => c.beats).length,
1864
1886
  tooFew: here.filter(unread).length,
1865
- widest
1887
+ widest,
1888
+ ...shareRead(here, real)
1866
1889
  };
1867
1890
  }),
1868
1891
  comparisons
@@ -2295,6 +2318,110 @@ function trueOutcome(ratio, verdict = {}) {
2295
2318
  if ((verdict.rule ?? "difference") === "difference" && Math.abs(Math.log(ratio)) <= verdictMargin(verdict)) return "same";
2296
2319
  return ratio < 1 ? "faster" : ratio > 1 ? "slower" : "same";
2297
2320
  }
2321
+ // src/results.ts
2322
+ const keyOf = (row) => JSON.stringify([
2323
+ row.case,
2324
+ row.base,
2325
+ row.head
2326
+ ]);
2327
+ /** This function checks the parsed content of a file of rows. A row with an empty field, or the same row two times, stops the read with an error. */
2328
+ function resultRows(content) {
2329
+ if (!Array.isArray(content)) throw new Error("resultRows: the rows are an array.");
2330
+ const known = /* @__PURE__ */ new Set();
2331
+ return content.map((item, index) => {
2332
+ const row = typeof item === "object" && item !== null ? item : {};
2333
+ const where = `resultRows: row ${String(index)}`;
2334
+ const { case: name, base, head, reason } = row;
2335
+ if (typeof name !== "string" || name === "") throw new Error(`${where} has no case.`);
2336
+ if (typeof base !== "string" || base === "") throw new Error(`${where} has no hash of the base.`);
2337
+ if (typeof head !== "string" || head === "") throw new Error(`${where} has no hash of the head.`);
2338
+ if (typeof reason !== "string" || reason.trim() === "") throw new Error(`${where} has no reason.`);
2339
+ const key = keyOf({
2340
+ case: name,
2341
+ base,
2342
+ head
2343
+ });
2344
+ if (known.has(key)) throw new Error(`${where} repeats the case ${JSON.stringify(name)} with the same hashes.`);
2345
+ known.add(key);
2346
+ return {
2347
+ case: name,
2348
+ base,
2349
+ head,
2350
+ reason
2351
+ };
2352
+ });
2353
+ }
2354
+ /** This function tells which side of a run differs from a row. */
2355
+ function moved(item, row) {
2356
+ if (item.base !== row.base && item.head !== row.head) return "both sides moved";
2357
+ return item.base !== row.base ? "the base moved" : "the head moved";
2358
+ }
2359
+ /** This function gives the line of a case that no row accepts. */
2360
+ function refusal(item, live, spent) {
2361
+ const start = `The case ${JSON.stringify(item.case)} gives two different results`;
2362
+ if (spent.has(keyOf(item))) return `${start}, and the base already has the row of this change, so that row is spent. Delete that row in its own pull request, then add the row again.`;
2363
+ const others = live.filter((row) => row.case === item.case);
2364
+ const read = `base ${item.base} and head ${item.head}`;
2365
+ if (others.length > 0) return `${start}: ${read}. ${others.map((row) => `A row accepts base ${row.base} and head ${row.head}, so ${moved(item, row)}.`).join(" ")}`;
2366
+ return `${start}, and no row accepts them. To accept this change, add the row ${JSON.stringify({
2367
+ case: item.case,
2368
+ base: item.base,
2369
+ head: item.head,
2370
+ reason: "the reason for the change"
2371
+ })} in this pull request.`;
2372
+ }
2373
+ /**
2374
+ * This function gives the verdict over the results of a run. A case with two different results passes only with a new row of its exact hashes.
2375
+ * The verdict reads results only, so an accepted case still needs its time verdict.
2376
+ */
2377
+ function resultVerdict(results, rows) {
2378
+ const spentKeys = new Set(rows.base.map(keyOf));
2379
+ const live = rows.head.filter((row) => !spentKeys.has(keyOf(row)));
2380
+ const used = /* @__PURE__ */ new Set();
2381
+ const cases = results.filter((item) => item.base !== item.head).map((item) => {
2382
+ const row = live.find((other) => keyOf(other) === keyOf(item));
2383
+ if (row === void 0) return {
2384
+ case: item.case,
2385
+ base: item.base,
2386
+ head: item.head,
2387
+ outcome: "refused",
2388
+ line: refusal(item, live, spentKeys)
2389
+ };
2390
+ used.add(keyOf(row));
2391
+ return {
2392
+ case: item.case,
2393
+ base: item.base,
2394
+ head: item.head,
2395
+ outcome: "accepted",
2396
+ line: `The case ${JSON.stringify(item.case)} changes its result from ${item.base} to ${item.head}, and a row accepts this: ${row.reason}`
2397
+ };
2398
+ });
2399
+ const named = new Set(results.map((item) => item.case));
2400
+ const idle = live.filter((row) => !used.has(keyOf(row)));
2401
+ const unused = idle.filter((row) => named.has(row.case)).map((row) => ({
2402
+ row,
2403
+ line: `The new row of the case ${JSON.stringify(row.case)} accepts no change of this run. Delete or correct the row.`
2404
+ }));
2405
+ const absent = idle.filter((row) => !named.has(row.case)).map((row) => ({
2406
+ row,
2407
+ line: `The new row of the case ${JSON.stringify(row.case)} has no read: the case has no result in this run.`
2408
+ }));
2409
+ const spent = rows.head.filter((row) => spentKeys.has(keyOf(row)));
2410
+ const fails = cases.some((item) => item.outcome === "refused") || unused.length > 0 || absent.length > 0;
2411
+ const count = spent.length > 0 ? [`The spent rows: ${String(spent.length)}. The base has them, so they accept nothing.`] : [];
2412
+ return {
2413
+ outcome: fails ? "fail" : "pass",
2414
+ cases,
2415
+ unused,
2416
+ absent,
2417
+ spent,
2418
+ lines: [...[
2419
+ ...cases,
2420
+ ...unused,
2421
+ ...absent
2422
+ ].map((item) => item.line), ...count]
2423
+ };
2424
+ }
2298
2425
  // src/rounds.ts
2299
2426
  /**
2300
2427
  * The timed rounds of one case in one process. The two arms first run for a warm-up time. Then the count of calls of
@@ -2351,6 +2478,6 @@ function timeRounds(arms, options) {
2351
2478
  sink
2352
2479
  };
2353
2480
  }
2354
- export { BUDGET_LOOKS, CEILING_ONLY, GATE_LOOKS, LADDER_FORMAT, UNKNOWN_MODEL, aaBand, aaSpread, armModels, armOrder, armVerdicts, balanceOrders, budgetLookSpend, budgetLooksVerdict, budgetVerdict, caseIntervals, caseRatios, caseTails, checkLadder, checkMeasures, checkPairedTime, controlFactor, firstArm, gateOf, jointClaim, ladderVerdict, limitOnModel, limitVerdict, modelRowText, modelTest, notSlowerVerdict, orderSize, poolRecords, pooledBand, pooledLimitVerdict, pooledVerdict, rungVerdict, tailFalseFails, tailLimitVerdict, timeRounds, timeVerdict, verdictMargin, verdictPower, visibleShift, winClaim };
2481
+ export { BUDGET_LOOKS, CEILING_ONLY, GATE_LOOKS, LADDER_FORMAT, NARROW_SPREAD_SHARE, UNKNOWN_MODEL, aaBand, aaSpread, armModels, armOrder, armVerdicts, balanceOrders, budgetLookSpend, budgetLooksVerdict, budgetVerdict, caseIntervals, caseRatios, caseTails, checkLadder, checkMeasures, checkPairedTime, controlFactor, firstArm, gateOf, jointClaim, ladderVerdict, limitOnModel, limitVerdict, modelRowText, modelTest, notSlowerVerdict, orderSize, poolRecords, pooledBand, pooledLimitVerdict, pooledVerdict, resultRows, resultVerdict, rungVerdict, tailFalseFails, tailLimitVerdict, timeRounds, timeVerdict, verdictMargin, verdictPower, visibleShift, winClaim };
2355
2482
 
2356
2483
  //# sourceMappingURL=index.js.map