@lumenflow/core 2.2.2 → 2.3.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.
Files changed (213) hide show
  1. package/dist/active-wu-detector.d.ts +1 -1
  2. package/dist/active-wu-detector.js +1 -1
  3. package/dist/arg-parser.js +51 -18
  4. package/dist/backlog-generator.d.ts +4 -4
  5. package/dist/backlog-generator.js +4 -4
  6. package/dist/backlog-sync-validator.js +1 -1
  7. package/dist/cleanup-lock.d.ts +9 -2
  8. package/dist/cleanup-lock.js +17 -7
  9. package/dist/code-path-validator.d.ts +3 -3
  10. package/dist/code-path-validator.js +3 -3
  11. package/dist/compliance-parser.d.ts +1 -1
  12. package/dist/compliance-parser.js +1 -1
  13. package/dist/constants/backlog-patterns.d.ts +1 -1
  14. package/dist/constants/backlog-patterns.js +1 -1
  15. package/dist/constants/dora-constants.d.ts +1 -1
  16. package/dist/constants/dora-constants.js +1 -1
  17. package/dist/constants/gate-constants.d.ts +1 -1
  18. package/dist/constants/gate-constants.js +1 -1
  19. package/dist/constants/linter-constants.d.ts +1 -1
  20. package/dist/constants/linter-constants.js +1 -1
  21. package/dist/constants/tokenizer-constants.d.ts +1 -1
  22. package/dist/constants/tokenizer-constants.js +1 -1
  23. package/dist/context/location-resolver.js +2 -1
  24. package/dist/context-validation-integration.d.ts +1 -0
  25. package/dist/core/scope-checker.d.ts +3 -3
  26. package/dist/core/scope-checker.js +3 -3
  27. package/dist/core/tool-runner.d.ts +5 -5
  28. package/dist/core/tool-runner.js +5 -5
  29. package/dist/core/tool.constants.d.ts +1 -1
  30. package/dist/core/tool.constants.js +1 -1
  31. package/dist/core/tool.schemas.d.ts +2 -2
  32. package/dist/core/tool.schemas.js +1 -1
  33. package/dist/core/worktree-guard.d.ts +1 -1
  34. package/dist/core/worktree-guard.js +1 -1
  35. package/dist/coverage-gate.d.ts +12 -3
  36. package/dist/coverage-gate.js +15 -8
  37. package/dist/date-utils.d.ts +4 -4
  38. package/dist/date-utils.js +4 -4
  39. package/dist/dependency-graph.d.ts +6 -0
  40. package/dist/dependency-graph.js +43 -2
  41. package/dist/dependency-guard.d.ts +2 -2
  42. package/dist/dependency-guard.js +3 -3
  43. package/dist/dependency-validator.d.ts +4 -4
  44. package/dist/dependency-validator.js +4 -7
  45. package/dist/domain/orchestration.constants.d.ts +31 -10
  46. package/dist/domain/orchestration.constants.js +45 -16
  47. package/dist/domain/orchestration.schemas.d.ts +54 -28
  48. package/dist/domain/orchestration.schemas.js +2 -2
  49. package/dist/domain/orchestration.types.d.ts +2 -2
  50. package/dist/domain/orchestration.types.js +2 -2
  51. package/dist/error-handler.d.ts +10 -10
  52. package/dist/error-handler.js +10 -10
  53. package/dist/file-classifiers.d.ts +6 -6
  54. package/dist/file-classifiers.js +6 -6
  55. package/dist/gates-config.d.ts +74 -0
  56. package/dist/gates-config.js +209 -2
  57. package/dist/git-adapter.d.ts +11 -11
  58. package/dist/git-adapter.js +11 -11
  59. package/dist/git-context-extractor.d.ts +112 -0
  60. package/dist/git-context-extractor.js +559 -0
  61. package/dist/hardcoded-strings.d.ts +1 -1
  62. package/dist/hardcoded-strings.js +1 -1
  63. package/dist/incremental-lint.d.ts +1 -1
  64. package/dist/incremental-lint.js +2 -2
  65. package/dist/incremental-test.d.ts +1 -1
  66. package/dist/incremental-test.js +1 -1
  67. package/dist/index.d.ts +13 -0
  68. package/dist/index.js +25 -0
  69. package/dist/invariants/check-automated-tests.d.ts +2 -2
  70. package/dist/invariants/check-automated-tests.js +3 -3
  71. package/dist/lane-checker.d.ts +28 -7
  72. package/dist/lane-checker.js +316 -159
  73. package/dist/lane-suggest-prompt.d.ts +108 -0
  74. package/dist/lane-suggest-prompt.js +359 -0
  75. package/dist/lane-validator.d.ts +3 -3
  76. package/dist/lane-validator.js +3 -3
  77. package/dist/logs-lib.d.ts +1 -1
  78. package/dist/logs-lib.js +1 -1
  79. package/dist/lumenflow-config-schema.d.ts +162 -0
  80. package/dist/lumenflow-config-schema.js +180 -0
  81. package/dist/manual-test-validator.d.ts +2 -2
  82. package/dist/manual-test-validator.js +3 -3
  83. package/dist/merge-lock.d.ts +8 -1
  84. package/dist/merge-lock.js +16 -7
  85. package/dist/micro-worktree.d.ts +81 -13
  86. package/dist/micro-worktree.js +98 -17
  87. package/dist/migration-deployer.d.ts +1 -1
  88. package/dist/migration-deployer.js +1 -1
  89. package/dist/orchestration-advisory-loader.d.ts +2 -2
  90. package/dist/orchestration-advisory-loader.js +10 -6
  91. package/dist/orchestration-advisory.d.ts +3 -3
  92. package/dist/orchestration-advisory.js +4 -4
  93. package/dist/orchestration-di.d.ts +4 -4
  94. package/dist/orchestration-di.js +4 -4
  95. package/dist/orchestration-rules.d.ts +4 -4
  96. package/dist/orchestration-rules.js +18 -10
  97. package/dist/orphan-detector.d.ts +3 -3
  98. package/dist/orphan-detector.js +3 -3
  99. package/dist/patrol-loop.d.ts +170 -0
  100. package/dist/patrol-loop.js +186 -0
  101. package/dist/process-detector.d.ts +5 -5
  102. package/dist/process-detector.js +5 -5
  103. package/dist/rebase-artifact-cleanup.d.ts +3 -3
  104. package/dist/rebase-artifact-cleanup.js +3 -3
  105. package/dist/resolve-policy.d.ts +195 -0
  106. package/dist/resolve-policy.js +203 -0
  107. package/dist/risk-detector.d.ts +2 -2
  108. package/dist/risk-detector.js +2 -2
  109. package/dist/rollback-utils.d.ts +1 -1
  110. package/dist/rollback-utils.js +1 -1
  111. package/dist/section-headings.d.ts +1 -1
  112. package/dist/section-headings.js +1 -1
  113. package/dist/spawn-escalation.d.ts +4 -4
  114. package/dist/spawn-escalation.js +3 -3
  115. package/dist/spawn-monitor.d.ts +4 -4
  116. package/dist/spawn-monitor.js +4 -4
  117. package/dist/spawn-recovery.d.ts +3 -3
  118. package/dist/spawn-recovery.js +3 -3
  119. package/dist/spawn-registry-schema.d.ts +2 -2
  120. package/dist/spawn-registry-schema.js +2 -2
  121. package/dist/spawn-registry-store.d.ts +2 -2
  122. package/dist/spawn-registry-store.js +2 -2
  123. package/dist/spawn-strategy.d.ts +17 -11
  124. package/dist/spawn-strategy.js +47 -44
  125. package/dist/spawn-tree.d.ts +3 -3
  126. package/dist/spawn-tree.js +3 -3
  127. package/dist/state-cleanup-core.d.ts +205 -0
  128. package/dist/state-cleanup-core.js +240 -0
  129. package/dist/state-doctor-core.d.ts +168 -0
  130. package/dist/state-doctor-core.js +251 -0
  131. package/dist/stream-error-handler.d.ts +67 -0
  132. package/dist/stream-error-handler.js +94 -0
  133. package/dist/telemetry.d.ts +1 -1
  134. package/dist/telemetry.js +1 -1
  135. package/dist/template-loader.d.ts +162 -0
  136. package/dist/template-loader.js +372 -0
  137. package/dist/test-baseline.d.ts +176 -0
  138. package/dist/test-baseline.js +282 -0
  139. package/dist/usecases/get-suggestions.usecase.d.ts +1 -1
  140. package/dist/validation/command-registry.js +37 -0
  141. package/dist/validators/backlog-sync.js +4 -2
  142. package/dist/worktree-scanner.d.ts +1 -1
  143. package/dist/worktree-scanner.js +1 -1
  144. package/dist/worktree-symlink.d.ts +3 -3
  145. package/dist/worktree-symlink.js +3 -3
  146. package/dist/wu-backlog-updater.d.ts +1 -1
  147. package/dist/wu-backlog-updater.js +1 -1
  148. package/dist/wu-claim-helpers.d.ts +1 -1
  149. package/dist/wu-claim-helpers.js +1 -1
  150. package/dist/wu-claim-resume.d.ts +1 -1
  151. package/dist/wu-claim-resume.js +1 -1
  152. package/dist/wu-consistency-checker.d.ts +1 -1
  153. package/dist/wu-consistency-checker.js +17 -11
  154. package/dist/wu-constants.d.ts +73 -21
  155. package/dist/wu-constants.js +65 -22
  156. package/dist/wu-done-branch-only.d.ts +1 -1
  157. package/dist/wu-done-branch-only.js +1 -1
  158. package/dist/wu-done-docs-generate.d.ts +1 -1
  159. package/dist/wu-done-docs-generate.js +1 -1
  160. package/dist/wu-done-messages.d.ts +2 -2
  161. package/dist/wu-done-messages.js +2 -2
  162. package/dist/wu-done-metadata.d.ts +3 -3
  163. package/dist/wu-done-metadata.js +3 -3
  164. package/dist/wu-done-pr.d.ts +1 -1
  165. package/dist/wu-done-pr.js +4 -2
  166. package/dist/wu-done-preflight.d.ts +8 -0
  167. package/dist/wu-done-preflight.js +18 -2
  168. package/dist/wu-done-ui.d.ts +3 -3
  169. package/dist/wu-done-ui.js +3 -3
  170. package/dist/wu-done-validation.d.ts +30 -0
  171. package/dist/wu-done-validation.js +106 -1
  172. package/dist/wu-done-worktree.d.ts +1 -1
  173. package/dist/wu-done-worktree.js +11 -1
  174. package/dist/wu-events-cleanup.d.ts +148 -0
  175. package/dist/wu-events-cleanup.js +401 -0
  176. package/dist/wu-helpers.d.ts +2 -2
  177. package/dist/wu-helpers.js +2 -2
  178. package/dist/wu-id-generator.d.ts +58 -0
  179. package/dist/wu-id-generator.js +103 -0
  180. package/dist/wu-lint.js +1 -1
  181. package/dist/wu-preflight-validators.d.ts +13 -1
  182. package/dist/wu-preflight-validators.js +56 -1
  183. package/dist/wu-recovery.d.ts +2 -2
  184. package/dist/wu-recovery.js +4 -4
  185. package/dist/wu-repair-core.d.ts +5 -5
  186. package/dist/wu-repair-core.js +6 -6
  187. package/dist/wu-schema-normalization.d.ts +1 -1
  188. package/dist/wu-schema-normalization.js +1 -1
  189. package/dist/wu-schema.d.ts +7 -7
  190. package/dist/wu-schema.js +8 -8
  191. package/dist/wu-spawn-context.d.ts +87 -0
  192. package/dist/wu-spawn-context.js +175 -0
  193. package/dist/wu-spawn-helpers.d.ts +1 -1
  194. package/dist/wu-spawn-helpers.js +1 -1
  195. package/dist/wu-spawn.d.ts +177 -4
  196. package/dist/wu-spawn.js +694 -72
  197. package/dist/wu-state-schema.d.ts +1 -1
  198. package/dist/wu-state-schema.js +1 -1
  199. package/dist/wu-state-store.d.ts +3 -3
  200. package/dist/wu-state-store.js +3 -3
  201. package/dist/wu-status-transition.d.ts +1 -1
  202. package/dist/wu-status-transition.js +1 -1
  203. package/dist/wu-status-updater.d.ts +3 -3
  204. package/dist/wu-status-updater.js +3 -3
  205. package/dist/wu-validation-constants.d.ts +2 -2
  206. package/dist/wu-validation-constants.js +2 -2
  207. package/dist/wu-validation.d.ts +3 -3
  208. package/dist/wu-validation.js +3 -3
  209. package/dist/wu-yaml-fixer.d.ts +2 -2
  210. package/dist/wu-yaml-fixer.js +3 -3
  211. package/dist/wu-yaml.d.ts +23 -0
  212. package/dist/wu-yaml.js +76 -2
  213. package/package.json +5 -2
