@lumenflow/cli 1.3.6 → 1.4.0

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 CHANGED
@@ -63,6 +63,13 @@ This package provides CLI commands for the LumenFlow workflow framework, includi
63
63
  | `initiative-status` | Show initiative status and progress |
64
64
  | `initiative-add-wu` | Link a WU to an initiative |
65
65
 
66
+ ### Setup Commands
67
+
68
+ | Command | Description |
69
+ | ----------- | --------------------------------------------------- |
70
+ | `init` | Scaffold LumenFlow into a project |
71
+ | `docs-sync` | Sync agent onboarding docs (for upgrading projects) |
72
+
66
73
  ### Other Commands
67
74
 
68
75
  | Command | Description |
@@ -0,0 +1,452 @@
1
+ /**
2
+ * @file docs-sync.ts
3
+ * LumenFlow docs:sync command for syncing agent docs to existing projects (WU-1083)
4
+ */
5
+ import * as fs from 'node:fs';
6
+ import * as path from 'node:path';
7
+ /**
8
+ * Get current date in YYYY-MM-DD format
9
+ */
10
+ function getCurrentDate() {
11
+ return new Date().toISOString().split('T')[0];
12
+ }
13
+ /**
14
+ * Process template content by replacing placeholders
15
+ */
16
+ function processTemplate(content, tokens) {
17
+ let output = content;
18
+ for (const [key, value] of Object.entries(tokens)) {
19
+ output = output.replace(new RegExp(`\\{\\{${key}\\}\\}`, 'g'), value);
20
+ }
21
+ return output;
22
+ }
23
+ function getRelativePath(targetDir, filePath) {
24
+ return path.relative(targetDir, filePath).split(path.sep).join('/');
25
+ }
26
+ /**
27
+ * Create a directory if missing
28
+ */
29
+ async function createDirectory(dirPath, result, targetDir) {
30
+ if (!fs.existsSync(dirPath)) {
31
+ fs.mkdirSync(dirPath, { recursive: true });
32
+ result.created.push(getRelativePath(targetDir, dirPath));
33
+ }
34
+ }
35
+ /**
36
+ * Create a file, respecting force option
37
+ */
38
+ async function createFile(filePath, content, force, result, targetDir) {
39
+ const relativePath = getRelativePath(targetDir, filePath);
40
+ if (fs.existsSync(filePath) && !force) {
41
+ result.skipped.push(relativePath);
42
+ return;
43
+ }
44
+ const parentDir = path.dirname(filePath);
45
+ if (!fs.existsSync(parentDir)) {
46
+ fs.mkdirSync(parentDir, { recursive: true });
47
+ }
48
+ fs.writeFileSync(filePath, content);
49
+ result.created.push(relativePath);
50
+ }
51
+ // Agent onboarding docs templates (duplicated from init.ts for modularity)
52
+ const QUICK_REF_COMMANDS_TEMPLATE = `# Quick Reference: LumenFlow Commands
53
+
54
+ **Last updated:** {{DATE}}
55
+
56
+ ---
57
+
58
+ ## Project Setup
59
+
60
+ | Command | Description |
61
+ | --------------------------------------------- | --------------------------------------- |
62
+ | \`pnpm exec lumenflow init\` | Scaffold minimal LumenFlow core |
63
+ | \`pnpm exec lumenflow init --full\` | Add docs/04-operations task scaffolding |
64
+ | \`pnpm exec lumenflow init --framework <name>\` | Add framework hint + overlay docs |
65
+ | \`pnpm exec lumenflow init --force\` | Overwrite existing files |
66
+
67
+ ---
68
+
69
+ ## WU Management
70
+
71
+ | Command | Description |
72
+ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------- |
73
+ | \`pnpm wu:create --id WU-XXX --lane <Lane> --title "Title" --description "..." --acceptance "..." --code-paths "path" --test-paths-unit "path" --exposure backend-only --spec-refs "~/.lumenflow/plans/WU-XXX.md"\` | Create new WU |
74
+ | \`pnpm wu:claim --id WU-XXX --lane <Lane>\` | Claim WU (creates worktree) |
75
+ | \`pnpm wu:done --id WU-XXX\` | Complete WU (merge, stamp, cleanup) |
76
+ | \`pnpm wu:block --id WU-XXX --reason "Reason"\` | Block a WU |
77
+ | \`pnpm wu:unblock --id WU-XXX\` | Unblock a WU |
78
+
79
+ ---
80
+
81
+ ## Gates
82
+
83
+ | Command | Description |
84
+ | ------------------------ | -------------------------- |
85
+ | \`pnpm gates\` | Run all quality gates |
86
+ | \`pnpm gates --docs-only\` | Run gates for docs changes |
87
+ | \`pnpm format\` | Format all files |
88
+ | \`pnpm lint\` | Run linter |
89
+ | \`pnpm typecheck\` | Run TypeScript check |
90
+
91
+ ---
92
+
93
+ ## File Paths
94
+
95
+ | Path | Description |
96
+ | ----------------------------------------- | -------------------- |
97
+ | \`docs/04-operations/tasks/wu/WU-XXX.yaml\` | WU specification |
98
+ | \`docs/04-operations/tasks/status.md\` | Current status board |
99
+ | \`.lumenflow/stamps/WU-XXX.done\` | Completion stamp |
100
+ | \`worktrees/<lane>-wu-xxx/\` | Worktree directory |
101
+ `;
102
+ const FIRST_WU_MISTAKES_TEMPLATE = `# First WU Mistakes
103
+
104
+ **Last updated:** {{DATE}}
105
+
106
+ Common mistakes agents make on their first WU, and how to avoid them.
107
+
108
+ ---
109
+
110
+ ## Mistake 1: Not Using Worktrees
111
+
112
+ ### Wrong
113
+
114
+ \`\`\`bash
115
+ # Working directly in main
116
+ vim src/feature.ts
117
+ git commit -m "feat: add feature"
118
+ git push origin main
119
+ \`\`\`
120
+
121
+ ### Right
122
+
123
+ \`\`\`bash
124
+ # Claim first, then work in worktree
125
+ pnpm wu:claim --id WU-123 --lane Core
126
+ cd worktrees/core-wu-123
127
+ vim src/feature.ts
128
+ git commit -m "feat: add feature"
129
+ git push origin lane/core/wu-123
130
+ cd /path/to/main
131
+ pnpm wu:done --id WU-123
132
+ \`\`\`
133
+
134
+ ---
135
+
136
+ ## Mistake 2: Forgetting to Run wu:done
137
+
138
+ **TL;DR:** After gates pass, ALWAYS run \`pnpm wu:done --id WU-XXX\`.
139
+
140
+ ---
141
+
142
+ ## Mistake 3: Working Outside code_paths
143
+
144
+ Only edit files within the specified \`code_paths\`.
145
+
146
+ ---
147
+
148
+ ## Quick Checklist
149
+
150
+ - [ ] Claim the WU with \`pnpm wu:claim\`
151
+ - [ ] cd to the worktree IMMEDIATELY
152
+ - [ ] Work only in the worktree
153
+ - [ ] Run gates before wu:done
154
+ - [ ] ALWAYS run wu:done
155
+ `;
156
+ const TROUBLESHOOTING_WU_DONE_TEMPLATE = `# Troubleshooting: wu:done Not Run
157
+
158
+ **Last updated:** {{DATE}}
159
+
160
+ This is the most common mistake agents make.
161
+
162
+ ---
163
+
164
+ ## The Fix
165
+
166
+ ### Rule: ALWAYS Run wu:done
167
+
168
+ After gates pass, you MUST run:
169
+
170
+ \`\`\`bash
171
+ cd /path/to/main
172
+ pnpm wu:done --id WU-XXX
173
+ \`\`\`
174
+
175
+ Do NOT:
176
+
177
+ - Ask "Should I run wu:done?"
178
+ - Write "To Complete: pnpm wu:done"
179
+ - Wait for permission
180
+
181
+ ---
182
+
183
+ ## What wu:done Does
184
+
185
+ 1. Validates the worktree exists and has commits
186
+ 2. Runs gates in the worktree (not main)
187
+ 3. Fast-forward merges to main
188
+ 4. Creates the done stamp
189
+ 5. Updates status and backlog docs
190
+ 6. Removes the worktree
191
+ 7. Pushes to origin
192
+ `;
193
+ const AGENT_SAFETY_CARD_TEMPLATE = `# Agent Safety Card
194
+
195
+ **Last updated:** {{DATE}}
196
+
197
+ Quick reference for AI agents working in LumenFlow projects.
198
+
199
+ ---
200
+
201
+ ## Stop and Ask When
202
+
203
+ - Same error repeats 3 times
204
+ - Auth or permissions changes needed
205
+ - PII/PHI/secrets involved
206
+ - Cloud spend decisions
207
+
208
+ ---
209
+
210
+ ## Never Do
211
+
212
+ | Action | Why |
213
+ | ------------------------ | ---------------- |
214
+ | \`git reset --hard\` | Data loss |
215
+ | \`git push --force\` | History rewrite |
216
+ | \`--no-verify\` | Bypasses safety |
217
+ | Work in main after claim | Breaks isolation |
218
+ | Skip wu:done | Incomplete WU |
219
+
220
+ ---
221
+
222
+ ## Always Do
223
+
224
+ | Action | Why |
225
+ | -------------------------- | ---------------- |
226
+ | Read WU spec first | Understand scope |
227
+ | cd to worktree after claim | Isolation |
228
+ | Write tests before code | TDD |
229
+ | Run gates before wu:done | Quality |
230
+ | Run wu:done | Complete WU |
231
+ `;
232
+ const WU_CREATE_CHECKLIST_TEMPLATE = `# WU Creation Checklist
233
+
234
+ **Last updated:** {{DATE}}
235
+
236
+ Before running \`pnpm wu:create\`, verify these items.
237
+
238
+ ---
239
+
240
+ ## Step 1: Check Valid Lanes
241
+
242
+ \`\`\`bash
243
+ grep -A 30 "lanes:" .lumenflow.config.yaml
244
+ \`\`\`
245
+
246
+ **Format:** \`"Parent: Sublane"\` (colon + single space)
247
+
248
+ ---
249
+
250
+ ## Step 2: Required Fields
251
+
252
+ | Field | Required For | Example |
253
+ |-------|--------------|---------|
254
+ | \`--id\` | All | \`WU-1234\` |
255
+ | \`--lane\` | All | \`"Experience: Chat"\` |
256
+ | \`--title\` | All | \`"Add feature"\` |
257
+ | \`--description\` | All | \`"Context: ... Problem: ... Solution: ..."\` |
258
+ | \`--acceptance\` | All | \`--acceptance "Works"\` (repeatable) |
259
+ | \`--exposure\` | All | \`ui\`, \`api\`, \`backend-only\`, \`documentation\` |
260
+ | \`--code-paths\` | Code WUs | \`"src/a.ts,src/b.ts"\` |
261
+ | \`--test-paths-unit\` | Code WUs | \`"src/__tests__/a.test.ts"\` |
262
+ | \`--spec-refs\` | Feature WUs | \`"~/.lumenflow/plans/WU-XXX.md"\` |
263
+
264
+ ---
265
+
266
+ ## Step 3: Plan Storage
267
+
268
+ Plans go in \`~/.lumenflow/plans/\` (NOT in project):
269
+
270
+ \`\`\`bash
271
+ mkdir -p ~/.lumenflow/plans
272
+ vim ~/.lumenflow/plans/WU-XXX-plan.md
273
+ \`\`\`
274
+
275
+ Reference in wu:create:
276
+ \`\`\`bash
277
+ --spec-refs "~/.lumenflow/plans/WU-XXX-plan.md"
278
+ \`\`\`
279
+
280
+ ---
281
+
282
+ ## Step 4: Validate First
283
+
284
+ \`\`\`bash
285
+ pnpm wu:create --id WU-XXX ... --validate
286
+ \`\`\`
287
+
288
+ Fix errors, then remove \`--validate\` to create.
289
+ `;
290
+ // Claude skills templates
291
+ const WU_LIFECYCLE_SKILL_TEMPLATE = `---
292
+ name: wu-lifecycle
293
+ description: Work Unit claim/block/done workflow automation.
294
+ version: 1.0.0
295
+ ---
296
+
297
+ # WU Lifecycle Skill
298
+
299
+ ## State Machine
300
+
301
+ \`\`\`
302
+ ready -> in_progress -> waiting/blocked -> done
303
+ \`\`\`
304
+
305
+ ## Core Commands
306
+
307
+ \`\`\`bash
308
+ # Claim WU
309
+ pnpm wu:claim --id WU-XXX --lane <lane>
310
+ cd worktrees/<lane>-wu-xxx # IMMEDIATELY
311
+
312
+ # Complete WU (from main)
313
+ cd ../..
314
+ pnpm wu:done --id WU-XXX
315
+ \`\`\`
316
+ `;
317
+ const WORKTREE_DISCIPLINE_SKILL_TEMPLATE = `---
318
+ name: worktree-discipline
319
+ description: Prevents the "absolute path trap" in Write/Edit/Read tools.
320
+ version: 1.0.0
321
+ ---
322
+
323
+ # Worktree Discipline: Absolute Path Trap Prevention
324
+
325
+ **Purpose**: Prevent AI agents from bypassing worktree isolation via absolute file paths.
326
+
327
+ ## The Absolute Path Trap
328
+
329
+ **Problem**: AI agents using Write/Edit/Read tools can bypass worktree isolation by passing absolute paths.
330
+
331
+ ## Golden Rules
332
+
333
+ 1. **Always verify pwd** before file operations
334
+ 2. **Never use absolute paths** in Write/Edit/Read tools
335
+ 3. **When in doubt, use relative paths**
336
+ `;
337
+ const LUMENFLOW_GATES_SKILL_TEMPLATE = `---
338
+ name: lumenflow-gates
339
+ description: Quality gates troubleshooting (format, lint, typecheck, tests).
340
+ version: 1.0.0
341
+ ---
342
+
343
+ # LumenFlow Gates Skill
344
+
345
+ ## Gate Sequence
346
+
347
+ \`\`\`
348
+ pnpm gates = format:check -> lint -> typecheck -> spec:linter -> tests
349
+ \`\`\`
350
+
351
+ ## Fix Patterns
352
+
353
+ | Gate | Auto-fix | Manual |
354
+ | --------- | --------------- | ----------------------------------- |
355
+ | Format | \`pnpm format\` | - |
356
+ | Lint | \`pnpm lint:fix\` | Fix reported issues |
357
+ | Typecheck | - | Fix type errors (first error first) |
358
+ | Tests | - | Debug, fix mocks, update snapshots |
359
+ `;
360
+ /**
361
+ * Sync agent onboarding docs to an existing project
362
+ */
363
+ export async function syncAgentDocs(targetDir, options) {
364
+ const result = {
365
+ created: [],
366
+ skipped: [],
367
+ };
368
+ const tokens = {
369
+ DATE: getCurrentDate(),
370
+ };
371
+ const onboardingDir = path.join(targetDir, 'docs', '04-operations', '_frameworks', 'lumenflow', 'agent', 'onboarding');
372
+ await createDirectory(onboardingDir, result, targetDir);
373
+ await createFile(path.join(onboardingDir, 'quick-ref-commands.md'), processTemplate(QUICK_REF_COMMANDS_TEMPLATE, tokens), options.force, result, targetDir);
374
+ await createFile(path.join(onboardingDir, 'first-wu-mistakes.md'), processTemplate(FIRST_WU_MISTAKES_TEMPLATE, tokens), options.force, result, targetDir);
375
+ await createFile(path.join(onboardingDir, 'troubleshooting-wu-done.md'), processTemplate(TROUBLESHOOTING_WU_DONE_TEMPLATE, tokens), options.force, result, targetDir);
376
+ await createFile(path.join(onboardingDir, 'agent-safety-card.md'), processTemplate(AGENT_SAFETY_CARD_TEMPLATE, tokens), options.force, result, targetDir);
377
+ await createFile(path.join(onboardingDir, 'wu-create-checklist.md'), processTemplate(WU_CREATE_CHECKLIST_TEMPLATE, tokens), options.force, result, targetDir);
378
+ return result;
379
+ }
380
+ /**
381
+ * Sync Claude skills to an existing project
382
+ */
383
+ export async function syncSkills(targetDir, options) {
384
+ const result = {
385
+ created: [],
386
+ skipped: [],
387
+ };
388
+ const vendor = options.vendor ?? 'none';
389
+ if (vendor !== 'claude' && vendor !== 'all') {
390
+ return result;
391
+ }
392
+ const tokens = {
393
+ DATE: getCurrentDate(),
394
+ };
395
+ const skillsDir = path.join(targetDir, '.claude', 'skills');
396
+ // wu-lifecycle skill
397
+ const wuLifecycleDir = path.join(skillsDir, 'wu-lifecycle');
398
+ await createDirectory(wuLifecycleDir, result, targetDir);
399
+ await createFile(path.join(wuLifecycleDir, 'SKILL.md'), processTemplate(WU_LIFECYCLE_SKILL_TEMPLATE, tokens), options.force, result, targetDir);
400
+ // worktree-discipline skill
401
+ const worktreeDir = path.join(skillsDir, 'worktree-discipline');
402
+ await createDirectory(worktreeDir, result, targetDir);
403
+ await createFile(path.join(worktreeDir, 'SKILL.md'), processTemplate(WORKTREE_DISCIPLINE_SKILL_TEMPLATE, tokens), options.force, result, targetDir);
404
+ // lumenflow-gates skill
405
+ const gatesDir = path.join(skillsDir, 'lumenflow-gates');
406
+ await createDirectory(gatesDir, result, targetDir);
407
+ await createFile(path.join(gatesDir, 'SKILL.md'), processTemplate(LUMENFLOW_GATES_SKILL_TEMPLATE, tokens), options.force, result, targetDir);
408
+ return result;
409
+ }
410
+ /**
411
+ * Parse vendor flag from arguments
412
+ */
413
+ function parseVendorArg(args) {
414
+ const vendorIndex = args.findIndex((arg) => arg === '--vendor');
415
+ if (vendorIndex !== -1 && args[vendorIndex + 1]) {
416
+ const vendor = args[vendorIndex + 1].toLowerCase();
417
+ if (['claude', 'cursor', 'aider', 'all', 'none'].includes(vendor)) {
418
+ return vendor;
419
+ }
420
+ }
421
+ return undefined;
422
+ }
423
+ /**
424
+ * CLI entry point for docs:sync command
425
+ */
426
+ export async function main() {
427
+ const args = process.argv.slice(2);
428
+ const force = args.includes('--force') || args.includes('-f');
429
+ const vendor = parseVendorArg(args) ?? 'claude'; // Default to claude
430
+ const targetDir = process.cwd();
431
+ console.log('[lumenflow docs:sync] Syncing agent documentation...');
432
+ console.log(` Vendor: ${vendor}`);
433
+ console.log(` Force: ${force}`);
434
+ const docsResult = await syncAgentDocs(targetDir, { force });
435
+ const skillsResult = await syncSkills(targetDir, { force, vendor });
436
+ const created = [...docsResult.created, ...skillsResult.created];
437
+ const skipped = [...docsResult.skipped, ...skillsResult.skipped];
438
+ if (created.length > 0) {
439
+ console.log('\nCreated:');
440
+ created.forEach((f) => console.log(` + ${f}`));
441
+ }
442
+ if (skipped.length > 0) {
443
+ console.log('\nSkipped (already exists, use --force to overwrite):');
444
+ skipped.forEach((f) => console.log(` - ${f}`));
445
+ }
446
+ console.log('\n[lumenflow docs:sync] Done!');
447
+ }
448
+ // CLI entry point (WU-1071 pattern: import.meta.main)
449
+ import { runCLI } from './cli-entry-point.js';
450
+ if (import.meta.main) {
451
+ runCLI(main);
452
+ }
package/dist/init.js CHANGED
@@ -118,6 +118,773 @@ const WU_TEMPLATE_YAML = `# Work Unit Template (LumenFlow WU Schema)\n#\n# Copy
118
118
  const FRAMEWORK_HINT_TEMPLATE = `# LumenFlow Framework Hint\n# Generated by: lumenflow init --framework {{FRAMEWORK_NAME}}\n\nframework: "{{FRAMEWORK_NAME}}"\nslug: "{{FRAMEWORK_SLUG}}"\n`;
