@lumenflow/metrics 3.17.6 → 3.18.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.
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=dora-edge-cases.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dora-edge-cases.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/dora-edge-cases.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,214 @@
1
+ // Copyright (c) 2026 Hellmai Ltd
2
+ // SPDX-License-Identifier: AGPL-3.0-only
3
+ /**
4
+ * Edge case tests for DORA metrics calculations.
5
+ *
6
+ * Complements the happy-path coverage in __tests__/dora/ with edge cases:
7
+ * - Single data point scenarios
8
+ * - Overlapping time windows
9
+ * - Empty data across all metric types
10
+ * - Boundary values at classification thresholds
11
+ */
12
+ import { describe, it, expect } from 'vitest';
13
+ import { calculateDeploymentFrequency, calculateLeadTime, calculateCFR, calculateMTTR, calculateDORAMetrics, identifyEmergencyFixes, } from '../dora/calculate-dora-metrics.js';
14
+ describe('DORA edge cases: deployment frequency', () => {
15
+ it('counts exactly 1 commit for a 1-deploy high classification', () => {
16
+ const weekStart = new Date('2026-03-01');
17
+ const weekEnd = new Date('2026-03-07');
18
+ const commits = [
19
+ { hash: 'single', timestamp: new Date('2026-03-03'), message: 'feat: only one' },
20
+ ];
21
+ const result = calculateDeploymentFrequency(commits, weekStart, weekEnd);
22
+ expect(result.deploysPerWeek).toBe(1);
23
+ expect(result.status).toBe('high');
24
+ });
25
+ it('counts exactly 5 commits at the elite/high boundary', () => {
26
+ const weekStart = new Date('2026-03-01');
27
+ const weekEnd = new Date('2026-03-07');
28
+ const commits = Array.from({ length: 5 }, (_, i) => ({
29
+ hash: `h${i}`,
30
+ timestamp: new Date('2026-03-03'),
31
+ message: `feat: ${i}`,
32
+ }));
33
+ const result = calculateDeploymentFrequency(commits, weekStart, weekEnd);
34
+ expect(result.deploysPerWeek).toBe(5);
35
+ expect(result.status).toBe('high');
36
+ });
37
+ it('includes commits at exact weekStart and weekEnd timestamps', () => {
38
+ const weekStart = new Date('2026-03-01T00:00:00.000Z');
39
+ const weekEnd = new Date('2026-03-07T23:59:59.999Z');
40
+ const commits = [
41
+ { hash: 'start', timestamp: weekStart, message: 'feat: at start' },
42
+ { hash: 'end', timestamp: weekEnd, message: 'feat: at end' },
43
+ ];
44
+ const result = calculateDeploymentFrequency(commits, weekStart, weekEnd);
45
+ expect(result.deploysPerWeek).toBe(2);
46
+ });
47
+ it('excludes commits just outside the time window', () => {
48
+ const weekStart = new Date('2026-03-01T00:00:00.001Z');
49
+ const weekEnd = new Date('2026-03-07T23:59:59.999Z');
50
+ const commits = [
51
+ { hash: 'before', timestamp: new Date('2026-03-01T00:00:00.000Z'), message: 'before' },
52
+ { hash: 'inside', timestamp: new Date('2026-03-03T12:00:00.000Z'), message: 'inside' },
53
+ ];
54
+ const result = calculateDeploymentFrequency(commits, weekStart, weekEnd);
55
+ expect(result.deploysPerWeek).toBe(1);
56
+ });
57
+ });
58
+ describe('DORA edge cases: lead time', () => {
59
+ it('handles single WU metric correctly', () => {
60
+ const wuMetrics = [
61
+ { id: 'WU-1', title: 'solo', lane: 'Ops', status: 'done', cycleTimeHours: 12 },
62
+ ];
63
+ const result = calculateLeadTime(wuMetrics);
64
+ expect(result.averageHours).toBe(12);
65
+ expect(result.medianHours).toBe(12);
66
+ expect(result.p90Hours).toBe(12);
67
+ expect(result.status).toBe('elite');
68
+ });
69
+ it('filters out non-numeric cycle times without crashing', () => {
70
+ const wuMetrics = [
71
+ { id: 'WU-1', title: 'a', lane: 'Ops', status: 'done' },
72
+ { id: 'WU-2', title: 'b', lane: 'Ops', status: 'in_progress' },
73
+ ];
74
+ const result = calculateLeadTime(wuMetrics);
75
+ expect(result.averageHours).toBe(0);
76
+ expect(result.status).toBe('low');
77
+ });
78
+ it('rounds averageHours to one decimal place', () => {
79
+ const wuMetrics = [
80
+ { id: 'WU-1', title: 'a', lane: 'Ops', status: 'done', cycleTimeHours: 10 },
81
+ { id: 'WU-2', title: 'b', lane: 'Ops', status: 'done', cycleTimeHours: 11 },
82
+ { id: 'WU-3', title: 'c', lane: 'Ops', status: 'done', cycleTimeHours: 12 },
83
+ ];
84
+ const result = calculateLeadTime(wuMetrics);
85
+ expect(result.averageHours).toBe(11);
86
+ });
87
+ it('returns high status at exactly 24h boundary', () => {
88
+ const wuMetrics = [
89
+ { id: 'WU-1', title: 'a', lane: 'Ops', status: 'done', cycleTimeHours: 24 },
90
+ ];
91
+ const result = calculateLeadTime(wuMetrics);
92
+ expect(result.status).toBe('high');
93
+ });
94
+ it('returns elite status at just under 24h', () => {
95
+ const wuMetrics = [
96
+ { id: 'WU-1', title: 'a', lane: 'Ops', status: 'done', cycleTimeHours: 23.9 },
97
+ ];
98
+ const result = calculateLeadTime(wuMetrics);
99
+ expect(result.status).toBe('elite');
100
+ });
101
+ });
102
+ describe('DORA edge cases: change failure rate', () => {
103
+ it('handles no failures with commits', () => {
104
+ const commits = [{ hash: 'a', timestamp: new Date(), message: 'feat: a' }];
105
+ const result = calculateCFR(commits, []);
106
+ expect(result.failurePercentage).toBe(0);
107
+ expect(result.totalDeployments).toBe(1);
108
+ expect(result.failures).toBe(0);
109
+ expect(result.status).toBe('elite');
110
+ });
111
+ it('handles all-failure scenario', () => {
112
+ const commits = [{ hash: 'a', timestamp: new Date(), message: 'feat: a' }];
113
+ const entries = [
114
+ { timestamp: new Date(), wuId: 'WU-1', reason: 'broke', gate: 'test' },
115
+ ];
116
+ const result = calculateCFR(commits, entries);
117
+ expect(result.failurePercentage).toBe(100);
118
+ expect(result.status).toBe('low');
119
+ });
120
+ it('handles exactly 15% boundary (elite/high)', () => {
121
+ const commits = Array.from({ length: 100 }, (_, i) => ({
122
+ hash: `h${i}`,
123
+ timestamp: new Date(),
124
+ message: `feat: ${i}`,
125
+ }));
126
+ const entries = Array.from({ length: 15 }, (_, i) => ({
127
+ timestamp: new Date(),
128
+ wuId: `WU-${i}`,
129
+ reason: 'test',
130
+ gate: 'lint',
131
+ }));
132
+ const result = calculateCFR(commits, entries);
133
+ expect(result.failurePercentage).toBe(15);
134
+ expect(result.status).toBe('high');
135
+ });
136
+ });
137
+ describe('DORA edge cases: MTTR', () => {
138
+ it('handles multiple emergency fix pairs and averages their recovery times', () => {
139
+ const commits = [
140
+ { hash: 'a', timestamp: new Date('2026-01-01T00:00:00Z'), message: 'EMERGENCY: break1' },
141
+ { hash: 'b', timestamp: new Date('2026-01-01T01:00:00Z'), message: 'EMERGENCY: fix1' },
142
+ { hash: 'c', timestamp: new Date('2026-01-02T00:00:00Z'), message: 'EMERGENCY: break2' },
143
+ { hash: 'd', timestamp: new Date('2026-01-02T03:00:00Z'), message: 'EMERGENCY: fix2' },
144
+ ];
145
+ const result = calculateMTTR(commits);
146
+ expect(result.incidents).toBe(2);
147
+ expect(result.averageHours).toBe(2);
148
+ });
149
+ it('ignores trailing odd emergency fix (unpaired)', () => {
150
+ const commits = [
151
+ { hash: 'a', timestamp: new Date('2026-01-01T00:00:00Z'), message: 'EMERGENCY: break' },
152
+ { hash: 'b', timestamp: new Date('2026-01-01T00:30:00Z'), message: 'EMERGENCY: fix' },
153
+ { hash: 'c', timestamp: new Date('2026-01-02T00:00:00Z'), message: 'EMERGENCY: orphan' },
154
+ ];
155
+ const result = calculateMTTR(commits);
156
+ expect(result.incidents).toBe(1);
157
+ expect(result.averageHours).toBe(0.5);
158
+ });
159
+ it('returns elite for MTTR under 1 hour', () => {
160
+ const commits = [
161
+ { hash: 'a', timestamp: new Date('2026-01-01T00:00:00Z'), message: 'EMERGENCY: break' },
162
+ { hash: 'b', timestamp: new Date('2026-01-01T00:30:00Z'), message: 'EMERGENCY: fix' },
163
+ ];
164
+ const result = calculateMTTR(commits);
165
+ expect(result.averageHours).toBe(0.5);
166
+ expect(result.status).toBe('elite');
167
+ });
168
+ });
169
+ describe('DORA edge cases: identifyEmergencyFixes', () => {
170
+ it('matches EMERGENCY substring in any position', () => {
171
+ const commits = [
172
+ { hash: 'a', timestamp: new Date(), message: 'feat: NON_EMERGENCY update' },
173
+ ];
174
+ // The function uses .includes('EMERGENCY'), so any substring match counts
175
+ const result = identifyEmergencyFixes(commits);
176
+ expect(result).toHaveLength(1);
177
+ });
178
+ it('does not match lowercase emergency', () => {
179
+ const commits = [
180
+ { hash: 'a', timestamp: new Date(), message: 'fix: emergency hotfix' },
181
+ ];
182
+ const result = identifyEmergencyFixes(commits);
183
+ expect(result).toHaveLength(0);
184
+ });
185
+ it('matches EMERGENCY anywhere in message', () => {
186
+ const commits = [
187
+ { hash: 'a', timestamp: new Date(), message: 'foo EMERGENCY bar' },
188
+ ];
189
+ const result = identifyEmergencyFixes(commits);
190
+ expect(result).toHaveLength(1);
191
+ });
192
+ it('matches fix(EMERGENCY) pattern', () => {
193
+ const commits = [
194
+ { hash: 'a', timestamp: new Date(), message: 'fix(EMERGENCY): restored service' },
195
+ ];
196
+ const result = identifyEmergencyFixes(commits);
197
+ expect(result).toHaveLength(1);
198
+ });
199
+ });
200
+ describe('DORA edge cases: calculateDORAMetrics integration', () => {
201
+ it('handles entirely empty inputs gracefully', () => {
202
+ const weekStart = new Date('2026-03-01');
203
+ const weekEnd = new Date('2026-03-07');
204
+ const result = calculateDORAMetrics([], [], [], weekStart, weekEnd);
205
+ expect(result.deploymentFrequency.deploysPerWeek).toBe(0);
206
+ expect(result.deploymentFrequency.status).toBe('low');
207
+ expect(result.leadTimeForChanges.averageHours).toBe(0);
208
+ expect(result.leadTimeForChanges.status).toBe('low');
209
+ expect(result.changeFailureRate.failurePercentage).toBe(0);
210
+ expect(result.meanTimeToRecovery.incidents).toBe(0);
211
+ expect(result.meanTimeToRecovery.status).toBe('elite');
212
+ });
213
+ });
214
+ //# sourceMappingURL=dora-edge-cases.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dora-edge-cases.test.js","sourceRoot":"","sources":["../../src/__tests__/dora-edge-cases.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=flow-edge-cases.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flow-edge-cases.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/flow-edge-cases.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,265 @@
1
+ // Copyright (c) 2026 Hellmai Ltd
2
+ // SPDX-License-Identifier: AGPL-3.0-only
3
+ /**
4
+ * Edge case tests for SPACE / flow metrics calculations.
5
+ *
6
+ * Covers:
7
+ * - Flow state with all same-status WUs
8
+ * - Bottleneck analysis with diamond dependencies
9
+ * - Critical path through complex DAGs
10
+ * - Metrics snapshot type filtering
11
+ * - Lane health status classification edges
12
+ */
13
+ import { describe, it, expect } from 'vitest';
14
+ import { calculateFlowState } from '../flow/calculate-flow-state.js';
15
+ import { topologicalSort, criticalPath, impactScore, analyzeBottlenecks, getBottleneckAnalysis, } from '../flow/analyze-bottlenecks.js';
16
+ import { captureMetricsSnapshot } from '../flow/capture-metrics-snapshot.js';
17
+ function makeNode(id, blocks = [], blockedBy = [], status = 'ready') {
18
+ return { id, title: `Title: ${id}`, blocks, blockedBy, status };
19
+ }
20
+ describe('flow state edge cases', () => {
21
+ it('handles single WU in each status', () => {
22
+ const wuMetrics = [
23
+ { id: 'WU-1', title: 'a', lane: 'A', status: 'ready' },
24
+ { id: 'WU-2', title: 'b', lane: 'A', status: 'in_progress' },
25
+ { id: 'WU-3', title: 'c', lane: 'A', status: 'blocked' },
26
+ { id: 'WU-4', title: 'd', lane: 'A', status: 'waiting' },
27
+ { id: 'WU-5', title: 'e', lane: 'A', status: 'done' },
28
+ ];
29
+ const result = calculateFlowState(wuMetrics);
30
+ expect(result.ready).toBe(1);
31
+ expect(result.inProgress).toBe(1);
32
+ expect(result.blocked).toBe(1);
33
+ expect(result.waiting).toBe(1);
34
+ expect(result.done).toBe(1);
35
+ expect(result.totalActive).toBe(4);
36
+ });
37
+ it('all done WUs yield totalActive of 0', () => {
38
+ const wuMetrics = [
39
+ { id: 'WU-1', title: 'a', lane: 'A', status: 'done' },
40
+ { id: 'WU-2', title: 'b', lane: 'A', status: 'done' },
41
+ ];
42
+ const result = calculateFlowState(wuMetrics);
43
+ expect(result.totalActive).toBe(0);
44
+ expect(result.done).toBe(2);
45
+ });
46
+ });
47
+ describe('bottleneck analysis edge cases', () => {
48
+ it('diamond dependency pattern: single node blocks two which converge', () => {
49
+ // WU-1 blocks WU-2 and WU-3, both block WU-4
50
+ const graph = new Map([
51
+ ['WU-1', makeNode('WU-1', ['WU-2', 'WU-3'], [])],
52
+ ['WU-2', makeNode('WU-2', ['WU-4'], ['WU-1'])],
53
+ ['WU-3', makeNode('WU-3', ['WU-4'], ['WU-1'])],
54
+ ['WU-4', makeNode('WU-4', [], ['WU-2', 'WU-3'])],
55
+ ]);
56
+ const bottlenecks = analyzeBottlenecks(graph, 4);
57
+ expect(bottlenecks[0]?.id).toBe('WU-1');
58
+ expect(bottlenecks[0]?.score).toBe(3);
59
+ });
60
+ it('impactScore returns 0 for a node not in the graph', () => {
61
+ const graph = new Map([['WU-1', makeNode('WU-1', [], [])]]);
62
+ expect(impactScore(graph, 'WU-999')).toBe(0);
63
+ });
64
+ it('impactScore returns 0 for a done node', () => {
65
+ const graph = new Map([
66
+ ['WU-1', makeNode('WU-1', ['WU-2'], [], 'done')],
67
+ ['WU-2', makeNode('WU-2', [], ['WU-1'])],
68
+ ]);
69
+ expect(impactScore(graph, 'WU-1')).toBe(0);
70
+ });
71
+ it('impactScore returns 0 for a leaf node (no downstream)', () => {
72
+ const graph = new Map([['WU-1', makeNode('WU-1', [], [])]]);
73
+ expect(impactScore(graph, 'WU-1')).toBe(0);
74
+ });
75
+ it('analyzeBottlenecks limits output to requested count', () => {
76
+ const graph = new Map([
77
+ ['WU-1', makeNode('WU-1', ['WU-3'], [])],
78
+ ['WU-2', makeNode('WU-2', ['WU-3'], [])],
79
+ ['WU-3', makeNode('WU-3', [], ['WU-1', 'WU-2'])],
80
+ ]);
81
+ const bottlenecks = analyzeBottlenecks(graph, 1);
82
+ expect(bottlenecks).toHaveLength(1);
83
+ });
84
+ });
85
+ describe('topological sort edge cases', () => {
86
+ it('single node graph', () => {
87
+ const graph = new Map([['WU-1', makeNode('WU-1', [], [])]]);
88
+ const result = topologicalSort(graph);
89
+ expect(result.hasCycle).toBe(false);
90
+ expect(result.order).toEqual(['WU-1']);
91
+ });
92
+ it('all done nodes yield empty order', () => {
93
+ const graph = new Map([
94
+ ['WU-1', makeNode('WU-1', ['WU-2'], [], 'done')],
95
+ ['WU-2', makeNode('WU-2', [], ['WU-1'], 'done')],
96
+ ]);
97
+ const result = topologicalSort(graph);
98
+ expect(result.order).toEqual([]);
99
+ expect(result.hasCycle).toBe(false);
100
+ });
101
+ it('detects a simple cycle between two nodes', () => {
102
+ const graph = new Map([
103
+ ['WU-1', makeNode('WU-1', ['WU-2'], ['WU-2'])],
104
+ ['WU-2', makeNode('WU-2', ['WU-1'], ['WU-1'])],
105
+ ]);
106
+ const result = topologicalSort(graph);
107
+ expect(result.hasCycle).toBe(true);
108
+ expect(result.cycleNodes).toBeDefined();
109
+ expect(result.cycleNodes?.length).toBeGreaterThan(0);
110
+ });
111
+ });
112
+ describe('critical path edge cases', () => {
113
+ it('returns empty path for all-done graph', () => {
114
+ const graph = new Map([['WU-1', makeNode('WU-1', [], [], 'done')]]);
115
+ const result = criticalPath(graph);
116
+ expect(result.path).toEqual([]);
117
+ expect(result.length).toBe(0);
118
+ });
119
+ it('returns warning for cyclic graph', () => {
120
+ const graph = new Map([
121
+ ['WU-1', makeNode('WU-1', ['WU-2'], ['WU-2'])],
122
+ ['WU-2', makeNode('WU-2', ['WU-1'], ['WU-1'])],
123
+ ]);
124
+ const result = criticalPath(graph);
125
+ expect(result.warning).toBeDefined();
126
+ expect(result.cycleNodes).toBeDefined();
127
+ });
128
+ it('finds correct path in 3-node chain', () => {
129
+ const graph = new Map([
130
+ ['WU-1', makeNode('WU-1', ['WU-2'], [])],
131
+ ['WU-2', makeNode('WU-2', ['WU-3'], ['WU-1'])],
132
+ ['WU-3', makeNode('WU-3', [], ['WU-2'])],
133
+ ]);
134
+ const result = criticalPath(graph);
135
+ expect(result.path).toEqual(['WU-1', 'WU-2', 'WU-3']);
136
+ expect(result.length).toBe(3);
137
+ });
138
+ });
139
+ describe('getBottleneckAnalysis', () => {
140
+ it('returns both bottlenecks and critical path', () => {
141
+ const graph = new Map([
142
+ ['WU-1', makeNode('WU-1', ['WU-2'], [])],
143
+ ['WU-2', makeNode('WU-2', [], ['WU-1'])],
144
+ ]);
145
+ const analysis = getBottleneckAnalysis(graph, 5);
146
+ expect(analysis.bottlenecks).toBeDefined();
147
+ expect(analysis.criticalPath).toBeDefined();
148
+ expect(analysis.bottlenecks.length).toBeGreaterThan(0);
149
+ });
150
+ it('uses default limit of 10', () => {
151
+ const graph = new Map([['WU-1', makeNode('WU-1', [], [])]]);
152
+ const analysis = getBottleneckAnalysis(graph);
153
+ expect(analysis.bottlenecks).toBeDefined();
154
+ });
155
+ });
156
+ describe('captureMetricsSnapshot edge cases', () => {
157
+ it('captures only DORA when type is "dora"', () => {
158
+ const snapshot = captureMetricsSnapshot({
159
+ commits: [],
160
+ wuMetrics: [],
161
+ skipGatesEntries: [],
162
+ weekStart: new Date('2026-03-01'),
163
+ weekEnd: new Date('2026-03-07'),
164
+ type: 'dora',
165
+ });
166
+ expect(snapshot.dora).toBeDefined();
167
+ expect(snapshot.lanes).toBeUndefined();
168
+ expect(snapshot.flow).toBeUndefined();
169
+ });
170
+ it('captures only lanes when type is "lanes"', () => {
171
+ const snapshot = captureMetricsSnapshot({
172
+ commits: [],
173
+ wuMetrics: [],
174
+ skipGatesEntries: [],
175
+ weekStart: new Date('2026-03-01'),
176
+ weekEnd: new Date('2026-03-07'),
177
+ type: 'lanes',
178
+ });
179
+ expect(snapshot.dora).toBeUndefined();
180
+ expect(snapshot.lanes).toBeDefined();
181
+ expect(snapshot.flow).toBeUndefined();
182
+ });
183
+ it('captures only flow when type is "flow"', () => {
184
+ const snapshot = captureMetricsSnapshot({
185
+ commits: [],
186
+ wuMetrics: [],
187
+ skipGatesEntries: [],
188
+ weekStart: new Date('2026-03-01'),
189
+ weekEnd: new Date('2026-03-07'),
190
+ type: 'flow',
191
+ });
192
+ expect(snapshot.dora).toBeUndefined();
193
+ expect(snapshot.lanes).toBeUndefined();
194
+ expect(snapshot.flow).toBeDefined();
195
+ });
196
+ it('captures all metric types when type is "all"', () => {
197
+ const snapshot = captureMetricsSnapshot({
198
+ commits: [],
199
+ wuMetrics: [],
200
+ skipGatesEntries: [],
201
+ weekStart: new Date('2026-03-01'),
202
+ weekEnd: new Date('2026-03-07'),
203
+ type: 'all',
204
+ });
205
+ expect(snapshot.dora).toBeDefined();
206
+ expect(snapshot.lanes).toBeDefined();
207
+ expect(snapshot.flow).toBeDefined();
208
+ });
209
+ it('computes lane health status correctly for mixed WU statuses', () => {
210
+ const snapshot = captureMetricsSnapshot({
211
+ commits: [],
212
+ wuMetrics: [
213
+ { id: 'WU-1', title: 'a', lane: 'Ops', status: 'done', cycleTimeHours: 10 },
214
+ { id: 'WU-2', title: 'b', lane: 'Ops', status: 'in_progress' },
215
+ { id: 'WU-3', title: 'c', lane: 'Ops', status: 'blocked' },
216
+ { id: 'WU-4', title: 'd', lane: 'Dev', status: 'done', cycleTimeHours: 20 },
217
+ ],
218
+ skipGatesEntries: [],
219
+ weekStart: new Date('2026-03-01'),
220
+ weekEnd: new Date('2026-03-07'),
221
+ type: 'lanes',
222
+ });
223
+ expect(snapshot.lanes).toBeDefined();
224
+ expect(snapshot.lanes?.totalActive).toBe(2);
225
+ expect(snapshot.lanes?.totalBlocked).toBe(1);
226
+ expect(snapshot.lanes?.totalCompleted).toBe(2);
227
+ const opsLane = snapshot.lanes?.lanes.find((l) => l.lane === 'Ops');
228
+ expect(opsLane).toBeDefined();
229
+ expect(opsLane?.status).toBe('at-risk');
230
+ expect(opsLane?.wusCompleted).toBe(1);
231
+ expect(opsLane?.wusInProgress).toBe(1);
232
+ expect(opsLane?.wusBlocked).toBe(1);
233
+ });
234
+ it('lane health is "healthy" when no WUs are blocked', () => {
235
+ const snapshot = captureMetricsSnapshot({
236
+ commits: [],
237
+ wuMetrics: [
238
+ { id: 'WU-1', title: 'a', lane: 'Ops', status: 'in_progress' },
239
+ { id: 'WU-2', title: 'b', lane: 'Ops', status: 'done', cycleTimeHours: 5 },
240
+ ],
241
+ skipGatesEntries: [],
242
+ weekStart: new Date('2026-03-01'),
243
+ weekEnd: new Date('2026-03-07'),
244
+ type: 'lanes',
245
+ });
246
+ const opsLane = snapshot.lanes?.lanes.find((l) => l.lane === 'Ops');
247
+ expect(opsLane?.status).toBe('healthy');
248
+ });
249
+ it('lane health is "blocked" when all in-progress are blocked', () => {
250
+ const snapshot = captureMetricsSnapshot({
251
+ commits: [],
252
+ wuMetrics: [
253
+ { id: 'WU-1', title: 'a', lane: 'Ops', status: 'blocked' },
254
+ { id: 'WU-2', title: 'b', lane: 'Ops', status: 'blocked' },
255
+ ],
256
+ skipGatesEntries: [],
257
+ weekStart: new Date('2026-03-01'),
258
+ weekEnd: new Date('2026-03-07'),
259
+ type: 'lanes',
260
+ });
261
+ const opsLane = snapshot.lanes?.lanes.find((l) => l.lane === 'Ops');
262
+ expect(opsLane?.status).toBe('blocked');
263
+ });
264
+ });
265
+ //# sourceMappingURL=flow-edge-cases.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flow-edge-cases.test.js","sourceRoot":"","sources":["../../src/__tests__/flow-edge-cases.test.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lumenflow/metrics",
3
- "version": "3.17.6",
3
+ "version": "3.18.0",
4
4
  "description": "DORA/SPACE analytics and flow metrics for LumenFlow workflow framework",
5
5
  "keywords": [
6
6
  "lumenflow",