@@ -64,6 +64,7 @@ export async function executePreflightCodePathValidation(id, paths, options = {}
64
64
  errors: result.errors,
65
65
  missingCodePaths: result.missingCodePaths || [],
66
66
  missingTestPaths: result.missingTestPaths || [],
67
+ suggestedTestPaths: result.suggestedTestPaths || {},
67
68
  abortedBeforeGates: true,
68
69
  };
69
70
  }
@@ -71,7 +72,7 @@ export async function executePreflightCodePathValidation(id, paths, options = {}
71
72
  * WU-1805: Build preflight code_paths error message with actionable guidance
72
73
  */
73
74
  export function buildPreflightCodePathErrorMessage(id, result) {
74
- const { errors, missingCodePaths = [], missingTestPaths = [] } = result;
75
+ const { errors, missingCodePaths = [], missingTestPaths = [], suggestedTestPaths = {}, } = result;
75
76
  let message = `
76
77
  ❌ PREFLIGHT CODE_PATHS VALIDATION FAILED
77
78
 
@@ -100,12 +101,27 @@ Fix options for missing test_paths:
100
101
 
101
102
  `;
102
103
  }
104
+ // Add suggested paths if available
105
+ const suggestionsMap = suggestedTestPaths;
106
+ const hasSuggestions = Object.keys(suggestionsMap).some((missingPath) => suggestionsMap[missingPath]?.length > 0);
107
+ if (hasSuggestions) {
108
+ message += `Suggested alternatives found:
109
+ `;
110
+ for (const [missingPath, suggestions] of Object.entries(suggestionsMap)) {
111
+ if (suggestions.length > 0) {
112
+ message += `For "${missingPath}":
113
+ ${suggestions.map((s) => ` - ${s}`).join('\n')}
114
+
115
+ `;
116
+ }
117
+ }
118
+ }
103
119
  message += `
104
120
  After fixing, retry:
105
121
  pnpm wu:done --id ${id}
106
122
 
107
123
  This preflight check runs BEFORE gates to catch YAML mismatches early.
108
- See: docs/04-operations/_frameworks/lumenflow/agent/onboarding/troubleshooting-wu-done.md for more recovery options.
124
+ See: https://lumenflow.dev/reference/troubleshooting-wu-done/ for more recovery options.
109
125
  `;
110
126
  return message;
111
127
  }
