@lumenflow/cli 2.20.1 → 2.21.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 (111) hide show
  1. package/README.md +8 -4
  2. package/dist/hooks/enforcement-checks.js +120 -0
  3. package/dist/hooks/enforcement-checks.js.map +1 -1
  4. package/dist/init-lane-validation.js +141 -0
  5. package/dist/init-lane-validation.js.map +1 -0
  6. package/dist/init-templates.js +36 -8
  7. package/dist/init-templates.js.map +1 -1
  8. package/dist/init.js +27 -58
  9. package/dist/init.js.map +1 -1
  10. package/dist/initiative-create.js +35 -4
  11. package/dist/initiative-create.js.map +1 -1
  12. package/dist/lane-lifecycle-process.js +364 -0
  13. package/dist/lane-lifecycle-process.js.map +1 -0
  14. package/dist/lane-lock.js +41 -0
  15. package/dist/lane-lock.js.map +1 -0
  16. package/dist/lane-setup.js +55 -0
  17. package/dist/lane-setup.js.map +1 -0
  18. package/dist/lane-status.js +38 -0
  19. package/dist/lane-status.js.map +1 -0
  20. package/dist/lane-validate.js +43 -0
  21. package/dist/lane-validate.js.map +1 -0
  22. package/dist/onboarding-smoke-test.js +17 -0
  23. package/dist/onboarding-smoke-test.js.map +1 -1
  24. package/dist/public-manifest.js +28 -0
  25. package/dist/public-manifest.js.map +1 -1
  26. package/dist/wu-claim-cloud.js +16 -0
  27. package/dist/wu-claim-cloud.js.map +1 -1
  28. package/dist/wu-claim.js +12 -2
  29. package/dist/wu-claim.js.map +1 -1
  30. package/dist/wu-create-content.js +8 -2
  31. package/dist/wu-create-content.js.map +1 -1
  32. package/dist/wu-create-validation.js +5 -3
  33. package/dist/wu-create-validation.js.map +1 -1
  34. package/dist/wu-create.js +21 -1
  35. package/dist/wu-create.js.map +1 -1
  36. package/dist/wu-done.js +57 -8
  37. package/dist/wu-done.js.map +1 -1
  38. package/dist/wu-prep.js +22 -0
  39. package/dist/wu-prep.js.map +1 -1
  40. package/package.json +15 -11
  41. package/dist/__tests__/agent-log-issue.test.js +0 -56
  42. package/dist/__tests__/agent-spawn-coordination.test.js +0 -451
  43. package/dist/__tests__/backlog-prune.test.js +0 -478
  44. package/dist/__tests__/cli-entry-point.test.js +0 -160
  45. package/dist/__tests__/cli-subprocess.test.js +0 -89
  46. package/dist/__tests__/commands/integrate.test.js +0 -165
  47. package/dist/__tests__/commands.test.js +0 -271
  48. package/dist/__tests__/deps-operations.test.js +0 -206
  49. package/dist/__tests__/doctor.test.js +0 -510
  50. package/dist/__tests__/file-operations.test.js +0 -906
  51. package/dist/__tests__/flow-report.test.js +0 -24
  52. package/dist/__tests__/gates-config.test.js +0 -303
  53. package/dist/__tests__/gates-integration-tests.test.js +0 -112
  54. package/dist/__tests__/git-operations.test.js +0 -668
  55. package/dist/__tests__/guard-main-branch.test.js +0 -79
  56. package/dist/__tests__/guards-validation.test.js +0 -416
  57. package/dist/__tests__/hooks/enforcement.test.js +0 -279
  58. package/dist/__tests__/init-config-lanes.test.js +0 -131
  59. package/dist/__tests__/init-docs-structure.test.js +0 -152
  60. package/dist/__tests__/init-greenfield.test.js +0 -247
  61. package/dist/__tests__/init-lane-inference.test.js +0 -125
  62. package/dist/__tests__/init-onboarding-docs.test.js +0 -132
  63. package/dist/__tests__/init-quick-ref.test.js +0 -144
  64. package/dist/__tests__/init-scripts.test.js +0 -207
  65. package/dist/__tests__/init-template-portability.test.js +0 -96
  66. package/dist/__tests__/init.test.js +0 -968
  67. package/dist/__tests__/initiative-add-wu.test.js +0 -490
  68. package/dist/__tests__/initiative-e2e.test.js +0 -442
  69. package/dist/__tests__/initiative-plan-replacement.test.js +0 -161
  70. package/dist/__tests__/initiative-plan.test.js +0 -340
  71. package/dist/__tests__/initiative-remove-wu.test.js +0 -458
  72. package/dist/__tests__/lumenflow-upgrade.test.js +0 -260
  73. package/dist/__tests__/mem-cleanup-execution.test.js +0 -19
  74. package/dist/__tests__/memory-integration.test.js +0 -333
  75. package/dist/__tests__/merge-block.test.js +0 -220
  76. package/dist/__tests__/metrics-cli.test.js +0 -619
  77. package/dist/__tests__/metrics-snapshot.test.js +0 -24
  78. package/dist/__tests__/no-beacon-references-docs.test.js +0 -30
  79. package/dist/__tests__/no-beacon-references.test.js +0 -39
  80. package/dist/__tests__/onboarding-smoke-test.test.js +0 -211
  81. package/dist/__tests__/path-centralization-cli.test.js +0 -234
  82. package/dist/__tests__/plan-create.test.js +0 -126
  83. package/dist/__tests__/plan-edit.test.js +0 -157
  84. package/dist/__tests__/plan-link.test.js +0 -239
  85. package/dist/__tests__/plan-promote.test.js +0 -181
  86. package/dist/__tests__/release.test.js +0 -372
  87. package/dist/__tests__/rotate-progress.test.js +0 -127
  88. package/dist/__tests__/safe-git.test.js +0 -190
  89. package/dist/__tests__/session-coordinator.test.js +0 -109
  90. package/dist/__tests__/state-bootstrap.test.js +0 -432
  91. package/dist/__tests__/state-doctor.test.js +0 -328
  92. package/dist/__tests__/sync-templates.test.js +0 -255
  93. package/dist/__tests__/templates-sync.test.js +0 -219
  94. package/dist/__tests__/trace-gen.test.js +0 -115
  95. package/dist/__tests__/wu-create-required-fields.test.js +0 -143
  96. package/dist/__tests__/wu-create-strict.test.js +0 -118
  97. package/dist/__tests__/wu-create.test.js +0 -121
  98. package/dist/__tests__/wu-done-auto-cleanup.test.js +0 -135
  99. package/dist/__tests__/wu-done-docs-only-policy.test.js +0 -20
  100. package/dist/__tests__/wu-done-staging-whitelist.test.js +0 -35
  101. package/dist/__tests__/wu-done.test.js +0 -36
  102. package/dist/__tests__/wu-edit-strict.test.js +0 -109
  103. package/dist/__tests__/wu-edit.test.js +0 -119
  104. package/dist/__tests__/wu-lifecycle-integration.test.js +0 -388
  105. package/dist/__tests__/wu-prep-default-exec.test.js +0 -35
  106. package/dist/__tests__/wu-prep.test.js +0 -140
  107. package/dist/__tests__/wu-proto.test.js +0 -97
  108. package/dist/__tests__/wu-validate-strict.test.js +0 -113
  109. package/dist/__tests__/wu-validate.test.js +0 -36
  110. package/dist/spawn-list.js +0 -143
  111. package/dist/spawn-list.js.map +0 -1
