@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.
- package/dist/active-wu-detector.d.ts +1 -1
- package/dist/active-wu-detector.js +1 -1
- package/dist/arg-parser.js +51 -18
- package/dist/backlog-generator.d.ts +4 -4
- package/dist/backlog-generator.js +4 -4
- package/dist/backlog-sync-validator.js +1 -1
- package/dist/cleanup-lock.d.ts +9 -2
- package/dist/cleanup-lock.js +17 -7
- package/dist/code-path-validator.d.ts +3 -3
- package/dist/code-path-validator.js +3 -3
- package/dist/compliance-parser.d.ts +1 -1
- package/dist/compliance-parser.js +1 -1
- package/dist/constants/backlog-patterns.d.ts +1 -1
- package/dist/constants/backlog-patterns.js +1 -1
- package/dist/constants/dora-constants.d.ts +1 -1
- package/dist/constants/dora-constants.js +1 -1
- package/dist/constants/gate-constants.d.ts +1 -1
- package/dist/constants/gate-constants.js +1 -1
- package/dist/constants/linter-constants.d.ts +1 -1
- package/dist/constants/linter-constants.js +1 -1
- package/dist/constants/tokenizer-constants.d.ts +1 -1
- package/dist/constants/tokenizer-constants.js +1 -1
- package/dist/context/location-resolver.js +2 -1
- package/dist/context-validation-integration.d.ts +1 -0
- package/dist/core/scope-checker.d.ts +3 -3
- package/dist/core/scope-checker.js +3 -3
- package/dist/core/tool-runner.d.ts +5 -5
- package/dist/core/tool-runner.js +5 -5
- package/dist/core/tool.constants.d.ts +1 -1
- package/dist/core/tool.constants.js +1 -1
- package/dist/core/tool.schemas.d.ts +2 -2
- package/dist/core/tool.schemas.js +1 -1
- package/dist/core/worktree-guard.d.ts +1 -1
- package/dist/core/worktree-guard.js +1 -1
- package/dist/coverage-gate.d.ts +12 -3
- package/dist/coverage-gate.js +15 -8
- package/dist/date-utils.d.ts +4 -4
- package/dist/date-utils.js +4 -4
- package/dist/dependency-graph.d.ts +6 -0
- package/dist/dependency-graph.js +43 -2
- package/dist/dependency-guard.d.ts +2 -2
- package/dist/dependency-guard.js +3 -3
- package/dist/dependency-validator.d.ts +4 -4
- package/dist/dependency-validator.js +4 -7
- package/dist/domain/orchestration.constants.d.ts +31 -10
- package/dist/domain/orchestration.constants.js +45 -16
- package/dist/domain/orchestration.schemas.d.ts +54 -28
- package/dist/domain/orchestration.schemas.js +2 -2
- package/dist/domain/orchestration.types.d.ts +2 -2
- package/dist/domain/orchestration.types.js +2 -2
- package/dist/error-handler.d.ts +10 -10
- package/dist/error-handler.js +10 -10
- package/dist/file-classifiers.d.ts +6 -6
- package/dist/file-classifiers.js +6 -6
- package/dist/gates-config.d.ts +74 -0
- package/dist/gates-config.js +209 -2
- package/dist/git-adapter.d.ts +11 -11
- package/dist/git-adapter.js +11 -11
- package/dist/git-context-extractor.d.ts +112 -0
- package/dist/git-context-extractor.js +559 -0
- package/dist/hardcoded-strings.d.ts +1 -1
- package/dist/hardcoded-strings.js +1 -1
- package/dist/incremental-lint.d.ts +1 -1
- package/dist/incremental-lint.js +2 -2
- package/dist/incremental-test.d.ts +1 -1
- package/dist/incremental-test.js +1 -1
- package/dist/index.d.ts +13 -0
- package/dist/index.js +25 -0
- package/dist/invariants/check-automated-tests.d.ts +2 -2
- package/dist/invariants/check-automated-tests.js +3 -3
- package/dist/lane-checker.d.ts +28 -7
- package/dist/lane-checker.js +316 -159
- package/dist/lane-suggest-prompt.d.ts +108 -0
- package/dist/lane-suggest-prompt.js +359 -0
- package/dist/lane-validator.d.ts +3 -3
- package/dist/lane-validator.js +3 -3
- package/dist/logs-lib.d.ts +1 -1
- package/dist/logs-lib.js +1 -1
- package/dist/lumenflow-config-schema.d.ts +162 -0
- package/dist/lumenflow-config-schema.js +180 -0
- package/dist/manual-test-validator.d.ts +2 -2
- package/dist/manual-test-validator.js +3 -3
- package/dist/merge-lock.d.ts +8 -1
- package/dist/merge-lock.js +16 -7
- package/dist/micro-worktree.d.ts +81 -13
- package/dist/micro-worktree.js +98 -17
- package/dist/migration-deployer.d.ts +1 -1
- package/dist/migration-deployer.js +1 -1
- package/dist/orchestration-advisory-loader.d.ts +2 -2
- package/dist/orchestration-advisory-loader.js +10 -6
- package/dist/orchestration-advisory.d.ts +3 -3
- package/dist/orchestration-advisory.js +4 -4
- package/dist/orchestration-di.d.ts +4 -4
- package/dist/orchestration-di.js +4 -4
- package/dist/orchestration-rules.d.ts +4 -4
- package/dist/orchestration-rules.js +18 -10
- package/dist/orphan-detector.d.ts +3 -3
- package/dist/orphan-detector.js +3 -3
- package/dist/patrol-loop.d.ts +170 -0
- package/dist/patrol-loop.js +186 -0
- package/dist/process-detector.d.ts +5 -5
- package/dist/process-detector.js +5 -5
- package/dist/rebase-artifact-cleanup.d.ts +3 -3
- package/dist/rebase-artifact-cleanup.js +3 -3
- package/dist/resolve-policy.d.ts +195 -0
- package/dist/resolve-policy.js +203 -0
- package/dist/risk-detector.d.ts +2 -2
- package/dist/risk-detector.js +2 -2
- package/dist/rollback-utils.d.ts +1 -1
- package/dist/rollback-utils.js +1 -1
- package/dist/section-headings.d.ts +1 -1
- package/dist/section-headings.js +1 -1
- package/dist/spawn-escalation.d.ts +4 -4
- package/dist/spawn-escalation.js +3 -3
- package/dist/spawn-monitor.d.ts +4 -4
- package/dist/spawn-monitor.js +4 -4
- package/dist/spawn-recovery.d.ts +3 -3
- package/dist/spawn-recovery.js +3 -3
- package/dist/spawn-registry-schema.d.ts +2 -2
- package/dist/spawn-registry-schema.js +2 -2
- package/dist/spawn-registry-store.d.ts +2 -2
- package/dist/spawn-registry-store.js +2 -2
- package/dist/spawn-strategy.d.ts +17 -11
- package/dist/spawn-strategy.js +47 -44
- package/dist/spawn-tree.d.ts +3 -3
- package/dist/spawn-tree.js +3 -3
- package/dist/state-cleanup-core.d.ts +205 -0
- package/dist/state-cleanup-core.js +240 -0
- package/dist/state-doctor-core.d.ts +168 -0
- package/dist/state-doctor-core.js +251 -0
- package/dist/stream-error-handler.d.ts +67 -0
- package/dist/stream-error-handler.js +94 -0
- package/dist/telemetry.d.ts +1 -1
- package/dist/telemetry.js +1 -1
- package/dist/template-loader.d.ts +162 -0
- package/dist/template-loader.js +372 -0
- package/dist/test-baseline.d.ts +176 -0
- package/dist/test-baseline.js +282 -0
- package/dist/usecases/get-suggestions.usecase.d.ts +1 -1
- package/dist/validation/command-registry.js +37 -0
- package/dist/validators/backlog-sync.js +4 -2
- package/dist/worktree-scanner.d.ts +1 -1
- package/dist/worktree-scanner.js +1 -1
- package/dist/worktree-symlink.d.ts +3 -3
- package/dist/worktree-symlink.js +3 -3
- package/dist/wu-backlog-updater.d.ts +1 -1
- package/dist/wu-backlog-updater.js +1 -1
- package/dist/wu-claim-helpers.d.ts +1 -1
- package/dist/wu-claim-helpers.js +1 -1
- package/dist/wu-claim-resume.d.ts +1 -1
- package/dist/wu-claim-resume.js +1 -1
- package/dist/wu-consistency-checker.d.ts +1 -1
- package/dist/wu-consistency-checker.js +17 -11
- package/dist/wu-constants.d.ts +73 -21
- package/dist/wu-constants.js +65 -22
- package/dist/wu-done-branch-only.d.ts +1 -1
- package/dist/wu-done-branch-only.js +1 -1
- package/dist/wu-done-docs-generate.d.ts +1 -1
- package/dist/wu-done-docs-generate.js +1 -1
- package/dist/wu-done-messages.d.ts +2 -2
- package/dist/wu-done-messages.js +2 -2
- package/dist/wu-done-metadata.d.ts +3 -3
- package/dist/wu-done-metadata.js +3 -3
- package/dist/wu-done-pr.d.ts +1 -1
- package/dist/wu-done-pr.js +4 -2
- package/dist/wu-done-preflight.d.ts +8 -0
- package/dist/wu-done-preflight.js +18 -2
- package/dist/wu-done-ui.d.ts +3 -3
- package/dist/wu-done-ui.js +3 -3
- package/dist/wu-done-validation.d.ts +30 -0
- package/dist/wu-done-validation.js +106 -1
- package/dist/wu-done-worktree.d.ts +1 -1
- package/dist/wu-done-worktree.js +11 -1
- package/dist/wu-events-cleanup.d.ts +148 -0
- package/dist/wu-events-cleanup.js +401 -0
- package/dist/wu-helpers.d.ts +2 -2
- package/dist/wu-helpers.js +2 -2
- package/dist/wu-id-generator.d.ts +58 -0
- package/dist/wu-id-generator.js +103 -0
- package/dist/wu-lint.js +1 -1
- package/dist/wu-preflight-validators.d.ts +13 -1
- package/dist/wu-preflight-validators.js +56 -1
- package/dist/wu-recovery.d.ts +2 -2
- package/dist/wu-recovery.js +4 -4
- package/dist/wu-repair-core.d.ts +5 -5
- package/dist/wu-repair-core.js +6 -6
- package/dist/wu-schema-normalization.d.ts +1 -1
- package/dist/wu-schema-normalization.js +1 -1
- package/dist/wu-schema.d.ts +7 -7
- package/dist/wu-schema.js +8 -8
- package/dist/wu-spawn-context.d.ts +87 -0
- package/dist/wu-spawn-context.js +175 -0
- package/dist/wu-spawn-helpers.d.ts +1 -1
- package/dist/wu-spawn-helpers.js +1 -1
- package/dist/wu-spawn.d.ts +177 -4
- package/dist/wu-spawn.js +694 -72
- package/dist/wu-state-schema.d.ts +1 -1
- package/dist/wu-state-schema.js +1 -1
- package/dist/wu-state-store.d.ts +3 -3
- package/dist/wu-state-store.js +3 -3
- package/dist/wu-status-transition.d.ts +1 -1
- package/dist/wu-status-transition.js +1 -1
- package/dist/wu-status-updater.d.ts +3 -3
- package/dist/wu-status-updater.js +3 -3
- package/dist/wu-validation-constants.d.ts +2 -2
- package/dist/wu-validation-constants.js +2 -2
- package/dist/wu-validation.d.ts +3 -3
- package/dist/wu-validation.js +3 -3
- package/dist/wu-yaml-fixer.d.ts +2 -2
- package/dist/wu-yaml-fixer.js +3 -3
- package/dist/wu-yaml.d.ts +23 -0
- package/dist/wu-yaml.js +76 -2
- 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:
|
|
124
|
+
See: https://lumenflow.dev/reference/troubleshooting-wu-done/ for more recovery options.
|
|
109
125
|
`;
|
|
110
126
|
return message;
|
|
111
127
|
}
|
package/dist/wu-done-ui.d.ts
CHANGED
|
@@ -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
|
|
8
|
-
* @see {@link
|
|
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.
|
|
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
|
*
|
package/dist/wu-done-ui.js
CHANGED
|
@@ -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
|
|
8
|
-
* @see {@link
|
|
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.
|
|
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.
|
|
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.
|
|
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):
|
package/dist/wu-done-worktree.js
CHANGED
|
@@ -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.
|
|
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>;
|