@lumenflow/cli 4.0.0 → 4.0.1

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 (119) hide show
  1. package/dist/wu-done-preflight.js +4 -3
  2. package/dist/wu-done-preflight.js.map +1 -1
  3. package/dist/wu-done.js +1 -1
  4. package/dist/wu-done.js.map +1 -1
  5. package/dist/wu-prep.js +13 -3
  6. package/dist/wu-prep.js.map +1 -1
  7. package/dist/wu-state-mutation-ownership.js +3 -1
  8. package/dist/wu-state-mutation-ownership.js.map +1 -1
  9. package/package.json +8 -8
  10. package/packs/agent-runtime/.turbo/turbo-build.log +1 -1
  11. package/packs/agent-runtime/package.json +1 -1
  12. package/packs/sidekick/.turbo/turbo-build.log +1 -1
  13. package/packs/sidekick/package.json +1 -1
  14. package/packs/software-delivery/.turbo/turbo-build.log +1 -1
  15. package/packs/software-delivery/package.json +1 -1
  16. package/dist/chunk-2D2VOCA4.js +0 -37
  17. package/dist/chunk-2D5KFYGX.js +0 -284
  18. package/dist/chunk-2GXVIN57.js +0 -14072
  19. package/dist/chunk-2MQ7HZWZ.js +0 -26
  20. package/dist/chunk-2UFQ3A3C.js +0 -643
  21. package/dist/chunk-3RG5ZIWI.js +0 -10
  22. package/dist/chunk-4N74J3UT.js +0 -15
  23. package/dist/chunk-5GTOXFYR.js +0 -392
  24. package/dist/chunk-5VY6MQMC.js +0 -240
  25. package/dist/chunk-67XVPMRY.js +0 -1297
  26. package/dist/chunk-6HO4GWJE.js +0 -164
  27. package/dist/chunk-6W5XHWYV.js +0 -1890
  28. package/dist/chunk-6X4EMYJQ.js +0 -64
  29. package/dist/chunk-6XYXI2NQ.js +0 -772
  30. package/dist/chunk-7ANSOV6Q.js +0 -285
  31. package/dist/chunk-A624LFLB.js +0 -1380
  32. package/dist/chunk-ADN5NHG4.js +0 -126
  33. package/dist/chunk-B7YJYJKG.js +0 -33
  34. package/dist/chunk-CCLHCPKG.js +0 -210
  35. package/dist/chunk-CK36VROC.js +0 -1584
  36. package/dist/chunk-D3UOFRSB.js +0 -81
  37. package/dist/chunk-DFR4DJBM.js +0 -230
  38. package/dist/chunk-DSYBDHYH.js +0 -79
  39. package/dist/chunk-DWMLTXKQ.js +0 -1176
  40. package/dist/chunk-E3REJTAJ.js +0 -28
  41. package/dist/chunk-EA3IVO64.js +0 -633
  42. package/dist/chunk-EK2AKZKD.js +0 -55
  43. package/dist/chunk-ELD7JTTT.js +0 -343
  44. package/dist/chunk-EX6TT2XI.js +0 -195
  45. package/dist/chunk-EXINSFZE.js +0 -82
  46. package/dist/chunk-EZ6ZBYBM.js +0 -510
  47. package/dist/chunk-FBKAPTJ2.js +0 -16
  48. package/dist/chunk-FVLV5RYH.js +0 -1118
  49. package/dist/chunk-GDNSBQVK.js +0 -2485
  50. package/dist/chunk-GPQHMBNN.js +0 -278
  51. package/dist/chunk-GTFJB67L.js +0 -68
  52. package/dist/chunk-HANJXVKW.js +0 -1127
  53. package/dist/chunk-HEVS5YLD.js +0 -269
  54. package/dist/chunk-HMEVZKPQ.js +0 -9
  55. package/dist/chunk-HRGSYNLM.js +0 -3511
  56. package/dist/chunk-ISZR5N4K.js +0 -60
  57. package/dist/chunk-J6SUPR2C.js +0 -226
  58. package/dist/chunk-JERYVEIZ.js +0 -244
  59. package/dist/chunk-JHHWGL2N.js +0 -87
  60. package/dist/chunk-JONWQUB5.js +0 -775
  61. package/dist/chunk-K2DIWWDM.js +0 -1766
  62. package/dist/chunk-KY4PGL5V.js +0 -969
  63. package/dist/chunk-L737LQ4C.js +0 -1285
  64. package/dist/chunk-LFTWYIB2.js +0 -497
  65. package/dist/chunk-LV47RFNJ.js +0 -41
  66. package/dist/chunk-MKSAITI7.js +0 -15
  67. package/dist/chunk-MZ7RKIX4.js +0 -212
  68. package/dist/chunk-NAP6CFSO.js +0 -84
  69. package/dist/chunk-ND6MY37M.js +0 -16
  70. package/dist/chunk-NMG736UR.js +0 -683
  71. package/dist/chunk-NRAXROED.js +0 -32
  72. package/dist/chunk-NRIZR3A7.js +0 -690
  73. package/dist/chunk-NX43BG3M.js +0 -233
  74. package/dist/chunk-O645XLSI.js +0 -297
  75. package/dist/chunk-OMJD6A3S.js +0 -235
  76. package/dist/chunk-QB6SJD4T.js +0 -430
  77. package/dist/chunk-QFSTL4J3.js +0 -276
  78. package/dist/chunk-QLGDFMFX.js +0 -212
  79. package/dist/chunk-RIAAGL2E.js +0 -13
  80. package/dist/chunk-RWO5XMZ6.js +0 -86
  81. package/dist/chunk-RXRKBBSM.js +0 -149
  82. package/dist/chunk-RZOZMML6.js +0 -363
  83. package/dist/chunk-U7I7FS7T.js +0 -113
  84. package/dist/chunk-UI42RODY.js +0 -717
  85. package/dist/chunk-UTVMVSCO.js +0 -519
  86. package/dist/chunk-V6OJGLBA.js +0 -1746
  87. package/dist/chunk-W2JHVH7D.js +0 -152
  88. package/dist/chunk-WD3Y7VQN.js +0 -280
  89. package/dist/chunk-WOCTQ5MS.js +0 -303
  90. package/dist/chunk-WZR3ZUNN.js +0 -696
  91. package/dist/chunk-XGI665H7.js +0 -150
  92. package/dist/chunk-XKY65P2T.js +0 -304
  93. package/dist/chunk-Y4CQZY65.js +0 -57
  94. package/dist/chunk-YFEXKLVE.js +0 -194
  95. package/dist/chunk-YHO3HS5X.js +0 -287
  96. package/dist/chunk-YLS7AZSX.js +0 -738
  97. package/dist/chunk-ZE473AO6.js +0 -49
  98. package/dist/chunk-ZF747T3O.js +0 -644
  99. package/dist/chunk-ZHCZHZH3.js +0 -43
  100. package/dist/chunk-ZZNZX2XY.js +0 -87
  101. package/dist/constants-7QAP3VQ4.js +0 -23
  102. package/dist/dist-IY3UUMWK.js +0 -33
  103. package/dist/invariants-runner-W5RGHCSU.js +0 -27
  104. package/dist/lane-lock-6J36HD5O.js +0 -35
  105. package/dist/mem-checkpoint-core-EANG2GVN.js +0 -14
  106. package/dist/mem-signal-core-2LZ2WYHW.js +0 -19
  107. package/dist/memory-store-OLB5FO7K.js +0 -18
  108. package/dist/service-6BYCOCO5.js +0 -13
  109. package/dist/spawn-policy-resolver-NTSZYQ6R.js +0 -17
  110. package/dist/spawn-task-builder-R4E2BHSW.js +0 -22
  111. package/dist/wu-done-pr-WLFFFEPJ.js +0 -25
  112. package/dist/wu-done-validation-3J5E36FE.js +0 -30
  113. package/dist/wu-duplicate-id-detector-5S7JHELK.js +0 -232
  114. package/packs/agent-runtime/.turbo/turbo-test.log +0 -21
  115. package/packs/agent-runtime/.turbo/turbo-typecheck.log +0 -4
  116. package/packs/sidekick/.turbo/turbo-test.log +0 -157
  117. package/packs/sidekick/.turbo/turbo-typecheck.log +0 -4
  118. package/packs/software-delivery/.turbo/turbo-test.log +0 -32
  119. package/packs/software-delivery/.turbo/turbo-typecheck.log +0 -4