@@ -4,13 +4,13 @@
4
4
  * WU-1281: Extracted display helpers to consolidate DRY violations
5
5
  * and use library-first duration formatting.
6
6
  *
7
- * @see {@link tools/wu-done.mjs} - Primary consumer
8
- * @see {@link tools/lib/wu-constants.mjs} - UI constants
7
+ * @see {@link packages/@lumenflow/cli/src/wu-done.ts} - Primary consumer
8
+ * @see {@link packages/@lumenflow/cli/src/lib/wu-constants.ts} - UI constants
9
9
  */
10
10
  /**
11
11
  * Print prominent gate failure box
12
12
  *
13
- * Consolidated from two duplicate implementations in wu-done.mjs
13
+ * Consolidated from two duplicate implementations in wu-done.ts
14
14
  * (worktree mode and branch-only mode). Uses pretty-ms for
15
15
  * human-readable duration formatting.
16
16
  *
@@ -4,15 +4,15 @@
4
4
  * WU-1281: Extracted display helpers to consolidate DRY violations
5
5
  * and use library-first duration formatting.
6
6
  *
7
- * @see {@link tools/wu-done.mjs} - Primary consumer
8
- * @see {@link tools/lib/wu-constants.mjs} - UI constants
7
+ * @see {@link packages/@lumenflow/cli/src/wu-done.ts} - Primary consumer
8
+ * @see {@link packages/@lumenflow/cli/src/lib/wu-constants.ts} - UI constants
9
9
  */
