@pipeline-builder/pipeline-data 4.1.1 → 4.1.2

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.
@@ -0,0 +1,2 @@
1
+ export declare const inventoryCache: import("@pipeline-builder/api-core").CacheService;
2
+ export declare const timeseriesCache: import("@pipeline-builder/api-core").CacheService;
@@ -0,0 +1,14 @@
1
+ // Copyright 2026 Pipeline Builder Contributors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ /**
4
+ * The two report caches. A separate module because both the service (for
5
+ * invalidation) and the extracted query modules (via runReport) need them, and a
6
+ * shared singleton must have exactly one definition site.
7
+ *
8
+ * Inventory reads (plugin summary/distribution/versions) change rarely — 5 min.
9
+ * Timeseries reads (execution/build metrics over a range) — 2 min.
10
+ */
11
+ import { createCacheService } from '@pipeline-builder/api-core';
12
+ export const inventoryCache = createCacheService('report:inv:', parseInt(process.env.CACHE_TTL_REPORT_INVENTORY || '300', 10));
13
+ export const timeseriesCache = createCacheService('report:ts:', parseInt(process.env.CACHE_TTL_REPORT_TIMESERIES || '120', 10));
14
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2FjaGVzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2FwaS9yZXBvcnRpbmcvY2FjaGVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLCtDQUErQztBQUMvQyxzQ0FBc0M7QUFFdEM7Ozs7Ozs7R0FPRztBQUVILE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBRWhFLE1BQU0sQ0FBQyxNQUFNLGNBQWMsR0FBRyxrQkFBa0IsQ0FBQyxhQUFhLEVBQUUsUUFBUSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsMEJBQTBCLElBQUksS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUM7QUFDL0gsTUFBTSxDQUFDLE1BQU0sZUFBZSxHQUFHLGtCQUFrQixDQUFDLFlBQVksRUFBRSxRQUFRLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQywyQkFBMkIsSUFBSSxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCAyMDI2IFBpcGVsaW5lIEJ1aWxkZXIgQ29udHJpYnV0b3JzXG4vLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuXG4vKipcbiAqIFRoZSB0d28gcmVwb3J0IGNhY2hlcy4gQSBzZXBhcmF0ZSBtb2R1bGUgYmVjYXVzZSBib3RoIHRoZSBzZXJ2aWNlIChmb3JcbiAqIGludmFsaWRhdGlvbikgYW5kIHRoZSBleHRyYWN0ZWQgcXVlcnkgbW9kdWxlcyAodmlhIHJ1blJlcG9ydCkgbmVlZCB0aGVtLCBhbmQgYVxuICogc2hhcmVkIHNpbmdsZXRvbiBtdXN0IGhhdmUgZXhhY3RseSBvbmUgZGVmaW5pdGlvbiBzaXRlLlxuICpcbiAqIEludmVudG9yeSByZWFkcyAocGx1Z2luIHN1bW1hcnkvZGlzdHJpYnV0aW9uL3ZlcnNpb25zKSBjaGFuZ2UgcmFyZWx5IOKAlCA1IG1pbi5cbiAqIFRpbWVzZXJpZXMgcmVhZHMgKGV4ZWN1dGlvbi9idWlsZCBtZXRyaWNzIG92ZXIgYSByYW5nZSkg4oCUIDIgbWluLlxuICovXG5cbmltcG9ydCB7IGNyZWF0ZUNhY2hlU2VydmljZSB9IGZyb20gJ0BwaXBlbGluZS1idWlsZGVyL2FwaS1jb3JlJztcblxuZXhwb3J0IGNvbnN0IGludmVudG9yeUNhY2hlID0gY3JlYXRlQ2FjaGVTZXJ2aWNlKCdyZXBvcnQ6aW52OicsIHBhcnNlSW50KHByb2Nlc3MuZW52LkNBQ0hFX1RUTF9SRVBPUlRfSU5WRU5UT1JZIHx8ICczMDAnLCAxMCkpO1xuZXhwb3J0IGNvbnN0IHRpbWVzZXJpZXNDYWNoZSA9IGNyZWF0ZUNhY2hlU2VydmljZSgncmVwb3J0OnRzOicsIHBhcnNlSW50KHByb2Nlc3MuZW52LkNBQ0hFX1RUTF9SRVBPUlRfVElNRVNFUklFUyB8fCAnMTIwJywgMTApKTtcbiJdfQ==
@@ -0,0 +1,71 @@
1
+ import type { DoraLevel } from './types.js';
2
+ /**
3
+ * DORA performance banding plus the small statistics helpers it needs.
4
+ * Pure functions — no database access, no I/O — which is what lets the
5
+ * thresholds be unit-tested independently of the queries that feed them.
6
+ */
7
+ /**
8
+ * The DORA headline environment. Deployment to this literal env name is the
9
+ * industry-standard DORA signal; MTTR is measured production-only, and this
10
+ * environment's card is the summary shown at the top of the panel.
11
+ */
12
+ export declare const HEADLINE_ENV = "production";
13
+ /**
14
+ * Incident→deploy correlation window (Phase 5). An incident is attributed to the
15
+ * most recent SUCCESSFUL deploy to its environment whose `completed_at` is within
16
+ * this many hours before the incident's `opened_at`. Default 24h; override via
17
+ * `DORA_INCIDENT_WINDOW_HOURS`. Guarded to a positive finite number.
18
+ */
19
+ export declare const DORA_INCIDENT_WINDOW_HOURS: number;
20
+ /**
21
+ * Resolve the effective incident→deploy correlation window (Phase 5b). A per-org
22
+ * override (from `dora_settings.incident_window_hours`, surfaced through the
23
+ * settings endpoint and threaded into {@link DoraOptions.incidentWindowHours})
24
+ * wins when it is a positive finite number; otherwise the global env default
25
+ * `DORA_INCIDENT_WINDOW_HOURS` applies. Centralized so the DORA correlation, the
26
+ * incidents list, and the wiring-test dry-run all agree on the same rule.
27
+ */
28
+ export declare function resolveIncidentWindowHours(override?: number | null): number;
29
+ /**
30
+ * Reporting retention windows (Phase 7). Records in `pipeline_events`,
31
+ * `deployment_outcomes`, and `incidents` grow unbounded without a sweep, so a
32
+ * split, per-org retention purge (see {@link ReportingService.purgeExpiredReportingData})
33
+ * hard-deletes rows older than these windows, by `created_at`:
34
+ * - **Standard events** — `pipeline_events` with `environment IS NULL`
35
+ * (non-deploy STAGE/ACTION/build). High volume → short default (30 days).
36
+ * - **DORA source** — `pipeline_events` with `environment IS NOT NULL` (deploy
37
+ * stages) plus all of `deployment_outcomes` and `incidents`. Low volume →
38
+ * longer default (180 days). DORA history is therefore bounded by this window;
39
+ * the report query still hard-caps at 365 days (a longer per-org override only
40
+ * retains raw source rows, never widens a report).
41
+ * `ingest_health` and `dora_settings` are never purged. Env-overridable globals;
42
+ * a per-org override in `dora_settings` wins (see {@link resolveEventRetentionDays}).
43
+ */
44
+ /** Deployment frequency by deploys/day: elite ≥1/day, high ≥1/week, medium ≥1/month. */
45
+ export declare function doraLevelForFrequency(perDay: number, deployments: number): DoraLevel;
46
+ /** Change failure rate by percent: elite ≤5%, high ≤10%, medium ≤15%. */
47
+ export declare function doraLevelForChangeFailure(pct: number, total: number): DoraLevel;
48
+ /** Time to restore by seconds: elite <1h, high <1 day, medium <1 week. */
49
+ export declare function doraLevelForRestore(avgSeconds: number | null): DoraLevel;
50
+ /** Lead time by seconds: elite <1 day, high <1 week, medium <1 month. */
51
+ export declare function doraLevelForLeadTime(medianSeconds: number | null): DoraLevel;
52
+ /**
53
+ * Round `value` to `digits` decimal places, returning a real number. Small
54
+ * module-private helper so the DORA shaping doesn't repeat the
55
+ * `Number(Number(x).toFixed(n))` pattern (toFixed alone yields a string).
56
+ */
57
+ export declare function round(value: number, digits: number): number;
58
+ /**
59
+ * Median of a numeric sample, or `null` when empty. Used for measured lead time
60
+ * and MTTR — both are cross-source gaps computed in JS from clamped deltas, so
61
+ * the median lives here rather than in SQL PERCENTILE_CONT (keeps the golden
62
+ * fixture tests able to prove the metric math without a live Postgres).
63
+ */
64
+ export declare function median(values: number[]): number | null;
65
+ /**
66
+ * Roll a group of deploy/stage events (grouped per execution) up to one terminal
67
+ * status: FAILED wins, then SUCCEEDED, else OTHER (still-running / non-terminal).
68
+ * Shared by the three per-(env|stage, execution) rollup CTEs — DORA metrics, DORA
69
+ * trend, and build health — so the precedence can't drift between them. Assumes the
70
+ * grouped event alias is `e`.
71
+ */
@@ -0,0 +1,126 @@
1
+ // Copyright 2026 Pipeline Builder Contributors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ /**
4
+ * DORA performance banding plus the small statistics helpers it needs.
5
+ * Pure functions — no database access, no I/O — which is what lets the
6
+ * thresholds be unit-tested independently of the queries that feed them.
7
+ */
8
+ /**
9
+ * The DORA headline environment. Deployment to this literal env name is the
10
+ * industry-standard DORA signal; MTTR is measured production-only, and this
11
+ * environment's card is the summary shown at the top of the panel.
12
+ */
13
+ export const HEADLINE_ENV = 'production';
14
+ /**
15
+ * Incident→deploy correlation window (Phase 5). An incident is attributed to the
16
+ * most recent SUCCESSFUL deploy to its environment whose `completed_at` is within
17
+ * this many hours before the incident's `opened_at`. Default 24h; override via
18
+ * `DORA_INCIDENT_WINDOW_HOURS`. Guarded to a positive finite number.
19
+ */
20
+ export const DORA_INCIDENT_WINDOW_HOURS = (() => {
21
+ const raw = Number(process.env.DORA_INCIDENT_WINDOW_HOURS);
22
+ return Number.isFinite(raw) && raw > 0 ? raw : 24;
23
+ })();
24
+ /**
25
+ * Resolve the effective incident→deploy correlation window (Phase 5b). A per-org
26
+ * override (from `dora_settings.incident_window_hours`, surfaced through the
27
+ * settings endpoint and threaded into {@link DoraOptions.incidentWindowHours})
28
+ * wins when it is a positive finite number; otherwise the global env default
29
+ * `DORA_INCIDENT_WINDOW_HOURS` applies. Centralized so the DORA correlation, the
30
+ * incidents list, and the wiring-test dry-run all agree on the same rule.
31
+ */
32
+ export function resolveIncidentWindowHours(override) {
33
+ return override != null && Number.isFinite(override) && override > 0 ? override : DORA_INCIDENT_WINDOW_HOURS;
34
+ }
35
+ /**
36
+ * Reporting retention windows (Phase 7). Records in `pipeline_events`,
37
+ * `deployment_outcomes`, and `incidents` grow unbounded without a sweep, so a
38
+ * split, per-org retention purge (see {@link ReportingService.purgeExpiredReportingData})
39
+ * hard-deletes rows older than these windows, by `created_at`:
40
+ * - **Standard events** — `pipeline_events` with `environment IS NULL`
41
+ * (non-deploy STAGE/ACTION/build). High volume → short default (30 days).
42
+ * - **DORA source** — `pipeline_events` with `environment IS NOT NULL` (deploy
43
+ * stages) plus all of `deployment_outcomes` and `incidents`. Low volume →
44
+ * longer default (180 days). DORA history is therefore bounded by this window;
45
+ * the report query still hard-caps at 365 days (a longer per-org override only
46
+ * retains raw source rows, never widens a report).
47
+ * `ingest_health` and `dora_settings` are never purged. Env-overridable globals;
48
+ * a per-org override in `dora_settings` wins (see {@link resolveEventRetentionDays}).
49
+ */
50
+ /** Deployment frequency by deploys/day: elite ≥1/day, high ≥1/week, medium ≥1/month. */
51
+ export function doraLevelForFrequency(perDay, deployments) {
52
+ if (deployments <= 0)
53
+ return null;
54
+ if (perDay >= 1)
55
+ return 'elite';
56
+ if (perDay >= 1 / 7)
57
+ return 'high';
58
+ if (perDay >= 1 / 30)
59
+ return 'medium';
60
+ return 'low';
61
+ }
62
+ /** Change failure rate by percent: elite ≤5%, high ≤10%, medium ≤15%. */
63
+ export function doraLevelForChangeFailure(pct, total) {
64
+ if (total <= 0)
65
+ return null;
66
+ if (pct <= 5)
67
+ return 'elite';
68
+ if (pct <= 10)
69
+ return 'high';
70
+ if (pct <= 15)
71
+ return 'medium';
72
+ return 'low';
73
+ }
74
+ /** Time to restore by seconds: elite <1h, high <1 day, medium <1 week. */
75
+ export function doraLevelForRestore(avgSeconds) {
76
+ if (avgSeconds == null)
77
+ return null;
78
+ if (avgSeconds < 3600)
79
+ return 'elite';
80
+ if (avgSeconds < 86400)
81
+ return 'high';
82
+ if (avgSeconds < 604800)
83
+ return 'medium';
84
+ return 'low';
85
+ }
86
+ /** Lead time by seconds: elite <1 day, high <1 week, medium <1 month. */
87
+ export function doraLevelForLeadTime(medianSeconds) {
88
+ if (medianSeconds == null)
89
+ return null;
90
+ if (medianSeconds < 86400)
91
+ return 'elite';
92
+ if (medianSeconds < 604800)
93
+ return 'high';
94
+ if (medianSeconds < 2592000)
95
+ return 'medium';
96
+ return 'low';
97
+ }
98
+ /**
99
+ * Round `value` to `digits` decimal places, returning a real number. Small
100
+ * module-private helper so the DORA shaping doesn't repeat the
101
+ * `Number(Number(x).toFixed(n))` pattern (toFixed alone yields a string).
102
+ */
103
+ export function round(value, digits) {
104
+ return Number(value.toFixed(digits));
105
+ }
106
+ /**
107
+ * Median of a numeric sample, or `null` when empty. Used for measured lead time
108
+ * and MTTR — both are cross-source gaps computed in JS from clamped deltas, so
109
+ * the median lives here rather than in SQL PERCENTILE_CONT (keeps the golden
110
+ * fixture tests able to prove the metric math without a live Postgres).
111
+ */
112
+ export function median(values) {
113
+ if (values.length === 0)
114
+ return null;
115
+ const s = [...values].sort((a, b) => a - b);
116
+ const mid = Math.floor(s.length / 2);
117
+ return s.length % 2 === 1 ? s[mid] : (s[mid - 1] + s[mid]) / 2;
118
+ }
119
+ /**
120
+ * Roll a group of deploy/stage events (grouped per execution) up to one terminal
121
+ * status: FAILED wins, then SUCCEEDED, else OTHER (still-running / non-terminal).
122
+ * Shared by the three per-(env|stage, execution) rollup CTEs — DORA metrics, DORA
123
+ * trend, and build health — so the precedence can't drift between them. Assumes the
124
+ * grouped event alias is `e`.
125
+ */
126
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZG9yYS1zY29yaW5nLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2FwaS9yZXBvcnRpbmcvZG9yYS1zY29yaW5nLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLCtDQUErQztBQUMvQyxzQ0FBc0M7QUFJdEM7Ozs7R0FJRztBQUVIOzs7O0dBSUc7QUFDSCxNQUFNLENBQUMsTUFBTSxZQUFZLEdBQUcsWUFBWSxDQUFDO0FBRXpDOzs7OztHQUtHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sMEJBQTBCLEdBQUcsQ0FBQyxHQUFHLEVBQUU7SUFDOUMsTUFBTSxHQUFHLEdBQUcsTUFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsMEJBQTBCLENBQUMsQ0FBQztJQUMzRCxPQUFPLE1BQU0sQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLElBQUksR0FBRyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7QUFDcEQsQ0FBQyxDQUFDLEVBQUUsQ0FBQztBQUVMOzs7Ozs7O0dBT0c7QUFDSCxNQUFNLFVBQVUsMEJBQTBCLENBQUMsUUFBd0I7SUFDakUsT0FBTyxRQUFRLElBQUksSUFBSSxJQUFJLE1BQU0sQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLElBQUksUUFBUSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQywwQkFBMEIsQ0FBQztBQUMvRyxDQUFDO0FBRUQ7Ozs7Ozs7Ozs7Ozs7O0dBY0c7QUFFSCx3RkFBd0Y7QUFDeEYsTUFBTSxVQUFVLHFCQUFxQixDQUFDLE1BQWMsRUFBRSxXQUFtQjtJQUN2RSxJQUFJLFdBQVcsSUFBSSxDQUFDO1FBQUUsT0FBTyxJQUFJLENBQUM7SUFDbEMsSUFBSSxNQUFNLElBQUksQ0FBQztRQUFFLE9BQU8sT0FBTyxDQUFDO0lBQ2hDLElBQUksTUFBTSxJQUFJLENBQUMsR0FBRyxDQUFDO1FBQUUsT0FBTyxNQUFNLENBQUM7SUFDbkMsSUFBSSxNQUFNLElBQUksQ0FBQyxHQUFHLEVBQUU7UUFBRSxPQUFPLFFBQVEsQ0FBQztJQUN0QyxPQUFPLEtBQUssQ0FBQztBQUNmLENBQUM7QUFDRCx5RUFBeUU7QUFDekUsTUFBTSxVQUFVLHlCQUF5QixDQUFDLEdBQVcsRUFBRSxLQUFhO0lBQ2xFLElBQUksS0FBSyxJQUFJLENBQUM7UUFBRSxPQUFPLElBQUksQ0FBQztJQUM1QixJQUFJLEdBQUcsSUFBSSxDQUFDO1FBQUUsT0FBTyxPQUFPLENBQUM7SUFDN0IsSUFBSSxHQUFHLElBQUksRUFBRTtRQUFFLE9BQU8sTUFBTSxDQUFDO0lBQzdCLElBQUksR0FBRyxJQUFJLEVBQUU7UUFBRSxPQUFPLFFBQVEsQ0FBQztJQUMvQixPQUFPLEtBQUssQ0FBQztBQUNmLENBQUM7QUFDRCwwRUFBMEU7QUFDMUUsTUFBTSxVQUFVLG1CQUFtQixDQUFDLFVBQXlCO0lBQzNELElBQUksVUFBVSxJQUFJLElBQUk7UUFBRSxPQUFPLElBQUksQ0FBQztJQUNwQyxJQUFJLFVBQVUsR0FBRyxJQUFJO1FBQUUsT0FBTyxPQUFPLENBQUM7SUFDdEMsSUFBSSxVQUFVLEdBQUcsS0FBSztRQUFFLE9BQU8sTUFBTSxDQUFDO0lBQ3RDLElBQUksVUFBVSxHQUFHLE1BQU07UUFBRSxPQUFPLFFBQVEsQ0FBQztJQUN6QyxPQUFPLEtBQUssQ0FBQztBQUNmLENBQUM7QUFDRCx5RUFBeUU7QUFDekUsTUFBTSxVQUFVLG9CQUFvQixDQUFDLGFBQTRCO0lBQy9ELElBQUksYUFBYSxJQUFJLElBQUk7UUFBRSxPQUFPLElBQUksQ0FBQztJQUN2QyxJQUFJLGFBQWEsR0FBRyxLQUFLO1FBQUUsT0FBTyxPQUFPLENBQUM7SUFDMUMsSUFBSSxhQUFhLEdBQUcsTUFBTTtRQUFFLE9BQU8sTUFBTSxDQUFDO0lBQzFDLElBQUksYUFBYSxHQUFHLE9BQU87UUFBRSxPQUFPLFFBQVEsQ0FBQztJQUM3QyxPQUFPLEtBQUssQ0FBQztBQUNmLENBQUM7QUFFRDs7OztHQUlHO0FBQ0gsTUFBTSxVQUFVLEtBQUssQ0FBQyxLQUFhLEVBQUUsTUFBYztJQUNqRCxPQUFPLE1BQU0sQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7QUFDdkMsQ0FBQztBQUVEOzs7OztHQUtHO0FBQ0gsTUFBTSxVQUFVLE1BQU0sQ0FBQyxNQUFnQjtJQUNyQyxJQUFJLE1BQU0sQ0FBQyxNQUFNLEtBQUssQ0FBQztRQUFFLE9BQU8sSUFBSSxDQUFDO0lBQ3JDLE1BQU0sQ0FBQyxHQUFHLENBQUMsR0FBRyxNQUFNLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDNUMsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDO0lBQ3JDLE9BQU8sQ0FBQyxDQUFDLE1BQU0sR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUM7QUFDakUsQ0FBQztBQUVEOzs7Ozs7R0FNRyIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCAyMDI2IFBpcGVsaW5lIEJ1aWxkZXIgQ29udHJpYnV0b3JzXG4vLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuXG5pbXBvcnQgdHlwZSB7IERvcmFMZXZlbCB9IGZyb20gJy4vdHlwZXMuanMnO1xuXG4vKipcbiAqIERPUkEgcGVyZm9ybWFuY2UgYmFuZGluZyBwbHVzIHRoZSBzbWFsbCBzdGF0aXN0aWNzIGhlbHBlcnMgaXQgbmVlZHMuXG4gKiBQdXJlIGZ1bmN0aW9ucyDigJQgbm8gZGF0YWJhc2UgYWNjZXNzLCBubyBJL08g4oCUIHdoaWNoIGlzIHdoYXQgbGV0cyB0aGVcbiAqIHRocmVzaG9sZHMgYmUgdW5pdC10ZXN0ZWQgaW5kZXBlbmRlbnRseSBvZiB0aGUgcXVlcmllcyB0aGF0IGZlZWQgdGhlbS5cbiAqL1xuXG4vKipcbiAqIFRoZSBET1JBIGhlYWRsaW5lIGVudmlyb25tZW50LiBEZXBsb3ltZW50IHRvIHRoaXMgbGl0ZXJhbCBlbnYgbmFtZSBpcyB0aGVcbiAqIGluZHVzdHJ5LXN0YW5kYXJkIERPUkEgc2lnbmFsOyBNVFRSIGlzIG1lYXN1cmVkIHByb2R1Y3Rpb24tb25seSwgYW5kIHRoaXNcbiAqIGVudmlyb25tZW50J3MgY2FyZCBpcyB0aGUgc3VtbWFyeSBzaG93biBhdCB0aGUgdG9wIG9mIHRoZSBwYW5lbC5cbiAqL1xuZXhwb3J0IGNvbnN0IEhFQURMSU5FX0VOViA9ICdwcm9kdWN0aW9uJztcblxuLyoqXG4gKiBJbmNpZGVudOKGkmRlcGxveSBjb3JyZWxhdGlvbiB3aW5kb3cgKFBoYXNlIDUpLiBBbiBpbmNpZGVudCBpcyBhdHRyaWJ1dGVkIHRvIHRoZVxuICogbW9zdCByZWNlbnQgU1VDQ0VTU0ZVTCBkZXBsb3kgdG8gaXRzIGVudmlyb25tZW50IHdob3NlIGBjb21wbGV0ZWRfYXRgIGlzIHdpdGhpblxuICogdGhpcyBtYW55IGhvdXJzIGJlZm9yZSB0aGUgaW5jaWRlbnQncyBgb3BlbmVkX2F0YC4gRGVmYXVsdCAyNGg7IG92ZXJyaWRlIHZpYVxuICogYERPUkFfSU5DSURFTlRfV0lORE9XX0hPVVJTYC4gR3VhcmRlZCB0byBhIHBvc2l0aXZlIGZpbml0ZSBudW1iZXIuXG4gKi9cbmV4cG9ydCBjb25zdCBET1JBX0lOQ0lERU5UX1dJTkRPV19IT1VSUyA9ICgoKSA9PiB7XG4gIGNvbnN0IHJhdyA9IE51bWJlcihwcm9jZXNzLmVudi5ET1JBX0lOQ0lERU5UX1dJTkRPV19IT1VSUyk7XG4gIHJldHVybiBOdW1iZXIuaXNGaW5pdGUocmF3KSAmJiByYXcgPiAwID8gcmF3IDogMjQ7XG59KSgpO1xuXG4vKipcbiAqIFJlc29sdmUgdGhlIGVmZmVjdGl2ZSBpbmNpZGVudOKGkmRlcGxveSBjb3JyZWxhdGlvbiB3aW5kb3cgKFBoYXNlIDViKS4gQSBwZXItb3JnXG4gKiBvdmVycmlkZSAoZnJvbSBgZG9yYV9zZXR0aW5ncy5pbmNpZGVudF93aW5kb3dfaG91cnNgLCBzdXJmYWNlZCB0aHJvdWdoIHRoZVxuICogc2V0dGluZ3MgZW5kcG9pbnQgYW5kIHRocmVhZGVkIGludG8ge0BsaW5rIERvcmFPcHRpb25zLmluY2lkZW50V2luZG93SG91cnN9KVxuICogd2lucyB3aGVuIGl0IGlzIGEgcG9zaXRpdmUgZmluaXRlIG51bWJlcjsgb3RoZXJ3aXNlIHRoZSBnbG9iYWwgZW52IGRlZmF1bHRcbiAqIGBET1JBX0lOQ0lERU5UX1dJTkRPV19IT1VSU2AgYXBwbGllcy4gQ2VudHJhbGl6ZWQgc28gdGhlIERPUkEgY29ycmVsYXRpb24sIHRoZVxuICogaW5jaWRlbnRzIGxpc3QsIGFuZCB0aGUgd2lyaW5nLXRlc3QgZHJ5LXJ1biBhbGwgYWdyZWUgb24gdGhlIHNhbWUgcnVsZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlc29sdmVJbmNpZGVudFdpbmRvd0hvdXJzKG92ZXJyaWRlPzogbnVtYmVyIHwgbnVsbCk6IG51bWJlciB7XG4gIHJldHVybiBvdmVycmlkZSAhPSBudWxsICYmIE51bWJlci5pc0Zpbml0ZShvdmVycmlkZSkgJiYgb3ZlcnJpZGUgPiAwID8gb3ZlcnJpZGUgOiBET1JBX0lOQ0lERU5UX1dJTkRPV19IT1VSUztcbn1cblxuLyoqXG4gKiBSZXBvcnRpbmcgcmV0ZW50aW9uIHdpbmRvd3MgKFBoYXNlIDcpLiBSZWNvcmRzIGluIGBwaXBlbGluZV9ldmVudHNgLFxuICogYGRlcGxveW1lbnRfb3V0Y29tZXNgLCBhbmQgYGluY2lkZW50c2AgZ3JvdyB1bmJvdW5kZWQgd2l0aG91dCBhIHN3ZWVwLCBzbyBhXG4gKiBzcGxpdCwgcGVyLW9yZyByZXRlbnRpb24gcHVyZ2UgKHNlZSB7QGxpbmsgUmVwb3J0aW5nU2VydmljZS5wdXJnZUV4cGlyZWRSZXBvcnRpbmdEYXRhfSlcbiAqIGhhcmQtZGVsZXRlcyByb3dzIG9sZGVyIHRoYW4gdGhlc2Ugd2luZG93cywgYnkgYGNyZWF0ZWRfYXRgOlxuICogIC0gKipTdGFuZGFyZCBldmVudHMqKiDigJQgYHBpcGVsaW5lX2V2ZW50c2Agd2l0aCBgZW52aXJvbm1lbnQgSVMgTlVMTGBcbiAqICAgIChub24tZGVwbG95IFNUQUdFL0FDVElPTi9idWlsZCkuIEhpZ2ggdm9sdW1lIOKGkiBzaG9ydCBkZWZhdWx0ICgzMCBkYXlzKS5cbiAqICAtICoqRE9SQSBzb3VyY2UqKiDigJQgYHBpcGVsaW5lX2V2ZW50c2Agd2l0aCBgZW52aXJvbm1lbnQgSVMgTk9UIE5VTExgIChkZXBsb3lcbiAqICAgIHN0YWdlcykgcGx1cyBhbGwgb2YgYGRlcGxveW1lbnRfb3V0Y29tZXNgIGFuZCBgaW5jaWRlbnRzYC4gTG93IHZvbHVtZSDihpJcbiAqICAgIGxvbmdlciBkZWZhdWx0ICgxODAgZGF5cykuIERPUkEgaGlzdG9yeSBpcyB0aGVyZWZvcmUgYm91bmRlZCBieSB0aGlzIHdpbmRvdztcbiAqICAgIHRoZSByZXBvcnQgcXVlcnkgc3RpbGwgaGFyZC1jYXBzIGF0IDM2NSBkYXlzIChhIGxvbmdlciBwZXItb3JnIG92ZXJyaWRlIG9ubHlcbiAqICAgIHJldGFpbnMgcmF3IHNvdXJjZSByb3dzLCBuZXZlciB3aWRlbnMgYSByZXBvcnQpLlxuICogYGluZ2VzdF9oZWFsdGhgIGFuZCBgZG9yYV9zZXR0aW5nc2AgYXJlIG5ldmVyIHB1cmdlZC4gRW52LW92ZXJyaWRhYmxlIGdsb2JhbHM7XG4gKiBhIHBlci1vcmcgb3ZlcnJpZGUgaW4gYGRvcmFfc2V0dGluZ3NgIHdpbnMgKHNlZSB7QGxpbmsgcmVzb2x2ZUV2ZW50UmV0ZW50aW9uRGF5c30pLlxuICovXG5cbi8qKiBEZXBsb3ltZW50IGZyZXF1ZW5jeSBieSBkZXBsb3lzL2RheTogZWxpdGUg4omlMS9kYXksIGhpZ2gg4omlMS93ZWVrLCBtZWRpdW0g4omlMS9tb250aC4gKi9cbmV4cG9ydCBmdW5jdGlvbiBkb3JhTGV2ZWxGb3JGcmVxdWVuY3kocGVyRGF5OiBudW1iZXIsIGRlcGxveW1lbnRzOiBudW1iZXIpOiBEb3JhTGV2ZWwge1xuICBpZiAoZGVwbG95bWVudHMgPD0gMCkgcmV0dXJuIG51bGw7XG4gIGlmIChwZXJEYXkgPj0gMSkgcmV0dXJuICdlbGl0ZSc7XG4gIGlmIChwZXJEYXkgPj0gMSAvIDcpIHJldHVybiAnaGlnaCc7XG4gIGlmIChwZXJEYXkgPj0gMSAvIDMwKSByZXR1cm4gJ21lZGl1bSc7XG4gIHJldHVybiAnbG93Jztcbn1cbi8qKiBDaGFuZ2UgZmFpbHVyZSByYXRlIGJ5IHBlcmNlbnQ6IGVsaXRlIOKJpDUlLCBoaWdoIOKJpDEwJSwgbWVkaXVtIOKJpDE1JS4gKi9cbmV4cG9ydCBmdW5jdGlvbiBkb3JhTGV2ZWxGb3JDaGFuZ2VGYWlsdXJlKHBjdDogbnVtYmVyLCB0b3RhbDogbnVtYmVyKTogRG9yYUxldmVsIHtcbiAgaWYgKHRvdGFsIDw9IDApIHJldHVybiBudWxsO1xuICBpZiAocGN0IDw9IDUpIHJldHVybiAnZWxpdGUnO1xuICBpZiAocGN0IDw9IDEwKSByZXR1cm4gJ2hpZ2gnO1xuICBpZiAocGN0IDw9IDE1KSByZXR1cm4gJ21lZGl1bSc7XG4gIHJldHVybiAnbG93Jztcbn1cbi8qKiBUaW1lIHRvIHJlc3RvcmUgYnkgc2Vjb25kczogZWxpdGUgPDFoLCBoaWdoIDwxIGRheSwgbWVkaXVtIDwxIHdlZWsuICovXG5leHBvcnQgZnVuY3Rpb24gZG9yYUxldmVsRm9yUmVzdG9yZShhdmdTZWNvbmRzOiBudW1iZXIgfCBudWxsKTogRG9yYUxldmVsIHtcbiAgaWYgKGF2Z1NlY29uZHMgPT0gbnVsbCkgcmV0dXJuIG51bGw7XG4gIGlmIChhdmdTZWNvbmRzIDwgMzYwMCkgcmV0dXJuICdlbGl0ZSc7XG4gIGlmIChhdmdTZWNvbmRzIDwgODY0MDApIHJldHVybiAnaGlnaCc7XG4gIGlmIChhdmdTZWNvbmRzIDwgNjA0ODAwKSByZXR1cm4gJ21lZGl1bSc7XG4gIHJldHVybiAnbG93Jztcbn1cbi8qKiBMZWFkIHRpbWUgYnkgc2Vjb25kczogZWxpdGUgPDEgZGF5LCBoaWdoIDwxIHdlZWssIG1lZGl1bSA8MSBtb250aC4gKi9cbmV4cG9ydCBmdW5jdGlvbiBkb3JhTGV2ZWxGb3JMZWFkVGltZShtZWRpYW5TZWNvbmRzOiBudW1iZXIgfCBudWxsKTogRG9yYUxldmVsIHtcbiAgaWYgKG1lZGlhblNlY29uZHMgPT0gbnVsbCkgcmV0dXJuIG51bGw7XG4gIGlmIChtZWRpYW5TZWNvbmRzIDwgODY0MDApIHJldHVybiAnZWxpdGUnO1xuICBpZiAobWVkaWFuU2Vjb25kcyA8IDYwNDgwMCkgcmV0dXJuICdoaWdoJztcbiAgaWYgKG1lZGlhblNlY29uZHMgPCAyNTkyMDAwKSByZXR1cm4gJ21lZGl1bSc7XG4gIHJldHVybiAnbG93Jztcbn1cblxuLyoqXG4gKiBSb3VuZCBgdmFsdWVgIHRvIGBkaWdpdHNgIGRlY2ltYWwgcGxhY2VzLCByZXR1cm5pbmcgYSByZWFsIG51bWJlci4gU21hbGxcbiAqIG1vZHVsZS1wcml2YXRlIGhlbHBlciBzbyB0aGUgRE9SQSBzaGFwaW5nIGRvZXNuJ3QgcmVwZWF0IHRoZVxuICogYE51bWJlcihOdW1iZXIoeCkudG9GaXhlZChuKSlgIHBhdHRlcm4gKHRvRml4ZWQgYWxvbmUgeWllbGRzIGEgc3RyaW5nKS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJvdW5kKHZhbHVlOiBudW1iZXIsIGRpZ2l0czogbnVtYmVyKTogbnVtYmVyIHtcbiAgcmV0dXJuIE51bWJlcih2YWx1ZS50b0ZpeGVkKGRpZ2l0cykpO1xufVxuXG4vKipcbiAqIE1lZGlhbiBvZiBhIG51bWVyaWMgc2FtcGxlLCBvciBgbnVsbGAgd2hlbiBlbXB0eS4gVXNlZCBmb3IgbWVhc3VyZWQgbGVhZCB0aW1lXG4gKiBhbmQgTVRUUiDigJQgYm90aCBhcmUgY3Jvc3Mtc291cmNlIGdhcHMgY29tcHV0ZWQgaW4gSlMgZnJvbSBjbGFtcGVkIGRlbHRhcywgc29cbiAqIHRoZSBtZWRpYW4gbGl2ZXMgaGVyZSByYXRoZXIgdGhhbiBpbiBTUUwgUEVSQ0VOVElMRV9DT05UIChrZWVwcyB0aGUgZ29sZGVuXG4gKiBmaXh0dXJlIHRlc3RzIGFibGUgdG8gcHJvdmUgdGhlIG1ldHJpYyBtYXRoIHdpdGhvdXQgYSBsaXZlIFBvc3RncmVzKS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG1lZGlhbih2YWx1ZXM6IG51bWJlcltdKTogbnVtYmVyIHwgbnVsbCB7XG4gIGlmICh2YWx1ZXMubGVuZ3RoID09PSAwKSByZXR1cm4gbnVsbDtcbiAgY29uc3QgcyA9IFsuLi52YWx1ZXNdLnNvcnQoKGEsIGIpID0+IGEgLSBiKTtcbiAgY29uc3QgbWlkID0gTWF0aC5mbG9vcihzLmxlbmd0aCAvIDIpO1xuICByZXR1cm4gcy5sZW5ndGggJSAyID09PSAxID8gc1ttaWRdIDogKHNbbWlkIC0gMV0gKyBzW21pZF0pIC8gMjtcbn1cblxuLyoqXG4gKiBSb2xsIGEgZ3JvdXAgb2YgZGVwbG95L3N0YWdlIGV2ZW50cyAoZ3JvdXBlZCBwZXIgZXhlY3V0aW9uKSB1cCB0byBvbmUgdGVybWluYWxcbiAqIHN0YXR1czogRkFJTEVEIHdpbnMsIHRoZW4gU1VDQ0VFREVELCBlbHNlIE9USEVSIChzdGlsbC1ydW5uaW5nIC8gbm9uLXRlcm1pbmFsKS5cbiAqIFNoYXJlZCBieSB0aGUgdGhyZWUgcGVyLShlbnZ8c3RhZ2UsIGV4ZWN1dGlvbikgcm9sbHVwIENURXMg4oCUIERPUkEgbWV0cmljcywgRE9SQVxuICogdHJlbmQsIGFuZCBidWlsZCBoZWFsdGgg4oCUIHNvIHRoZSBwcmVjZWRlbmNlIGNhbid0IGRyaWZ0IGJldHdlZW4gdGhlbS4gQXNzdW1lcyB0aGVcbiAqIGdyb3VwZWQgZXZlbnQgYWxpYXMgaXMgYGVgLlxuICovXG4iXX0=
@@ -0,0 +1,47 @@
1
+ import type { DoraOptions, DoraMetrics, DoraTrendPoint, BuildHealth } from './types.js';
2
+ /**
3
+ * 1.9 DORA metrics over a [from,to] deploy-completion window, org-scoped +
4
+ * rollup-aware. DEPLOY-BASIS ONLY — every metric derives from real deploy-stage
5
+ * executions (`event_type='STAGE'` with a non-null `environment`, set by the
6
+ * forwarder for the stages a user declared in `pb.deploys`). No run-based
7
+ * fallback: a pipeline with no deploy stage produces no DORA data.
8
+ *
9
+ * Four scoped SQL scans run inside one tx (each org-gated by `p.org_id ${pred}`
10
+ * / `o.org_id ${pred}` so a rollup passes the org→team subtree and a foreign
11
+ * org's rows never enter): (1) terminal deploy rows PER (execution, env) — one
12
+ * "deployment" = one execution reaching an env (D1) — → DF / deploy-time CFR /
13
+ * measured lead time (lead time joins the execution's earliest commit, D2);
14
+ * the scan also reaches back `windowHours` before `from` so incidents opened
15
+ * near the window start can correlate to a just-prior deploy; (2) `deployment_outcomes`
16
+ * in-window → post-deploy CFR component; (3) production restored/failed
17
+ * outcomes joined to their deploy → MTTR; (4) registry vs deploying → coverage.
18
+ * The cross-source medians (lead time, MTTR) are computed in JS from clamped
19
+ * (≥0) deltas.
20
+ *
21
+ * @param opts.pipelineId restrict to one pipeline (per-pipeline DORA)
22
+ * @param opts.environment restrict to one deploy environment
23
+ */
24
+ export declare function getDoraMetrics(orgId: string, from: string, to: string, orgIds?: string[], opts?: DoraOptions): Promise<DoraMetrics>;
25
+ /**
26
+ * 1.9b DORA trend — deployment frequency + deploy-time change-failure rate
27
+ * bucketed by `interval` (day/week/month) for a sparkline. Deploy-basis like
28
+ * getDoraMetrics: buckets terminal deploy-stage executions on their
29
+ * `completed_at`. Shares the org/rollup + pipelineId/environment scoping. MTTR,
30
+ * lead time, and post-deploy CFR are intentionally omitted (too heavy to bucket).
31
+ */
32
+ export declare function getDoraTrend(orgId: string, interval: string, from: string, to: string, orgIds?: string[], opts?: DoraOptions): Promise<DoraTrendPoint[]>;
33
+ /**
34
+ * 1.10 Per-pipeline BUILD HEALTH (Phase 6) — a standard (NOT `advanced_reporting`)
35
+ * per-stage breakdown for one pipeline over a [from,to] window. Aggregates the
36
+ * existing `pipeline_events` STAGE rows: each stage is rolled up per execution
37
+ * to a terminal status (FAILED wins, then SUCCEEDED) + its max duration, then
38
+ * grouped per stage into run/success/failure counts, a success rate, and
39
+ * duration percentiles (p50/p90/p99). Totals sum across stages. Org-scoped via
40
+ * the pipeline join (`p.org_id ${pred}`) + rollup-aware like the sibling reports;
41
+ * a pipelineId owned by another org returns an empty breakdown.
42
+ */
43
+ export declare function getBuildHealth(orgId: string, pipelineId: string, from: string, to: string, orgIds?: string[]): Promise<BuildHealth>;
44
+ /** 2.1 Plugin summary — counts and breakdowns.
45
+ * INTENTIONALLY SINGLE-ORG (no rollup): plugin inventory is an org-owned
46
+ * asset count, not an execution/build activity report, so a parent's view is
47
+ * its own plugins — teams manage their own inventory. Single `= $org` scope. */