119
119
  // Template for docs/04-operations/_frameworks/<framework>/README.md
120
120
  const FRAMEWORK_OVERLAY_TEMPLATE = `# {{FRAMEWORK_NAME}} Framework Overlay\n\n**Last updated:** {{DATE}}\n\nThis overlay captures framework-specific conventions, constraints, and references for {{FRAMEWORK_NAME}} projects.\n\n## Scope\n\n- Project structure conventions\n- Framework-specific testing guidance\n- Common pitfalls and mitigations\n\n## References\n\n- Add official docs links here\n`;
121
+ // WU-1083: Agent onboarding docs templates
122
+ const QUICK_REF_COMMANDS_TEMPLATE = `# Quick Reference: LumenFlow Commands
123
+
124
+ **Last updated:** {{DATE}}
125
+
126
+ ---
127
+
128
+ ## Project Setup
129
+
130
+ | Command | Description |
131
+ | --------------------------------------------- | --------------------------------------- |
132
+ | \`pnpm exec lumenflow init\` | Scaffold minimal LumenFlow core |
133
+ | \`pnpm exec lumenflow init --full\` | Add docs/04-operations task scaffolding |
134
+ | \`pnpm exec lumenflow init --framework <name>\` | Add framework hint + overlay docs |
135
+ | \`pnpm exec lumenflow init --force\` | Overwrite existing files |
136
+
137
+ ---
138
+
139
+ ## WU Management
140
+
141
+ | Command | Description |
142
+ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------- |
143
+ | \`pnpm wu:create --id WU-XXX --lane <Lane> --title "Title" --description "..." --acceptance "..." --code-paths "path" --test-paths-unit "path" --exposure backend-only --spec-refs "~/.lumenflow/plans/WU-XXX.md"\` | Create new WU |
144
+ | \`pnpm wu:claim --id WU-XXX --lane <Lane>\` | Claim WU (creates worktree) |
145
+ | \`pnpm wu:done --id WU-XXX\` | Complete WU (merge, stamp, cleanup) |
146
+ | \`pnpm wu:block --id WU-XXX --reason "Reason"\` | Block a WU |
147
+ | \`pnpm wu:unblock --id WU-XXX\` | Unblock a WU |
148
+
149
+ ---
150
+
151
+ ## Gates
152
+
153
+ | Command | Description |
154
+ | ------------------------ | -------------------------- |
155
+ | \`pnpm gates\` | Run all quality gates |
156
+ | \`pnpm gates --docs-only\` | Run gates for docs changes |
157
+ | \`pnpm format\` | Format all files |
158
+ | \`pnpm lint\` | Run linter |
159
+ | \`pnpm typecheck\` | Run TypeScript check |
160
+ | \`pnpm test\` | Run tests |
161
+
162
+ ---
163
+
164
+ ## Git (Safe Operations)
165
+
166
+ | Command | Description |
167
+ | ------------------------------------ | ------------------------- |
168
+ | \`git status\` | Check working tree status |
169
+ | \`git add .\` | Stage all changes |
170
+ | \`git commit -m "type: message"\` | Commit with message |
171
+ | \`git push origin lane/<lane>/wu-xxx\` | Push to remote |
172
+
173
+ ---
174
+
175
+ ## Navigation
176
+
177
+ \`\`\`bash
178
+ # After claiming, go to worktree
179
+ cd worktrees/<lane>-wu-xxx
180
+
181
+ # Return to main for wu:done
182
+ cd /path/to/main
183
+ \`\`\`
184
+
185
+ ---
186
+
187
+ ## Workflow Sequence
188
+
189
+ \`\`\`bash
190
+ # 1. Create
191
+ pnpm wu:create --id WU-001 --lane "Framework: Core" --title "Add feature" \\
192
+ --description "Context: ...\\nProblem: ...\\nSolution: ..." \\
193
+ --acceptance "Criterion 1" --acceptance "Criterion 2" \\
194
+ --code-paths "src/example.ts" \\
195
+ --test-paths-unit "src/__tests__/example.test.ts" \\
196
+ --exposure backend-only
197
+
198
+ # 2. Claim
199
+ pnpm wu:claim --id WU-001 --lane "Framework: Core"
200
+ cd worktrees/framework-core-wu-001
201
+
202
+ # 3. Work (TDD)
203
+ # ... write tests first, then code ...
204
+
205
+ # 4. Commit
206
+ git add .
207
+ git commit -m "feat: add feature"
208
+ git push origin lane/framework-core/wu-001
209
+
210
+ # 5. Gates
211
+ pnpm gates
212
+
213
+ # 6. Complete
214
+ cd /path/to/main
215
+ pnpm wu:done --id WU-001
216
+ \`\`\`
217
+
218
+ ---
219
+
220
+ ## File Paths
221
+
222
+ | Path | Description |
223
+ | ----------------------------------------- | -------------------- |
224
+ | \`docs/04-operations/tasks/wu/WU-XXX.yaml\` | WU specification |
225
+ | \`docs/04-operations/tasks/status.md\` | Current status board |
226
+ | \`.lumenflow/stamps/WU-XXX.done\` | Completion stamp |
227
+ | \`worktrees/<lane>-wu-xxx/\` | Worktree directory |
228
+ `;
229
+ const FIRST_WU_MISTAKES_TEMPLATE = `# First WU Mistakes
230
+
231
+ **Last updated:** {{DATE}}
232
+
233
+ Common mistakes agents make on their first WU, and how to avoid them.
234
+
235
+ ---
236
+
237
+ ## Mistake 1: Not Using Worktrees
238
+
239
+ ### Wrong
240
+
241
+ \`\`\`bash
242
+ # Working directly in main
243
+ vim src/feature.ts
244
+ git commit -m "feat: add feature"
245
+ git push origin main
246
+ \`\`\`
247
+
248
+ ### Right
249
+
250
+ \`\`\`bash
251
+ # Claim first, then work in worktree
252
+ pnpm wu:claim --id WU-123 --lane Core
253
+ cd worktrees/core-wu-123
254
+ vim src/feature.ts
255
+ git commit -m "feat: add feature"
256
+ git push origin lane/core/wu-123
257
+ cd /path/to/main
258
+ pnpm wu:done --id WU-123
259
+ \`\`\`
260
+
261
+ ---
262
+
263
+ ## Mistake 2: Forgetting to Run wu:done
264
+
265
+ See [troubleshooting-wu-done.md](troubleshooting-wu-done.md) for the full explanation.
266
+
267
+ **TL;DR:** After gates pass, ALWAYS run \`pnpm wu:done --id WU-XXX\`.
268
+
269
+ ---
270
+
271
+ ## Mistake 3: Working Outside code_paths
272
+
273
+ ### Wrong
274
+
275
+ The WU says \`code_paths: [src/api/**]\` but you edit \`src/ui/component.ts\`.
276
+
277
+ ### Right
278
+
279
+ Only edit files within the specified \`code_paths\`. If you need to edit other files, that's a different WU.
280
+
281
+ ---
282
+
283
+ ## Mistake 4: Skipping TDD
284
+
285
+ ### Wrong
286
+
287
+ \`\`\`
288
+ 1. Write the feature
289
+ 2. Maybe write tests later
290
+ 3. Tests are hard, skip them
291
+ \`\`\`
292
+
293
+ ### Right
294
+
295
+ \`\`\`
296
+ 1. Write failing test
297
+ 2. Run test (confirm RED)
298
+ 3. Write minimum code
299
+ 4. Run test (confirm GREEN)
300
+ 5. Refactor if needed
301
+ \`\`\`
302
+
303
+ ---
304
+
305
+ ## Mistake 5: Using Forbidden Git Commands
306
+
307
+ ### Wrong
308
+
309
+ \`\`\`bash
310
+ git reset --hard HEAD
311
+ git push --force
312
+ git commit --no-verify
313
+ \`\`\`
314
+
315
+ ### Right
316
+
317
+ \`\`\`bash
318
+ git add .
319
+ git commit -m "feat: description"
320
+ git push origin lane/core/wu-123
321
+ \`\`\`
322
+
323
+ ---
324
+
325
+ ## Mistake 6: Ignoring Gate Failures
326
+
327
+ ### Wrong
328
+
329
+ \`\`\`
330
+ Gates failed but I think the code is fine.
331
+ Let me use --skip-gates.
332
+ \`\`\`
333
+
334
+ ### Right
335
+
336
+ \`\`\`
337
+ Gates failed. Let me read the error:
338
+ - TypeScript error in src/api/handler.ts
339
+ - Missing return type
340
+
341
+ Fix: Add the return type.
342
+ Re-run: pnpm gates
343
+ \`\`\`
344
+
345
+ ---
346
+
347
+ ## Quick Checklist
348
+
349
+ Before starting any WU:
350
+
351
+ - [ ] Read the full WU spec
352
+ - [ ] Understand acceptance criteria
353
+ - [ ] Claim the WU with \`pnpm wu:claim\`
354
+ - [ ] cd to the worktree IMMEDIATELY
355
+ - [ ] Work only in the worktree
356
+ - [ ] Stay within code_paths
357
+ - [ ] Follow TDD
358
+ - [ ] Run gates before wu:done
359
+ - [ ] ALWAYS run wu:done
360
+ `;
361
+ const TROUBLESHOOTING_WU_DONE_TEMPLATE = `# Troubleshooting: wu:done Not Run
362
+
363
+ **Last updated:** {{DATE}}
364
+
365
+ This is the most common mistake agents make. This document explains why it happens and how to fix it.
366
+
367
+ ---
368
+
369
+ ## The Problem
370
+
371
+ Agents complete their work, write "To Complete: pnpm wu:done --id WU-XXX" in their response, and then **stop without actually running the command**.
372
+
373
+ ### Why This Happens
374
+
375
+ 1. **Confusion about scope**: Agent thinks completion is a "next step" for the human
376
+ 2. **Fear of overstepping**: Agent hesitates to take "final" actions
377
+ 3. **Missing context**: Agent doesn't realize wu:done is expected to be run immediately
378
+ 4. **Token limits**: Agent runs out of context and summarizes remaining steps
379
+
380
+ ---
381
+
382
+ ## The Fix
383
+
384
+ ### Rule: ALWAYS Run wu:done
385
+
386
+ After gates pass, you MUST run:
387
+
388
+ \`\`\`bash
389
+ cd /path/to/main
390
+ pnpm wu:done --id WU-XXX
391
+ \`\`\`
392
+
393
+ Do NOT:
394
+
395
+ - Ask "Should I run wu:done?"
396
+ - Write "To Complete: pnpm wu:done"
397
+ - Wait for permission
398
+ - Treat it as a "future step"
399
+
400
+ ---
401
+
402
+ ## Correct Completion Flow
403
+
404
+ \`\`\`bash
405
+ # 1. In worktree, run gates
406
+ pnpm gates
407
+
408
+ # 2. If gates pass, return to main
409
+ cd /path/to/main
410
+
411
+ # 3. IMMEDIATELY run wu:done
412
+ pnpm wu:done --id WU-XXX
413
+
414
+ # 4. Report success with the wu:done output
415
+ \`\`\`
416
+
417
+ ---
418
+
419
+ ## What wu:done Does
420
+
421
+ When you run \`pnpm wu:done --id WU-XXX\`:
422
+
423
+ 1. Validates the worktree exists and has commits
424
+ 2. Runs gates in the worktree (not main)
425
+ 3. Fast-forward merges to main
426
+ 4. Creates the done stamp
427
+ 5. Updates status and backlog docs
428
+ 6. Removes the worktree
429
+ 7. Pushes to origin
430
+
431
+ **This is the ONLY way to complete a WU.** Manual steps will leave things in an inconsistent state.
432
+
433
+ ---
434
+
435
+ ## Symptoms of Incomplete WU
436
+
437
+ If wu:done wasn't run, you'll see:
438
+
439
+ - Worktree still exists: \`ls worktrees/\`
440
+ - No stamp: \`ls .lumenflow/stamps/WU-XXX.done\` returns nothing
441
+ - Status unchanged: WU still shows as \`in_progress\`
442
+ - Branch not merged: Changes only on lane branch
443
+
444
+ ---
445
+
446
+ ## Recovery
447
+
448
+ If a previous agent forgot to run wu:done:
449
+
450
+ \`\`\`bash
451
+ # 1. Check worktree exists
452
+ ls worktrees/
453
+
454
+ # 2. If it does, run wu:done
455
+ pnpm wu:done --id WU-XXX
456
+ \`\`\`
457
+
458
+ ---
459
+
460
+ ## Checklist Before Ending Session
461
+
462
+ - [ ] Did I run \`pnpm gates\` in the worktree?
463
+ - [ ] Did gates pass?
464
+ - [ ] Did I \`cd\` back to main?
465
+ - [ ] Did I run \`pnpm wu:done --id WU-XXX\`?
466
+ - [ ] Did wu:done complete successfully?
467
+
468
+ If any answer is "no", you're not done yet.
469
+ `;
470
+ const AGENT_SAFETY_CARD_TEMPLATE = `# Agent Safety Card
471
+
472
+ **Last updated:** {{DATE}}
473
+
474
+ Quick reference for AI agents working in LumenFlow projects.
475
+
476
+ ---
477
+
478
+ ## Stop and Ask When
479
+
480
+ - Same error repeats 3 times
481
+ - Auth or permissions changes needed
482
+ - PII/PHI/secrets involved
483
+ - Cloud spend decisions
484
+ - Policy changes required
485
+ - Anything feels irreversible
486
+
487
+ ---
488
+
489
+ ## Never Do
490
+
491
+ | Action | Why |
492
+ | ------------------------ | ---------------- |
493
+ | \`git reset --hard\` | Data loss |
494
+ | \`git push --force\` | History rewrite |
495
+ | \`--no-verify\` | Bypasses safety |
496
+ | \`git stash\` (on main) | Hides work |
497
+ | \`git clean -fd\` | Deletes files |
498
+ | Work in main after claim | Breaks isolation |
499
+ | Skip wu:done | Incomplete WU |
500
+
501
+ ---
502
+
503
+ ## Always Do
504
+
505
+ | Action | Why |
506
+ | -------------------------- | ---------------- |
507
+ | Read WU spec first | Understand scope |
508
+ | cd to worktree after claim | Isolation |
509
+ | Write tests before code | TDD |
510
+ | Run gates before wu:done | Quality |
511
+ | Run wu:done | Complete WU |
512
+ | Stay within code_paths | Scope discipline |
513
+
514
+ ---
515
+
516
+ ## Error Handling
517
+
518
+ ### Max 3 Attempts
519
+
520
+ If same error happens 3 times:
521
+
522
+ 1. Stop trying
523
+ 2. Document what happened
524
+ 3. Ask for help
525
+
526
+ ### Gate Failures
527
+
528
+ 1. Read the error message
529
+ 2. Fix the underlying issue
530
+ 3. Re-run gates
531
+ 4. Never use \`--skip-gates\` for new failures
532
+
533
+ ---
534
+
535
+ ## Quick Commands
536
+
537
+ \`\`\`bash
538
+ # Check lane availability
539
+ cat docs/04-operations/tasks/status.md
540
+
541
+ # Claim a WU
542
+ pnpm wu:claim --id WU-XXX --lane <Lane>
543
+
544
+ # Work in worktree
545
+ cd worktrees/<lane>-wu-xxx
546
+
547
+ # Run gates
548
+ pnpm gates # Code changes
549
+ pnpm gates --docs-only # Docs changes
550
+
551
+ # Complete WU
552
+ cd /path/to/main
553
+ pnpm wu:done --id WU-XXX
554
+ \`\`\`
555
+
556
+ ---
557
+
558
+ ## Completion Checklist
559
+
560
+ - [ ] Gates pass
561
+ - [ ] cd to main
562
+ - [ ] Run wu:done
563
+ - [ ] Verify success output
564
+ - [ ] Report completion
565
+
566
+ ---
567
+
568
+ ## When Uncertain
569
+
570
+ Choose the safer path:
571
+
572
+ - Don't modify files outside code_paths
573
+ - Don't bypass hooks
574
+ - Don't skip gates
575
+ - Ask rather than assume
576
+ `;
577
+ const WU_CREATE_CHECKLIST_TEMPLATE = `# WU Creation Checklist
578
+
579
+ **Last updated:** {{DATE}}
580
+
581
+ Before running \`pnpm wu:create\`, verify these items.
582
+
583
+ ---
584
+
585
+ ## Step 1: Check Valid Lanes
586
+
587
+ \`\`\`bash
588
+ grep -A 30 "lanes:" .lumenflow.config.yaml
589
+ \`\`\`
590
+
591
+ **Format:** \`"Parent: Sublane"\` (colon + single space)
592
+
593
+ Examples:
594
+ - \`"Framework: CLI"\`
595
+ - \`"Framework: Core"\`
596
+ - \`"Operations: CI/CD"\`
597
+ - \`"Content: Documentation"\`
598
+
599
+ ---
600
+
601
+ ## Step 2: Required Fields
602
+
603
+ | Field | Required For | Example |
604
+ |-------|--------------|---------|
605
+ | \`--id\` | All | \`WU-1234\` |
606
+ | \`--lane\` | All | \`"Experience: Chat"\` |
607
+ | \`--title\` | All | \`"Add feature"\` |
608
+ | \`--description\` | All | \`"Context: ... Problem: ... Solution: ..."\` |
609
+ | \`--acceptance\` | All | \`--acceptance "Works"\` (repeatable) |
610
+ | \`--exposure\` | All | \`ui\`, \`api\`, \`backend-only\`, \`documentation\` |
611
+ | \`--code-paths\` | Code WUs | \`"src/a.ts,src/b.ts"\` |
612
+ | \`--test-paths-unit\` | Code WUs | \`"src/__tests__/a.test.ts"\` |
613
+ | \`--spec-refs\` | Feature WUs | \`"~/.lumenflow/plans/WU-XXX.md"\` |
614
+
615
+ ---
616
+
617
+ ## Step 3: Plan Storage
618
+
619
+ Plans go in \`~/.lumenflow/plans/\` (NOT in project):
620
+
621
+ \`\`\`bash
622
+ mkdir -p ~/.lumenflow/plans
623
+ # Create your plan
624
+ vim ~/.lumenflow/plans/WU-XXX-plan.md
625
+ \`\`\`
626
+
627
+ Reference in wu:create:
628
+ \`\`\`bash
629
+ --spec-refs "~/.lumenflow/plans/WU-XXX-plan.md"
630
+ \`\`\`
631
+
632
+ ---
633
+
634
+ ## Step 4: Validate First
635
+
636
+ \`\`\`bash
637
+ pnpm wu:create --id WU-XXX ... --validate
638
+ \`\`\`
639
+
640
+ Fix errors, then remove \`--validate\` to create.
641
+
642
+ ---
643
+
644
+ ## Complete Example
645
+
646
+ \`\`\`bash
647
+ pnpm wu:create \\
648
+ --id WU-1234 \\
649
+ --lane "Framework: CLI" \\
650
+ --title "Add feature X" \\
651
+ --description "Context: Users need X. Problem: X doesn't exist. Solution: Add X." \\
652
+ --acceptance "Feature X works as specified" \\
653
+ --acceptance "Unit tests pass with >90% coverage" \\
654
+ --code-paths "packages/@lumenflow/cli/src/x.ts" \\
655
+ --test-paths-unit "packages/@lumenflow/cli/__tests__/x.test.ts" \\
656
+ --exposure backend-only \\
657
+ --spec-refs "~/.lumenflow/plans/WU-1234-plan.md"
658
+ \`\`\`
659
+
660
+ ---
661
+
662
+ ## Common Errors
663
+
664
+ ### "Lane format invalid"
665
+
666
+ **Cause:** Missing colon or space in lane format.
667
+
668
+ **Fix:** Use \`"Parent: Sublane"\` format (colon + space).
669
+
670
+ ### "Missing required field"
671
+
672
+ **Cause:** Required field not provided.
673
+
674
+ **Fix:** Add the missing \`--field\` argument.
675
+
676
+ ### "WU already exists"
677
+
678
+ **Cause:** WU with this ID already exists.
679
+
680
+ **Fix:** Use a different ID or check existing WUs.
681
+
682
+ ---
683
+
684
+ ## After Creation
685
+
686
+ 1. Review the created YAML: \`cat docs/04-operations/tasks/wu/WU-XXX.yaml\`
687
+ 2. Claim the WU: \`pnpm wu:claim --id WU-XXX --lane "Lane"\`
688
+ 3. cd to worktree: \`cd worktrees/<lane>-wu-xxx\`
689
+ `;
690
+ // WU-1083: Claude skills templates
691
+ const WU_LIFECYCLE_SKILL_TEMPLATE = `---
692
+ name: wu-lifecycle
693
+ description: Work Unit claim/block/done workflow automation.
694
+ version: 1.0.0
695
+ ---
696
+
697
+ # WU Lifecycle Skill
698
+
699
+ ## When to Use
700
+
701
+ Activate this skill when:
702
+
703
+ - Claiming a WU (\`pnpm wu:claim\`)
704
+ - Blocking/unblocking WUs due to dependencies
705
+ - Running \`wu:done\` completion workflow
706
+ - Understanding WU state machine transitions
707
+
708
+ ## State Machine
709
+
710
+ \`\`\`
711
+ ready -> in_progress -> waiting/blocked -> done
712
+ \`\`\`
713
+
714
+ ## Core Commands
715
+
716
+ \`\`\`bash
717
+ # Claim WU
718
+ pnpm wu:claim --id WU-XXX --lane <lane>
719
+ cd worktrees/<lane>-wu-xxx # IMMEDIATELY
720
+
721
+ # Complete WU (from main)
722
+ cd ../..
723
+ pnpm wu:done --id WU-XXX
724
+
725
+ # Block/Unblock
726
+ pnpm wu:block --id WU-XXX --reason "..."
727
+ pnpm wu:unblock --id WU-XXX
728
+
729
+ # Create (full spec)
730
+ pnpm wu:create --id WU-999 --lane "Operations" --title "Add feature" \\
731
+ --description "Context: ... Problem: ... Solution: ..." \\
732
+ --acceptance "Feature works" --code-paths "src/a.ts" --validate
733
+ \`\`\`
734
+
735
+ ## wu:done Workflow
736
+
737
+ 1. Runs gates in worktree
738
+ 2. Fast-forward merge to main
739
+ 3. Creates \`.lumenflow/stamps/WU-XXX.done\`
740
+ 4. Updates backlog.md + status.md
741
+ 5. Removes worktree
742
+
743
+ ## Worktree Discipline
744
+
745
+ After \`wu:claim\`:
746
+
747
+ - \`cd worktrees/<lane>-wu-xxx\` immediately
748
+ - Use relative paths (never absolute)
749
+ - Main is read-only
750
+ `;
751
+ const WORKTREE_DISCIPLINE_SKILL_TEMPLATE = `---
752
+ name: worktree-discipline
753
+ description: Prevents the "absolute path trap" in Write/Edit/Read tools.
754
+ version: 1.0.0
755
+ ---
756
+
757
+ # Worktree Discipline: Absolute Path Trap Prevention
758
+
759
+ **Purpose**: Prevent AI agents from bypassing worktree isolation via absolute file paths.
760
+
761
+ ## The Absolute Path Trap
762
+
763
+ **Problem**: AI agents using Write/Edit/Read tools can bypass worktree isolation by passing absolute paths. Even when your shell is in the worktree, absolute paths target the main checkout.
764
+
765
+ ### Example
766
+
767
+ \`\`\`typescript
768
+ // Shell: cd worktrees/operations-wu-427
769
+
770
+ // WRONG - Absolute path bypasses worktree
771
+ Write({
772
+ file_path: '/home/user/source/project/apps/web/src/validator.ts',
773
+ content: '...',
774
+ });
775
+ // Result: Written to MAIN checkout, not worktree!
776
+
777
+ // RIGHT - Relative path respects worktree
778
+ Write({
779
+ file_path: 'apps/web/src/validator.ts',
780
+ content: '...',
781
+ });
782
+ // Result: Written to worktree correctly
783
+ \`\`\`
784
+
785
+ ## Pre-Operation Checklist
786
+
787
+ **Before ANY Write/Edit/Read operation:**
788
+
789
+ 1. **Verify working directory**:
790
+
791
+ \`\`\`bash
792
+ pwd
793
+ # Must show: .../worktrees/<lane>-wu-xxx
794
+ \`\`\`
795
+
796
+ 2. **Check file path format**:
797
+
798
+ | Pattern | Safe? | Example |
799
+ | --------------------------------- | ----- | ------------------------ |
800
+ | Starts with \`/home/\` or \`/Users/\` | NO | \`/home/user/.../file.ts\` |
801
+ | Contains full repo path | NO | \`/source/project/...\` |
802
+ | Starts with package name | YES | \`apps/web/src/...\` |
803
+ | Starts with \`./\` or \`../\` | YES | \`./src/lib/...\` |
804
+ | Just filename | YES | \`README.md\` |
805
+
806
+ 3. **Use relative paths for ALL file operations**
807
+
808
+ ## Golden Rules
809
+
810
+ 1. **Always verify pwd** before file operations
811
+ 2. **Never use absolute paths** in Write/Edit/Read tools
812
+ 3. **When in doubt, use relative paths**
813
+ `;
814
+ const LUMENFLOW_GATES_SKILL_TEMPLATE = `---
815
+ name: lumenflow-gates
816
+ description: Quality gates troubleshooting (format, lint, typecheck, tests).
817
+ version: 1.0.0
818
+ ---
819
+
820
+ # LumenFlow Gates Skill
821
+
822
+ ## When to Use
823
+
824
+ Activate this skill when:
825
+
826
+ - \`pnpm gates\` fails with format, lint, or typecheck errors
827
+ - Need to determine if failure is from your changes vs pre-existing
828
+ - Debugging test failures or coverage issues
829
+ - Deciding whether to use \`--skip-gates\` (emergency only)
830
+
831
+ ## Gate Sequence
832
+
833
+ \`\`\`
834
+ pnpm gates = format:check -> lint -> typecheck -> spec:linter -> tests
835
+ \`\`\`
836
+
837
+ ## Fix Patterns
838
+
839
+ | Gate | Auto-fix | Manual |
840
+ | --------- | --------------- | ----------------------------------- |
841
+ | Format | \`pnpm format\` | - |
842
+ | Lint | \`pnpm lint:fix\` | Fix reported issues |
843
+ | Typecheck | - | Fix type errors (first error first) |
844
+ | Tests | - | Debug, fix mocks, update snapshots |
845
+
846
+ ## Decision Tree
847
+
848
+ **Gate failed. Is it from YOUR changes?**
849
+
850
+ \`\`\`bash
851
+ git checkout main && pnpm gates # Check main
852
+ # Pass on main -> Your change caused it -> Fix it
853
+ # Fail on main -> Pre-existing -> Consider --skip-gates
854
+ \`\`\`
855
+
856
+ **Can you fix it?**
857
+
858
+ - In your \`code_paths\`, <=10 lines -> Fix in place
859
+ - Different paths, >10 lines -> Create Bug WU
860
+
861
+ ## Skip Gates (Emergency)
862
+
863
+ Only when pre-existing failures:
864
+
865
+ \`\`\`bash
866
+ pnpm wu:done --id WU-XXX --skip-gates --reason "Pre-existing" --fix-wu WU-YYY
867
+ \`\`\`
868
+
869
+ ## Common Lint Fixes
870
+
871
+ \`\`\`
872
+ no-explicit-any -> Add proper types
873
+ no-unused-vars -> Remove or prefix with _
874
+ no-restricted-paths -> Check hex boundaries
875
+ exhaustive-deps -> Add missing dependencies
876
+ \`\`\`
877
+
878
+ ## Validation Commands
879
+
880
+ \`\`\`bash
881
+ pnpm gates # All gates
882
+ pnpm gates -- --docs-only # Docs WUs
883
+ pnpm format # Fix formatting
884
+ pnpm lint:fix # Fix lint issues
885
+ pnpm typecheck # Check types
886
+ \`\`\`
887
+ `;
121
888
  /**
122
889
  * Detect default client from environment
123
890
  */