10
10
  import prettyMs from 'pretty-ms';
11
11
  import { UI, LOG_PREFIX, STRING_LITERALS } from './wu-constants.js';
12
12
  /**
13
13
  * Print prominent gate failure box
14
14
  *
15
- * Consolidated from two duplicate implementations in wu-done.mjs
15
+ * Consolidated from two duplicate implementations in wu-done.ts
16
16
  * (worktree mode and branch-only mode). Uses pretty-ms for
17
17
  * human-readable duration formatting.
18
18
  *
@@ -79,4 +79,34 @@ export declare function validateTypeVsCodePathsPreflight(wu: any): {
79
79
  * WU-2310: Build error message for type vs code_paths preflight failure.
80
80
  */
81
81
  export declare function buildTypeVsCodePathsErrorMessage(id: any, blockedPaths: any): string;
82
+ /**
83
+ * WU-1153: Validate that code_paths are committed before wu:done metadata updates
84
+ *
85
+ * Prevents lost work by ensuring all code_paths are committed before metadata
86
+ * transaction starts. If code_paths are uncommitted and metadata transaction
87
+ * fails, the rollback could lose the uncommitted code changes.
88
+ *
89
+ * @param {object} wu - WU YAML document
90
+ * @param {object} gitAdapter - Git adapter instance
91
+ * @param {object} options - Validation options
92
+ * @param {boolean} [options.abortOnFailure=true] - Whether to call die() on failure
93
+ * @returns {Promise<{valid: boolean, errors: string[], uncommittedPaths: string[]}>}
94
+ */
95
+ export declare function validateCodePathsCommittedBeforeDone(wu: Record<string, unknown>, gitAdapter: {
96
+ getStatus: () => Promise<string>;
97
+ }, options?: {
98
+ abortOnFailure?: boolean;
99
+ }): Promise<{
100
+ valid: boolean;
101
+ errors: string[];
102
+ uncommittedPaths: string[];
103
+ }>;
104
+ /**
105
+ * WU-1153: Build error message for uncommitted code_paths validation failure
106
+ *
107
+ * @param {string} wuId - WU ID
108
+ * @param {string[]} uncommittedPaths - List of uncommitted code_paths
109
+ * @returns {string} Formatted error message
110
+ */
111
+ export declare function buildCodePathsCommittedErrorMessage(wuId: string, uncommittedPaths: string[]): string;
82
112
  export {};
