@lumenflow/cli 3.18.1 → 3.19.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.
Files changed (159) hide show
  1. package/dist/docs-sync.js +123 -6
  2. package/dist/docs-sync.js.map +1 -1
  3. package/dist/gate-co-change.js +23 -4
  4. package/dist/gate-co-change.js.map +1 -1
  5. package/dist/gates-runners.js +108 -12
  6. package/dist/gates-runners.js.map +1 -1
  7. package/dist/lumenflow-upgrade.js +1 -0
  8. package/dist/lumenflow-upgrade.js.map +1 -1
  9. package/dist/public-manifest.js +1 -1
  10. package/dist/public-manifest.js.map +1 -1
  11. package/dist/sync-templates.js +13 -0
  12. package/dist/sync-templates.js.map +1 -1
  13. package/dist/wu-block.js +10 -0
  14. package/dist/wu-block.js.map +1 -1
  15. package/dist/wu-claim-validation.js +3 -1
  16. package/dist/wu-claim-validation.js.map +1 -1
  17. package/dist/wu-claim.js +3 -1
  18. package/dist/wu-claim.js.map +1 -1
  19. package/dist/wu-done-memory-telemetry.js +5 -1
  20. package/dist/wu-done-memory-telemetry.js.map +1 -1
  21. package/dist/wu-done-ownership.js +6 -0
  22. package/dist/wu-done-ownership.js.map +1 -1
  23. package/dist/wu-edit-operations.js +4 -4
  24. package/dist/wu-edit-operations.js.map +1 -1
  25. package/dist/wu-prep.js +88 -13
  26. package/dist/wu-prep.js.map +1 -1
  27. package/dist/wu-recover.js +15 -0
  28. package/dist/wu-recover.js.map +1 -1
  29. package/dist/wu-release.js +10 -1
  30. package/dist/wu-release.js.map +1 -1
  31. package/dist/wu-spawn-prompt-builders.js +27 -2
  32. package/dist/wu-spawn-prompt-builders.js.map +1 -1
  33. package/dist/wu-state-mutation-ownership.js +136 -0
  34. package/dist/wu-state-mutation-ownership.js.map +1 -0
  35. package/dist/wu-unblock.js +10 -0
  36. package/dist/wu-unblock.js.map +1 -1
  37. package/package.json +111 -110
  38. package/packs/agent-runtime/.turbo/turbo-build.log +1 -1
  39. package/packs/agent-runtime/package.json +1 -1
  40. package/packs/sidekick/.turbo/turbo-build.log +1 -1
  41. package/packs/sidekick/package.json +1 -1
  42. package/packs/software-delivery/.turbo/turbo-build.log +1 -1
  43. package/packs/software-delivery/package.json +1 -1
  44. package/templates/core/AGENTS.md.template +157 -32
  45. package/templates/core/LUMENFLOW.md.template +44 -29
  46. package/templates/core/_frameworks/lumenflow/wu-sizing-guide.md.template +644 -0
  47. package/templates/core/ai/onboarding/agent-invocation-guide.md.template +5 -5
  48. package/templates/core/ai/onboarding/agent-safety-card.md.template +1 -0
  49. package/templates/core/ai/onboarding/docs-generation.md.template +94 -4
  50. package/templates/core/ai/onboarding/first-15-mins.md.template +1 -1
  51. package/templates/core/ai/onboarding/first-wu-mistakes.md.template +2 -1
  52. package/templates/core/ai/onboarding/initiative-orchestration.md.template +21 -21
  53. package/templates/core/ai/onboarding/quick-ref-commands.md.template +102 -95
  54. package/templates/core/ai/onboarding/release-process.md.template +12 -12
  55. package/templates/core/ai/onboarding/starting-prompt.md.template +31 -31
  56. package/templates/vendors/claude/.claude/skills/initiative-management/SKILL.md.template +2 -2
  57. package/templates/vendors/claude/.claude/skills/multi-agent-coordination/SKILL.md.template +2 -2
  58. package/templates/vendors/claude/.claude/skills/orchestration/SKILL.md.template +3 -3
  59. package/dist/chunk-2D2VOCA4.js +0 -37
  60. package/dist/chunk-2D5KFYGX.js +0 -284
  61. package/dist/chunk-2GXVIN57.js +0 -14072
  62. package/dist/chunk-2MQ7HZWZ.js +0 -26
  63. package/dist/chunk-2UFQ3A3C.js +0 -643
  64. package/dist/chunk-3RG5ZIWI.js +0 -10
  65. package/dist/chunk-4N74J3UT.js +0 -15
  66. package/dist/chunk-5GTOXFYR.js +0 -392
  67. package/dist/chunk-5VY6MQMC.js +0 -240
  68. package/dist/chunk-67XVPMRY.js +0 -1297
  69. package/dist/chunk-6HO4GWJE.js +0 -164
  70. package/dist/chunk-6W5XHWYV.js +0 -1890
  71. package/dist/chunk-6X4EMYJQ.js +0 -64
  72. package/dist/chunk-6XYXI2NQ.js +0 -772
  73. package/dist/chunk-7ANSOV6Q.js +0 -285
  74. package/dist/chunk-A624LFLB.js +0 -1380
  75. package/dist/chunk-ADN5NHG4.js +0 -126
  76. package/dist/chunk-B7YJYJKG.js +0 -33
  77. package/dist/chunk-CCLHCPKG.js +0 -210
  78. package/dist/chunk-CK36VROC.js +0 -1584
  79. package/dist/chunk-D3UOFRSB.js +0 -81
  80. package/dist/chunk-DFR4DJBM.js +0 -230
  81. package/dist/chunk-DSYBDHYH.js +0 -79
  82. package/dist/chunk-DWMLTXKQ.js +0 -1176
  83. package/dist/chunk-E3REJTAJ.js +0 -28
  84. package/dist/chunk-EA3IVO64.js +0 -633
  85. package/dist/chunk-EK2AKZKD.js +0 -55
  86. package/dist/chunk-ELD7JTTT.js +0 -343
  87. package/dist/chunk-EX6TT2XI.js +0 -195
  88. package/dist/chunk-EXINSFZE.js +0 -82
  89. package/dist/chunk-EZ6ZBYBM.js +0 -510
  90. package/dist/chunk-FBKAPTJ2.js +0 -16
  91. package/dist/chunk-FVLV5RYH.js +0 -1118
  92. package/dist/chunk-GDNSBQVK.js +0 -2485
  93. package/dist/chunk-GPQHMBNN.js +0 -278
  94. package/dist/chunk-GTFJB67L.js +0 -68
  95. package/dist/chunk-HANJXVKW.js +0 -1127
  96. package/dist/chunk-HEVS5YLD.js +0 -269
  97. package/dist/chunk-HMEVZKPQ.js +0 -9
  98. package/dist/chunk-HRGSYNLM.js +0 -3511
  99. package/dist/chunk-ISZR5N4K.js +0 -60
  100. package/dist/chunk-J6SUPR2C.js +0 -226
  101. package/dist/chunk-JERYVEIZ.js +0 -244
  102. package/dist/chunk-JHHWGL2N.js +0 -87
  103. package/dist/chunk-JONWQUB5.js +0 -775
  104. package/dist/chunk-K2DIWWDM.js +0 -1766
  105. package/dist/chunk-KY4PGL5V.js +0 -969
  106. package/dist/chunk-L737LQ4C.js +0 -1285
  107. package/dist/chunk-LFTWYIB2.js +0 -497
  108. package/dist/chunk-LV47RFNJ.js +0 -41
  109. package/dist/chunk-MKSAITI7.js +0 -15
  110. package/dist/chunk-MZ7RKIX4.js +0 -212
  111. package/dist/chunk-NAP6CFSO.js +0 -84
  112. package/dist/chunk-ND6MY37M.js +0 -16
  113. package/dist/chunk-NMG736UR.js +0 -683
  114. package/dist/chunk-NRAXROED.js +0 -32
  115. package/dist/chunk-NRIZR3A7.js +0 -690
  116. package/dist/chunk-NX43BG3M.js +0 -233
  117. package/dist/chunk-O645XLSI.js +0 -297
  118. package/dist/chunk-OMJD6A3S.js +0 -235
  119. package/dist/chunk-QB6SJD4T.js +0 -430
  120. package/dist/chunk-QFSTL4J3.js +0 -276
  121. package/dist/chunk-QLGDFMFX.js +0 -212
  122. package/dist/chunk-RIAAGL2E.js +0 -13
  123. package/dist/chunk-RWO5XMZ6.js +0 -86
  124. package/dist/chunk-RXRKBBSM.js +0 -149
  125. package/dist/chunk-RZOZMML6.js +0 -363
  126. package/dist/chunk-U7I7FS7T.js +0 -113
  127. package/dist/chunk-UI42RODY.js +0 -717
  128. package/dist/chunk-UTVMVSCO.js +0 -519
  129. package/dist/chunk-V6OJGLBA.js +0 -1746
  130. package/dist/chunk-W2JHVH7D.js +0 -152
  131. package/dist/chunk-WD3Y7VQN.js +0 -280
  132. package/dist/chunk-WOCTQ5MS.js +0 -303
  133. package/dist/chunk-WZR3ZUNN.js +0 -696
  134. package/dist/chunk-XGI665H7.js +0 -150
  135. package/dist/chunk-XKY65P2T.js +0 -304
  136. package/dist/chunk-Y4CQZY65.js +0 -57
  137. package/dist/chunk-YFEXKLVE.js +0 -194
  138. package/dist/chunk-YHO3HS5X.js +0 -287
  139. package/dist/chunk-YLS7AZSX.js +0 -738
  140. package/dist/chunk-ZE473AO6.js +0 -49
  141. package/dist/chunk-ZF747T3O.js +0 -644
  142. package/dist/chunk-ZHCZHZH3.js +0 -43
  143. package/dist/chunk-ZZNZX2XY.js +0 -87
  144. package/dist/constants-7QAP3VQ4.js +0 -23
  145. package/dist/dist-IY3UUMWK.js +0 -33
  146. package/dist/invariants-runner-W5RGHCSU.js +0 -27
  147. package/dist/lane-lock-6J36HD5O.js +0 -35
  148. package/dist/mem-checkpoint-core-EANG2GVN.js +0 -14
  149. package/dist/mem-signal-core-2LZ2WYHW.js +0 -19
  150. package/dist/memory-store-OLB5FO7K.js +0 -18
  151. package/dist/service-6BYCOCO5.js +0 -13
  152. package/dist/spawn-policy-resolver-NTSZYQ6R.js +0 -17
  153. package/dist/spawn-task-builder-R4E2BHSW.js +0 -22
  154. package/dist/wu-done-pr-WLFFFEPJ.js +0 -25
  155. package/dist/wu-done-validation-3J5E36FE.js +0 -30
  156. package/dist/wu-duplicate-id-detector-5S7JHELK.js +0 -232
  157. package/packs/sidekick/.turbo/turbo-test.log +0 -12
  158. package/packs/sidekick/.turbo/turbo-typecheck.log +0 -4
  159. package/packs/software-delivery/.turbo/turbo-typecheck.log +0 -4
