@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.
- package/README.md +8 -4
- package/dist/hooks/enforcement-checks.js +120 -0
- package/dist/hooks/enforcement-checks.js.map +1 -1
- package/dist/init-lane-validation.js +141 -0
- package/dist/init-lane-validation.js.map +1 -0
- package/dist/init-templates.js +36 -8
- package/dist/init-templates.js.map +1 -1
- package/dist/init.js +27 -58
- package/dist/init.js.map +1 -1
- package/dist/initiative-create.js +35 -4
- package/dist/initiative-create.js.map +1 -1
- package/dist/lane-lifecycle-process.js +364 -0
- package/dist/lane-lifecycle-process.js.map +1 -0
- package/dist/lane-lock.js +41 -0
- package/dist/lane-lock.js.map +1 -0
- package/dist/lane-setup.js +55 -0
- package/dist/lane-setup.js.map +1 -0
- package/dist/lane-status.js +38 -0
- package/dist/lane-status.js.map +1 -0
- package/dist/lane-validate.js +43 -0
- package/dist/lane-validate.js.map +1 -0
- package/dist/onboarding-smoke-test.js +17 -0
- package/dist/onboarding-smoke-test.js.map +1 -1
- package/dist/public-manifest.js +28 -0
- package/dist/public-manifest.js.map +1 -1
- package/dist/wu-claim-cloud.js +16 -0
- package/dist/wu-claim-cloud.js.map +1 -1
- package/dist/wu-claim.js +12 -2
- package/dist/wu-claim.js.map +1 -1
- package/dist/wu-create-content.js +8 -2
- package/dist/wu-create-content.js.map +1 -1
- package/dist/wu-create-validation.js +5 -3
- package/dist/wu-create-validation.js.map +1 -1
- package/dist/wu-create.js +21 -1
- package/dist/wu-create.js.map +1 -1
- package/dist/wu-done.js +57 -8
- package/dist/wu-done.js.map +1 -1
- package/dist/wu-prep.js +22 -0
- package/dist/wu-prep.js.map +1 -1
- package/package.json +15 -11
- package/dist/__tests__/agent-log-issue.test.js +0 -56
- package/dist/__tests__/agent-spawn-coordination.test.js +0 -451
- package/dist/__tests__/backlog-prune.test.js +0 -478
- package/dist/__tests__/cli-entry-point.test.js +0 -160
- package/dist/__tests__/cli-subprocess.test.js +0 -89
- package/dist/__tests__/commands/integrate.test.js +0 -165
- package/dist/__tests__/commands.test.js +0 -271
- package/dist/__tests__/deps-operations.test.js +0 -206
- package/dist/__tests__/doctor.test.js +0 -510
- package/dist/__tests__/file-operations.test.js +0 -906
- package/dist/__tests__/flow-report.test.js +0 -24
- package/dist/__tests__/gates-config.test.js +0 -303
- package/dist/__tests__/gates-integration-tests.test.js +0 -112
- package/dist/__tests__/git-operations.test.js +0 -668
- package/dist/__tests__/guard-main-branch.test.js +0 -79
- package/dist/__tests__/guards-validation.test.js +0 -416
- package/dist/__tests__/hooks/enforcement.test.js +0 -279
- package/dist/__tests__/init-config-lanes.test.js +0 -131
- package/dist/__tests__/init-docs-structure.test.js +0 -152
- package/dist/__tests__/init-greenfield.test.js +0 -247
- package/dist/__tests__/init-lane-inference.test.js +0 -125
- package/dist/__tests__/init-onboarding-docs.test.js +0 -132
- package/dist/__tests__/init-quick-ref.test.js +0 -144
- package/dist/__tests__/init-scripts.test.js +0 -207
- package/dist/__tests__/init-template-portability.test.js +0 -96
- package/dist/__tests__/init.test.js +0 -968
- package/dist/__tests__/initiative-add-wu.test.js +0 -490
- package/dist/__tests__/initiative-e2e.test.js +0 -442
- package/dist/__tests__/initiative-plan-replacement.test.js +0 -161
- package/dist/__tests__/initiative-plan.test.js +0 -340
- package/dist/__tests__/initiative-remove-wu.test.js +0 -458
- package/dist/__tests__/lumenflow-upgrade.test.js +0 -260
- package/dist/__tests__/mem-cleanup-execution.test.js +0 -19
- package/dist/__tests__/memory-integration.test.js +0 -333
- package/dist/__tests__/merge-block.test.js +0 -220
- package/dist/__tests__/metrics-cli.test.js +0 -619
- package/dist/__tests__/metrics-snapshot.test.js +0 -24
- package/dist/__tests__/no-beacon-references-docs.test.js +0 -30
- package/dist/__tests__/no-beacon-references.test.js +0 -39
- package/dist/__tests__/onboarding-smoke-test.test.js +0 -211
- package/dist/__tests__/path-centralization-cli.test.js +0 -234
- package/dist/__tests__/plan-create.test.js +0 -126
- package/dist/__tests__/plan-edit.test.js +0 -157
- package/dist/__tests__/plan-link.test.js +0 -239
- package/dist/__tests__/plan-promote.test.js +0 -181
- package/dist/__tests__/release.test.js +0 -372
- package/dist/__tests__/rotate-progress.test.js +0 -127
- package/dist/__tests__/safe-git.test.js +0 -190
- package/dist/__tests__/session-coordinator.test.js +0 -109
- package/dist/__tests__/state-bootstrap.test.js +0 -432
- package/dist/__tests__/state-doctor.test.js +0 -328
- package/dist/__tests__/sync-templates.test.js +0 -255
- package/dist/__tests__/templates-sync.test.js +0 -219
- package/dist/__tests__/trace-gen.test.js +0 -115
- package/dist/__tests__/wu-create-required-fields.test.js +0 -143
- package/dist/__tests__/wu-create-strict.test.js +0 -118
- package/dist/__tests__/wu-create.test.js +0 -121
- package/dist/__tests__/wu-done-auto-cleanup.test.js +0 -135
- package/dist/__tests__/wu-done-docs-only-policy.test.js +0 -20
- package/dist/__tests__/wu-done-staging-whitelist.test.js +0 -35
- package/dist/__tests__/wu-done.test.js +0 -36
- package/dist/__tests__/wu-edit-strict.test.js +0 -109
- package/dist/__tests__/wu-edit.test.js +0 -119
- package/dist/__tests__/wu-lifecycle-integration.test.js +0 -388
- package/dist/__tests__/wu-prep-default-exec.test.js +0 -35
- package/dist/__tests__/wu-prep.test.js +0 -140
- package/dist/__tests__/wu-proto.test.js +0 -97
- package/dist/__tests__/wu-validate-strict.test.js +0 -113
- package/dist/__tests__/wu-validate.test.js +0 -36
- package/dist/spawn-list.js +0 -143
- package/dist/spawn-list.js.map +0 -1
|
@@ -1,220 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file merge-block.test.ts
|
|
3
|
-
* Tests for merge block functionality (WU-1171)
|
|
4
|
-
*
|
|
5
|
-
* Tests the LUMENFLOW:START/END block insertion and update logic
|
|
6
|
-
* that enables safe, idempotent merging of LumenFlow config into existing files.
|
|
7
|
-
*/
|
|
8
|
-
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
9
|
-
import * as fs from 'node:fs';
|
|
10
|
-
import * as path from 'node:path';
|
|
11
|
-
import * as os from 'node:os';
|
|
12
|
-
// Import the functions we'll implement
|
|
13
|
-
import { detectLineEnding, extractMergeBlock, insertMergeBlock, updateMergeBlock, } from '../merge-block.js';
|
|
14
|
-
describe('merge-block', () => {
|
|
15
|
-
let tempDir;
|
|
16
|
-
beforeEach(() => {
|
|
17
|
-
tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'merge-block-test-'));
|
|
18
|
-
});
|
|
19
|
-
afterEach(() => {
|
|
20
|
-
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
21
|
-
});
|
|
22
|
-
describe('detectLineEnding', () => {
|
|
23
|
-
it('should detect LF line endings', () => {
|
|
24
|
-
const content = 'line1\nline2\nline3\n';
|
|
25
|
-
expect(detectLineEnding(content)).toBe('\n');
|
|
26
|
-
});
|
|
27
|
-
it('should detect CRLF line endings', () => {
|
|
28
|
-
const content = 'line1\r\nline2\r\nline3\r\n';
|
|
29
|
-
expect(detectLineEnding(content)).toBe('\r\n');
|
|
30
|
-
});
|
|
31
|
-
it('should default to LF for empty content', () => {
|
|
32
|
-
expect(detectLineEnding('')).toBe('\n');
|
|
33
|
-
});
|
|
34
|
-
it('should default to LF for content without line endings', () => {
|
|
35
|
-
expect(detectLineEnding('single line')).toBe('\n');
|
|
36
|
-
});
|
|
37
|
-
it('should use majority line ending when mixed', () => {
|
|
38
|
-
const content = 'line1\r\nline2\r\nline3\n';
|
|
39
|
-
// 2 CRLF vs 1 LF, should detect CRLF
|
|
40
|
-
expect(detectLineEnding(content)).toBe('\r\n');
|
|
41
|
-
});
|
|
42
|
-
});
|
|
43
|
-
describe('extractMergeBlock', () => {
|
|
44
|
-
it('should extract content between LUMENFLOW:START and LUMENFLOW:END markers', () => {
|
|
45
|
-
const content = `# My Project
|
|
46
|
-
|
|
47
|
-
<!-- LUMENFLOW:START -->
|
|
48
|
-
This is LumenFlow content.
|
|
49
|
-
<!-- LUMENFLOW:END -->
|
|
50
|
-
|
|
51
|
-
Other content
|
|
52
|
-
`;
|
|
53
|
-
const result = extractMergeBlock(content);
|
|
54
|
-
expect(result.found).toBe(true);
|
|
55
|
-
expect(result.content).toBe('This is LumenFlow content.');
|
|
56
|
-
expect(result.startIndex).toBeGreaterThan(0);
|
|
57
|
-
expect(result.endIndex).toBeGreaterThan(result.startIndex);
|
|
58
|
-
});
|
|
59
|
-
it('should return not found when no markers exist', () => {
|
|
60
|
-
const content = '# My Project\n\nNo LumenFlow content here.';
|
|
61
|
-
const result = extractMergeBlock(content);
|
|
62
|
-
expect(result.found).toBe(false);
|
|
63
|
-
expect(result.content).toBeUndefined();
|
|
64
|
-
});
|
|
65
|
-
it('should handle malformed markers (only START)', () => {
|
|
66
|
-
const content = `# My Project
|
|
67
|
-
|
|
68
|
-
<!-- LUMENFLOW:START -->
|
|
69
|
-
Incomplete block
|
|
70
|
-
`;
|
|
71
|
-
const result = extractMergeBlock(content);
|
|
72
|
-
expect(result.found).toBe(false);
|
|
73
|
-
expect(result.malformed).toBe(true);
|
|
74
|
-
expect(result.malformedReason).toBe('missing-end');
|
|
75
|
-
});
|
|
76
|
-
it('should handle malformed markers (only END)', () => {
|
|
77
|
-
const content = `# My Project
|
|
78
|
-
|
|
79
|
-
Some content
|
|
80
|
-
<!-- LUMENFLOW:END -->
|
|
81
|
-
`;
|
|
82
|
-
const result = extractMergeBlock(content);
|
|
83
|
-
expect(result.found).toBe(false);
|
|
84
|
-
expect(result.malformed).toBe(true);
|
|
85
|
-
expect(result.malformedReason).toBe('missing-start');
|
|
86
|
-
});
|
|
87
|
-
it('should handle multiple START markers', () => {
|
|
88
|
-
const content = `<!-- LUMENFLOW:START -->
|
|
89
|
-
First block
|
|
90
|
-
<!-- LUMENFLOW:START -->
|
|
91
|
-
Second start
|
|
92
|
-
<!-- LUMENFLOW:END -->
|
|
93
|
-
`;
|
|
94
|
-
const result = extractMergeBlock(content);
|
|
95
|
-
expect(result.malformed).toBe(true);
|
|
96
|
-
expect(result.malformedReason).toBe('multiple-start');
|
|
97
|
-
});
|
|
98
|
-
});
|
|
99
|
-
describe('insertMergeBlock', () => {
|
|
100
|
-
it('should append block to end of file', () => {
|
|
101
|
-
const originalContent = '# My Project\n\nExisting content.\n';
|
|
102
|
-
const blockContent = 'LumenFlow configuration goes here.';
|
|
103
|
-
const result = insertMergeBlock(originalContent, blockContent);
|
|
104
|
-
expect(result).toContain('<!-- LUMENFLOW:START -->');
|
|
105
|
-
expect(result).toContain(blockContent);
|
|
106
|
-
expect(result).toContain('<!-- LUMENFLOW:END -->');
|
|
107
|
-
expect(result.startsWith('# My Project')).toBe(true);
|
|
108
|
-
});
|
|
109
|
-
it('should preserve original line endings (LF)', () => {
|
|
110
|
-
const originalContent = '# My Project\nExisting content.\n';
|
|
111
|
-
const blockContent = 'New content';
|
|
112
|
-
const result = insertMergeBlock(originalContent, blockContent);
|
|
113
|
-
// Should not contain CRLF
|
|
114
|
-
expect(result).not.toContain('\r\n');
|
|
115
|
-
expect(result).toContain('\n');
|
|
116
|
-
});
|
|
117
|
-
it('should preserve original line endings (CRLF)', () => {
|
|
118
|
-
const originalContent = '# My Project\r\nExisting content.\r\n';
|
|
119
|
-
const blockContent = 'New content';
|
|
120
|
-
const result = insertMergeBlock(originalContent, blockContent);
|
|
121
|
-
// Should contain CRLF
|
|
122
|
-
expect(result).toContain('\r\n');
|
|
123
|
-
});
|
|
124
|
-
it('should add blank line before block if not present', () => {
|
|
125
|
-
const originalContent = '# My Project\nNo trailing newline';
|
|
126
|
-
const blockContent = 'New content';
|
|
127
|
-
const result = insertMergeBlock(originalContent, blockContent);
|
|
128
|
-
// Should have separation between original and block
|
|
129
|
-
expect(result).toMatch(/No trailing newline\n\n<!-- LUMENFLOW:START -->/);
|
|
130
|
-
});
|
|
131
|
-
});
|
|
132
|
-
describe('updateMergeBlock', () => {
|
|
133
|
-
it('should replace existing block content', () => {
|
|
134
|
-
const originalContent = `# My Project
|
|
135
|
-
|
|
136
|
-
<!-- LUMENFLOW:START -->
|
|
137
|
-
Old LumenFlow content.
|
|
138
|
-
<!-- LUMENFLOW:END -->
|
|
139
|
-
|
|
140
|
-
Other content
|
|
141
|
-
`;
|
|
142
|
-
const newBlockContent = 'New LumenFlow content.';
|
|
143
|
-
const result = updateMergeBlock(originalContent, newBlockContent);
|
|
144
|
-
expect(result.content).toContain('New LumenFlow content.');
|
|
145
|
-
expect(result.content).not.toContain('Old LumenFlow content.');
|
|
146
|
-
expect(result.content).toContain('Other content');
|
|
147
|
-
expect(result.updated).toBe(true);
|
|
148
|
-
});
|
|
149
|
-
it('should preserve content before and after the block', () => {
|
|
150
|
-
const originalContent = `# Header
|
|
151
|
-
|
|
152
|
-
Before the block.
|
|
153
|
-
|
|
154
|
-
<!-- LUMENFLOW:START -->
|
|
155
|
-
Old content
|
|
156
|
-
<!-- LUMENFLOW:END -->
|
|
157
|
-
|
|
158
|
-
After the block.
|
|
159
|
-
`;
|
|
160
|
-
const newBlockContent = 'Updated content';
|
|
161
|
-
const result = updateMergeBlock(originalContent, newBlockContent);
|
|
162
|
-
expect(result.content).toContain('# Header');
|
|
163
|
-
expect(result.content).toContain('Before the block.');
|
|
164
|
-
expect(result.content).toContain('After the block.');
|
|
165
|
-
});
|
|
166
|
-
it('should preserve original line endings when updating', () => {
|
|
167
|
-
const originalContent = `# Project\r\n\r\n<!-- LUMENFLOW:START -->\r\nOld\r\n<!-- LUMENFLOW:END -->\r\n`;
|
|
168
|
-
const newBlockContent = 'New';
|
|
169
|
-
const result = updateMergeBlock(originalContent, newBlockContent);
|
|
170
|
-
// All line endings in result should be CRLF
|
|
171
|
-
const lfCount = (result.content.match(/(?<!\r)\n/g) || []).length;
|
|
172
|
-
expect(lfCount).toBe(0); // No standalone LF
|
|
173
|
-
});
|
|
174
|
-
it('should insert block when no existing block (append mode)', () => {
|
|
175
|
-
const originalContent = '# Project\n\nNo block here.\n';
|
|
176
|
-
const newBlockContent = 'New content';
|
|
177
|
-
const result = updateMergeBlock(originalContent, newBlockContent);
|
|
178
|
-
expect(result.content).toContain('<!-- LUMENFLOW:START -->');
|
|
179
|
-
expect(result.content).toContain(newBlockContent);
|
|
180
|
-
expect(result.updated).toBe(true);
|
|
181
|
-
expect(result.wasInserted).toBe(true);
|
|
182
|
-
});
|
|
183
|
-
it('should warn and append fresh block on malformed markers', () => {
|
|
184
|
-
const originalContent = `# Project
|
|
185
|
-
|
|
186
|
-
<!-- LUMENFLOW:START -->
|
|
187
|
-
Incomplete block without end marker
|
|
188
|
-
`;
|
|
189
|
-
const newBlockContent = 'Fresh content';
|
|
190
|
-
const result = updateMergeBlock(originalContent, newBlockContent);
|
|
191
|
-
expect(result.warning).toContain('malformed');
|
|
192
|
-
expect(result.content).toContain('<!-- LUMENFLOW:START -->');
|
|
193
|
-
expect(result.content).toContain('Fresh content');
|
|
194
|
-
expect(result.content).toContain('<!-- LUMENFLOW:END -->');
|
|
195
|
-
});
|
|
196
|
-
});
|
|
197
|
-
describe('idempotency', () => {
|
|
198
|
-
it('should produce identical output when run twice with same input', () => {
|
|
199
|
-
const originalContent = '# My Project\n\nSome content.\n';
|
|
200
|
-
const blockContent = 'LumenFlow configuration';
|
|
201
|
-
// First merge
|
|
202
|
-
const firstResult = updateMergeBlock(originalContent, blockContent);
|
|
203
|
-
// Second merge with same block content
|
|
204
|
-
const secondResult = updateMergeBlock(firstResult.content, blockContent);
|
|
205
|
-
expect(firstResult.content).toBe(secondResult.content);
|
|
206
|
-
});
|
|
207
|
-
it('should not modify file when block content is unchanged', () => {
|
|
208
|
-
const existingContent = `# Project
|
|
209
|
-
|
|
210
|
-
<!-- LUMENFLOW:START -->
|
|
211
|
-
Same content
|
|
212
|
-
<!-- LUMENFLOW:END -->
|
|
213
|
-
`;
|
|
214
|
-
const blockContent = 'Same content';
|
|
215
|
-
const result = updateMergeBlock(existingContent, blockContent);
|
|
216
|
-
expect(result.unchanged).toBe(true);
|
|
217
|
-
expect(result.content).toBe(existingContent);
|
|
218
|
-
});
|
|
219
|
-
});
|
|
220
|
-
});
|