@@ -1,207 +0,0 @@
1
- /**
2
- * @file init-scripts.test.ts
3
- * Test: Generated package.json scripts use correct format (wu-create, wu-claim, wu-done, gates)
4
- *
5
- * WU-1307: Fix lumenflow-init scaffolding
6
- *
7
- * The init command should inject standalone binary scripts that work
8
- * in consumer projects without requiring the full @lumenflow/cli path.
9
- */
10
- import { describe, it, expect, beforeEach, afterEach } from 'vitest';
11
- import * as fs from 'node:fs';
12
- import * as path from 'node:path';
13
- import * as os from 'node:os';
14
- import { scaffoldProject } from '../init.js';
15
- /** Package.json file name - extracted to avoid duplicate string lint errors */
16
- const PACKAGE_JSON_FILE_NAME = 'package.json';
17
- describe('init scripts generation (WU-1307)', () => {
18
- let tempDir;
19
- beforeEach(() => {
20
- // Create a temporary directory for each test
21
- tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'lumenflow-init-scripts-'));
22
- });
23
- afterEach(() => {
24
- // Clean up temporary directory
25
- if (tempDir && fs.existsSync(tempDir)) {
26
- fs.rmSync(tempDir, { recursive: true, force: true });
27
- }
28
- });
29
- /** Helper to read and parse package.json from temp directory */
30
- function readPackageJson() {
31
- const packageJsonPath = path.join(tempDir, PACKAGE_JSON_FILE_NAME);
32
- return JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
33
- }
34
- it('should generate package.json scripts using standalone binaries', async () => {
35
- // Arrange
36
- const packageJsonPath = path.join(tempDir, PACKAGE_JSON_FILE_NAME);
37
- // Act
38
- await scaffoldProject(tempDir, { force: true, full: true });
39
- // Assert
40
- expect(fs.existsSync(packageJsonPath)).toBe(true);
41
- const packageJson = readPackageJson();
42
- expect(packageJson.scripts).toBeDefined();
43
- // Scripts should use standalone binary format (wu-create, wu-claim, etc.)
44
- // NOT 'pnpm exec lumenflow' format
45
- expect(packageJson.scripts?.['wu:claim']).toBe('wu-claim');
46
- expect(packageJson.scripts?.['wu:done']).toBe('wu-done');
47
- expect(packageJson.scripts?.['wu:create']).toBe('wu-create');
48
- expect(packageJson.scripts?.gates).toBe('gates');
49
- });
50
- it('should NOT use pnpm exec lumenflow format', async () => {
51
- // Act
52
- await scaffoldProject(tempDir, { force: true, full: true });
53
- // Assert
54
- const packageJson = readPackageJson();
55
- // Ensure scripts do NOT use the old 'pnpm exec lumenflow' format
56
- const scriptValues = Object.values(packageJson.scripts ?? {});
57
- const hasOldFormat = scriptValues.some((script) => script.includes('pnpm exec lumenflow'));
58
- expect(hasOldFormat).toBe(false);
59
- });
60
- it('should include all essential WU lifecycle scripts', async () => {
61
- // Act
62
- await scaffoldProject(tempDir, { force: true, full: true });
63
- // Assert
64
- const packageJson = readPackageJson();
65
- // Essential scripts that must be present
66
- const essentialScripts = ['wu:claim', 'wu:done', 'wu:create', 'wu:status', 'gates'];
67
- for (const scriptName of essentialScripts) {
68
- expect(packageJson.scripts?.[scriptName]).toBeDefined();
69
- }
70
- });
71
- it('should preserve existing scripts when updating package.json', async () => {
72
- // Arrange
73
- const packageJsonPath = path.join(tempDir, PACKAGE_JSON_FILE_NAME);
74
- const existingPackageJson = {
75
- name: 'test-project',
76
- version: '1.0.0',
77
- scripts: {
78
- test: 'vitest',
79
- build: 'tsc',
80
- custom: 'echo hello',
81
- },
82
- };
83
- fs.writeFileSync(packageJsonPath, JSON.stringify(existingPackageJson, null, 2));
84
- // Act
85
- await scaffoldProject(tempDir, { force: false, full: true });
86
- // Assert
87
- const packageJson = readPackageJson();
88
- // Existing scripts should be preserved
89
- expect(packageJson.scripts?.test).toBe('vitest');
90
- expect(packageJson.scripts?.build).toBe('tsc');
91
- expect(packageJson.scripts?.custom).toBe('echo hello');
92
- // LumenFlow scripts should be added
93
- expect(packageJson.scripts?.['wu:claim']).toBeDefined();
94
- expect(packageJson.scripts?.gates).toBeDefined();
95
- });
96
- // WU-1342: Test for all 17 essential commands
97
- it('should include all 17 essential commands (WU-1342)', async () => {
98
- // Act
99
- await scaffoldProject(tempDir, { force: true, full: true });
100
- // Assert
101
- const packageJson = readPackageJson();
102
- // All 17 essential commands that must be present per WU-1342 acceptance criteria
103
- const essentialScripts = [
104
- // Core WU lifecycle
105
- 'wu:claim',
106
- 'wu:done',
107
- 'wu:create',
108
- 'wu:status',
109
- 'wu:block',
110
- 'wu:unblock',
111
- // Additional critical commands (WU-1342)
112
- 'wu:prep',
113
- 'wu:recover',
114
- 'wu:spawn',
115
- 'wu:validate',
116
- 'wu:infer-lane',
117
- // Memory commands
118
- 'mem:init',
119
- 'mem:checkpoint',
120
- 'mem:inbox',
121
- // Lane commands
122
- 'lane:suggest',
123
- // Gates
124
- 'gates',
125
- 'gates:docs',
126
- ];
127
- for (const scriptName of essentialScripts) {
128
- expect(packageJson.scripts?.[scriptName], `Missing essential script: ${scriptName}`).toBeDefined();
129
- }
130
- // Verify count
131
- const lumenflowScripts = Object.keys(packageJson.scripts ?? {}).filter((key) => key.startsWith('wu:') ||
132
- key.startsWith('mem:') ||
133
- key.startsWith('lane:') ||
134
- key === 'gates' ||
135
- key === 'gates:docs');
136
- expect(lumenflowScripts.length).toBeGreaterThanOrEqual(17);
137
- });
138
- });
139
- describe('init .gitignore generation (WU-1342)', () => {
140
- let tempDir;
141
- beforeEach(() => {
142
- tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'lumenflow-init-gitignore-'));
143
- });
144
- afterEach(() => {
145
- if (tempDir && fs.existsSync(tempDir)) {
146
- fs.rmSync(tempDir, { recursive: true, force: true });
147
- }
148
- });
149
- it('should create .gitignore with required exclusions (WU-1342)', async () => {
150
- // Act
151
- await scaffoldProject(tempDir, { force: true, full: true });
152
- // Assert
153
- const gitignorePath = path.join(tempDir, '.gitignore');
154
- expect(fs.existsSync(gitignorePath)).toBe(true);
155
- const content = fs.readFileSync(gitignorePath, 'utf-8');
156
- // Must include node_modules
157
- expect(content).toContain('node_modules');
158
- // Must include .lumenflow/state
159
- expect(content).toContain('.lumenflow/state');
160
- // Must include worktrees
161
- expect(content).toContain('worktrees');
162
- });
163
- it('should preserve existing .gitignore content in merge mode (WU-1342)', async () => {
164
- // Arrange
165
- const gitignorePath = path.join(tempDir, '.gitignore');
166
- const existingContent = '# Custom ignores\n.env\n*.log\n';
167
- fs.writeFileSync(gitignorePath, existingContent);
168
- // Act
169
- await scaffoldProject(tempDir, { force: false, full: true, merge: true });
170
- // Assert
171
- const content = fs.readFileSync(gitignorePath, 'utf-8');
172
- // Should preserve existing content
173
- expect(content).toContain('.env');
174
- expect(content).toContain('*.log');
175
- // Should add LumenFlow exclusions
176
- expect(content).toContain('node_modules');
177
- expect(content).toContain('.lumenflow/state');
178
- expect(content).toContain('worktrees');
179
- });
180
- });
181
- describe('init .claude directory creation (WU-1342)', () => {
182
- let tempDir;
183
- beforeEach(() => {
184
- tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'lumenflow-init-claude-'));
185
- });
186
- afterEach(() => {
187
- if (tempDir && fs.existsSync(tempDir)) {
188
- fs.rmSync(tempDir, { recursive: true, force: true });
189
- }
190
- });
191
- it('should create .claude directory when --client claude specified (WU-1342)', async () => {
192
- // Act
193
- await scaffoldProject(tempDir, { force: true, full: false, client: 'claude' });
194
- // Assert
195
- const claudeDir = path.join(tempDir, '.claude');
196
- expect(fs.existsSync(claudeDir)).toBe(true);
197
- // Should have agents directory
198
- const agentsDir = path.join(claudeDir, 'agents');
199
- expect(fs.existsSync(agentsDir)).toBe(true);
200
- // Should have settings.json
201
- const settingsPath = path.join(claudeDir, 'settings.json');
202
- expect(fs.existsSync(settingsPath)).toBe(true);
203
- // Should have skills directory
204
- const skillsDir = path.join(claudeDir, 'skills');
205
- expect(fs.existsSync(skillsDir)).toBe(true);
206
- });
207
- });
@@ -1,96 +0,0 @@
1
- /**
2
- * @file init-template-portability.test.ts
3
- * Tests for template portability - no absolute paths (WU-1309)
4
- */
5
- import { describe, it, expect, beforeEach, afterEach } from 'vitest';
6
- import * as fs from 'node:fs';
7
- import * as path from 'node:path';
8
- import * as os from 'node:os';
9
- import { scaffoldProject } from '../init.js';
10
- // Constants to avoid duplicate strings (sonarjs/no-duplicate-string)
11
- const ARC42_DOCS_STRUCTURE = 'arc42';
12
- const PROJECT_ROOT_PLACEHOLDER = '<project-root>';
13
- describe('template portability', () => {
14
- let tempDir;
15
- beforeEach(() => {
16
- tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'lumenflow-portability-test-'));
17
- });
18
- afterEach(() => {
19
- fs.rmSync(tempDir, { recursive: true, force: true });
20
- });
21
- describe('no absolute paths in templates', () => {
22
- it('should use <project-root> placeholder instead of absolute paths', async () => {
23
- const options = {
24
- force: false,
25
- full: true,
26
- client: 'claude',
27
- };
28
- await scaffoldProject(tempDir, options);
29
- // Check LUMENFLOW.md for absolute paths
30
- const lumenflowContent = fs.readFileSync(path.join(tempDir, 'LUMENFLOW.md'), 'utf-8');
31
- expect(lumenflowContent).not.toMatch(/\/home\//);
32
- expect(lumenflowContent).not.toMatch(/\/Users\//);
33
- expect(lumenflowContent).not.toMatch(/C:\\/);
34
- // Should contain <project-root> placeholder for portable references
35
- expect(lumenflowContent).toContain(PROJECT_ROOT_PLACEHOLDER);
36
- });
37
- it('should not contain hardcoded user paths in AGENTS.md', async () => {
38
- const options = {
39
- force: false,
40
- full: true,
41
- };
42
- await scaffoldProject(tempDir, options);
43
- const agentsContent = fs.readFileSync(path.join(tempDir, 'AGENTS.md'), 'utf-8');
44
- expect(agentsContent).not.toMatch(/\/home\/[a-zA-Z0-9_-]+\//);
45
- expect(agentsContent).not.toMatch(/\/Users\/[a-zA-Z0-9_-]+\//);
46
- expect(agentsContent).not.toMatch(/C:\\Users\\[a-zA-Z0-9_-]+\\/);
47
- });
48
- it('should not contain hardcoded paths in quick-ref-commands.md', async () => {
49
- const options = {
50
- force: false,
51
- full: true,
52
- docsStructure: ARC42_DOCS_STRUCTURE,
53
- };
54
- await scaffoldProject(tempDir, options);
55
- // Find the quick-ref-commands.md based on docs structure (arc42)
56
- const quickRefPath = path.join(tempDir, 'docs', '04-operations', '_frameworks', 'lumenflow', 'agent', 'onboarding', 'quick-ref-commands.md');
57
- if (fs.existsSync(quickRefPath)) {
58
- const quickRefContent = fs.readFileSync(quickRefPath, 'utf-8');
59
- expect(quickRefContent).not.toMatch(/\/home\/[a-zA-Z0-9_-]+\//);
60
- expect(quickRefContent).not.toMatch(/\/Users\/[a-zA-Z0-9_-]+\//);
61
- expect(quickRefContent).toContain(PROJECT_ROOT_PLACEHOLDER);
62
- }
63
- });
64
- it('should use relative paths for docs cross-references', async () => {
65
- const options = {
66
- force: false,
67
- full: true,
68
- client: 'claude',
69
- docsStructure: ARC42_DOCS_STRUCTURE,
70
- };
71
- await scaffoldProject(tempDir, options);
72
- // Starting prompt should have relative paths to other docs
73
- const onboardingDir = path.join(tempDir, 'docs', '04-operations', '_frameworks', 'lumenflow', 'agent', 'onboarding');
74
- const startingPromptPath = path.join(onboardingDir, 'starting-prompt.md');
75
- if (fs.existsSync(startingPromptPath)) {
76
- const content = fs.readFileSync(startingPromptPath, 'utf-8');
77
- // Should use relative paths like ../../../../../../LUMENFLOW.md
78
- expect(content).toMatch(/\[.*?\]\([./]+.*?\.md\)/);
79
- }
80
- });
81
- });
82
- describe('PROJECT_ROOT token replacement', () => {
83
- it('should replace {{PROJECT_ROOT}} with <project-root> placeholder', async () => {
84
- const options = {
85
- force: false,
86
- full: true,
87
- };
88
- await scaffoldProject(tempDir, options);
89
- const lumenflowContent = fs.readFileSync(path.join(tempDir, 'LUMENFLOW.md'), 'utf-8');
90
- // Should not have unreplaced {{PROJECT_ROOT}} tokens
91
- expect(lumenflowContent).not.toContain('{{PROJECT_ROOT}}');
92
- // Should have the portable placeholder
93
- expect(lumenflowContent).toContain('<project-root>');
94
- });
95
- });
96
- });