@@ -1,696 +0,0 @@
1
- // ../metrics/dist/dora/calculate-dora-metrics.js
2
- import { quantile } from "simple-statistics";
3
-
4
- // ../metrics/dist/dora/constants.js
5
- var DEPLOYMENT_FREQUENCY = {
6
- /** Elite: >5 deploys per week */
7
- ELITE: 5,
8
- /** High: 1-5 deploys per week */
9
- HIGH: 1,
10
- /** Medium: ~1 deploy per month (0.25/week) */
11
- MEDIUM: 0.25
12
- // Low: <0.25 deploys per week (implicit)
13
- };
14
- var LEAD_TIME_HOURS = {
15
- /** Elite: <24 hours (<1 day) */
16
- ELITE: 24,
17
- /** High: <168 hours (<7 days) */
18
- HIGH: 168,
19
- /** Medium: <720 hours (<30 days) */
20
- MEDIUM: 720
21
- // Low: >720 hours (implicit)
22
- };
23
- var CFR_PERCENT = {
24
- /** Elite: <15% failures */
25
- ELITE: 15,
26
- /** High: 15-30% failures */
27
- HIGH: 30,
28
- /** Medium: 30-45% failures */
29
- MEDIUM: 45
30
- // Low: >45% failures (implicit)
31
- };
32
- var MTTR_HOURS = {
33
- /** Elite: <1 hour */
34
- ELITE: 1,
35
- /** High: <24 hours (<1 day) */
36
- HIGH: 24,
37
- /** Medium: <168 hours (<7 days) */
38
- MEDIUM: 168
39
- // Low: >168 hours (implicit)
40
- };
41
- var STATISTICS = {
42
- /** 90th percentile for p90Hours calculation */
43
- P90_PERCENTILE: 0.9,
44
- /** Decimal places for rounding (10 = 1 decimal place) */
45
- ROUNDING_FACTOR: 10,
46
- /** 95th percentile for p95 calculations */
47
- P95_PERCENTILE: 0.95,
48
- /** 99th percentile for p99 calculations */
49
- P99_PERCENTILE: 0.99,
50
- /** Median percentile */
51
- MEDIAN_PERCENTILE: 0.5,
52
- /** Milliseconds per hour */
53
- MS_PER_HOUR: 36e5,
54
- /** Percentage multiplier */
55
- PERCENTAGE_MULTIPLIER: 100
56
- };
57
-
58
- // ../metrics/dist/dora/calculate-dora-metrics.js
59
- function roundToOneDecimal(value) {
60
- return Math.round(value * STATISTICS.ROUNDING_FACTOR) / STATISTICS.ROUNDING_FACTOR;
61
- }
62
- function classifyDeploymentFrequency(deploysPerWeek) {
63
- if (deploysPerWeek > DEPLOYMENT_FREQUENCY.ELITE)
64
- return "elite";
65
- if (deploysPerWeek >= DEPLOYMENT_FREQUENCY.HIGH)
66
- return "high";
67
- if (deploysPerWeek >= DEPLOYMENT_FREQUENCY.MEDIUM)
68
- return "medium";
69
- return "low";
70
- }
71
- function classifyLeadTime(averageHours) {
72
- if (averageHours < LEAD_TIME_HOURS.ELITE)
73
- return "elite";
74
- if (averageHours < LEAD_TIME_HOURS.HIGH)
75
- return "high";
76
- if (averageHours < LEAD_TIME_HOURS.MEDIUM)
77
- return "medium";
78
- return "low";
79
- }
80
- function classifyCFR(failurePercentage) {
81
- if (failurePercentage < CFR_PERCENT.ELITE)
82
- return "elite";
83
- if (failurePercentage < CFR_PERCENT.HIGH)
84
- return "high";
85
- if (failurePercentage < CFR_PERCENT.MEDIUM)
86
- return "medium";
87
- return "low";
88
- }
89
- function classifyMTTR(averageHours) {
90
- if (averageHours === 0 || averageHours < MTTR_HOURS.ELITE)
91
- return "elite";
92
- if (averageHours < MTTR_HOURS.HIGH)
93
- return "high";
94
- if (averageHours < MTTR_HOURS.MEDIUM)
95
- return "medium";
96
- return "low";
97
- }
98
- function calculateDeploymentFrequency(commits, weekStart, weekEnd) {
99
- const weekCommits = commits.filter((c) => c.timestamp >= weekStart && c.timestamp <= weekEnd);
100
- const deploysPerWeek = weekCommits.length;
101
- const status = classifyDeploymentFrequency(deploysPerWeek);
102
- return { deploysPerWeek, status };
103
- }
104
- function calculateLeadTime(wuMetrics) {
105
- const cycleTimes = wuMetrics.map((wu) => wu.cycleTimeHours).filter((t) => typeof t === "number");
106
- if (cycleTimes.length === 0) {
107
- return {
108
- averageHours: 0,
109
- medianHours: 0,
110
- p90Hours: 0,
111
- status: "low"
112
- };
113
- }
114
- const averageHours = cycleTimes.reduce((sum, t) => sum + t, 0) / cycleTimes.length;
115
- const medianHours = quantile(cycleTimes, STATISTICS.MEDIAN_PERCENTILE);
116
- const p90Hours = quantile(cycleTimes, STATISTICS.P90_PERCENTILE);
117
- const status = classifyLeadTime(averageHours);
118
- return {
119
- averageHours: roundToOneDecimal(averageHours),
120
- medianHours: roundToOneDecimal(medianHours),
121
- p90Hours: roundToOneDecimal(p90Hours),
122
- status
123
- };
124
- }
125
- function calculateCFR(commits, skipGatesEntries) {
126
- const totalDeployments = commits.length;
127
- const failures = skipGatesEntries.length;
128
- const failurePercentage = totalDeployments > 0 ? failures / totalDeployments * STATISTICS.PERCENTAGE_MULTIPLIER : 0;
129
- const status = classifyCFR(failurePercentage);
130
- return {
131
- failurePercentage: roundToOneDecimal(failurePercentage),
132
- totalDeployments,
133
- failures,
134
- status
135
- };
136
- }
137
- function identifyEmergencyFixes(commits) {
138
- return commits.filter((c) => c.message.includes("EMERGENCY") || /fix\(EMERGENCY\)/.test(c.message));
139
- }
140
- function calculateRecoveryTime(emergencyFixes) {
141
- let totalRecoveryTimeMs = 0;
142
- let pairCount = 0;
143
- for (let i = 0; i < emergencyFixes.length - 1; i += 2) {
144
- const startFix = emergencyFixes.at(i);
145
- const endFix = emergencyFixes.at(i + 1);
146
- if (startFix && endFix) {
147
- totalRecoveryTimeMs += endFix.timestamp.getTime() - startFix.timestamp.getTime();
148
- pairCount++;
149
- }
150
- }
151
- if (pairCount === 0)
152
- return 0;
153
- return totalRecoveryTimeMs / (STATISTICS.MS_PER_HOUR * pairCount);
154
- }
155
- function calculateMTTR(commits) {
156
- const emergencyFixes = identifyEmergencyFixes(commits);
157
- if (emergencyFixes.length === 0) {
158
- return {
159
- averageHours: 0,
160
- incidents: 0,
161
- status: "elite"
162
- };
163
- }
164
- const incidents = Math.floor(emergencyFixes.length / 2);
165
- if (incidents === 0) {
166
- return {
167
- averageHours: 0,
168
- incidents: emergencyFixes.length,
169
- status: "elite"
170
- };
171
- }
172
- const averageHours = calculateRecoveryTime(emergencyFixes);
173
- const status = classifyMTTR(averageHours);
174
- return {
175
- averageHours: roundToOneDecimal(averageHours),
176
- incidents,
177
- status
178
- };
179
- }
180
- function calculateDORAMetrics(commits, skipGatesEntries, wuMetrics, weekStart, weekEnd) {
181
- return {
182
- deploymentFrequency: calculateDeploymentFrequency(commits, weekStart, weekEnd),
183
- leadTimeForChanges: calculateLeadTime(wuMetrics),
184
- changeFailureRate: calculateCFR(commits, skipGatesEntries),
185
- meanTimeToRecovery: calculateMTTR(commits)
186
- };
187
- }
188
-
189
- // ../metrics/dist/flow/calculate-flow-state.js
190
- function calculateFlowState(wuMetrics) {
191
- const ready = wuMetrics.filter((wu) => wu.status === "ready").length;
192
- const inProgress = wuMetrics.filter((wu) => wu.status === "in_progress").length;
193
- const blocked = wuMetrics.filter((wu) => wu.status === "blocked").length;
194
- const waiting = wuMetrics.filter((wu) => wu.status === "waiting").length;
195
- const done = wuMetrics.filter((wu) => wu.status === "done").length;
196
- const totalActive = ready + inProgress + blocked + waiting;
197
- return {
198
- ready,
199
- inProgress,
200
- blocked,
201
- waiting,
202
- done,
203
- totalActive
204
- };
205
- }
206
-
207
- // ../metrics/dist/flow/analyze-bottlenecks.js
208
- var WU_STATUS_DONE = "done";
209
- function filterActiveGraph(graph) {
210
- const activeGraph = /* @__PURE__ */ new Map();
211
- for (const [id, node] of graph.entries()) {
212
- if (node.status !== WU_STATUS_DONE) {
213
- activeGraph.set(id, node);
214
- }
215
- }
216
- return activeGraph;
217
- }
218
- function buildInDegreeMap(activeGraph) {
219
- const inDegree = /* @__PURE__ */ new Map();
220
- for (const [id, node] of activeGraph.entries()) {
221
- let count = 0;
222
- for (const depId of node.blockedBy) {
223
- if (activeGraph.has(depId)) {
224
- count++;
225
- }
226
- }
227
- inDegree.set(id, count);
228
- }
229
- return inDegree;
230
- }
231
- function findStartingNodes(inDegree) {
232
- const queue = [];
233
- for (const [id, degree] of inDegree.entries()) {
234
- if (degree === 0) {
235
- queue.push(id);
236
- }
237
- }
238
- return queue;
239
- }
240
- function processNode(current, activeGraph, inDegree, workQueue) {
241
- const node = activeGraph.get(current);
242
- if (!node)
243
- return;
244
- for (const depId of node.blocks) {
245
- if (!activeGraph.has(depId))
246
- continue;
247
- const currentDegree = inDegree.get(depId) ?? 0;
248
- const newDegree = currentDegree - 1;
249
- inDegree.set(depId, newDegree);
250
- if (newDegree === 0) {
251
- workQueue.push(depId);
252
- }
253
- }
254
- }
255
- function findCycleNodes(inDegree) {
256
- const cycleNodes = [];
257
- for (const [id, degree] of inDegree.entries()) {
258
- if (degree > 0) {
259
- cycleNodes.push(id);
260
- }
261
- }
262
- return cycleNodes;
263
- }
264
- function processTopologicalSort(activeGraph, inDegree, queue) {
265
- const sorted = [];
266
- const workQueue = [...queue];
267
- while (workQueue.length > 0) {
268
- const current = workQueue.shift();
269
- if (current) {
270
- sorted.push(current);
271
- processNode(current, activeGraph, inDegree, workQueue);
272
- }
273
- }
274
- return { sorted, cycleNodes: findCycleNodes(inDegree) };
275
- }
276
- function topologicalSort(graph) {
277
- const activeGraph = filterActiveGraph(graph);
278
- if (activeGraph.size === 0) {
279
- return { order: [], hasCycle: false };
280
- }
281
- const inDegree = buildInDegreeMap(activeGraph);
282
- const queue = findStartingNodes(inDegree);
283
- const { sorted, cycleNodes } = processTopologicalSort(activeGraph, inDegree, queue);
284
- if (sorted.length < activeGraph.size) {
285
- return {
286
- order: sorted,
287
- hasCycle: true,
288
- warning: "Cycle detected: some WUs have circular dependencies",
289
- cycleNodes
290
- };
291
- }
292
- return { order: sorted, hasCycle: false };
293
- }
294
- function calculateDistances(activeGraph, topoOrder) {
295
- const distance = /* @__PURE__ */ new Map();
296
- const predecessor = /* @__PURE__ */ new Map();
297
- for (const id of topoOrder) {
298
- distance.set(id, 1);
299
- predecessor.set(id, null);
300
- }
301
- for (const current of topoOrder) {
302
- const node = activeGraph.get(current);
303
- if (!node)
304
- continue;
305
- for (const depId of node.blocks) {
306
- if (!activeGraph.has(depId))
307
- continue;
308
- const currentDist = distance.get(current) ?? 0;
309
- const newDistance = currentDist + 1;
310
- const existingDist = distance.get(depId) ?? 0;
311
- if (newDistance > existingDist) {
312
- distance.set(depId, newDistance);
313
- predecessor.set(depId, current);
314
- }
315
- }
316
- }
317
- return { distance, predecessor };
318
- }
319
- function reconstructPath(predecessor, endNode) {
320
- const path = [];
321
- let current = endNode;
322
- while (current !== null) {
323
- path.unshift(current);
324
- current = predecessor.get(current) ?? null;
325
- }
326
- return path;
327
- }
328
- function criticalPath(graph) {
329
- const activeGraph = filterActiveGraph(graph);
330
- if (activeGraph.size === 0) {
331
- return { path: [], length: 0 };
332
- }
333
- const topoResult = topologicalSort(graph);
334
- if (topoResult.hasCycle) {
335
- return {
336
- path: [],
337
- length: 0,
338
- warning: topoResult.warning,
339
- cycleNodes: topoResult.cycleNodes
340
- };
341
- }
342
- const { distance, predecessor } = calculateDistances(activeGraph, topoResult.order);
343
- let maxDistance = 0;
344
- let endNode = null;
345
- for (const [id, dist] of distance.entries()) {
346
- if (dist > maxDistance) {
347
- maxDistance = dist;
348
- endNode = id;
349
- }
350
- }
351
- const path = reconstructPath(predecessor, endNode);
352
- return {
353
- path,
354
- length: path.length
355
- };
356
- }
357
- function impactScore(graph, wuId) {
358
- const activeGraph = filterActiveGraph(graph);
359
- if (!activeGraph.has(wuId)) {
360
- return 0;
361
- }
362
- const visited = /* @__PURE__ */ new Set();
363
- const queue = [wuId];
364
- visited.add(wuId);
365
- while (queue.length > 0) {
366
- const current = queue.shift();
367
- if (!current)
368
- continue;
369
- const node = activeGraph.get(current);
370
- if (!node)
371
- continue;
372
- for (const depId of node.blocks) {
373
- if (!visited.has(depId) && activeGraph.has(depId)) {
374
- visited.add(depId);
375
- queue.push(depId);
376
- }
377
- }
378
- }
379
- return visited.size - 1;
380
- }
381
- function analyzeBottlenecks(graph, limit) {
382
- const activeGraph = filterActiveGraph(graph);
383
- if (activeGraph.size === 0) {
384
- return [];
385
- }
386
- const scores = [];
387
- for (const [id, node] of activeGraph.entries()) {
388
- const score = impactScore(graph, id);
389
- scores.push({
390
- id,
391
- score,
392
- title: node.title
393
- });
394
- }
395
- scores.sort((a, b) => b.score - a.score);
396
- return scores.slice(0, limit);
397
- }
398
- function getBottleneckAnalysis(graph, limit = 10) {
399
- return {
400
- bottlenecks: analyzeBottlenecks(graph, limit),
401
- criticalPath: criticalPath(graph)
402
- };
403
- }
404
-
405
- // ../metrics/dist/flow/generate-flow-report.js
406
- import { quantile as quantile2 } from "simple-statistics";
407
- var PERCENTAGE_PRECISION = 1;
408
- function round(value, precision = PERCENTAGE_PRECISION) {
409
- return value.toFixed(precision);
410
- }
411
- function calculateGatePassRate(events) {
412
- const total = events.length;
413
- const passed = events.filter((e) => e.passed).length;
414
- const failed = total - passed;
415
- const passRate = total > 0 ? round(passed / total * STATISTICS.PERCENTAGE_MULTIPLIER) : "0.0";
416
- return { passRate, total, passed, failed };
417
- }
418
- function calculateGateP95(events) {
419
- if (events.length === 0)
420
- return 0;
421
- const durations = events.map((e) => e.durationMs).sort((a, b) => a - b);
422
- return quantile2(durations, STATISTICS.P95_PERCENTILE);
423
- }
424
- function initGateStats() {
425
- return { total: 0, passed: 0, failed: 0, passRate: "0.0" };
426
- }
427
- function updateGateStats(stats, passed) {
428
- stats.total++;
429
- if (passed) {
430
- stats.passed++;
431
- } else {
432
- stats.failed++;
433
- }
434
- }
435
- function calculatePassRate(stats) {
436
- if (stats.total > 0) {
437
- stats.passRate = round(stats.passed / stats.total * STATISTICS.PERCENTAGE_MULTIPLIER);
438
- }
439
- }
440
- function mapToObject(map) {
441
- const result = {};
442
- for (const [key, value] of map.entries()) {
443
- Object.defineProperty(result, key, {
444
- value,
445
- writable: true,
446
- enumerable: true,
447
- configurable: true
448
- });
449
- }
450
- return result;
451
- }
452
- function groupGatesByName(events) {
453
- const byNameMap = /* @__PURE__ */ new Map();
454
- for (const event of events) {
455
- const name = event.gateName;
456
- if (!byNameMap.has(name)) {
457
- byNameMap.set(name, initGateStats());
458
- }
459
- const stats = byNameMap.get(name);
460
- if (stats) {
461
- updateGateStats(stats, event.passed);
462
- }
463
- }
464
- for (const stats of byNameMap.values()) {
465
- calculatePassRate(stats);
466
- }
467
- return mapToObject(byNameMap);
468
- }
469
- function calculateLLMRates(completeEvents, errorCount) {
470
- const total = completeEvents.length + errorCount;
471
- const errorRate = total > 0 ? round(errorCount / total * STATISTICS.PERCENTAGE_MULTIPLIER) : "0.0";
472
- const fallbackCount = completeEvents.filter((e) => e.fallbackUsed).length;
473
- const fallbackRate = completeEvents.length > 0 ? round(fallbackCount / completeEvents.length * STATISTICS.PERCENTAGE_MULTIPLIER) : "0.0";
474
- return { errorRate, fallbackRate };
475
- }
476
- function calculateLLMLatencies(completeEvents) {
477
- const durations = completeEvents.map((e) => e.durationMs).filter((d) => d !== void 0).sort((a, b) => a - b);
478
- if (durations.length === 0) {
479
- return { avgLatencyMs: 0, p50LatencyMs: 0, p95LatencyMs: 0, p99LatencyMs: 0 };
480
- }
481
- const avgLatencyMs = Math.round(durations.reduce((sum, d) => sum + d, 0) / durations.length);
482
- const p50LatencyMs = quantile2(durations, STATISTICS.MEDIAN_PERCENTILE);
483
- const p95LatencyMs = quantile2(durations, STATISTICS.P95_PERCENTILE);
484
- const p99LatencyMs = quantile2(durations, STATISTICS.P99_PERCENTILE);
485
- return { avgLatencyMs, p50LatencyMs, p95LatencyMs, p99LatencyMs };
486
- }
487
- function calculateLLMCosts(completeEvents) {
488
- const totalTokens = completeEvents.reduce((sum, e) => sum + (e.tokensUsed ?? 0), 0);
489
- const totalCostUsd = completeEvents.reduce((sum, e) => sum + (e.estimatedCostUsd ?? 0), 0);
490
- const confidences = completeEvents.map((e) => e.confidence).filter((c) => c !== void 0);
491
- const avgConfidence = confidences.length > 0 ? (confidences.reduce((sum, c) => sum + c, 0) / confidences.length).toFixed(2) : "0.00";
492
- return { totalTokens, totalCostUsd, avgConfidence };
493
- }
494
- function initLLMTypeStats() {
495
- return {
496
- count: 0,
497
- avgLatencyMs: 0,
498
- totalCostUsd: 0,
499
- fallbackRate: "0.0"
500
- };
501
- }
502
- function updateLLMTypeStats(stats, event) {
503
- stats.count++;
504
- stats.avgLatencyMs += event.durationMs ?? 0;
505
- stats.totalCostUsd += event.estimatedCostUsd ?? 0;
506
- }
507
- function calculateLLMTypeAverages(stats, type, completeEvents) {
508
- if (stats.count > 0) {
509
- stats.avgLatencyMs = Math.round(stats.avgLatencyMs / stats.count);
510
- const typeFallbacks = completeEvents.filter((e) => e.classificationType === type && e.fallbackUsed).length;
511
- stats.fallbackRate = round(typeFallbacks / stats.count * STATISTICS.PERCENTAGE_MULTIPLIER);
512
- }
513
- }
514
- function groupLLMByType(completeEvents) {
515
- const byTypeMap = /* @__PURE__ */ new Map();
516
- for (const event of completeEvents) {
517
- const type = event.classificationType;
518
- if (!byTypeMap.has(type)) {
519
- byTypeMap.set(type, initLLMTypeStats());
520
- }
521
- const stats = byTypeMap.get(type);
522
- if (stats) {
523
- updateLLMTypeStats(stats, event);
524
- }
525
- }
526
- for (const [type, stats] of byTypeMap.entries()) {
527
- calculateLLMTypeAverages(stats, type, completeEvents);
528
- }
529
- return mapToObject(byTypeMap);
530
- }
531
- function calculateLLMMetrics(events) {
532
- const completeEvents = events.filter((e) => e.eventType === "llm.classification.complete");
533
- const errorEvents = events.filter((e) => e.eventType === "llm.classification.error");
534
- if (completeEvents.length === 0) {
535
- return {
536
- totalClassifications: 0,
537
- errorRate: "0.0",
538
- fallbackRate: "0.0",
539
- avgLatencyMs: 0,
540
- p50LatencyMs: 0,
541
- p95LatencyMs: 0,
542
- p99LatencyMs: 0,
543
- totalTokens: 0,
544
- totalCostUsd: 0,
545
- avgConfidence: "0.00",
546
- byType: {}
547
- };
548
- }
549
- const { errorRate, fallbackRate } = calculateLLMRates(completeEvents, errorEvents.length);
550
- const latencies = calculateLLMLatencies(completeEvents);
551
- const costs = calculateLLMCosts(completeEvents);
552
- const byType = groupLLMByType(completeEvents);
553
- return {
554
- totalClassifications: completeEvents.length,
555
- errorRate,
556
- fallbackRate,
557
- ...latencies,
558
- ...costs,
559
- byType
560
- };
561
- }
562
- function generateFlowReport(input) {
563
- const { gateEvents, llmEvents, completedWUs, dateRange } = input;
564
- const gateStats = calculateGatePassRate(gateEvents);
565
- const gateP95 = calculateGateP95(gateEvents);
566
- const byName = groupGatesByName(gateEvents);
567
- const llmMetrics = calculateLLMMetrics(llmEvents);
568
- const wuList = completedWUs.map((wu) => ({
569
- wuId: wu.id,
570
- completedDate: wu.completedAt?.toISOString().split("T")[0] ?? "",
571
- lane: wu.lane,
572
- title: wu.title
573
- }));
574
- return {
575
- range: dateRange,
576
- gates: {
577
- ...gateStats,
578
- p95: gateP95,
579
- byName
580
- },
581
- wus: {
582
- completed: completedWUs.length,
583
- list: wuList
584
- },
585
- llm: llmMetrics
586
- };
587
- }
588
-
589
- // ../metrics/dist/flow/capture-metrics-snapshot.js
590
- function determineLaneStatus(blocked, inProgress) {
591
- if (blocked === 0)
592
- return "healthy";
593
- if (inProgress > 0 && blocked <= inProgress)
594
- return "at-risk";
595
- return "blocked";
596
- }
597
- function createLaneAccumulator(lane) {
598
- return {
599
- lane,
600
- wusCompleted: 0,
601
- wusInProgress: 0,
602
- wusBlocked: 0,
603
- cycleTimes: []
604
- };
605
- }
606
- function updateLaneAccumulator(acc, wu) {
607
- switch (wu.status) {
608
- case "in_progress":
609
- acc.wusInProgress++;
610
- break;
611
- case "blocked":
612
- acc.wusBlocked++;
613
- break;
614
- case "done":
615
- acc.wusCompleted++;
616
- if (typeof wu.cycleTimeHours === "number") {
617
- acc.cycleTimes.push(wu.cycleTimeHours);
618
- }
619
- break;
620
- }
621
- }
622
- function medianFromSorted(sorted) {
623
- if (sorted.length === 0)
624
- return 0;
625
- const midIndex = Math.floor(sorted.length / 2);
626
- return sorted.at(midIndex) ?? 0;
627
- }
628
- function accumulatorToHealth(acc) {
629
- const avgCycleTime = acc.cycleTimes.length > 0 ? acc.cycleTimes.reduce((sum, t) => sum + t, 0) / acc.cycleTimes.length : 0;
630
- const sortedTimes = [...acc.cycleTimes].sort((a, b) => a - b);
631
- const medianCycleTime = medianFromSorted(sortedTimes);
632
- const status = determineLaneStatus(acc.wusBlocked, acc.wusInProgress);
633
- return {
634
- lane: acc.lane,
635
- wusCompleted: acc.wusCompleted,
636
- wusInProgress: acc.wusInProgress,
637
- wusBlocked: acc.wusBlocked,
638
- averageCycleTimeHours: Math.round(avgCycleTime * STATISTICS.ROUNDING_FACTOR) / STATISTICS.ROUNDING_FACTOR,
639
- medianCycleTimeHours: Math.round(medianCycleTime * STATISTICS.ROUNDING_FACTOR) / STATISTICS.ROUNDING_FACTOR,
640
- status
641
- };
642
- }
643
- function calculateLaneMetrics(wuMetrics) {
644
- const laneMap = /* @__PURE__ */ new Map();
645
- for (const wu of wuMetrics) {
646
- if (!laneMap.has(wu.lane)) {
647
- laneMap.set(wu.lane, createLaneAccumulator(wu.lane));
648
- }
649
- const laneData = laneMap.get(wu.lane);
650
- if (laneData) {
651
- updateLaneAccumulator(laneData, wu);
652
- }
653
- }
654
- const laneMetrics = Array.from(laneMap.values()).map(accumulatorToHealth);
655
- laneMetrics.sort((a, b) => a.lane.localeCompare(b.lane));
656
- const activeStatuses = ["ready", "in_progress", "blocked", "waiting"];
657
- const totalActive = wuMetrics.filter((wu) => activeStatuses.includes(wu.status)).length;
658
- const totalBlocked = wuMetrics.filter((wu) => wu.status === "blocked").length;
659
- const totalCompleted = wuMetrics.filter((wu) => wu.status === "done").length;
660
- return {
661
- lanes: laneMetrics,
662
- totalActive,
663
- totalBlocked,
664
- totalCompleted
665
- };
666
- }
667
- function captureMetricsSnapshot(input) {
668
- const { commits, wuMetrics, skipGatesEntries, weekStart, weekEnd, type } = input;
669
- const snapshot = {};
670
- if (type === "all" || type === "dora") {
671
- snapshot.dora = calculateDORAMetrics(commits, skipGatesEntries, wuMetrics, weekStart, weekEnd);
672
- }
673
- if (type === "all" || type === "lanes") {
674
- snapshot.lanes = calculateLaneMetrics(wuMetrics);
675
- }
676
- if (type === "all" || type === "flow") {
677
- snapshot.flow = calculateFlowState(wuMetrics);
678
- }
679
- return snapshot;
680
- }
681
-
682
- // ../metrics/dist/telemetry/emit-telemetry.js
683
- var TELEMETRY_PATHS = {
684
- GATES: ".lumenflow/telemetry/gates.ndjson",
685
- LLM_CLASSIFICATION: ".lumenflow/telemetry/llm-classification.ndjson",
686
- FLOW_LOG: ".lumenflow/flow.log"
687
- };
688
-
689
- export {
690
- calculateDORAMetrics,
691
- calculateFlowState,
692
- getBottleneckAnalysis,
693
- generateFlowReport,
694
- captureMetricsSnapshot,
695
- TELEMETRY_PATHS
696
- };