@@ -232,6 +999,38 @@ async function scaffoldFullDocs(targetDir, options, result, tokens) {
232
999
  await createFile(path.join(tasksDir, 'backlog.md'), BACKLOG_TEMPLATE, options.force, result, targetDir);
233
1000
  await createFile(path.join(tasksDir, 'status.md'), STATUS_TEMPLATE, options.force, result, targetDir);
234
1001
  await createFile(path.join(templatesDir, 'wu-template.yaml'), processTemplate(WU_TEMPLATE_YAML, tokens), options.force, result, targetDir);
1002
+ // WU-1083: Scaffold agent onboarding docs with --full
1003
+ await scaffoldAgentOnboardingDocs(targetDir, options, result, tokens);
1004
+ }
1005
+ /**
1006
+ * WU-1083: Scaffold agent onboarding documentation
1007
+ */
1008
+ async function scaffoldAgentOnboardingDocs(targetDir, options, result, tokens) {
1009
+ const onboardingDir = path.join(targetDir, 'docs', '04-operations', '_frameworks', 'lumenflow', 'agent', 'onboarding');
1010
+ await createDirectory(onboardingDir, result, targetDir);
1011
+ await createFile(path.join(onboardingDir, 'quick-ref-commands.md'), processTemplate(QUICK_REF_COMMANDS_TEMPLATE, tokens), options.force, result, targetDir);
1012
+ await createFile(path.join(onboardingDir, 'first-wu-mistakes.md'), processTemplate(FIRST_WU_MISTAKES_TEMPLATE, tokens), options.force, result, targetDir);
1013
+ await createFile(path.join(onboardingDir, 'troubleshooting-wu-done.md'), processTemplate(TROUBLESHOOTING_WU_DONE_TEMPLATE, tokens), options.force, result, targetDir);
1014
+ await createFile(path.join(onboardingDir, 'agent-safety-card.md'), processTemplate(AGENT_SAFETY_CARD_TEMPLATE, tokens), options.force, result, targetDir);
1015
+ await createFile(path.join(onboardingDir, 'wu-create-checklist.md'), processTemplate(WU_CREATE_CHECKLIST_TEMPLATE, tokens), options.force, result, targetDir);
1016
+ }
1017
+ /**
1018
+ * WU-1083: Scaffold Claude skills
1019
+ */
1020
+ async function scaffoldClaudeSkills(targetDir, options, result, tokens) {
1021
+ const skillsDir = path.join(targetDir, '.claude', 'skills');
1022
+ // wu-lifecycle skill
1023
+ const wuLifecycleDir = path.join(skillsDir, 'wu-lifecycle');
1024
+ await createDirectory(wuLifecycleDir, result, targetDir);
1025
+ await createFile(path.join(wuLifecycleDir, 'SKILL.md'), processTemplate(WU_LIFECYCLE_SKILL_TEMPLATE, tokens), options.force, result, targetDir);
1026
+ // worktree-discipline skill
1027
+ const worktreeDir = path.join(skillsDir, 'worktree-discipline');
1028
+ await createDirectory(worktreeDir, result, targetDir);
1029
+ await createFile(path.join(worktreeDir, 'SKILL.md'), processTemplate(WORKTREE_DISCIPLINE_SKILL_TEMPLATE, tokens), options.force, result, targetDir);
1030
+ // lumenflow-gates skill
1031
+ const gatesDir = path.join(skillsDir, 'lumenflow-gates');
1032
+ await createDirectory(gatesDir, result, targetDir);
1033
+ await createFile(path.join(gatesDir, 'SKILL.md'), processTemplate(LUMENFLOW_GATES_SKILL_TEMPLATE, tokens), options.force, result, targetDir);
235
1034
  }