@@ -1,772 +0,0 @@
1
- import {
2
- CONFIG_FILES,
3
- FILE_EXTENSIONS,
4
- LUMENFLOW_PATHS,
5
- STDIO,
6
- STRING_LITERALS
7
- } from "./chunk-DWMLTXKQ.js";
8
-
9
- // ../core/dist/telemetry.js
10
- import { appendFileSync, mkdirSync, existsSync, readFileSync, writeFileSync } from "fs";
11
- import { execSync } from "child_process";
12
- import path from "path";
13
- import YAML from "yaml";
14
- var TELEMETRY_DIR = LUMENFLOW_PATHS.TELEMETRY;
15
- var GATES_LOG = `${TELEMETRY_DIR}/gates${FILE_EXTENSIONS.NDJSON}`;
16
- var LLM_CLASSIFICATION_LOG = `${TELEMETRY_DIR}/llm-classification${FILE_EXTENSIONS.NDJSON}`;
17
- var COSTS_LOG = `${TELEMETRY_DIR}/costs${FILE_EXTENSIONS.NDJSON}`;
18
- var FLOW_LOG = LUMENFLOW_PATHS.FLOW_LOG;
19
- var DORA_LOG = `${TELEMETRY_DIR}/dora${FILE_EXTENSIONS.NDJSON}`;
20
- var WORKSPACE_FILE = CONFIG_FILES.WORKSPACE_CONFIG;
21
- var CLOUD_SYNC_STATE_FILE = `${TELEMETRY_DIR}/cloud-sync-state${FILE_EXTENSIONS.JSON}`;
22
- var CLOUD_SYNC_LOG_PREFIX = "[telemetry:cloud-sync]";
23
- var PACK_KEY_SOFTWARE_DELIVERY = "software_delivery";
24
- var CONTROL_PLANE_FIELD = "control_plane";
25
- var CONTROL_PLANE_AUTH_FIELD = "auth";
26
- var CONTROL_PLANE_ENDPOINT_FIELD = "endpoint";
27
- var CONTROL_PLANE_SYNC_INTERVAL_FIELD = "sync_interval";
28
- var CONTROL_PLANE_BATCH_SIZE_FIELD = "batch_size";
29
- var CONTROL_PLANE_TIMEOUT_MS_FIELD = "timeout_ms";
30
- var CONTROL_PLANE_TOKEN_ENV_FIELD = "token_env";
31
- var WORKSPACE_ID_FIELD = "id";
32
- var HTTP = {
33
- METHOD_POST: "POST",
34
- HEADER_AUTHORIZATION: "authorization",
35
- HEADER_CONTENT_TYPE: "content-type",
36
- CONTENT_TYPE_JSON: "application/json"
37
- };
38
- var CONTROL_PLANE_API_PATH = {
39
- TELEMETRY: "/api/v1/telemetry"
40
- };
41
- var DEFAULT_BATCH_SIZE = 100;
42
- var DEFAULT_TIMEOUT_MS = 1e4;
43
- var MS_PER_SECOND = 1e3;
44
- var ERROR_NAME = {
45
- ABORT: "AbortError"
46
- };
47
- var CONTROL_PLANE_TOKEN_ENV_PATTERN = /^[A-Z][A-Z0-9_]*$/;
48
- var METRIC_NAME = {
49
- GATES_DURATION_MS: "gates.duration_ms",
50
- FLOW_EVENT: "flow.event",
51
- DORA_METRIC: "dora",
52
- COST_USD: "cost.usd",
53
- RAW_GATES: "telemetry.raw.gates",
54
- RAW_FLOW: "telemetry.raw.flow",
55
- RAW_DORA: "telemetry.raw.dora",
56
- RAW_COSTS: "telemetry.raw.costs"
57
- };
58
- var TELEMETRY_SOURCE = {
59
- GATES: "gates",
60
- FLOW: "flow",
61
- DORA: "dora",
62
- COSTS: "costs"
63
- };
64
- function ensureTelemetryDir() {
65
- try {
66
- mkdirSync(TELEMETRY_DIR, { recursive: true });
67
- } catch {
68
- }
69
- }
70
- function emit(filePath, event) {
71
- ensureTelemetryDir();
72
- const line = `${JSON.stringify(event)}${STRING_LITERALS.NEWLINE}`;
73
- try {
74
- appendFileSync(filePath, line, { encoding: "utf-8" });
75
- } catch (err) {
76
- const message = err instanceof Error ? err.message : String(err);
77
- console.error(`[telemetry] Failed to emit to ${filePath}:`, message);
78
- }
79
- }
80
- function emitGateEvent(data) {
81
- const event = {
82
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
83
- wu_id: data.wu_id || null,
84
- lane: data.lane || null,
85
- gate_name: data.gate_name,
86
- passed: data.passed,
87
- duration_ms: data.duration_ms
88
- };
89
- emit(GATES_LOG, event);
90
- }
91
- function getCurrentWU() {
92
- try {
93
- const branch = execSync("git rev-parse --abbrev-ref HEAD", {
94
- encoding: "utf-8",
95
- stdio: [STDIO.PIPE, STDIO.PIPE, STDIO.IGNORE]
96
- }).trim();
97
- const match = branch.match(/wu-(\d+)/i);
98
- if (match) {
99
- return `WU-${match[1]}`.toUpperCase();
100
- }
101
- } catch {
102
- }
103
- return null;
104
- }
105
- function getCurrentLane() {
106
- try {
107
- const branch = execSync("git rev-parse --abbrev-ref HEAD", {
108
- encoding: "utf-8",
109
- stdio: [STDIO.PIPE, STDIO.PIPE, STDIO.IGNORE]
110
- }).trim();
111
- const match = branch.match(/^lane\/([^/]+)\//i);
112
- const laneSegment = match?.[1];
113
- if (laneSegment) {
114
- return laneSegment.charAt(0).toUpperCase() + laneSegment.slice(1).toLowerCase();
115
- }
116
- } catch {
117
- }
118
- return null;
119
- }
120
- function emitWUFlowEvent(event, logPath = FLOW_LOG) {
121
- const logDir = path.dirname(logPath);
122
- if (!existsSync(logDir)) {
123
- mkdirSync(logDir, { recursive: true });
124
- }
125
- const line = JSON.stringify({ timestamp: (/* @__PURE__ */ new Date()).toISOString(), ...event });
126
- try {
127
- appendFileSync(logPath, `${line}${STRING_LITERALS.NEWLINE}`, { encoding: "utf-8" });
128
- } catch (err) {
129
- const message = err instanceof Error ? err.message : String(err);
130
- console.error(`[telemetry] Failed to emit flow event: ${message}`);
131
- }
132
- }
133
- function emitDoraTelemetry(record) {
134
- ensureTelemetryDir();
135
- const line = JSON.stringify({
136
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
137
- metric: record.metric,
138
- value: record.value,
139
- tier: record.tier
140
- });
141
- try {
142
- appendFileSync(DORA_LOG, `${line}${STRING_LITERALS.NEWLINE}`, { encoding: "utf-8" });
143
- } catch (err) {
144
- const message = err instanceof Error ? err.message : String(err);
145
- console.error(`[telemetry] Failed to emit DORA telemetry: ${message}`);
146
- }
147
- }
148
- function isRecord(value) {
149
- return typeof value === "object" && value !== null;
150
- }
151
- function asNonEmptyString(value) {
152
- if (typeof value !== "string") {
153
- return void 0;
154
- }
155
- const trimmed = value.trim();
156
- return trimmed.length > 0 ? trimmed : void 0;
157
- }
158
- function asPositiveInteger(value) {
159
- if (typeof value !== "number" || !Number.isInteger(value) || value <= 0) {
160
- return void 0;
161
- }
162
- return value;
163
- }
164
- function asFiniteNumber(value) {
165
- return typeof value === "number" && Number.isFinite(value) ? value : void 0;
166
- }
167
- function asPrimitiveTagValue(value) {
168
- if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
169
- return value;
170
- }
171
- return void 0;
172
- }
173
- function normalizeEndpoint(endpoint) {
174
- return endpoint.endsWith("/") ? endpoint.slice(0, endpoint.length - 1) : endpoint;
175
- }
176
- function normalizeTimestamp(value, fallbackIso) {
177
- const rawTimestamp = asNonEmptyString(value);
178
- return rawTimestamp ?? fallbackIso;
179
- }
180
- function warnCloudSync(logger, message) {
181
- logger?.warn?.(`${CLOUD_SYNC_LOG_PREFIX} ${message}`);
182
- }
183
- function createDefaultCloudSyncState() {
184
- return {
185
- version: 1,
186
- lastSyncAtMs: 0,
187
- files: {
188
- gates: {
189
- offset: 0
190
- },
191
- flow: {
192
- offset: 0
193
- },
194
- dora: {
195
- offset: 0
196
- },
197
- costs: {
198
- offset: 0
199
- }
200
- }
201
- };
202
- }
203
- function normalizeStateOffset(value) {
204
- if (typeof value !== "number" || !Number.isInteger(value) || value < 0) {
205
- return 0;
206
- }
207
- return value;
208
- }
209
- function loadCloudSyncState(statePath) {
210
- if (!existsSync(statePath)) {
211
- return createDefaultCloudSyncState();
212
- }
213
- try {
214
- const raw = readFileSync(statePath, "utf-8");
215
- const parsed = JSON.parse(raw);
216
- if (!isRecord(parsed)) {
217
- return createDefaultCloudSyncState();
218
- }
219
- const filesRaw = Reflect.get(parsed, "files");
220
- const gatesRaw = isRecord(filesRaw) ? Reflect.get(filesRaw, TELEMETRY_SOURCE.GATES) : void 0;
221
- const flowRaw = isRecord(filesRaw) ? Reflect.get(filesRaw, TELEMETRY_SOURCE.FLOW) : void 0;
222
- const doraRaw = isRecord(filesRaw) ? Reflect.get(filesRaw, TELEMETRY_SOURCE.DORA) : void 0;
223
- const costsRaw = isRecord(filesRaw) ? Reflect.get(filesRaw, TELEMETRY_SOURCE.COSTS) : void 0;
224
- const gatesOffset = isRecord(gatesRaw) ? normalizeStateOffset(Reflect.get(gatesRaw, "offset")) : 0;
225
- const flowOffset = isRecord(flowRaw) ? normalizeStateOffset(Reflect.get(flowRaw, "offset")) : 0;
226
- const doraOffset = isRecord(doraRaw) ? normalizeStateOffset(Reflect.get(doraRaw, "offset")) : 0;
227
- const costsOffset = isRecord(costsRaw) ? normalizeStateOffset(Reflect.get(costsRaw, "offset")) : 0;
228
- const lastSyncAtMs = normalizeStateOffset(Reflect.get(parsed, "lastSyncAtMs"));
229
- return {
230
- version: 1,
231
- lastSyncAtMs,
232
- files: {
233
- gates: {
234
- offset: gatesOffset
235
- },
236
- flow: {
237
- offset: flowOffset
238
- },
239
- dora: {
240
- offset: doraOffset
241
- },
242
- costs: {
243
- offset: costsOffset
244
- }
245
- }
246
- };
247
- } catch {
248
- return createDefaultCloudSyncState();
249
- }
250
- }
251
- function saveCloudSyncState(statePath, state) {
252
- mkdirSync(path.dirname(statePath), { recursive: true });
253
- writeFileSync(statePath, `${JSON.stringify(state, null, 2)}${STRING_LITERALS.NEWLINE}`, {
254
- encoding: "utf-8"
255
- });
256
- }
257
- function getSourceOffset(state, source) {
258
- if (source === TELEMETRY_SOURCE.GATES) {
259
- return state.files.gates.offset;
260
- }
261
- if (source === TELEMETRY_SOURCE.DORA) {
262
- return state.files.dora.offset;
263
- }
264
- if (source === TELEMETRY_SOURCE.COSTS) {
265
- return state.files.costs.offset;
266
- }
267
- return state.files.flow.offset;
268
- }
269
- function setSourceOffset(state, source, offset) {
270
- if (source === TELEMETRY_SOURCE.GATES) {
271
- state.files.gates.offset = offset;
272
- return;
273
- }
274
- if (source === TELEMETRY_SOURCE.DORA) {
275
- state.files.dora.offset = offset;
276
- return;
277
- }
278
- if (source === TELEMETRY_SOURCE.COSTS) {
279
- state.files.costs.offset = offset;
280
- return;
281
- }
282
- state.files.flow.offset = offset;
283
- }
284
- function resolveTelemetryPath(workspaceRoot, source) {
285
- if (source === TELEMETRY_SOURCE.GATES) {
286
- return path.join(workspaceRoot, GATES_LOG);
287
- }
288
- if (source === TELEMETRY_SOURCE.DORA) {
289
- return path.join(workspaceRoot, DORA_LOG);
290
- }
291
- if (source === TELEMETRY_SOURCE.COSTS) {
292
- return path.join(workspaceRoot, COSTS_LOG);
293
- }
294
- return path.join(workspaceRoot, FLOW_LOG);
295
- }
296
- function mapGatesEventToTelemetryRecord(payload, fallbackIso) {
297
- const gateName = asNonEmptyString(Reflect.get(payload, "gate_name")) ?? "unknown";
298
- const passedRaw = Reflect.get(payload, "passed");
299
- const passed = typeof passedRaw === "boolean" ? passedRaw : false;
300
- const durationMs = asFiniteNumber(Reflect.get(payload, "duration_ms")) ?? 0;
301
- const wuId = asPrimitiveTagValue(Reflect.get(payload, "wu_id"));
302
- const lane = asPrimitiveTagValue(Reflect.get(payload, "lane"));
303
- const tags = {
304
- source: TELEMETRY_SOURCE.GATES,
305
- gate_name: gateName,
306
- passed
307
- };
308
- if (wuId !== void 0) {
309
- tags.wu_id = wuId;
310
- }
311
- if (lane !== void 0) {
312
- tags.lane = lane;
313
- }
314
- return {
315
- metric: METRIC_NAME.GATES_DURATION_MS,
316
- value: durationMs,
317
- timestamp: normalizeTimestamp(Reflect.get(payload, "timestamp"), fallbackIso),
318
- tags
319
- };
320
- }
321
- function mapFlowEventToTelemetryRecord(payload, fallbackIso) {
322
- const script = asNonEmptyString(Reflect.get(payload, "script")) ?? "unknown";
323
- const step = asNonEmptyString(Reflect.get(payload, "step")) ?? asNonEmptyString(Reflect.get(payload, "event_type")) ?? "event";
324
- const value = asFiniteNumber(Reflect.get(payload, "duration_ms")) ?? 1;
325
- const status = asPrimitiveTagValue(Reflect.get(payload, "status"));
326
- const wuId = asPrimitiveTagValue(Reflect.get(payload, "wu_id"));
327
- const lane = asPrimitiveTagValue(Reflect.get(payload, "lane"));
328
- const tags = {
329
- source: TELEMETRY_SOURCE.FLOW,
330
- script,
331
- step
332
- };
333
- if (status !== void 0) {
334
- tags.status = status;
335
- }
336
- if (wuId !== void 0) {
337
- tags.wu_id = wuId;
338
- }
339
- if (lane !== void 0) {
340
- tags.lane = lane;
341
- }
342
- return {
343
- metric: METRIC_NAME.FLOW_EVENT,
344
- value,
345
- timestamp: normalizeTimestamp(Reflect.get(payload, "timestamp"), fallbackIso),
346
- tags
347
- };
348
- }
349
- function mapDoraEventToTelemetryRecord(payload, fallbackIso) {
350
- const metric = asNonEmptyString(Reflect.get(payload, "metric")) ?? "dora.unknown";
351
- const value = asFiniteNumber(Reflect.get(payload, "value")) ?? 0;
352
- const tier = asNonEmptyString(Reflect.get(payload, "tier"));
353
- const tags = {
354
- source: TELEMETRY_SOURCE.DORA
355
- };
356
- if (tier !== void 0) {
357
- tags.tier = tier;
358
- }
359
- return {
360
- metric,
361
- value,
362
- timestamp: normalizeTimestamp(Reflect.get(payload, "timestamp"), fallbackIso),
363
- tags
364
- };
365
- }
366
- function mapCostEventToTelemetryRecord(payload, fallbackIso) {
367
- const costUsd = asFiniteNumber(Reflect.get(payload, "cost_usd")) ?? 0;
368
- const inputTokens = asFiniteNumber(Reflect.get(payload, "input_tokens"));
369
- const outputTokens = asFiniteNumber(Reflect.get(payload, "output_tokens"));
370
- const operation = asPrimitiveTagValue(Reflect.get(payload, "operation"));
371
- const model = asPrimitiveTagValue(Reflect.get(payload, "model"));
372
- const wuId = asPrimitiveTagValue(Reflect.get(payload, "wu_id"));
373
- const agentId = asPrimitiveTagValue(Reflect.get(payload, "agent_id"));
374
- const sessionId = asPrimitiveTagValue(Reflect.get(payload, "session_id"));
375
- const tags = {
376
- source: TELEMETRY_SOURCE.COSTS,
377
- source_type: "cost"
378
- };
379
- if (operation !== void 0) {
380
- tags.operation = operation;
381
- }
382
- if (model !== void 0) {
383
- tags.model = model;
384
- }
385
- if (wuId !== void 0) {
386
- tags.wu_id = wuId;
387
- }
388
- if (agentId !== void 0) {
389
- tags.agent_id = agentId;
390
- }
391
- if (sessionId !== void 0) {
392
- tags.session_id = sessionId;
393
- }
394
- if (inputTokens !== void 0) {
395
- tags.input_tokens = inputTokens;
396
- }
397
- if (outputTokens !== void 0) {
398
- tags.output_tokens = outputTokens;
399
- }
400
- return {
401
- metric: METRIC_NAME.COST_USD,
402
- value: costUsd,
403
- timestamp: normalizeTimestamp(Reflect.get(payload, "timestamp"), fallbackIso),
404
- tags
405
- };
406
- }
407
- function resolveRawMetricName(source) {
408
- if (source === TELEMETRY_SOURCE.GATES)
409
- return METRIC_NAME.RAW_GATES;
410
- if (source === TELEMETRY_SOURCE.DORA)
411
- return METRIC_NAME.RAW_DORA;
412
- if (source === TELEMETRY_SOURCE.COSTS)
413
- return METRIC_NAME.RAW_COSTS;
414
- return METRIC_NAME.RAW_FLOW;
415
- }
416
- function mapTelemetryLineToRecord(source, payload, fallbackIso) {
417
- if (!isRecord(payload)) {
418
- return {
419
- metric: resolveRawMetricName(source),
420
- value: 1,
421
- timestamp: fallbackIso,
422
- tags: {
423
- source
424
- }
425
- };
426
- }
427
- if (source === TELEMETRY_SOURCE.GATES) {
428
- return mapGatesEventToTelemetryRecord(payload, fallbackIso);
429
- }
430
- if (source === TELEMETRY_SOURCE.DORA) {
431
- return mapDoraEventToTelemetryRecord(payload, fallbackIso);
432
- }
433
- if (source === TELEMETRY_SOURCE.COSTS) {
434
- return mapCostEventToTelemetryRecord(payload, fallbackIso);
435
- }
436
- return mapFlowEventToTelemetryRecord(payload, fallbackIso);
437
- }
438
- function readTelemetryLinesFromOffset(input) {
439
- if (!existsSync(input.filePath)) {
440
- return {
441
- items: [],
442
- malformedLines: 0,
443
- effectiveOffset: 0
444
- };
445
- }
446
- const fileBuffer = readFileSync(input.filePath);
447
- const fileSize = fileBuffer.byteLength;
448
- const effectiveOffset = Math.min(input.initialOffset, fileSize);
449
- const sliceBuffer = fileBuffer.subarray(effectiveOffset);
450
- const content = sliceBuffer.toString("utf-8");
451
- let malformedLines = 0;
452
- const items = [];
453
- let cursor = 0;
454
- let runningOffset = effectiveOffset;
455
- while (cursor < content.length) {
456
- const newlineIndex = content.indexOf(STRING_LITERALS.NEWLINE, cursor);
457
- if (newlineIndex < 0) {
458
- break;
459
- }
460
- const lineWithNewline = content.slice(cursor, newlineIndex + 1);
461
- runningOffset += Buffer.byteLength(lineWithNewline, "utf8");
462
- const line = content.slice(cursor, newlineIndex).trim();
463
- cursor = newlineIndex + 1;
464
- if (line.length === 0) {
465
- items.push({
466
- record: null,
467
- offsetAfterLine: runningOffset
468
- });
469
- continue;
470
- }
471
- try {
472
- const parsed = JSON.parse(line);
473
- items.push({
474
- record: mapTelemetryLineToRecord(input.source, parsed, input.fallbackIso),
475
- offsetAfterLine: runningOffset
476
- });
477
- } catch {
478
- malformedLines += 1;
479
- warnCloudSync(input.logger, `Skipping malformed NDJSON line in ${input.filePath} at offset ${runningOffset}.`);
480
- items.push({
481
- record: null,
482
- offsetAfterLine: runningOffset
483
- });
484
- }
485
- }
486
- return {
487
- items,
488
- malformedLines,
489
- effectiveOffset
490
- };
491
- }
492
- function safeResponseText(response) {
493
- return response.text().catch(() => "");
494
- }
495
- async function pushTelemetryBatch(input) {
496
- const controller = new AbortController();
497
- const timeout = setTimeout(() => controller.abort(), input.timeoutMs);
498
- try {
499
- const response = await input.fetchFn(`${input.endpoint}${CONTROL_PLANE_API_PATH.TELEMETRY}`, {
500
- method: HTTP.METHOD_POST,
501
- headers: {
502
- [HTTP.HEADER_AUTHORIZATION]: `Bearer ${input.token}`,
503
- [HTTP.HEADER_CONTENT_TYPE]: HTTP.CONTENT_TYPE_JSON
504
- },
505
- body: JSON.stringify({
506
- workspace_id: input.workspaceId,
507
- records: input.records
508
- }),
509
- signal: controller.signal
510
- });
511
- if (!response.ok) {
512
- const responseText = await safeResponseText(response);
513
- const suffix = responseText.length > 0 ? `: ${responseText}` : "";
514
- throw new Error(`HTTP ${response.status}${suffix}`);
515
- }
516
- } catch (error) {
517
- if (error instanceof Error && error.name === ERROR_NAME.ABORT) {
518
- throw new Error(`request timed out after ${input.timeoutMs}ms`, { cause: error });
519
- }
520
- throw error;
521
- } finally {
522
- clearTimeout(timeout);
523
- }
524
- }
525
- function detectMisnestedControlPlane(workspace) {
526
- const rootControlPlane = Reflect.get(workspace, CONTROL_PLANE_FIELD);
527
- if (isRecord(rootControlPlane)) {
528
- return null;
529
- }
530
- const softwareDelivery = Reflect.get(workspace, PACK_KEY_SOFTWARE_DELIVERY);
531
- if (!isRecord(softwareDelivery)) {
532
- return null;
533
- }
534
- const nestedControlPlane = Reflect.get(softwareDelivery, CONTROL_PLANE_FIELD);
535
- if (!isRecord(nestedControlPlane)) {
536
- return null;
537
- }
538
- const detectedPath = `${PACK_KEY_SOFTWARE_DELIVERY}.${CONTROL_PLANE_FIELD}`;
539
- return {
540
- message: `${CONTROL_PLANE_FIELD} is misnested under ${PACK_KEY_SOFTWARE_DELIVERY}. It must be a root-level key in workspace.yaml.`,
541
- detectedPath,
542
- remediation: `Move ${CONTROL_PLANE_FIELD} to the workspace root. Run: pnpm config:set --key control_plane.<sub-key> --value <value>`
543
- };
544
- }
545
- function resolveCloudSyncConfig(input) {
546
- const workspacePath = path.join(input.workspaceRoot, WORKSPACE_FILE);
547
- if (!existsSync(workspacePath)) {
548
- return null;
549
- }
550
- let parsedWorkspace;
551
- try {
552
- parsedWorkspace = YAML.parse(readFileSync(workspacePath, "utf-8"));
553
- } catch (error) {
554
- const message = error instanceof Error ? error.message : String(error);
555
- warnCloudSync(input.logger, `Unable to parse workspace config: ${message}`);
556
- return null;
557
- }
558
- if (!isRecord(parsedWorkspace)) {
559
- return null;
560
- }
561
- const workspaceId = asNonEmptyString(Reflect.get(parsedWorkspace, WORKSPACE_ID_FIELD));
562
- if (!workspaceId) {
563
- warnCloudSync(input.logger, "Skipping sync: workspace id is missing in workspace.yaml.");
564
- return null;
565
- }
566
- const controlPlaneRaw = Reflect.get(parsedWorkspace, CONTROL_PLANE_FIELD);
567
- if (!isRecord(controlPlaneRaw)) {
568
- const misnesting = detectMisnestedControlPlane(parsedWorkspace);
569
- if (misnesting) {
570
- warnCloudSync(input.logger, misnesting.message);
571
- warnCloudSync(input.logger, misnesting.remediation);
572
- }
573
- return null;
574
- }
575
- const endpoint = asNonEmptyString(Reflect.get(controlPlaneRaw, CONTROL_PLANE_ENDPOINT_FIELD));
576
- const syncIntervalSeconds = asPositiveInteger(Reflect.get(controlPlaneRaw, CONTROL_PLANE_SYNC_INTERVAL_FIELD));
577
- const batchSize = asPositiveInteger(Reflect.get(controlPlaneRaw, CONTROL_PLANE_BATCH_SIZE_FIELD)) ?? DEFAULT_BATCH_SIZE;
578
- const timeoutMs = asPositiveInteger(Reflect.get(controlPlaneRaw, CONTROL_PLANE_TIMEOUT_MS_FIELD)) ?? DEFAULT_TIMEOUT_MS;
579
- if (!endpoint || !syncIntervalSeconds) {
580
- warnCloudSync(input.logger, "Skipping sync: control_plane endpoint and sync_interval must be configured.");
581
- return null;
582
- }
583
- const authRaw = Reflect.get(controlPlaneRaw, CONTROL_PLANE_AUTH_FIELD);
584
- if (!isRecord(authRaw)) {
585
- warnCloudSync(input.logger, "Skipping sync: control_plane.auth is missing.");
586
- return null;
587
- }
588
- const tokenEnv = asNonEmptyString(Reflect.get(authRaw, CONTROL_PLANE_TOKEN_ENV_FIELD));
589
- if (!tokenEnv || !CONTROL_PLANE_TOKEN_ENV_PATTERN.test(tokenEnv)) {
590
- warnCloudSync(input.logger, "Skipping sync: control_plane.auth.token_env is invalid.");
591
- return null;
592
- }
593
- const tokenValue = input.environment[tokenEnv];
594
- const token = typeof tokenValue === "string" ? tokenValue.trim() : "";
595
- if (token.length === 0) {
596
- warnCloudSync(input.logger, `Skipping sync: missing cloud auth token in env "${tokenEnv}".`);
597
- return null;
598
- }
599
- try {
600
- void new URL(endpoint);
601
- } catch {
602
- warnCloudSync(input.logger, `Skipping sync: invalid control_plane endpoint "${endpoint}".`);
603
- return null;
604
- }
605
- return {
606
- workspaceId,
607
- endpoint: normalizeEndpoint(endpoint),
608
- token,
609
- syncIntervalMs: syncIntervalSeconds * MS_PER_SECOND,
610
- batchSize,
611
- timeoutMs
612
- };
613
- }
614
- async function syncNdjsonTelemetryToCloud(options = {}) {
615
- const workspaceRoot = options.workspaceRoot ?? process.cwd();
616
- const logger = options.logger;
617
- const fetchFn = options.fetchFn ?? fetch;
618
- const now = options.now ?? Date.now;
619
- const environment = options.environment ?? process.env;
620
- const statePath = path.join(workspaceRoot, CLOUD_SYNC_STATE_FILE);
621
- const config = resolveCloudSyncConfig({
622
- workspaceRoot,
623
- environment,
624
- logger
625
- });
626
- if (config === null) {
627
- return {
628
- recordsRead: 0,
629
- recordsSent: 0,
630
- malformedLines: 0,
631
- batchesAttempted: 0,
632
- batchesSucceeded: 0,
633
- skippedReason: "control-plane-unavailable"
634
- };
635
- }
636
- const state = loadCloudSyncState(statePath);
637
- const nowMs = now();
638
- if (state.lastSyncAtMs > 0 && nowMs - state.lastSyncAtMs < config.syncIntervalMs) {
639
- return {
640
- recordsRead: 0,
641
- recordsSent: 0,
642
- malformedLines: 0,
643
- batchesAttempted: 0,
644
- batchesSucceeded: 0,
645
- skippedReason: "sync-interval-not-elapsed"
646
- };
647
- }
648
- const fallbackIso = new Date(nowMs).toISOString();
649
- const nextState = {
650
- version: 1,
651
- lastSyncAtMs: state.lastSyncAtMs,
652
- files: {
653
- gates: { offset: state.files.gates.offset },
654
- flow: { offset: state.files.flow.offset },
655
- dora: { offset: state.files.dora.offset },
656
- costs: { offset: state.files.costs.offset }
657
- }
658
- };
659
- let malformedLines = 0;
660
- let recordsRead = 0;
661
- let recordsSent = 0;
662
- let batchesAttempted = 0;
663
- let batchesSucceeded = 0;
664
- let syncFailed = false;
665
- let stateChanged = false;
666
- for (const source of [
667
- TELEMETRY_SOURCE.GATES,
668
- TELEMETRY_SOURCE.FLOW,
669
- TELEMETRY_SOURCE.DORA,
670
- TELEMETRY_SOURCE.COSTS
671
- ]) {
672
- const filePath = resolveTelemetryPath(workspaceRoot, source);
673
- const sourceLines = readTelemetryLinesFromOffset({
674
- filePath,
675
- source,
676
- initialOffset: getSourceOffset(nextState, source),
677
- logger,
678
- fallbackIso
679
- });
680
- malformedLines += sourceLines.malformedLines;
681
- let acknowledgedOffset = sourceLines.effectiveOffset;
682
- let index = 0;
683
- while (index < sourceLines.items.length) {
684
- const currentLine = sourceLines.items[index];
685
- if (currentLine?.record === null) {
686
- acknowledgedOffset = currentLine.offsetAfterLine;
687
- stateChanged = true;
688
- index += 1;
689
- continue;
690
- }
691
- const batch = [];
692
- let lastBatchOffset = acknowledgedOffset;
693
- while (index < sourceLines.items.length && sourceLines.items[index]?.record !== null && batch.length < config.batchSize) {
694
- const line = sourceLines.items[index];
695
- if (!line || line.record === null) {
696
- break;
697
- }
698
- batch.push(line.record);
699
- lastBatchOffset = line.offsetAfterLine;
700
- index += 1;
701
- }
702
- recordsRead += batch.length;
703
- batchesAttempted += 1;
704
- try {
705
- await pushTelemetryBatch({
706
- endpoint: config.endpoint,
707
- workspaceId: config.workspaceId,
708
- token: config.token,
709
- timeoutMs: config.timeoutMs,
710
- records: batch,
711
- fetchFn
712
- });
713
- recordsSent += batch.length;
714
- batchesSucceeded += 1;
715
- acknowledgedOffset = lastBatchOffset;
716
- stateChanged = true;
717
- } catch (error) {
718
- const message = error instanceof Error ? error.message : String(error);
719
- warnCloudSync(logger, `Telemetry sync failed: ${message}`);
720
- syncFailed = true;
721
- break;
722
- }
723
- }
724
- setSourceOffset(nextState, source, acknowledgedOffset);
725
- if (syncFailed) {
726
- break;
727
- }
728
- }
729
- if (stateChanged) {
730
- if (!syncFailed) {
731
- nextState.lastSyncAtMs = nowMs;
732
- }
733
- saveCloudSyncState(statePath, nextState);
734
- } else if (!syncFailed) {
735
- nextState.lastSyncAtMs = nowMs;
736
- saveCloudSyncState(statePath, nextState);
737
- }
738
- return {
739
- recordsRead,
740
- recordsSent,
741
- malformedLines,
742
- batchesAttempted,
743
- batchesSucceeded,
744
- ...syncFailed ? { skippedReason: "sync-failed" } : {}
745
- };
746
- }
747
-
748
- // ../core/dist/spawn-policy-resolver.js
749
- function emitMethodologyTelemetry(config, policy) {
750
- if (!config.telemetry?.methodology?.enabled) {
751
- return;
752
- }
753
- const event = {
754
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
755
- event_type: "methodology.selection",
756
- methodology_testing: policy.testing,
757
- methodology_architecture: policy.architecture,
758
- event_context: "spawn"
759
- };
760
- emit(LUMENFLOW_PATHS.METHODOLOGY_LOG, event);
761
- }
762
-
763
- export {
764
- emit,
765
- emitGateEvent,
766
- getCurrentWU,
767
- getCurrentLane,
768
- emitWUFlowEvent,
769
- emitDoraTelemetry,
770
- syncNdjsonTelemetryToCloud,
771
- emitMethodologyTelemetry
772
- };