@uptimizr/db 2.0.1 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +228 -3
- package/README.md +13 -0
- package/dist/duckdb/migrations.d.ts.map +1 -1
- package/dist/duckdb/migrations.js +169 -0
- package/dist/duckdb/migrations.js.map +1 -1
- package/dist/duckdb/panelSpecs.d.ts +29 -0
- package/dist/duckdb/panelSpecs.d.ts.map +1 -0
- package/dist/duckdb/panelSpecs.js +104 -0
- package/dist/duckdb/panelSpecs.js.map +1 -0
- package/dist/duckdb/projectMetadata.d.ts +43 -0
- package/dist/duckdb/projectMetadata.d.ts.map +1 -0
- package/dist/duckdb/projectMetadata.js +222 -0
- package/dist/duckdb/projectMetadata.js.map +1 -0
- package/dist/duckdb/subscriptions.d.ts +45 -0
- package/dist/duckdb/subscriptions.d.ts.map +1 -0
- package/dist/duckdb/subscriptions.js +202 -0
- package/dist/duckdb/subscriptions.js.map +1 -0
- package/dist/index.d.ts +18 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +48 -3
- package/dist/index.js.map +1 -1
- package/dist/insights/anomalies.d.ts +213 -0
- package/dist/insights/anomalies.d.ts.map +1 -0
- package/dist/insights/anomalies.js +340 -0
- package/dist/insights/anomalies.js.map +1 -0
- package/dist/insights/baseline.d.ts +51 -0
- package/dist/insights/baseline.d.ts.map +1 -0
- package/dist/insights/baseline.js +48 -0
- package/dist/insights/baseline.js.map +1 -0
- package/dist/insights/buckets.d.ts +114 -0
- package/dist/insights/buckets.d.ts.map +1 -0
- package/dist/insights/buckets.js +220 -0
- package/dist/insights/buckets.js.map +1 -0
- package/dist/insights/changepoint.d.ts +130 -0
- package/dist/insights/changepoint.d.ts.map +1 -0
- package/dist/insights/changepoint.js +209 -0
- package/dist/insights/changepoint.js.map +1 -0
- package/dist/insights/evaluate.d.ts +63 -0
- package/dist/insights/evaluate.d.ts.map +1 -0
- package/dist/insights/evaluate.js +158 -0
- package/dist/insights/evaluate.js.map +1 -0
- package/dist/insights/health.d.ts +219 -0
- package/dist/insights/health.d.ts.map +1 -0
- package/dist/insights/health.js +349 -0
- package/dist/insights/health.js.map +1 -0
- package/dist/insights/index.d.ts +45 -0
- package/dist/insights/index.d.ts.map +1 -0
- package/dist/insights/index.js +40 -0
- package/dist/insights/index.js.map +1 -0
- package/dist/insights/measures.d.ts +222 -0
- package/dist/insights/measures.d.ts.map +1 -0
- package/dist/insights/measures.js +431 -0
- package/dist/insights/measures.js.map +1 -0
- package/dist/insights/movers.d.ts +123 -0
- package/dist/insights/movers.d.ts.map +1 -0
- package/dist/insights/movers.js +166 -0
- package/dist/insights/movers.js.map +1 -0
- package/dist/insights/significance.d.ts +221 -0
- package/dist/insights/significance.d.ts.map +1 -0
- package/dist/insights/significance.js +531 -0
- package/dist/insights/significance.js.map +1 -0
- package/dist/insights/stats.d.ts +104 -0
- package/dist/insights/stats.d.ts.map +1 -0
- package/dist/insights/stats.js +181 -0
- package/dist/insights/stats.js.map +1 -0
- package/dist/insights/windows.d.ts +95 -0
- package/dist/insights/windows.d.ts.map +1 -0
- package/dist/insights/windows.js +97 -0
- package/dist/insights/windows.js.map +1 -0
- package/dist/metadata.d.ts +178 -1
- package/dist/metadata.d.ts.map +1 -1
- package/dist/metadata.js +80 -0
- package/dist/metadata.js.map +1 -1
- package/dist/narrative/build.d.ts +78 -0
- package/dist/narrative/build.d.ts.map +1 -0
- package/dist/narrative/build.js +437 -0
- package/dist/narrative/build.js.map +1 -0
- package/dist/narrative/index.d.ts +14 -0
- package/dist/narrative/index.d.ts.map +1 -0
- package/dist/narrative/index.js +13 -0
- package/dist/narrative/index.js.map +1 -0
- package/dist/narrative/text.d.ts +25 -0
- package/dist/narrative/text.d.ts.map +1 -0
- package/dist/narrative/text.js +41 -0
- package/dist/narrative/text.js.map +1 -0
- package/dist/parity/cases.d.ts +3 -0
- package/dist/parity/cases.d.ts.map +1 -1
- package/dist/parity/cases.js +387 -7
- package/dist/parity/cases.js.map +1 -1
- package/dist/parity/compare.d.ts +19 -0
- package/dist/parity/compare.d.ts.map +1 -1
- package/dist/parity/compare.js +19 -0
- package/dist/parity/compare.js.map +1 -1
- package/dist/parity/fixtures.d.ts.map +1 -1
- package/dist/parity/fixtures.js +25 -0
- package/dist/parity/fixtures.js.map +1 -1
- package/dist/query/aggregations.d.ts +46 -1
- package/dist/query/aggregations.d.ts.map +1 -1
- package/dist/query/aggregations.js +86 -0
- package/dist/query/aggregations.js.map +1 -1
- package/dist/query/clickhouseDialect.d.ts.map +1 -1
- package/dist/query/clickhouseDialect.js +5 -1
- package/dist/query/clickhouseDialect.js.map +1 -1
- package/dist/query/customEventVocabulary.d.ts +46 -0
- package/dist/query/customEventVocabulary.d.ts.map +1 -0
- package/dist/query/customEventVocabulary.js +127 -0
- package/dist/query/customEventVocabulary.js.map +1 -0
- package/dist/query/dsl/builders.d.ts +38 -0
- package/dist/query/dsl/builders.d.ts.map +1 -0
- package/dist/query/dsl/builders.js +35 -0
- package/dist/query/dsl/builders.js.map +1 -0
- package/dist/query/dsl/compare.d.ts +167 -0
- package/dist/query/dsl/compare.d.ts.map +1 -0
- package/dist/query/dsl/compare.js +358 -0
- package/dist/query/dsl/compare.js.map +1 -0
- package/dist/query/dsl/compile.d.ts +89 -0
- package/dist/query/dsl/compile.d.ts.map +1 -0
- package/dist/query/dsl/compile.js +174 -0
- package/dist/query/dsl/compile.js.map +1 -0
- package/dist/query/dsl/explain.d.ts +115 -0
- package/dist/query/dsl/explain.d.ts.map +1 -0
- package/dist/query/dsl/explain.js +143 -0
- package/dist/query/dsl/explain.js.map +1 -0
- package/dist/query/dsl/generic.d.ts +127 -0
- package/dist/query/dsl/generic.d.ts.map +1 -0
- package/dist/query/dsl/generic.js +323 -0
- package/dist/query/dsl/generic.js.map +1 -0
- package/dist/query/dsl/index.d.ts +30 -0
- package/dist/query/dsl/index.d.ts.map +1 -0
- package/dist/query/dsl/index.js +23 -0
- package/dist/query/dsl/index.js.map +1 -0
- package/dist/query/dsl/order.d.ts +41 -0
- package/dist/query/dsl/order.d.ts.map +1 -0
- package/dist/query/dsl/order.js +55 -0
- package/dist/query/dsl/order.js.map +1 -0
- package/dist/query/dsl/significance.d.ts +130 -0
- package/dist/query/dsl/significance.d.ts.map +1 -0
- package/dist/query/dsl/significance.js +224 -0
- package/dist/query/dsl/significance.js.map +1 -0
- package/dist/query/index.d.ts +2 -0
- package/dist/query/index.d.ts.map +1 -1
- package/dist/query/index.js +8 -0
- package/dist/query/index.js.map +1 -1
- package/dist/query/summary/index.d.ts +4 -2
- package/dist/query/summary/index.d.ts.map +1 -1
- package/dist/query/summary/index.js +2 -1
- package/dist/query/summary/index.js.map +1 -1
- package/dist/query/summary/labels.d.ts +101 -0
- package/dist/query/summary/labels.d.ts.map +1 -0
- package/dist/query/summary/labels.js +261 -0
- package/dist/query/summary/labels.js.map +1 -0
- package/dist/query/summary/reading.d.ts.map +1 -1
- package/dist/query/summary/reading.js +21 -2
- package/dist/query/summary/reading.js.map +1 -1
- package/dist/query/summary/schema.d.ts +250 -20
- package/dist/query/summary/schema.d.ts.map +1 -1
- package/dist/query/summary/schema.js +135 -123
- package/dist/query/summary/schema.js.map +1 -1
- package/dist/query/summary/summarize.d.ts.map +1 -1
- package/dist/query/summary/summarize.js +91 -5
- package/dist/query/summary/summarize.js.map +1 -1
- package/dist/query/summary/types.d.ts +77 -2
- package/dist/query/summary/types.d.ts.map +1 -1
- package/dist/query/types.d.ts +47 -1
- package/dist/query/types.d.ts.map +1 -1
- package/dist/subscriptions.d.ts +208 -0
- package/dist/subscriptions.d.ts.map +1 -0
- package/dist/subscriptions.js +153 -0
- package/dist/subscriptions.js.map +1 -0
- package/llms.txt +9 -0
- package/package.json +8 -8
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"measures.js","sourceRoot":"","sources":["../../src/insights/measures.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* **`movers`** — "what changed since last week?" (ADR 0051 §4, sketch §D).
|
|
3
|
+
*
|
|
4
|
+
* For every comparable metric in scope, compares the current window against a
|
|
5
|
+
* reference window and ranks the differences by a **robust z-score**:
|
|
6
|
+
* `delta / (MAD of the reference bucket series + ε)`. The MAD is what makes the
|
|
7
|
+
* ranking trustworthy — a metric that swings by 30% every day has to move far
|
|
8
|
+
* more than one that never moves before it is called a mover, and no threshold
|
|
9
|
+
* has to be configured per metric to say so.
|
|
10
|
+
*
|
|
11
|
+
* Pure: it takes, per metric, the bucket series that `buildMetricBuckets`
|
|
12
|
+
* produced over the combined window, plus the registry's comparison semantics,
|
|
13
|
+
* and returns the ranked rows. No store, no request, no dialect.
|
|
14
|
+
*
|
|
15
|
+
* ## Small samples are reported, never silently dropped
|
|
16
|
+
*
|
|
17
|
+
* A delta computed from eleven events is not evidence, but hiding it is its own
|
|
18
|
+
* failure mode: an agent asked "did anything change?" would be told "no" when
|
|
19
|
+
* the honest answer is "nothing with enough data behind it". So every metric
|
|
20
|
+
* keeps its row and carries `aboveMinSample`, and the *ranking* is what enforces
|
|
21
|
+
* the gate — gated movers sort above every ungated one, so the top of the list
|
|
22
|
+
* is always the part worth reading (the acceptance criterion "movers never
|
|
23
|
+
* reports a delta below `minSample` as meaningful").
|
|
24
|
+
*/
|
|
25
|
+
import type { MetricBucketRow } from "./buckets.js";
|
|
26
|
+
import type { BucketRollup } from "./measures.js";
|
|
27
|
+
/** Everything `rankMovers` needs about one metric. */
|
|
28
|
+
export interface MoverInput {
|
|
29
|
+
/** Registry metric id. */
|
|
30
|
+
metric: string;
|
|
31
|
+
/** `comparable.direction` — whether a rise is good, bad or merely a fact. */
|
|
32
|
+
direction: "up" | "down" | "neutral";
|
|
33
|
+
/** `comparable.minSample` — the denominator below which a delta is not evidence. */
|
|
34
|
+
minSample: number;
|
|
35
|
+
/** How the metric's bucket values combine into a window value. */
|
|
36
|
+
rollup: BucketRollup;
|
|
37
|
+
/** Buckets inside the current range. */
|
|
38
|
+
current: readonly MetricBucketRow[];
|
|
39
|
+
/** Buckets inside the reference range. */
|
|
40
|
+
reference: readonly MetricBucketRow[];
|
|
41
|
+
}
|
|
42
|
+
/** One ranked mover. */
|
|
43
|
+
export interface MoverRow {
|
|
44
|
+
metric: string;
|
|
45
|
+
/**
|
|
46
|
+
* The dimension value this move is attributed to, or `null`.
|
|
47
|
+
*
|
|
48
|
+
* Always `null` in v1: movers are computed at the scene (or project) level.
|
|
49
|
+
* The per-dimension attribution — "the drop is almost all on mobile" — is the
|
|
50
|
+
* `contributor` work that arrives with `anomalies` (ADR 0051 §4); the column
|
|
51
|
+
* exists now so that adding it later is not a breaking change to the row.
|
|
52
|
+
*/
|
|
53
|
+
dimensionValue: string | null;
|
|
54
|
+
/** The metric's primary column over the current range. */
|
|
55
|
+
current: number | null;
|
|
56
|
+
/** The same over the reference range. */
|
|
57
|
+
previous: number | null;
|
|
58
|
+
/** `current − previous`. */
|
|
59
|
+
delta: number | null;
|
|
60
|
+
/** `delta / |previous|`; `null` when `previous` is zero or missing. */
|
|
61
|
+
deltaPct: number | null;
|
|
62
|
+
/** Robust z: `delta / (MAD of the reference bucket series + ε)`. */
|
|
63
|
+
z: number | null;
|
|
64
|
+
direction: "up" | "down" | "neutral";
|
|
65
|
+
/** Whether the current range cleared the metric's `minSample`. */
|
|
66
|
+
aboveMinSample: boolean;
|
|
67
|
+
/** The current range's denominator — what `aboveMinSample` was decided on. */
|
|
68
|
+
sampleSize: number;
|
|
69
|
+
}
|
|
70
|
+
/** Decimals a mover's numbers are rounded to before they leave the API. */
|
|
71
|
+
export declare const MOVERS_PRECISION = 6;
|
|
72
|
+
/**
|
|
73
|
+
* Floor on the reference spread, as a fraction of the reference level.
|
|
74
|
+
*
|
|
75
|
+
* A short reference window routinely has a MAD of exactly 0 — a single bucket
|
|
76
|
+
* always does, and so does any window whose buckets happen to be equal. Dividing
|
|
77
|
+
* by it (well, by `0 + ε`) is finite but useless: every such metric scores in the
|
|
78
|
+
* billions, and since they all divide by the same tiny constant their *relative*
|
|
79
|
+
* order degenerates into a comparison of raw deltas across incompatible units —
|
|
80
|
+
* 37 sessions ranked against 17.8 FPS.
|
|
81
|
+
*
|
|
82
|
+
* So the spread a mover divides by is the MAD **or** 1% of the reference level,
|
|
83
|
+
* whichever is larger: a metric sitting at 60 FPS is never treated as having
|
|
84
|
+
* less than 0.6 FPS of ordinary variation. That keeps `z` readable, keeps the
|
|
85
|
+
* ranking a comparison of proportional moves, and costs nothing where the MAD is
|
|
86
|
+
* genuinely informative — a real MAD is almost always well above 1% of the
|
|
87
|
+
* level, so the floor simply does not bind.
|
|
88
|
+
*
|
|
89
|
+
* A reference that is flat *at zero* has no level either, so it falls through to
|
|
90
|
+
* the epsilon in {@link robustZ} and scores very large. That is the honest
|
|
91
|
+
* reading — the first event of its kind is unprecedented — and `aboveMinSample`
|
|
92
|
+
* is what stops it being reported as a finding.
|
|
93
|
+
*/
|
|
94
|
+
export declare const MIN_SPREAD_FRACTION = 0.01;
|
|
95
|
+
/**
|
|
96
|
+
* The spread a change is measured against: the reference series' MAD, floored at
|
|
97
|
+
* {@link MIN_SPREAD_FRACTION} of its level. `null` when the reference is empty.
|
|
98
|
+
*/
|
|
99
|
+
export declare function referenceSpread(values: readonly number[]): number | null;
|
|
100
|
+
/**
|
|
101
|
+
* Collapse a window's buckets into the one number the metric's primary column
|
|
102
|
+
* means over that window.
|
|
103
|
+
*
|
|
104
|
+
* Additive quantities sum; levels (an FPS median, a heap percentile) average,
|
|
105
|
+
* because adding two days' median FPS together produces a number that means
|
|
106
|
+
* nothing — the same rule the `format=summary` series envelope applies.
|
|
107
|
+
* `null` when the window carried no value at all.
|
|
108
|
+
*/
|
|
109
|
+
export declare function rollupWindow(values: readonly number[], rollup: BucketRollup): number | null;
|
|
110
|
+
/** Compute one metric's mover row, unranked. */
|
|
111
|
+
export declare function computeMover(input: MoverInput): MoverRow;
|
|
112
|
+
/**
|
|
113
|
+
* Rank a set of metrics into the top `limit` risers and the top `limit` fallers.
|
|
114
|
+
*
|
|
115
|
+
* A metric appears at most once — the sign of its `z` decides which half it
|
|
116
|
+
* belongs to. Metrics whose `z` could not be computed (no reference data, so no
|
|
117
|
+
* spread to compare against) are reported at the end of whichever half their
|
|
118
|
+
* `delta` points at, and last of all when even that is unknown, rather than
|
|
119
|
+
* being dropped: "we could not tell" is a different answer from "nothing
|
|
120
|
+
* changed".
|
|
121
|
+
*/
|
|
122
|
+
export declare function rankMovers(inputs: readonly MoverInput[], limit: number): MoverRow[];
|
|
123
|
+
//# sourceMappingURL=movers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"movers.d.ts","sourceRoot":"","sources":["../../src/insights/movers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAGH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAElD,sDAAsD;AACtD,MAAM,WAAW,UAAU;IACzB,0BAA0B;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,6EAA6E;IAC7E,SAAS,EAAE,IAAI,GAAG,MAAM,GAAG,SAAS,CAAC;IACrC,oFAAoF;IACpF,SAAS,EAAE,MAAM,CAAC;IAClB,kEAAkE;IAClE,MAAM,EAAE,YAAY,CAAC;IACrB,wCAAwC;IACxC,OAAO,EAAE,SAAS,eAAe,EAAE,CAAC;IACpC,0CAA0C;IAC1C,SAAS,EAAE,SAAS,eAAe,EAAE,CAAC;CACvC;AAED,wBAAwB;AACxB,MAAM,WAAW,QAAQ;IACvB,MAAM,EAAE,MAAM,CAAC;IACf;;;;;;;OAOG;IACH,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,0DAA0D;IAC1D,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,yCAAyC;IACzC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,4BAA4B;IAC5B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,uEAAuE;IACvE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,oEAAoE;IACpE,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACjB,SAAS,EAAE,IAAI,GAAG,MAAM,GAAG,SAAS,CAAC;IACrC,kEAAkE;IAClE,cAAc,EAAE,OAAO,CAAC;IACxB,8EAA8E;IAC9E,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,2EAA2E;AAC3E,eAAO,MAAM,gBAAgB,IAAI,CAAC;AAElC;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,mBAAmB,OAAO,CAAC;AAExC;;;GAGG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,GAAG,IAAI,CAKxE;AAiBD;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,EAAE,MAAM,EAAE,YAAY,GAAG,MAAM,GAAG,IAAI,CAK3F;AAED,gDAAgD;AAChD,wBAAgB,YAAY,CAAC,KAAK,EAAE,UAAU,GAAG,QAAQ,CAyBxD;AAeD;;;;;;;;;GASG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,SAAS,UAAU,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,QAAQ,EAAE,CAkBnF"}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* **`movers`** — "what changed since last week?" (ADR 0051 §4, sketch §D).
|
|
3
|
+
*
|
|
4
|
+
* For every comparable metric in scope, compares the current window against a
|
|
5
|
+
* reference window and ranks the differences by a **robust z-score**:
|
|
6
|
+
* `delta / (MAD of the reference bucket series + ε)`. The MAD is what makes the
|
|
7
|
+
* ranking trustworthy — a metric that swings by 30% every day has to move far
|
|
8
|
+
* more than one that never moves before it is called a mover, and no threshold
|
|
9
|
+
* has to be configured per metric to say so.
|
|
10
|
+
*
|
|
11
|
+
* Pure: it takes, per metric, the bucket series that `buildMetricBuckets`
|
|
12
|
+
* produced over the combined window, plus the registry's comparison semantics,
|
|
13
|
+
* and returns the ranked rows. No store, no request, no dialect.
|
|
14
|
+
*
|
|
15
|
+
* ## Small samples are reported, never silently dropped
|
|
16
|
+
*
|
|
17
|
+
* A delta computed from eleven events is not evidence, but hiding it is its own
|
|
18
|
+
* failure mode: an agent asked "did anything change?" would be told "no" when
|
|
19
|
+
* the honest answer is "nothing with enough data behind it". So every metric
|
|
20
|
+
* keeps its row and carries `aboveMinSample`, and the *ranking* is what enforces
|
|
21
|
+
* the gate — gated movers sort above every ungated one, so the top of the list
|
|
22
|
+
* is always the part worth reading (the acceptance criterion "movers never
|
|
23
|
+
* reports a delta below `minSample` as meaningful").
|
|
24
|
+
*/
|
|
25
|
+
import { median, medianAbsoluteDeviation, relativeChange, robustZ, round } from "./stats.js";
|
|
26
|
+
/** Decimals a mover's numbers are rounded to before they leave the API. */
|
|
27
|
+
export const MOVERS_PRECISION = 6;
|
|
28
|
+
/**
|
|
29
|
+
* Floor on the reference spread, as a fraction of the reference level.
|
|
30
|
+
*
|
|
31
|
+
* A short reference window routinely has a MAD of exactly 0 — a single bucket
|
|
32
|
+
* always does, and so does any window whose buckets happen to be equal. Dividing
|
|
33
|
+
* by it (well, by `0 + ε`) is finite but useless: every such metric scores in the
|
|
34
|
+
* billions, and since they all divide by the same tiny constant their *relative*
|
|
35
|
+
* order degenerates into a comparison of raw deltas across incompatible units —
|
|
36
|
+
* 37 sessions ranked against 17.8 FPS.
|
|
37
|
+
*
|
|
38
|
+
* So the spread a mover divides by is the MAD **or** 1% of the reference level,
|
|
39
|
+
* whichever is larger: a metric sitting at 60 FPS is never treated as having
|
|
40
|
+
* less than 0.6 FPS of ordinary variation. That keeps `z` readable, keeps the
|
|
41
|
+
* ranking a comparison of proportional moves, and costs nothing where the MAD is
|
|
42
|
+
* genuinely informative — a real MAD is almost always well above 1% of the
|
|
43
|
+
* level, so the floor simply does not bind.
|
|
44
|
+
*
|
|
45
|
+
* A reference that is flat *at zero* has no level either, so it falls through to
|
|
46
|
+
* the epsilon in {@link robustZ} and scores very large. That is the honest
|
|
47
|
+
* reading — the first event of its kind is unprecedented — and `aboveMinSample`
|
|
48
|
+
* is what stops it being reported as a finding.
|
|
49
|
+
*/
|
|
50
|
+
export const MIN_SPREAD_FRACTION = 0.01;
|
|
51
|
+
/**
|
|
52
|
+
* The spread a change is measured against: the reference series' MAD, floored at
|
|
53
|
+
* {@link MIN_SPREAD_FRACTION} of its level. `null` when the reference is empty.
|
|
54
|
+
*/
|
|
55
|
+
export function referenceSpread(values) {
|
|
56
|
+
const mad = medianAbsoluteDeviation(values);
|
|
57
|
+
if (mad == null)
|
|
58
|
+
return null;
|
|
59
|
+
const centre = median(values) ?? 0;
|
|
60
|
+
return Math.max(mad, Math.abs(centre) * MIN_SPREAD_FRACTION);
|
|
61
|
+
}
|
|
62
|
+
/** The finite values of a bucket series, in bucket order. */
|
|
63
|
+
function valuesOf(rows) {
|
|
64
|
+
return [...rows]
|
|
65
|
+
.sort((a, b) => a.bucket - b.bucket)
|
|
66
|
+
.map((row) => row.value)
|
|
67
|
+
.filter((value) => value != null && Number.isFinite(value));
|
|
68
|
+
}
|
|
69
|
+
/** The denominator behind a window: the sum of its buckets' sample sizes. */
|
|
70
|
+
function sampleOf(rows) {
|
|
71
|
+
let total = 0;
|
|
72
|
+
for (const row of rows)
|
|
73
|
+
if (Number.isFinite(row.sample_size))
|
|
74
|
+
total += row.sample_size;
|
|
75
|
+
return total;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Collapse a window's buckets into the one number the metric's primary column
|
|
79
|
+
* means over that window.
|
|
80
|
+
*
|
|
81
|
+
* Additive quantities sum; levels (an FPS median, a heap percentile) average,
|
|
82
|
+
* because adding two days' median FPS together produces a number that means
|
|
83
|
+
* nothing — the same rule the `format=summary` series envelope applies.
|
|
84
|
+
* `null` when the window carried no value at all.
|
|
85
|
+
*/
|
|
86
|
+
export function rollupWindow(values, rollup) {
|
|
87
|
+
if (values.length === 0)
|
|
88
|
+
return null;
|
|
89
|
+
let total = 0;
|
|
90
|
+
for (const value of values)
|
|
91
|
+
total += value;
|
|
92
|
+
return rollup === "sum" ? total : total / values.length;
|
|
93
|
+
}
|
|
94
|
+
/** Compute one metric's mover row, unranked. */
|
|
95
|
+
export function computeMover(input) {
|
|
96
|
+
const currentValues = valuesOf(input.current);
|
|
97
|
+
const referenceValues = valuesOf(input.reference);
|
|
98
|
+
const current = rollupWindow(currentValues, input.rollup);
|
|
99
|
+
const previous = rollupWindow(referenceValues, input.rollup);
|
|
100
|
+
const delta = current != null && previous != null ? current - previous : null;
|
|
101
|
+
// The spread is taken over the **reference** bucket series: "how unusual is
|
|
102
|
+
// this move compared with how this metric normally behaved" — using the
|
|
103
|
+
// current window's own spread would let a newly-volatile metric hide its own
|
|
104
|
+
// change inside its new volatility.
|
|
105
|
+
const mad = referenceSpread(referenceValues);
|
|
106
|
+
const sampleSize = sampleOf(input.current);
|
|
107
|
+
return {
|
|
108
|
+
metric: input.metric,
|
|
109
|
+
dimensionValue: null,
|
|
110
|
+
current: round(current, MOVERS_PRECISION),
|
|
111
|
+
previous: round(previous, MOVERS_PRECISION),
|
|
112
|
+
delta: round(delta, MOVERS_PRECISION),
|
|
113
|
+
deltaPct: round(relativeChange(current, previous), MOVERS_PRECISION),
|
|
114
|
+
z: round(robustZ(delta, mad), MOVERS_PRECISION),
|
|
115
|
+
direction: input.direction,
|
|
116
|
+
aboveMinSample: sampleSize >= input.minSample,
|
|
117
|
+
sampleSize,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Order two rows "most notable first": gated movers before ungated ones, then by
|
|
122
|
+
* the magnitude of `z`, then by metric id so the order is a function of the row
|
|
123
|
+
* set rather than of the order the metrics happened to be scanned in.
|
|
124
|
+
*/
|
|
125
|
+
function byNotability(a, b) {
|
|
126
|
+
if (a.aboveMinSample !== b.aboveMinSample)
|
|
127
|
+
return a.aboveMinSample ? -1 : 1;
|
|
128
|
+
const left = a.z == null ? -1 : Math.abs(a.z);
|
|
129
|
+
const right = b.z == null ? -1 : Math.abs(b.z);
|
|
130
|
+
if (left !== right)
|
|
131
|
+
return right - left;
|
|
132
|
+
return a.metric < b.metric ? -1 : a.metric > b.metric ? 1 : 0;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Rank a set of metrics into the top `limit` risers and the top `limit` fallers.
|
|
136
|
+
*
|
|
137
|
+
* A metric appears at most once — the sign of its `z` decides which half it
|
|
138
|
+
* belongs to. Metrics whose `z` could not be computed (no reference data, so no
|
|
139
|
+
* spread to compare against) are reported at the end of whichever half their
|
|
140
|
+
* `delta` points at, and last of all when even that is unknown, rather than
|
|
141
|
+
* being dropped: "we could not tell" is a different answer from "nothing
|
|
142
|
+
* changed".
|
|
143
|
+
*/
|
|
144
|
+
export function rankMovers(inputs, limit) {
|
|
145
|
+
const rows = inputs.map(computeMover);
|
|
146
|
+
const up = [];
|
|
147
|
+
const down = [];
|
|
148
|
+
const unknown = [];
|
|
149
|
+
for (const row of rows) {
|
|
150
|
+
const signal = row.z ?? row.delta;
|
|
151
|
+
if (signal == null || signal === 0)
|
|
152
|
+
unknown.push(row);
|
|
153
|
+
else if (signal > 0)
|
|
154
|
+
up.push(row);
|
|
155
|
+
else
|
|
156
|
+
down.push(row);
|
|
157
|
+
}
|
|
158
|
+
up.sort(byNotability);
|
|
159
|
+
down.sort(byNotability);
|
|
160
|
+
unknown.sort(byNotability);
|
|
161
|
+
const capped = Math.max(0, limit);
|
|
162
|
+
// Risers first, then fallers, then the flat/undetermined tail — the tail is
|
|
163
|
+
// capped too, so the response stays bounded even when nothing moved.
|
|
164
|
+
return [...up.slice(0, capped), ...down.slice(0, capped), ...unknown.slice(0, capped)];
|
|
165
|
+
}
|
|
166
|
+
//# sourceMappingURL=movers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"movers.js","sourceRoot":"","sources":["../../src/insights/movers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAE,MAAM,EAAE,uBAAuB,EAAE,cAAc,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAiD7F,2EAA2E;AAC3E,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC;AAElC;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,IAAI,CAAC;AAExC;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,MAAyB;IACvD,MAAM,GAAG,GAAG,uBAAuB,CAAC,MAAM,CAAC,CAAC;IAC5C,IAAI,GAAG,IAAI,IAAI;QAAE,OAAO,IAAI,CAAC;IAC7B,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACnC,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,mBAAmB,CAAC,CAAC;AAC/D,CAAC;AAED,6DAA6D;AAC7D,SAAS,QAAQ,CAAC,IAAgC;IAChD,OAAO,CAAC,GAAG,IAAI,CAAC;SACb,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC;SACnC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC;SACvB,MAAM,CAAC,CAAC,KAAK,EAAmB,EAAE,CAAC,KAAK,IAAI,IAAI,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;AACjF,CAAC;AAED,6EAA6E;AAC7E,SAAS,QAAQ,CAAC,IAAgC;IAChD,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,MAAM,GAAG,IAAI,IAAI;QAAE,IAAI,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,WAAW,CAAC;YAAE,KAAK,IAAI,GAAG,CAAC,WAAW,CAAC;IACvF,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,YAAY,CAAC,MAAyB,EAAE,MAAoB;IAC1E,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACrC,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,MAAM,KAAK,IAAI,MAAM;QAAE,KAAK,IAAI,KAAK,CAAC;IAC3C,OAAO,MAAM,KAAK,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC;AAC1D,CAAC;AAED,gDAAgD;AAChD,MAAM,UAAU,YAAY,CAAC,KAAiB;IAC5C,MAAM,aAAa,GAAG,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC9C,MAAM,eAAe,GAAG,QAAQ,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IAClD,MAAM,OAAO,GAAG,YAAY,CAAC,aAAa,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAC1D,MAAM,QAAQ,GAAG,YAAY,CAAC,eAAe,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAC7D,MAAM,KAAK,GAAG,OAAO,IAAI,IAAI,IAAI,QAAQ,IAAI,IAAI,CAAC,CAAC,CAAC,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC;IAC9E,4EAA4E;IAC5E,wEAAwE;IACxE,6EAA6E;IAC7E,oCAAoC;IACpC,MAAM,GAAG,GAAG,eAAe,CAAC,eAAe,CAAC,CAAC;IAC7C,MAAM,UAAU,GAAG,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAE3C,OAAO;QACL,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,cAAc,EAAE,IAAI;QACpB,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,gBAAgB,CAAC;QACzC,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,gBAAgB,CAAC;QAC3C,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,gBAAgB,CAAC;QACrC,QAAQ,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,EAAE,QAAQ,CAAC,EAAE,gBAAgB,CAAC;QACpE,CAAC,EAAE,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,EAAE,gBAAgB,CAAC;QAC/C,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,cAAc,EAAE,UAAU,IAAI,KAAK,CAAC,SAAS;QAC7C,UAAU;KACX,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,SAAS,YAAY,CAAC,CAAW,EAAE,CAAW;IAC5C,IAAI,CAAC,CAAC,cAAc,KAAK,CAAC,CAAC,cAAc;QAAE,OAAO,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5E,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9C,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/C,IAAI,IAAI,KAAK,KAAK;QAAE,OAAO,KAAK,GAAG,IAAI,CAAC;IACxC,OAAO,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAChE,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,UAAU,CAAC,MAA6B,EAAE,KAAa;IACrE,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IACtC,MAAM,EAAE,GAAe,EAAE,CAAC;IAC1B,MAAM,IAAI,GAAe,EAAE,CAAC;IAC5B,MAAM,OAAO,GAAe,EAAE,CAAC;IAC/B,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,MAAM,GAAG,GAAG,CAAC,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC;QAClC,IAAI,MAAM,IAAI,IAAI,IAAI,MAAM,KAAK,CAAC;YAAE,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;aACjD,IAAI,MAAM,GAAG,CAAC;YAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;;YAC7B,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACtB,CAAC;IACD,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IACtB,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IACxB,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAC3B,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IAClC,4EAA4E;IAC5E,qEAAqE;IACrE,OAAO,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,EAAE,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;AACzF,CAAC"}
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* **`significance`** — "is that difference real?" (ADR 0051 §4, sketch §D).
|
|
3
|
+
*
|
|
4
|
+
* `movers` ranks changes by how unusual they are; this answers the next
|
|
5
|
+
* question, the one a robust z-score deliberately does not: *given how much
|
|
6
|
+
* data is behind each side, could this difference have come from chance alone?*
|
|
7
|
+
*
|
|
8
|
+
* Pure TypeScript over the same bucket series as every other primitive — no
|
|
9
|
+
* SQL, no dialect, no I/O — so DuckDB, ClickHouse, Postgres and SQL Server
|
|
10
|
+
* cannot disagree about a p-value.
|
|
11
|
+
*
|
|
12
|
+
* ## One test per shape of measure, chosen from the catalog, never guessed
|
|
13
|
+
*
|
|
14
|
+
* The right test is a property of what the number *is*, and the registry plus
|
|
15
|
+
* the bucket-measure catalog already say what it is. So the choice is derived,
|
|
16
|
+
* not configured:
|
|
17
|
+
*
|
|
18
|
+
* | The measure is… | Test | Effect | Interval |
|
|
19
|
+
* | --- | --- | --- | --- |
|
|
20
|
+
* | a **rate** — its `comparable.primary` declares `rateOf` and the catalog declares the matching denominator series | two-proportion z (pooled) | difference of proportions | Newcombe hybrid score, built from the two **Wilson** intervals |
|
|
21
|
+
* | a **count** of events with no denominator | Poisson rate test (exact conditional binomial) | difference in events per bucket | normal approximation on the rate difference |
|
|
22
|
+
* | anything else — a level or a summed quantity (`fps`, `ms`, bytes) | Welch's t over the per-bucket values | difference of means | `effect ± t(1−α/2, ν) · SE` |
|
|
23
|
+
*
|
|
24
|
+
* Every special function below is implemented here rather than pulled in as a
|
|
25
|
+
* dependency, for the same reason the statistics are not computed in SQL: a
|
|
26
|
+
* self-hoster's p-value must not depend on a transitive package version. They
|
|
27
|
+
* are the textbook algorithms (Lentz's continued fraction for the incomplete
|
|
28
|
+
* beta, Lanczos for the log-gamma, Abramowitz & Stegun 7.1.26 for the error
|
|
29
|
+
* function) and `src/__tests__/insightSignificance.test.ts` pins each one
|
|
30
|
+
* against published reference values.
|
|
31
|
+
*
|
|
32
|
+
* ## What this deliberately does not do
|
|
33
|
+
*
|
|
34
|
+
* **Two windows, not two segments.** Sketch §D allows either. Comparing two
|
|
35
|
+
* *segments* (`variant=red` vs `variant=blue`) needs the bucket series split by
|
|
36
|
+
* a promoted dimension, which the catalog cannot express in v1 — that is the
|
|
37
|
+
* `splitBy` work that arrives with `anomalies` (#306). A segment comparison is
|
|
38
|
+
* therefore refused at the route with a message naming the window parameters,
|
|
39
|
+
* rather than silently answered with the wrong contrast.
|
|
40
|
+
*/
|
|
41
|
+
import type { MetricBucketRow } from "./buckets.js";
|
|
42
|
+
/** The regularized incomplete beta function `I_x(a, b)`. */
|
|
43
|
+
export declare function regularizedIncompleteBeta(a: number, b: number, x: number): number;
|
|
44
|
+
/**
|
|
45
|
+
* The standard normal CDF, Φ(z), to full double precision.
|
|
46
|
+
*
|
|
47
|
+
* Hart’s rational approximation as given by West, *Better Approximations to
|
|
48
|
+
* Cumulative Normal Functions* (2005): a 6/7-degree rational for |z| < 7.07 and
|
|
49
|
+
* a continued fraction beyond it. The familiar Abramowitz & Stegun 7.1.26
|
|
50
|
+
* `erf` is not good enough here — its error is ~1.5e-7 *absolute*, which is
|
|
51
|
+
* larger than the p-values this function is asked to produce.
|
|
52
|
+
*/
|
|
53
|
+
export declare function normalCdf(z: number): number;
|
|
54
|
+
/** Two-sided p-value of a standard normal test statistic. */
|
|
55
|
+
export declare function normalTwoSidedP(z: number): number;
|
|
56
|
+
/** Two-sided p-value of a Student-t statistic on `df` degrees of freedom. */
|
|
57
|
+
export declare function studentTwoSidedP(t: number, df: number): number;
|
|
58
|
+
/** The 1−α/2 quantile of Student's t on `df` degrees of freedom, by bisection. */
|
|
59
|
+
export declare function studentTCritical(df: number, alpha?: number): number;
|
|
60
|
+
/** `P(X ≤ k)` for `X ~ Binomial(n, p)`, via the incomplete beta identity. */
|
|
61
|
+
export declare function binomialCdf(k: number, n: number, p: number): number;
|
|
62
|
+
/** The 80th percentile of the standard normal — the z for 80% power. */
|
|
63
|
+
export declare const Z_80 = 0.8416212335729143;
|
|
64
|
+
/**
|
|
65
|
+
* The shared Wilson interval as a plain pair, with the one behaviour this
|
|
66
|
+
* module needs that the summariser’s does not: an answer even when the count
|
|
67
|
+
* is not a proper proportion.
|
|
68
|
+
*
|
|
69
|
+
* `wilsonInterval` returns `null` for `successes > trials` because a share
|
|
70
|
+
* summary must refuse to draw an interval on a number that is not a share. Here
|
|
71
|
+
* that case is already reported to the caller in `powerNote`, so the widest
|
|
72
|
+
* honest interval — the whole unit range — is the right fallback rather than a
|
|
73
|
+
* missing row.
|
|
74
|
+
*/
|
|
75
|
+
export declare function wilsonBounds(successes: number, trials: number): [number, number];
|
|
76
|
+
/**
|
|
77
|
+
* **Newcombe's hybrid score interval** (1998, method 10) for the difference
|
|
78
|
+
* between two independent proportions, built from the two Wilson intervals.
|
|
79
|
+
*
|
|
80
|
+
* The natural companion to a Wilson interval per arm: it inherits Wilson's
|
|
81
|
+
* behaviour at the boundaries, so a comparison against a zero-count arm still
|
|
82
|
+
* produces an interval of finite, honest width instead of collapsing.
|
|
83
|
+
*/
|
|
84
|
+
export declare function newcombeDifferenceInterval(successesA: number, trialsA: number, successesB: number, trialsB: number): [number, number];
|
|
85
|
+
/** Which test produced a row. Also the `test` column's closed vocabulary. */
|
|
86
|
+
export type SignificanceTest = "two_proportion_z" | "welch_t" | "poisson_rate";
|
|
87
|
+
/**
|
|
88
|
+
* One side of a comparison.
|
|
89
|
+
*
|
|
90
|
+
* `n` is always **the denominator `value` rests on** — trials for a
|
|
91
|
+
* proportion, buckets for a rate or a mean — so `value * n` recovers the
|
|
92
|
+
* total the arm was computed from whichever test ran. Keeping that invariant
|
|
93
|
+
* across the three tests is what lets a reader check the arithmetic without
|
|
94
|
+
* first working out which test produced the row.
|
|
95
|
+
*/
|
|
96
|
+
export interface SignificanceArm {
|
|
97
|
+
/** The metric's value over this window, in its own unit (a proportion for a rate). */
|
|
98
|
+
value: number | null;
|
|
99
|
+
/** The denominator the value rests on: trials, or buckets. */
|
|
100
|
+
n: number;
|
|
101
|
+
}
|
|
102
|
+
/** What `significance` reports. One row per request. */
|
|
103
|
+
export interface SignificanceRow {
|
|
104
|
+
metric: string;
|
|
105
|
+
/** The scene it was scoped to; `''` when the comparison spans every scene. */
|
|
106
|
+
scene: string;
|
|
107
|
+
/** The current window. */
|
|
108
|
+
a: SignificanceArm;
|
|
109
|
+
/** The reference window. */
|
|
110
|
+
b: SignificanceArm;
|
|
111
|
+
/** `a − b`, in the unit named by `effectUnit`. */
|
|
112
|
+
effect: number | null;
|
|
113
|
+
/** The 95% confidence interval for `effect`. */
|
|
114
|
+
ci95: [number | null, number | null];
|
|
115
|
+
/** Two-sided p-value for H₀: no difference. */
|
|
116
|
+
p: number | null;
|
|
117
|
+
test: SignificanceTest;
|
|
118
|
+
/** What one unit of `effect` means — the difference is never unitless. */
|
|
119
|
+
effectUnit: string;
|
|
120
|
+
/** Whether `p` cleared α = 0.05. A convenience, never a substitute for the interval. */
|
|
121
|
+
significant: boolean;
|
|
122
|
+
/**
|
|
123
|
+
* What these sample sizes can and cannot detect, in one sentence: the
|
|
124
|
+
* smallest difference detectable at 80% power, and any assumption the data
|
|
125
|
+
* strained on the way.
|
|
126
|
+
*/
|
|
127
|
+
powerNote: string;
|
|
128
|
+
}
|
|
129
|
+
/** Decimals a significance number is rounded to before it leaves the API. */
|
|
130
|
+
export declare const SIGNIFICANCE_PRECISION = 6;
|
|
131
|
+
/** Conventional significance level. Fixed: a caller-tunable α is p-hacking with extra steps. */
|
|
132
|
+
export declare const SIGNIFICANCE_ALPHA = 0.05;
|
|
133
|
+
/**
|
|
134
|
+
* **Two-proportion z-test**, pooled, with a Newcombe interval on the difference.
|
|
135
|
+
*
|
|
136
|
+
* `H₀: p_a = p_b`. The pooled proportion is used in the standard error because
|
|
137
|
+
* that is the variance *under the null* — the hypothesis being tested — while
|
|
138
|
+
* the interval is unpooled, because an interval describes the difference that
|
|
139
|
+
* was actually observed. The two therefore answer slightly different questions
|
|
140
|
+
* and can, in a borderline case, disagree about whether zero is excluded. That
|
|
141
|
+
* is a property of the textbook procedure, not a bug, and the interval is the
|
|
142
|
+
* one to believe.
|
|
143
|
+
*/
|
|
144
|
+
export declare function twoProportionTest(successesA: number, trialsA: number, successesB: number, trialsB: number): {
|
|
145
|
+
effect: number | null;
|
|
146
|
+
ci95: [number | null, number | null];
|
|
147
|
+
p: number | null;
|
|
148
|
+
se: number | null;
|
|
149
|
+
};
|
|
150
|
+
/**
|
|
151
|
+
* **Welch's unequal-variances t-test** over two samples of per-bucket values.
|
|
152
|
+
*
|
|
153
|
+
* Welch rather than Student because the two windows are routinely of different
|
|
154
|
+
* length *and* different volatility — a regressed week is both lower and more
|
|
155
|
+
* erratic than the week before it — and pooling those variances would understate
|
|
156
|
+
* the uncertainty exactly when it matters most.
|
|
157
|
+
*
|
|
158
|
+
* The samples are the **bucket values**, so `n` is the number of days (or
|
|
159
|
+
* hours) compared, not the number of events behind them. That is the honest
|
|
160
|
+
* unit: consecutive frame samples inside one day are anything but independent,
|
|
161
|
+
* and treating them as `n` would produce a p-value of 1e-40 for a difference
|
|
162
|
+
* any observer could see is within normal day-to-day drift.
|
|
163
|
+
*/
|
|
164
|
+
export declare function welchTest(sampleA: readonly number[], sampleB: readonly number[]): {
|
|
165
|
+
effect: number | null;
|
|
166
|
+
ci95: [number | null, number | null];
|
|
167
|
+
p: number | null;
|
|
168
|
+
se: number | null;
|
|
169
|
+
df: number | null;
|
|
170
|
+
};
|
|
171
|
+
/**
|
|
172
|
+
* **Two-sample Poisson rate test** (Przyborowski & Wilks 1940).
|
|
173
|
+
*
|
|
174
|
+
* Conditional on the total `x_a + x_b`, the split between the two windows is
|
|
175
|
+
* Binomial(total, t_a / (t_a + t_b)) under `H₀: λ_a = λ_b`, where `t` is each
|
|
176
|
+
* window's exposure — here its number of buckets. That makes the exact p-value
|
|
177
|
+
* a binomial tail, which is what this returns: exact whatever the counts, with
|
|
178
|
+
* no normal approximation to fail at the small counts an error metric usually
|
|
179
|
+
* has.
|
|
180
|
+
*
|
|
181
|
+
* The **interval**, by contrast, is the normal approximation on the rate
|
|
182
|
+
* difference (`sqrt(x_a/t_a² + x_b/t_b²)`). There is no closed-form exact
|
|
183
|
+
* interval for a difference of Poisson rates, and an approximate interval
|
|
184
|
+
* reported as approximate is better than none; `powerNote` says so when the
|
|
185
|
+
* counts are small enough for it to matter.
|
|
186
|
+
*/
|
|
187
|
+
export declare function poissonRateTest(countA: number, exposureA: number, countB: number, exposureB: number): {
|
|
188
|
+
effect: number | null;
|
|
189
|
+
ci95: [number | null, number | null];
|
|
190
|
+
p: number | null;
|
|
191
|
+
se: number | null;
|
|
192
|
+
};
|
|
193
|
+
/** Everything `computeSignificance` needs about one comparison. */
|
|
194
|
+
export interface SignificanceInput {
|
|
195
|
+
metric: string;
|
|
196
|
+
scene?: string;
|
|
197
|
+
/** `true` when the measure counts events (so a rate or a Poisson count). */
|
|
198
|
+
counting: boolean;
|
|
199
|
+
/** Buckets of the current window. */
|
|
200
|
+
current: readonly MetricBucketRow[];
|
|
201
|
+
/** Buckets of the reference window. */
|
|
202
|
+
reference: readonly MetricBucketRow[];
|
|
203
|
+
/**
|
|
204
|
+
* The denominator series, when the metric is a declared rate: the same two
|
|
205
|
+
* windows of its `rateOf` column. Absent for everything else.
|
|
206
|
+
*/
|
|
207
|
+
denominator?: {
|
|
208
|
+
current: readonly MetricBucketRow[];
|
|
209
|
+
reference: readonly MetricBucketRow[];
|
|
210
|
+
};
|
|
211
|
+
/** What one unit of the metric is, for the `effectUnit` column. */
|
|
212
|
+
unit: string;
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Compare one metric across two windows and say whether the difference is real.
|
|
216
|
+
*
|
|
217
|
+
* Pure: it takes the bucket series both windows produced (plus, for a rate, the
|
|
218
|
+
* denominator's) and returns the row. No store, no request, no dialect.
|
|
219
|
+
*/
|
|
220
|
+
export declare function computeSignificance(input: SignificanceInput): SignificanceRow;
|
|
221
|
+
//# sourceMappingURL=significance.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"significance.d.ts","sourceRoot":"","sources":["../../src/insights/significance.ts"],"names":[],"mappings":"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"}
|