@@ -5,6 +5,7 @@ import path from 'node:path';
5
5
  import { existsSync, readFileSync } from 'node:fs';
6
6
  import { getGitForCwd } from './git-adapter.js';
7
7
  import { parseYAML } from './wu-yaml.js';
8
+ import { die } from './error-handler.js';
8
9
  import { BRANCHES, EMOJI, FILE_SYSTEM, GIT_COMMANDS, LOG_PREFIX, STRING_LITERALS, TEST_TYPES, VALIDATION, WU_TYPES, } from './wu-constants.js';
9
10
  import { PLACEHOLDER_SENTINEL } from './wu-schema.js';
10
11
  import { resolveExposureDefault } from './wu-validation.js';
@@ -251,7 +252,7 @@ export function validateTestPathsRequired(wu) {
251
252
  }
252
253
  /**
253
254
  * WU-2310: Allowed path patterns for documentation WUs.
254
- * Mirrors the patterns in gates-pre-commit.mjs gateDocsOnlyPathEnforcement()
255
+ * Mirrors the patterns in gates-pre-commit.ts gateDocsOnlyPathEnforcement()
255
256
  * to enable early validation at preflight (before transaction starts).
256
257
  *
257
258
  * @constant {RegExp[]}
@@ -338,3 +339,107 @@ Allowed paths for documentation WUs:
338
339
  After fixing, retry: pnpm wu:done --id ${id}
339
340
  `;
340
341
  }
342
+ /**
343
+ * WU-1153: Validate that code_paths are committed before wu:done metadata updates
344
+ *
345
+ * Prevents lost work by ensuring all code_paths are committed before metadata
346
+ * transaction starts. If code_paths are uncommitted and metadata transaction
347
+ * fails, the rollback could lose the uncommitted code changes.
348
+ *
349
+ * @param {object} wu - WU YAML document
350
+ * @param {object} gitAdapter - Git adapter instance
351
+ * @param {object} options - Validation options
352
+ * @param {boolean} [options.abortOnFailure=true] - Whether to call die() on failure
353
+ * @returns {Promise<{valid: boolean, errors: string[], uncommittedPaths: string[]}>}
354
+ */
355
+ export async function validateCodePathsCommittedBeforeDone(wu, gitAdapter, options = {}) {
356
+ const { abortOnFailure = true } = options;
357
+ const errors = [];
358
+ const uncommittedPaths = [];
359
+ // Skip validation if no code_paths
360
+ const codePaths = wu.code_paths;
361
+ if (!codePaths || codePaths.length === 0) {
362
+ return { valid: true, errors: [], uncommittedPaths: [] };
363
+ }
364
+ try {
365
+ // Get git status to check for uncommitted files
366
+ const gitStatus = await gitAdapter.getStatus();
367
+ // Parse git status output to find uncommitted files
368
+ const statusLines = gitStatus.split('\n').filter((line) => line.trim());
369
+ // Create a Set of uncommitted file paths for efficient lookup
370
+ const uncommittedFiles = new Set();
371
+ for (const line of statusLines) {
372
+ // Git status porcelain format:
373
+ // XY PATH
374
+ // where X = staged, Y = working tree
375
+ // We care about any file that's not in a clean state
376
+ const match = line.match(/^.{2}\s+(.+)$/);
377
+ if (match) {
378
+ const filePath = match[1];
379
+ uncommittedFiles.add(filePath);
380
+ }
381
+ }
382
+ // Check each code_path against uncommitted files
383
+ for (const codePath of codePaths) {
384
+ if (uncommittedFiles.has(codePath)) {
385
+ uncommittedPaths.push(codePath);
386
+ }
387
+ }
388
+ // If any code_paths are uncommitted, validation fails
389
+ if (uncommittedPaths.length > 0) {
390
+ const count = uncommittedPaths.length;
391
+ const pathList = uncommittedPaths.map((p) => ` - ${p}`).join('\n');
392
+ errors.push(`${count} code_path${count === 1 ? '' : 's'} are not committed:\n${pathList}`);
393
+ if (abortOnFailure) {
394
+ const errorMessage = buildCodePathsCommittedErrorMessage(wu.id, uncommittedPaths);
395
+ die(errorMessage);
396
+ }
397
+ }
398
+ }
399
+ catch (err) {
400
+ // If git status fails, warn but don't block (non-fatal)
401
+ console.warn(`${LOG_PREFIX.DONE} ${EMOJI.WARNING} Could not validate code_paths commit status: ${err instanceof Error ? err.message : String(err)}`);
402
+ return { valid: true, errors: [], uncommittedPaths: [] };
403
+ }
404
+ return {
405
+ valid: errors.length === 0,
406
+ errors,
407
+ uncommittedPaths,
408
+ };
409
+ }
410
+ /**
411
+ * WU-1153: Build error message for uncommitted code_paths validation failure
412
+ *
413
+ * @param {string} wuId - WU ID
414
+ * @param {string[]} uncommittedPaths - List of uncommitted code_paths
415
+ * @returns {string} Formatted error message
416
+ */
417
+ export function buildCodePathsCommittedErrorMessage(wuId, uncommittedPaths) {
418
+ const count = uncommittedPaths.length;
419
+ const pathList = uncommittedPaths.map((p) => ` - ${p}`).join('\n');
420
+ return `
421
+ ❌ UNCOMMITTED CODE_PATHS DETECTED (WU-1153)
422
+
423
+ ${count} code_path${count === 1 ? '' : 's'} for ${wuId} are not committed:
424
+
425
+ ${pathList}
426
+
427
+ wu:done cannot proceed because uncommitted code_paths would be lost
428
+ if the metadata transaction fails and needs to roll back.
429
+
430
+ This prevents lost work from metadata rollbacks after code commits.
431
+
432
+ Required actions:
433
+ 1. Commit your code changes:
434
+ git add ${uncommittedPaths.join(' ')}
435
+ git commit -m "implement: ${wuId} changes"
436
+
437
+ 2. Retry wu:done:
438
+ pnpm wu:done --id ${wuId}
439
+
440
+ The guard ensures atomic completion: either both code and metadata succeed,
441
+ or neither is modified. This prevents partial state corruption.
442
+
443
+ Context: WU-1153 prevents lost work from metadata rollbacks
444
+ `;
445
+ }
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
3
  * Worktree mode completion workflow for wu:done
