@lumenflow/cli 2.4.0 → 2.5.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.
- package/README.md +11 -8
- package/dist/__tests__/init-config-lanes.test.js +131 -0
- package/dist/__tests__/init-docs-structure.test.js +119 -0
- package/dist/__tests__/init-lane-inference.test.js +125 -0
- package/dist/__tests__/init-onboarding-docs.test.js +132 -0
- package/dist/__tests__/init-quick-ref.test.js +145 -0
- package/dist/__tests__/init-scripts.test.js +207 -0
- package/dist/__tests__/init-template-portability.test.js +97 -0
- package/dist/__tests__/init.test.js +7 -2
- package/dist/__tests__/initiative-add-wu.test.js +420 -0
- package/dist/__tests__/initiative-plan-replacement.test.js +162 -0
- package/dist/__tests__/initiative-remove-wu.test.js +458 -0
- package/dist/__tests__/onboarding-smoke-test.test.js +211 -0
- package/dist/__tests__/path-centralization-cli.test.js +234 -0
- package/dist/__tests__/plan-create.test.js +126 -0
- package/dist/__tests__/plan-edit.test.js +157 -0
- package/dist/__tests__/plan-link.test.js +239 -0
- package/dist/__tests__/plan-promote.test.js +181 -0
- package/dist/__tests__/templates-sync.test.js +219 -0
- package/dist/__tests__/wu-create-strict.test.js +118 -0
- package/dist/__tests__/wu-edit-strict.test.js +109 -0
- package/dist/__tests__/wu-validate-strict.test.js +113 -0
- package/dist/flow-bottlenecks.js +4 -2
- package/dist/gates.js +22 -0
- package/dist/init.js +670 -87
- package/dist/initiative-add-wu.js +112 -16
- package/dist/initiative-remove-wu.js +248 -0
- package/dist/onboarding-smoke-test.js +400 -0
- package/dist/orchestrate-init-status.js +37 -9
- package/dist/orchestrate-initiative.js +10 -4
- package/dist/plan-create.js +199 -0
- package/dist/plan-edit.js +235 -0
- package/dist/plan-link.js +233 -0
- package/dist/plan-promote.js +231 -0
- package/dist/sync-templates.js +137 -5
- package/dist/wu-block.js +16 -5
- package/dist/wu-claim.js +15 -9
- package/dist/wu-create.js +50 -2
- package/dist/wu-deps.js +3 -1
- package/dist/wu-done.js +14 -5
- package/dist/wu-edit.js +35 -0
- package/dist/wu-prep.js +131 -8
- package/dist/wu-spawn.js +14 -1
- package/dist/wu-unblock.js +34 -2
- package/dist/wu-validate.js +25 -17
- package/package.json +11 -7
- package/templates/core/.lumenflow/constraints.md.template +61 -3
- package/templates/core/AGENTS.md.template +2 -2
- package/templates/core/LUMENFLOW.md.template +85 -23
- package/templates/core/ai/onboarding/agent-invocation-guide.md.template +157 -0
- package/templates/core/ai/onboarding/agent-safety-card.md.template +227 -0
- package/templates/core/ai/onboarding/docs-generation.md.template +277 -0
- package/templates/core/ai/onboarding/first-wu-mistakes.md.template +49 -7
- package/templates/core/ai/onboarding/quick-ref-commands.md.template +343 -110
- package/templates/core/ai/onboarding/release-process.md.template +8 -2
- package/templates/core/ai/onboarding/starting-prompt.md.template +407 -0
- package/templates/core/ai/onboarding/test-ratchet.md.template +131 -0
- package/templates/core/ai/onboarding/troubleshooting-wu-done.md.template +91 -38
- package/templates/core/ai/onboarding/vendor-support.md.template +219 -0
- package/templates/vendors/claude/.claude/skills/context-management/SKILL.md.template +13 -1
- package/templates/vendors/claude/.claude/skills/execution-memory/SKILL.md.template +14 -16
- package/templates/vendors/claude/.claude/skills/orchestration/SKILL.md.template +48 -4
- package/templates/vendors/claude/.claude/skills/worktree-discipline/SKILL.md.template +5 -1
- package/templates/vendors/claude/.claude/skills/wu-lifecycle/SKILL.md.template +19 -8
- package/dist/__tests__/init-plan.test.js +0 -340
- package/dist/agent-issues-query.d.ts +0 -16
- package/dist/agent-log-issue.d.ts +0 -10
- package/dist/agent-session-end.d.ts +0 -10
- package/dist/agent-session.d.ts +0 -10
- package/dist/backlog-prune.d.ts +0 -84
- package/dist/cli-entry-point.d.ts +0 -8
- package/dist/deps-add.d.ts +0 -91
- package/dist/deps-remove.d.ts +0 -17
- package/dist/docs-sync.d.ts +0 -50
- package/dist/file-delete.d.ts +0 -84
- package/dist/file-edit.d.ts +0 -82
- package/dist/file-read.d.ts +0 -92
- package/dist/file-write.d.ts +0 -90
- package/dist/flow-bottlenecks.d.ts +0 -16
- package/dist/flow-report.d.ts +0 -16
- package/dist/gates.d.ts +0 -94
- package/dist/git-branch.d.ts +0 -65
- package/dist/git-diff.d.ts +0 -58
- package/dist/git-log.d.ts +0 -69
- package/dist/git-status.d.ts +0 -58
- package/dist/guard-locked.d.ts +0 -62
- package/dist/guard-main-branch.d.ts +0 -50
- package/dist/guard-worktree-commit.d.ts +0 -59
- package/dist/index.d.ts +0 -10
- package/dist/init-plan.d.ts +0 -80
- package/dist/init-plan.js +0 -337
- package/dist/init.d.ts +0 -46
- package/dist/initiative-add-wu.d.ts +0 -22
- package/dist/initiative-bulk-assign-wus.d.ts +0 -16
- package/dist/initiative-create.d.ts +0 -28
- package/dist/initiative-edit.d.ts +0 -34
- package/dist/initiative-list.d.ts +0 -12
- package/dist/initiative-status.d.ts +0 -11
- package/dist/lumenflow-upgrade.d.ts +0 -103
- package/dist/mem-checkpoint.d.ts +0 -16
- package/dist/mem-cleanup.d.ts +0 -29
- package/dist/mem-create.d.ts +0 -17
- package/dist/mem-export.d.ts +0 -10
- package/dist/mem-inbox.d.ts +0 -35
- package/dist/mem-init.d.ts +0 -15
- package/dist/mem-ready.d.ts +0 -16
- package/dist/mem-signal.d.ts +0 -16
- package/dist/mem-start.d.ts +0 -16
- package/dist/mem-summarize.d.ts +0 -22
- package/dist/mem-triage.d.ts +0 -22
- package/dist/metrics-cli.d.ts +0 -90
- package/dist/metrics-snapshot.d.ts +0 -18
- package/dist/orchestrate-init-status.d.ts +0 -11
- package/dist/orchestrate-initiative.d.ts +0 -12
- package/dist/orchestrate-monitor.d.ts +0 -11
- package/dist/release.d.ts +0 -117
- package/dist/rotate-progress.d.ts +0 -48
- package/dist/session-coordinator.d.ts +0 -74
- package/dist/spawn-list.d.ts +0 -16
- package/dist/state-bootstrap.d.ts +0 -92
- package/dist/sync-templates.d.ts +0 -52
- package/dist/trace-gen.d.ts +0 -84
- package/dist/validate-agent-skills.d.ts +0 -50
- package/dist/validate-agent-sync.d.ts +0 -36
- package/dist/validate-backlog-sync.d.ts +0 -37
- package/dist/validate-skills-spec.d.ts +0 -40
- package/dist/validate.d.ts +0 -60
- package/dist/wu-block.d.ts +0 -16
- package/dist/wu-claim.d.ts +0 -74
- package/dist/wu-cleanup.d.ts +0 -35
- package/dist/wu-create.d.ts +0 -69
- package/dist/wu-delete.d.ts +0 -21
- package/dist/wu-deps.d.ts +0 -13
- package/dist/wu-done.d.ts +0 -225
- package/dist/wu-edit.d.ts +0 -63
- package/dist/wu-infer-lane.d.ts +0 -17
- package/dist/wu-preflight.d.ts +0 -47
- package/dist/wu-prune.d.ts +0 -16
- package/dist/wu-recover.d.ts +0 -37
- package/dist/wu-release.d.ts +0 -19
- package/dist/wu-repair.d.ts +0 -60
- package/dist/wu-spawn-completion.d.ts +0 -10
- package/dist/wu-spawn.d.ts +0 -192
- package/dist/wu-status.d.ts +0 -25
- package/dist/wu-unblock.d.ts +0 -16
- package/dist/wu-unlock-lane.d.ts +0 -19
- package/dist/wu-validate.d.ts +0 -16
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file wu-create-strict.test.ts
|
|
3
|
+
* Test suite for wu:create strict validation behavior (WU-1329)
|
|
4
|
+
*
|
|
5
|
+
* WU-1329: Make wu:create run strict validation by default
|
|
6
|
+
*
|
|
7
|
+
* Tests:
|
|
8
|
+
* - Strict validation runs by default (validates code_paths/test_paths exist)
|
|
9
|
+
* - --no-strict flag bypasses strict validation
|
|
10
|
+
* - --no-strict usage is logged
|
|
11
|
+
*/
|
|
12
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
13
|
+
// Import test utilities (WU-1329)
|
|
14
|
+
import { validateCreateSpec } from '../wu-create.js';
|
|
15
|
+
// WU-1329: Constants for test file paths
|
|
16
|
+
const NON_EXISTENT_CODE_PATH = 'non-existent/file.ts';
|
|
17
|
+
const NON_EXISTENT_TEST_PATH = 'non-existent/test.test.ts';
|
|
18
|
+
describe('wu:create strict validation (WU-1329)', () => {
|
|
19
|
+
describe('validateCreateSpec strict mode', () => {
|
|
20
|
+
const baseOpts = {
|
|
21
|
+
id: 'WU-9999',
|
|
22
|
+
lane: 'Framework: CLI',
|
|
23
|
+
title: 'Test WU',
|
|
24
|
+
priority: 'P2',
|
|
25
|
+
type: 'feature',
|
|
26
|
+
opts: {
|
|
27
|
+
description: 'Context: test context.\nProblem: test problem.\nSolution: test solution that exceeds minimum length requirement.',
|
|
28
|
+
acceptance: ['Acceptance criterion 1'],
|
|
29
|
+
codePaths: ['packages/@lumenflow/cli/src/wu-create.ts'],
|
|
30
|
+
testPathsUnit: ['packages/@lumenflow/cli/src/__tests__/wu-create-strict.test.ts'],
|
|
31
|
+
exposure: 'backend-only',
|
|
32
|
+
specRefs: ['lumenflow://plans/WU-9999-plan.md'],
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
it('should pass validation with valid spec in non-strict mode', () => {
|
|
36
|
+
const result = validateCreateSpec({
|
|
37
|
+
...baseOpts,
|
|
38
|
+
opts: {
|
|
39
|
+
...baseOpts.opts,
|
|
40
|
+
strict: false,
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
expect(result.valid).toBe(true);
|
|
44
|
+
expect(result.errors).toHaveLength(0);
|
|
45
|
+
});
|
|
46
|
+
// WU-1329: This test verifies that strict validation is the default
|
|
47
|
+
it('should validate code_paths existence by default (strict=true)', () => {
|
|
48
|
+
const result = validateCreateSpec({
|
|
49
|
+
...baseOpts,
|
|
50
|
+
opts: {
|
|
51
|
+
...baseOpts.opts,
|
|
52
|
+
codePaths: [NON_EXISTENT_CODE_PATH],
|
|
53
|
+
// strict is not explicitly set - should default to true
|
|
54
|
+
},
|
|
55
|
+
});
|
|
56
|
+
// In strict mode, non-existent paths should be caught
|
|
57
|
+
expect(result.valid).toBe(false);
|
|
58
|
+
expect(result.errors.some((e) => e.includes('code_paths') || e.includes('not found'))).toBe(true);
|
|
59
|
+
});
|
|
60
|
+
// WU-1329: This test verifies --no-strict bypasses path validation
|
|
61
|
+
it('should skip code_paths existence check when strict=false', () => {
|
|
62
|
+
const result = validateCreateSpec({
|
|
63
|
+
...baseOpts,
|
|
64
|
+
opts: {
|
|
65
|
+
...baseOpts.opts,
|
|
66
|
+
codePaths: [NON_EXISTENT_CODE_PATH],
|
|
67
|
+
strict: false,
|
|
68
|
+
},
|
|
69
|
+
});
|
|
70
|
+
// In non-strict mode, non-existent paths should not fail validation
|
|
71
|
+
// (other schema validation may still fail)
|
|
72
|
+
expect(result.errors.every((e) => !e.includes('not found') && !e.includes('does not exist'))).toBe(true);
|
|
73
|
+
});
|
|
74
|
+
// WU-1329: This test verifies test_paths validation in strict mode
|
|
75
|
+
it('should validate test_paths existence by default (strict=true)', () => {
|
|
76
|
+
const result = validateCreateSpec({
|
|
77
|
+
...baseOpts,
|
|
78
|
+
opts: {
|
|
79
|
+
...baseOpts.opts,
|
|
80
|
+
testPathsUnit: [NON_EXISTENT_TEST_PATH],
|
|
81
|
+
},
|
|
82
|
+
});
|
|
83
|
+
// In strict mode, non-existent test paths should be caught
|
|
84
|
+
expect(result.valid).toBe(false);
|
|
85
|
+
expect(result.errors.some((e) => e.includes('test') || e.includes('not found'))).toBe(true);
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
describe('--no-strict logging', () => {
|
|
89
|
+
let consoleSpy;
|
|
90
|
+
beforeEach(() => {
|
|
91
|
+
consoleSpy = vi.spyOn(console, 'warn').mockImplementation(() => { });
|
|
92
|
+
});
|
|
93
|
+
afterEach(() => {
|
|
94
|
+
consoleSpy.mockRestore();
|
|
95
|
+
});
|
|
96
|
+
// WU-1329: This test verifies --no-strict usage is logged
|
|
97
|
+
it('should log warning when --no-strict is used', () => {
|
|
98
|
+
validateCreateSpec({
|
|
99
|
+
id: 'WU-9999',
|
|
100
|
+
lane: 'Framework: CLI',
|
|
101
|
+
title: 'Test WU',
|
|
102
|
+
priority: 'P2',
|
|
103
|
+
type: 'feature',
|
|
104
|
+
opts: {
|
|
105
|
+
description: 'Context: test context.\nProblem: test problem.\nSolution: test solution that exceeds minimum.',
|
|
106
|
+
acceptance: ['Acceptance criterion'],
|
|
107
|
+
codePaths: [NON_EXISTENT_CODE_PATH],
|
|
108
|
+
testPathsUnit: [NON_EXISTENT_TEST_PATH],
|
|
109
|
+
exposure: 'backend-only',
|
|
110
|
+
specRefs: ['lumenflow://plans/WU-9999-plan.md'],
|
|
111
|
+
strict: false,
|
|
112
|
+
},
|
|
113
|
+
});
|
|
114
|
+
// Should log that strict validation was bypassed
|
|
115
|
+
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining('strict validation bypassed'));
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
});
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file wu-edit-strict.test.ts
|
|
3
|
+
* Test suite for wu:edit strict validation behavior (WU-1329)
|
|
4
|
+
*
|
|
5
|
+
* WU-1329: Make wu:edit run strict validation by default
|
|
6
|
+
*
|
|
7
|
+
* Tests:
|
|
8
|
+
* - applyEdits function works correctly (unit test for edit logic)
|
|
9
|
+
* - validateDoneWUEdits properly validates done WU edits
|
|
10
|
+
* - The main() function validates paths in strict mode (covered by e2e tests)
|
|
11
|
+
*/
|
|
12
|
+
import { describe, it, expect } from 'vitest';
|
|
13
|
+
// Import test utilities (WU-1329)
|
|
14
|
+
import { applyEdits, validateDoneWUEdits, validateExposureValue } from '../wu-edit.js';
|
|
15
|
+
// WU-1329: Constants for test file paths
|
|
16
|
+
const TEST_NEW_FILE_PATH = 'new/file.ts';
|
|
17
|
+
const TEST_NEW_TEST_PATH = 'new/test.test.ts';
|
|
18
|
+
describe('wu:edit strict validation (WU-1329)', () => {
|
|
19
|
+
describe('applyEdits code_paths handling', () => {
|
|
20
|
+
const baseWU = {
|
|
21
|
+
id: 'WU-9999',
|
|
22
|
+
title: 'Test WU',
|
|
23
|
+
lane: 'Framework: CLI',
|
|
24
|
+
type: 'feature',
|
|
25
|
+
status: 'ready',
|
|
26
|
+
priority: 'P2',
|
|
27
|
+
description: 'Context: test context.\nProblem: test problem.\nSolution: test solution that exceeds minimum length.',
|
|
28
|
+
acceptance: ['Existing criterion'],
|
|
29
|
+
code_paths: ['packages/@lumenflow/cli/src/wu-edit.ts'],
|
|
30
|
+
tests: {
|
|
31
|
+
unit: ['packages/@lumenflow/cli/src/__tests__/wu-edit-strict.test.ts'],
|
|
32
|
+
manual: [],
|
|
33
|
+
e2e: [],
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
// WU-1329: applyEdits transforms WU object - path validation is done separately
|
|
37
|
+
it('should apply code_paths edits correctly', () => {
|
|
38
|
+
const result = applyEdits(baseWU, {
|
|
39
|
+
codePaths: [TEST_NEW_FILE_PATH],
|
|
40
|
+
replaceCodePaths: true,
|
|
41
|
+
});
|
|
42
|
+
// applyEdits transforms the WU, validation happens later in main()
|
|
43
|
+
expect(result.code_paths).toContain(TEST_NEW_FILE_PATH);
|
|
44
|
+
expect(result.code_paths).toHaveLength(1);
|
|
45
|
+
});
|
|
46
|
+
it('should append code_paths by default', () => {
|
|
47
|
+
const result = applyEdits(baseWU, {
|
|
48
|
+
codePaths: [TEST_NEW_FILE_PATH],
|
|
49
|
+
});
|
|
50
|
+
expect(result.code_paths).toContain('packages/@lumenflow/cli/src/wu-edit.ts');
|
|
51
|
+
expect(result.code_paths).toContain(TEST_NEW_FILE_PATH);
|
|
52
|
+
expect(result.code_paths).toHaveLength(2);
|
|
53
|
+
});
|
|
54
|
+
it('should apply test_paths edits correctly', () => {
|
|
55
|
+
const result = applyEdits(baseWU, {
|
|
56
|
+
testPathsUnit: [TEST_NEW_TEST_PATH],
|
|
57
|
+
});
|
|
58
|
+
// Should append test paths
|
|
59
|
+
expect(result.tests.unit).toContain('packages/@lumenflow/cli/src/__tests__/wu-edit-strict.test.ts');
|
|
60
|
+
expect(result.tests.unit).toContain(TEST_NEW_TEST_PATH);
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
describe('validateDoneWUEdits', () => {
|
|
64
|
+
// WU-1329: Done WUs only allow initiative/phase/exposure edits
|
|
65
|
+
it('should allow exposure edits on done WUs', () => {
|
|
66
|
+
const result = validateDoneWUEdits({ exposure: 'backend-only' });
|
|
67
|
+
expect(result.valid).toBe(true);
|
|
68
|
+
expect(result.disallowedEdits).toHaveLength(0);
|
|
69
|
+
});
|
|
70
|
+
it('should disallow code_paths edits on done WUs', () => {
|
|
71
|
+
const result = validateDoneWUEdits({ codePaths: [TEST_NEW_FILE_PATH] });
|
|
72
|
+
expect(result.valid).toBe(false);
|
|
73
|
+
expect(result.disallowedEdits).toContain('--code-paths');
|
|
74
|
+
});
|
|
75
|
+
it('should disallow description edits on done WUs', () => {
|
|
76
|
+
const result = validateDoneWUEdits({ description: 'new description' });
|
|
77
|
+
expect(result.valid).toBe(false);
|
|
78
|
+
expect(result.disallowedEdits).toContain('--description');
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
describe('validateExposureValue', () => {
|
|
82
|
+
it('should accept valid exposure values', () => {
|
|
83
|
+
expect(validateExposureValue('ui').valid).toBe(true);
|
|
84
|
+
expect(validateExposureValue('api').valid).toBe(true);
|
|
85
|
+
expect(validateExposureValue('backend-only').valid).toBe(true);
|
|
86
|
+
expect(validateExposureValue('documentation').valid).toBe(true);
|
|
87
|
+
});
|
|
88
|
+
it('should reject invalid exposure values', () => {
|
|
89
|
+
const result = validateExposureValue('invalid-exposure');
|
|
90
|
+
expect(result.valid).toBe(false);
|
|
91
|
+
expect(result.error).toContain('Invalid exposure value');
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
describe('noStrict option support', () => {
|
|
95
|
+
// WU-1329: Verify CLI option parsing pattern
|
|
96
|
+
it('should support noStrict option in CLI argument pattern', () => {
|
|
97
|
+
// CLI uses --no-strict which Commander.js parses as noStrict
|
|
98
|
+
// The main() function converts this to strict: !noStrict
|
|
99
|
+
const cliArgs = { noStrict: true };
|
|
100
|
+
const strict = !cliArgs.noStrict;
|
|
101
|
+
expect(strict).toBe(false);
|
|
102
|
+
});
|
|
103
|
+
it('should default to strict=true when noStrict is undefined', () => {
|
|
104
|
+
const cliArgs = { noStrict: undefined };
|
|
105
|
+
const strict = !cliArgs.noStrict;
|
|
106
|
+
expect(strict).toBe(true);
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
});
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file wu-validate-strict.test.ts
|
|
3
|
+
* Test suite for wu:validate strict validation behavior (WU-1329)
|
|
4
|
+
*
|
|
5
|
+
* WU-1329: Make wu:validate treat warnings as errors by default
|
|
6
|
+
*
|
|
7
|
+
* Tests:
|
|
8
|
+
* - Default strict mode behavior (warnings treated as errors)
|
|
9
|
+
* - --no-strict flag restores original behavior (warnings advisory)
|
|
10
|
+
* - Help text documents strict default
|
|
11
|
+
*/
|
|
12
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
13
|
+
import { WU_OPTIONS, NEGATED_OPTIONS } from '@lumenflow/core/dist/arg-parser.js';
|
|
14
|
+
describe('wu:validate strict validation (WU-1329)', () => {
|
|
15
|
+
describe('WU_OPTIONS.noStrict configuration', () => {
|
|
16
|
+
// WU-1329: Verify the noStrict option is properly configured
|
|
17
|
+
it('should have noStrict option defined in WU_OPTIONS', () => {
|
|
18
|
+
expect(WU_OPTIONS.noStrict).toBeDefined();
|
|
19
|
+
expect(WU_OPTIONS.noStrict.name).toBe('noStrict');
|
|
20
|
+
expect(WU_OPTIONS.noStrict.flags).toBe('--no-strict');
|
|
21
|
+
expect(WU_OPTIONS.noStrict.isNegated).toBe(true);
|
|
22
|
+
});
|
|
23
|
+
it('should include description about bypassing strict validation', () => {
|
|
24
|
+
expect(WU_OPTIONS.noStrict.description).toContain('Bypass strict validation');
|
|
25
|
+
});
|
|
26
|
+
// WU-1329: Verify 'strict' is in NEGATED_OPTIONS array
|
|
27
|
+
it('should include strict in NEGATED_OPTIONS array', () => {
|
|
28
|
+
expect(NEGATED_OPTIONS).toContain('strict');
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
describe('strict mode logic', () => {
|
|
32
|
+
// WU-1329: Verify the strict mode conversion pattern
|
|
33
|
+
it('should default to strict=true when noStrict is undefined', () => {
|
|
34
|
+
const args = { noStrict: undefined };
|
|
35
|
+
const strict = !args.noStrict;
|
|
36
|
+
expect(strict).toBe(true);
|
|
37
|
+
});
|
|
38
|
+
it('should set strict=false when noStrict is true (--no-strict flag)', () => {
|
|
39
|
+
const args = { noStrict: true };
|
|
40
|
+
const strict = !args.noStrict;
|
|
41
|
+
expect(strict).toBe(false);
|
|
42
|
+
});
|
|
43
|
+
it('should set strict=true when noStrict is false (explicit)', () => {
|
|
44
|
+
const args = { noStrict: false };
|
|
45
|
+
const strict = !args.noStrict;
|
|
46
|
+
expect(strict).toBe(true);
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
describe('--no-strict logging behavior', () => {
|
|
50
|
+
let consoleSpy;
|
|
51
|
+
beforeEach(() => {
|
|
52
|
+
consoleSpy = vi.spyOn(console, 'warn').mockImplementation(() => { });
|
|
53
|
+
});
|
|
54
|
+
afterEach(() => {
|
|
55
|
+
consoleSpy.mockRestore();
|
|
56
|
+
});
|
|
57
|
+
// WU-1329: The logging behavior is implemented in main() functions
|
|
58
|
+
// This test documents the expected behavior pattern using the spy
|
|
59
|
+
it('should log when --no-strict bypass is used', () => {
|
|
60
|
+
// Simulate the logging pattern from wu-validate.ts main()
|
|
61
|
+
const noStrict = true;
|
|
62
|
+
const LOG_PREFIX = '[wu:validate]';
|
|
63
|
+
const message = `${LOG_PREFIX} WARNING: strict validation bypassed (--no-strict). Warnings will be advisory only.`;
|
|
64
|
+
if (noStrict) {
|
|
65
|
+
// Use the spy to simulate logging
|
|
66
|
+
consoleSpy(message);
|
|
67
|
+
}
|
|
68
|
+
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining('strict validation bypassed'));
|
|
69
|
+
});
|
|
70
|
+
it('should not log when strict mode is active', () => {
|
|
71
|
+
// When noStrict is false, no logging should occur
|
|
72
|
+
const noStrict = false;
|
|
73
|
+
if (noStrict) {
|
|
74
|
+
consoleSpy('This should not be called');
|
|
75
|
+
}
|
|
76
|
+
expect(consoleSpy).not.toHaveBeenCalled();
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
describe('validateSingleWU strict mode behavior', () => {
|
|
80
|
+
// WU-1329: These tests document the expected behavior
|
|
81
|
+
// The actual validation is done by calling the CLI command
|
|
82
|
+
it('should treat warnings as errors by default (strict=true)', () => {
|
|
83
|
+
// In strict mode, any warnings from completeness validation
|
|
84
|
+
// should become errors and cause validation to fail
|
|
85
|
+
const strict = true;
|
|
86
|
+
const warnings = ['Missing recommended field: notes'];
|
|
87
|
+
const errors = [];
|
|
88
|
+
if (strict && warnings.length > 0) {
|
|
89
|
+
errors.push(...warnings.map((w) => `[STRICT] ${w}`));
|
|
90
|
+
}
|
|
91
|
+
expect(errors.length).toBeGreaterThan(0);
|
|
92
|
+
expect(errors[0]).toContain('[STRICT]');
|
|
93
|
+
});
|
|
94
|
+
it('should allow warnings when strict=false (--no-strict)', () => {
|
|
95
|
+
// In non-strict mode, warnings should remain warnings
|
|
96
|
+
// and validation should pass
|
|
97
|
+
const strict = false;
|
|
98
|
+
const warnings = ['Missing recommended field: notes'];
|
|
99
|
+
const errors = [];
|
|
100
|
+
if (strict && warnings.length > 0) {
|
|
101
|
+
errors.push(...warnings.map((w) => `[STRICT] ${w}`));
|
|
102
|
+
}
|
|
103
|
+
expect(errors.length).toBe(0);
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
describe('help text documentation', () => {
|
|
107
|
+
// WU-1329: Verify help text documents strict default
|
|
108
|
+
it('should document that --no-strict bypasses strict validation', () => {
|
|
109
|
+
const expectedDescription = 'Bypass strict validation';
|
|
110
|
+
expect(WU_OPTIONS.noStrict.description).toContain(expectedDescription);
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
});
|
package/dist/flow-bottlenecks.js
CHANGED
|
@@ -15,8 +15,9 @@
|
|
|
15
15
|
*/
|
|
16
16
|
import { Command } from 'commander';
|
|
17
17
|
import { getBottleneckAnalysis, } from '@lumenflow/metrics';
|
|
18
|
-
import { buildDependencyGraphAsync, renderMermaid
|
|
18
|
+
import { buildDependencyGraphAsync, renderMermaid } from '@lumenflow/core/dist/dependency-graph.js';
|
|
19
19
|
import { die } from '@lumenflow/core/dist/error-handler.js';
|
|
20
|
+
import { getConfig } from '@lumenflow/core/dist/lumenflow-config.js';
|
|
20
21
|
/** Log prefix for console output */
|
|
21
22
|
const LOG_PREFIX = '[flow:bottlenecks]';
|
|
22
23
|
/** Default bottleneck limit */
|
|
@@ -147,7 +148,8 @@ async function main() {
|
|
|
147
148
|
const coreGraph = await buildDependencyGraphAsync();
|
|
148
149
|
if (coreGraph.size === 0) {
|
|
149
150
|
console.log(`${LOG_PREFIX} No WUs found in dependency graph.`);
|
|
150
|
-
|
|
151
|
+
// WU-1311: Use config-based WU directory path
|
|
152
|
+
console.log(`${LOG_PREFIX} Ensure WU YAML files exist in ${getConfig().directories.wuDir}/ with blocked_by/blocks fields.`);
|
|
151
153
|
return;
|
|
152
154
|
}
|
|
153
155
|
console.log(`${LOG_PREFIX} Found ${coreGraph.size} WUs in graph`);
|
package/dist/gates.js
CHANGED
|
@@ -68,6 +68,8 @@ import { runSystemMapValidation } from '@lumenflow/core/dist/system-map-validato
|
|
|
68
68
|
import { loadLaneHealthConfig, resolveTestPolicy, } from '@lumenflow/core/dist/gates-config.js';
|
|
69
69
|
// WU-1191: Lane health check
|
|
70
70
|
import { runLaneHealthCheck } from './lane-health.js';
|
|
71
|
+
// WU-1315: Onboarding smoke test
|
|
72
|
+
import { runOnboardingSmokeTestGate } from './onboarding-smoke-test.js';
|
|
71
73
|
import { BRANCHES, PACKAGES, PKG_MANAGER, ESLINT_FLAGS, ESLINT_COMMANDS, ESLINT_DEFAULTS, SCRIPTS, CACHE_STRATEGIES, DIRECTORIES, GATE_NAMES, GATE_COMMANDS, CLI_MODES, EXIT_CODES, FILE_SYSTEM, PRETTIER_ARGS, PRETTIER_FLAGS, } from '@lumenflow/core/dist/wu-constants.js';
|
|
72
74
|
/**
|
|
73
75
|
* WU-1087: Gates-specific option definitions for createWUParser.
|
|
@@ -1115,6 +1117,11 @@ async function executeGates(opts) {
|
|
|
1115
1117
|
run: (ctx) => runLaneHealthGate({ ...ctx, mode: laneHealthMode }),
|
|
1116
1118
|
warnOnly: laneHealthMode !== 'error',
|
|
1117
1119
|
},
|
|
1120
|
+
// WU-1315: Onboarding smoke test (init + wu:create validation)
|
|
1121
|
+
{
|
|
1122
|
+
name: GATE_NAMES.ONBOARDING_SMOKE_TEST,
|
|
1123
|
+
cmd: GATE_COMMANDS.ONBOARDING_SMOKE_TEST,
|
|
1124
|
+
},
|
|
1118
1125
|
// WU-1299: Filtered tests for packages in code_paths (if any)
|
|
1119
1126
|
// When docs-only mode has packages in code_paths, run tests only for those packages
|
|
1120
1127
|
// This prevents pre-existing failures in unrelated packages from blocking
|
|
@@ -1163,6 +1170,11 @@ async function executeGates(opts) {
|
|
|
1163
1170
|
run: (ctx) => runLaneHealthGate({ ...ctx, mode: laneHealthMode }),
|
|
1164
1171
|
warnOnly: laneHealthMode !== 'error',
|
|
1165
1172
|
},
|
|
1173
|
+
// WU-1315: Onboarding smoke test (init + wu:create validation)
|
|
1174
|
+
{
|
|
1175
|
+
name: GATE_NAMES.ONBOARDING_SMOKE_TEST,
|
|
1176
|
+
cmd: GATE_COMMANDS.ONBOARDING_SMOKE_TEST,
|
|
1177
|
+
},
|
|
1166
1178
|
// WU-2062: Safety-critical tests ALWAYS run
|
|
1167
1179
|
// WU-1280: When tests_required=false (methodology.testing: none), failures only warn
|
|
1168
1180
|
{
|
|
@@ -1285,6 +1297,16 @@ async function executeGates(opts) {
|
|
|
1285
1297
|
: console,
|
|
1286
1298
|
});
|
|
1287
1299
|
}
|
|
1300
|
+
else if (gate.cmd === GATE_COMMANDS.ONBOARDING_SMOKE_TEST) {
|
|
1301
|
+
// WU-1315: Onboarding smoke test (init + wu:create validation)
|
|
1302
|
+
const logLine = useAgentMode
|
|
1303
|
+
? (line) => writeSync(agentLog.logFd, `${line}\n`)
|
|
1304
|
+
: (line) => console.log(line);
|
|
1305
|
+
logLine('\n> Onboarding smoke test\n');
|
|
1306
|
+
result = await runOnboardingSmokeTestGate({
|
|
1307
|
+
logger: { log: logLine },
|
|
1308
|
+
});
|
|
1309
|
+
}
|
|
1288
1310
|
else {
|
|
1289
1311
|
result = run(gate.cmd, { agentLog });
|
|
1290
1312
|
}
|