236
1035
  async function scaffoldFrameworkOverlay(targetDir, options, result, tokens) {
237
1036
  if (!options.framework) {
@@ -258,6 +1057,10 @@ async function scaffoldVendorFiles(targetDir, options, result, tokens, vendor) {
258
1057
  await createDirectory(path.join(targetDir, CLAUDE_AGENTS_DIR), result, targetDir);
259
1058
  await createFile(path.join(targetDir, CLAUDE_AGENTS_DIR, '.gitkeep'), '', options.force, result, targetDir);
260
1059
  await createFile(path.join(targetDir, CLAUDE_DIR, 'settings.json'), CLAUDE_SETTINGS_TEMPLATE, options.force, result, targetDir);
1060
+ // WU-1083: Scaffold Claude skills
1061
+ await scaffoldClaudeSkills(targetDir, options, result, tokens);
1062
+ // WU-1083: Scaffold agent onboarding docs for Claude vendor (even without --full)
1063
+ await scaffoldAgentOnboardingDocs(targetDir, options, result, tokens);
261
1064
  }
262
1065
  // Cursor
263
1066
  if (vendor === 'cursor' || vendor === 'all') {
package/dist/wu-done.js CHANGED
@@ -534,6 +534,32 @@ async function ensureCleanWorkingTree() {
534
534
  ` - Leftover changes from previous session`);
535
535
  }
536
536
  }
537
+ /**
538
+ * WU-1084: Check for uncommitted changes on main after merge completes.
539
+ *
540
+ * This catches cases where pnpm format (or other tooling) touched files
541
+ * outside the WU's code_paths during worktree work. These changes survive
542
+ * the merge and would be silently left behind when the worktree is removed.
543
+ *
544
+ * @param gitStatus - Output from git status (porcelain format)
545
+ * @param wuId - The WU ID for error messaging
546
+ * @returns Object with isDirty flag and optional error message
547
+ */
548
+ export function checkPostMergeDirtyState(gitStatus, wuId) {
549
+ const trimmedStatus = gitStatus.trim();
550
+ if (!trimmedStatus) {
551
+ return { isDirty: false };
552
+ }
553
+ const error = `Main branch has uncommitted changes after merge:\n\n${trimmedStatus}\n\n` +
554
+ `This indicates files were modified outside the WU's code_paths.\n` +
555
+ `Common cause: pnpm format touched files outside the WU scope.\n\n` +
556
+ `The worktree has NOT been removed to allow investigation.\n\n` +
557
+ `Options:\n` +
558
+ ` 1. Review and commit the changes: git add . && git commit -m "format: fix formatting"\n` +
559
+ ` 2. Discard if unwanted: git checkout -- .\n` +
560
+ ` 3. Then re-run: pnpm wu:done --id ${wuId} --skip-worktree-completion`;
561
+ return { isDirty: true, error };
562
+ }
537
563
  /**
538
564
  * Extract completed WU IDs from git log output.
539
565
  * @param {string} logOutput - Git log output (one commit per line)
@@ -2033,6 +2059,13 @@ async function main() {
2033
2059
  else {
2034
2060
  await ensureNoAutoStagedOrNoop([WU_PATH, STATUS_PATH, BACKLOG_PATH, STAMPS_DIR]);
2035
2061
  }
2062
+ // WU-1084: Check for uncommitted changes on main after merge
2063
+ // This catches cases where pnpm format touched files outside code_paths
2064
+ const postMergeStatus = await getGitForCwd().getStatus();
2065
+ const dirtyCheck = checkPostMergeDirtyState(postMergeStatus, id);
2066
+ if (dirtyCheck.isDirty) {
2067
+ die(dirtyCheck.error);
2068
+ }
2036
2069
  // Step 6 & 7: Cleanup (remove worktree, delete branch) - WU-1215
2037
2070
  // WU-1811: Only run cleanup if all completion steps succeeded
2038
2071
  if (completionResult.cleanupSafe !== false) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lumenflow/cli",
3
- "version": "1.3.6",
3
+ "version": "1.4.0",
4
4
  "description": "Command-line interface for LumenFlow workflow framework",
5
5
  "keywords": [
6
6
  "lumenflow",
@@ -70,7 +70,8 @@
70
70
  "lumenflow-gates": "./dist/gates.js",
71
71
  "lumenflow-init": "./dist/init.js",
72
72
  "lumenflow": "./dist/init.js",
73
- "lumenflow-release": "./dist/release.js"
73
+ "lumenflow-release": "./dist/release.js",
74
+ "lumenflow-docs-sync": "./dist/docs-sync.js"
74
75
  },
75
76
  "files": [
76
77
  "dist",
@@ -87,11 +88,11 @@
87
88
  "pretty-ms": "^9.2.0",
88
89
  "simple-git": "^3.30.0",
89
90
  "yaml": "^2.8.2",
90
- "@lumenflow/core": "1.3.6",
91
- "@lumenflow/metrics": "1.3.6",
92
- "@lumenflow/memory": "1.3.6",
93
- "@lumenflow/initiatives": "1.3.6",
94
- "@lumenflow/agent": "1.3.6"
91
+ "@lumenflow/core": "1.4.0",
92
+ "@lumenflow/metrics": "1.4.0",
93
+ "@lumenflow/memory": "1.4.0",
94
+ "@lumenflow/initiatives": "1.4.0",
95
+ "@lumenflow/agent": "1.4.0"
95
96
  },
96
97
  "devDependencies": {
97
98
  "@vitest/coverage-v8": "^4.0.17",