4
- * Extracted from wu-done.mjs (WU-1215 refactoring)
4
+ * Extracted from wu-done.ts (WU-1215 refactoring)
5
5
  * Updated in WU-1369 to use atomic transaction pattern.
6
6
  *
7
7
  * Flow (WU-1369 Atomic Pattern):
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
3
  * Worktree mode completion workflow for wu:done
4
- * Extracted from wu-done.mjs (WU-1215 refactoring)
4
+ * Extracted from wu-done.ts (WU-1215 refactoring)
5
5
  * Updated in WU-1369 to use atomic transaction pattern.
6
6
  *
7
7
  * Flow (WU-1369 Atomic Pattern):
@@ -30,6 +30,7 @@ import { getDriftLevel, DRIFT_LEVELS } from './branch-drift.js';
30
30
  import { createError, ErrorCodes } from './error-handler.js';
31
31
  import { createRecoveryError, createValidationError } from './wu-done-errors.js';
32
32
  import { validateDoneWU, validateAndNormalizeWUYAML } from './wu-schema.js';
33
+ import { validateCodePathsCommittedBeforeDone } from './wu-done-validation.js';
33
34
  import { assertTransition } from './state-machine.js';
34
35
  import { detectZombieState, resetWorktreeYAMLForRecovery, getRecoveryAttemptCount, incrementRecoveryAttempt, clearRecoveryAttempts, shouldEscalateToManualIntervention, MAX_RECOVERY_ATTEMPTS, } from './wu-recovery.js';
35
36
  import { isPRModeEnabled, createPR, printPRCreatedMessage } from './wu-done-pr.js';
@@ -203,6 +204,15 @@ export async function executeWorktreeCompletion(context) {
203
204
  if (!completenessResult.valid) {
204
205
  throw createValidationError(`Cannot mark WU as done - spec incomplete:\n ${completenessResult.errors.join('\n ')}\n\nNext step: Update ${workingWUPath} to meet completion requirements and rerun wu:done`, { wuId: id });
205
206
  }
207
+ // WU-1153: Validate code_paths are committed before metadata transaction
208
+ // This prevents lost work from metadata rollbacks after code commits
209
+ console.log(`${LOG_PREFIX.DONE} Checking code_paths commit status (WU-1153)...`);
210
+ const gitAdapter = getGitForCwd();
211
+ const codePathsResult = await validateCodePathsCommittedBeforeDone(normalizeResult.normalized, gitAdapter, { abortOnFailure: false });
212
+ if (!codePathsResult.valid) {
213
+ const errorMessage = await import('./wu-done-validation.js').then((m) => m.buildCodePathsCommittedErrorMessage(id, codePathsResult.uncommittedPaths));
214
+ throw createValidationError(errorMessage, { wuId: id });
215
+ }
206
216
  console.log(`${LOG_PREFIX.DONE} ${EMOJI.SUCCESS} All validations passed`);
207
217
  // ======================================================================
208
218
  // PHASE 2: COLLECT ALL CHANGES TO TRANSACTION (in memory, no writes)
@@ -0,0 +1,148 @@
1
+ /**
2
+ * WU Events Cleanup (WU-1207)
3
+ *
4
+ * Archive old WU events to prevent unbounded growth of wu-events.jsonl.
5
+ * Moves completed WU events older than 90d to .lumenflow/archive/wu-events-YYYY-MM.jsonl.
6
+ * Keeps active WU events intact.
7
+ *
8
+ * Features:
9
+ * - Configurable archiveAfter threshold (default: 90 days)
10
+ * - Groups events by WU ID for atomic archival
11
+ * - Monthly archive file rollup
12
+ * - Active WU protection (in_progress/blocked/waiting never archived)
13
+ * - Dry-run mode for preview
14
+ *
15
+ * Reuses atomic write patterns from wu-state-store.ts.
16
+ *
17
+ * @see {@link packages/@lumenflow/core/src/__tests__/wu-events-cleanup.test.ts} - Tests
18
+ */
19
+ import { type WUEvent } from './wu-state-schema.js';
20
+ import type { EventArchivalConfig } from './lumenflow-config-schema.js';
21
+ export type { EventArchivalConfig };
22
+ /**
23
+ * Default event archival configuration
24
+ */
25
+ export declare const DEFAULT_EVENT_ARCHIVAL_CONFIG: EventArchivalConfig;
26
+ /**
27
+ * Context for archive decision making
28
+ */
29
+ export interface ArchiveContext {
30
+ /** Current timestamp for age calculations */
31
+ now: number;
32
+ /** Set of WU IDs that are currently active (in_progress/blocked/waiting) */
33
+ activeWuIds: Set<string>;
34
+ }
35
+ /**
36
+ * Result of shouldArchiveEvent decision
37
+ */
38
+ export interface ArchiveDecision {
39
+ archive: boolean;
40
+ reason: string;
41
+ }
42
+ /**
43
+ * Breakdown of archival by category
44
+ */
45
+ export interface ArchivalBreakdown {
46
+ archivedOlderThanThreshold: number;
47
+ retainedActiveWu: number;
48
+ retainedWithinThreshold: number;
49
+ }
50
+ /**
51
+ * Options for archiveWuEvents operation
52
+ */
53
+ export interface ArchiveWuEventsOptions {
54
+ /** If true, preview without modifications */
55
+ dryRun?: boolean;
56
+ /** Archive threshold duration string (e.g., '90d') */
57
+ archiveAfter?: string;
58
+ /** Archive threshold in milliseconds (alternative to archiveAfter string) */
59
+ archiveAfterMs?: number;
60
+ /** Current timestamp for testing (defaults to Date.now()) */
61
+ now?: number;
62
+ /** Function to get active WU IDs (override for testing) */
63
+ getActiveWuIds?: (baseDir: string) => Promise<Set<string>>;
64
+ }
65
+ /**
66
+ * Result of archiveWuEvents operation
67
+ */
68
+ export interface ArchiveWuEventsResult {
69
+ /** Whether archival succeeded */
70
+ success: boolean;
71
+ /** WU IDs that were archived */
72
+ archivedWuIds: string[];
73
+ /** WU IDs that were retained */
74
+ retainedWuIds: string[];
75
+ /** Total number of events archived */
76
+ archivedEventCount: number;
77
+ /** Total number of events retained */
78
+ retainedEventCount: number;
79
+ /** Approximate bytes moved to archive */
80
+ bytesArchived: number;
81
+ /** True if in dry-run mode */
82
+ dryRun?: boolean;
83
+ /** Breakdown by category */
84
+ breakdown: ArchivalBreakdown;
85
+ }
86
+ /**
87
+ * Parse an archiveAfter duration string into milliseconds.
88
+ *
89
+ * Uses the `ms` package to parse human-readable duration strings.
90
+ *
91
+ * @param archiveAfterString - Duration string (e.g., '90d', '30d', '24h')
92
+ * @returns Duration in milliseconds
93
+ * @throws If format is invalid
94
+ *
95
+ * @example
96
+ * parseArchiveAfter('90d'); // 7776000000 (90 days in ms)
97
+ * parseArchiveAfter('30d'); // 2592000000 (30 days in ms)
98
+ */
99
+ export declare function parseArchiveAfter(archiveAfterString: string): number;
100
+ /**
101
+ * Get the archive file path for a given event timestamp.
102
+ *
103
+ * Groups events by month into files like:
104
+ * .lumenflow/archive/wu-events-2026-01.jsonl
105
+ *
106
+ * @param timestamp - ISO 8601 timestamp string
107
+ * @returns Relative path to archive file
108
+ *
109
+ * @example
110
+ * getArchiveFilePath('2026-01-15T10:30:00.000Z');
111
+ * // Returns: '.lumenflow/archive/wu-events-2026-01.jsonl'
112
+ */
113
+ export declare function getArchiveFilePath(timestamp: string): string;
114
+ /**
115
+ * Determine if an event should be archived based on WU status and age.
116
+ *
117
+ * Policy rules (checked in order):
118
+ * 1. Active WU events (in_progress/blocked/waiting) are never archived
119
+ * 2. Completed WU events older than threshold are archived
120
+ * 3. Otherwise, event is retained
121
+ *
122
+ * @param event - WU event to check
123
+ * @param config - Archival configuration
124
+ * @param context - Archive context (now timestamp, active WU IDs)
125
+ * @returns Archive decision with reason
126
+ */
127
+ export declare function shouldArchiveEvent(event: WUEvent, config: EventArchivalConfig, context: ArchiveContext): ArchiveDecision;
128
+ /**
129
+ * Archive old WU events to monthly archive files.
130
+ *
131
+ * Moves completed WU events older than threshold to archive files.
132
+ * Events are grouped by WU ID so all events for a WU are archived together.
133
+ * Active WU events (in_progress/blocked/waiting) are never archived.
134
+ *
135
+ * @param baseDir - Project base directory
136
+ * @param options - Archive options
137
+ * @returns Archive result with statistics
138
+ *
139
+ * @example
140
+ * // Preview archival
141
+ * const preview = await archiveWuEvents(baseDir, { dryRun: true });
142
+ * console.log(`Would archive ${preview.archivedWuIds.length} WUs`);
143
+ *
144
+ * @example
145
+ * // Archive with custom threshold
146
+ * const result = await archiveWuEvents(baseDir, { archiveAfter: '30d' });
147
+ */
148
+ export declare function archiveWuEvents(baseDir: string, options?: ArchiveWuEventsOptions): Promise<ArchiveWuEventsResult>;