@lumenflow/cli 2.2.2 → 2.3.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 (118) hide show
  1. package/README.md +147 -57
  2. package/dist/__tests__/agent-log-issue.test.js +56 -0
  3. package/dist/__tests__/cli-entry-point.test.js +66 -17
  4. package/dist/__tests__/cli-subprocess.test.js +25 -0
  5. package/dist/__tests__/init.test.js +298 -0
  6. package/dist/__tests__/initiative-plan.test.js +340 -0
  7. package/dist/__tests__/mem-cleanup-execution.test.js +19 -0
  8. package/dist/__tests__/merge-block.test.js +220 -0
  9. package/dist/__tests__/safe-git.test.js +191 -0
  10. package/dist/__tests__/state-doctor.test.js +274 -0
  11. package/dist/__tests__/wu-done.test.js +36 -0
  12. package/dist/__tests__/wu-edit.test.js +119 -0
  13. package/dist/__tests__/wu-prep.test.js +108 -0
  14. package/dist/agent-issues-query.js +4 -3
  15. package/dist/agent-log-issue.js +25 -4
  16. package/dist/backlog-prune.js +5 -4
  17. package/dist/cli-entry-point.js +11 -1
  18. package/dist/doctor.js +368 -0
  19. package/dist/flow-bottlenecks.js +6 -5
  20. package/dist/flow-report.js +4 -3
  21. package/dist/gates.js +356 -101
  22. package/dist/guard-locked.js +4 -3
  23. package/dist/guard-worktree-commit.js +4 -3
  24. package/dist/init.js +508 -86
  25. package/dist/initiative-add-wu.js +4 -3
  26. package/dist/initiative-bulk-assign-wus.js +8 -5
  27. package/dist/initiative-create.js +73 -37
  28. package/dist/initiative-edit.js +37 -21
  29. package/dist/initiative-list.js +4 -3
  30. package/dist/initiative-plan.js +337 -0
  31. package/dist/initiative-status.js +4 -3
  32. package/dist/lane-health.js +377 -0
  33. package/dist/lane-suggest.js +382 -0
  34. package/dist/mem-checkpoint.js +2 -2
  35. package/dist/mem-cleanup.js +2 -2
  36. package/dist/mem-context.js +306 -0
  37. package/dist/mem-create.js +2 -2
  38. package/dist/mem-delete.js +293 -0
  39. package/dist/mem-inbox.js +2 -2
  40. package/dist/mem-index.js +211 -0
  41. package/dist/mem-init.js +1 -1
  42. package/dist/mem-profile.js +207 -0
  43. package/dist/mem-promote.js +254 -0
  44. package/dist/mem-ready.js +2 -2
  45. package/dist/mem-signal.js +2 -2
  46. package/dist/mem-start.js +2 -2
  47. package/dist/mem-summarize.js +2 -2
  48. package/dist/mem-triage.js +2 -2
  49. package/dist/merge-block.js +222 -0
  50. package/dist/metrics-cli.js +7 -4
  51. package/dist/metrics-snapshot.js +4 -3
  52. package/dist/orchestrate-initiative.js +10 -4
  53. package/dist/orchestrate-monitor.js +379 -31
  54. package/dist/signal-cleanup.js +296 -0
  55. package/dist/spawn-list.js +6 -5
  56. package/dist/state-bootstrap.js +5 -4
  57. package/dist/state-cleanup.js +360 -0
  58. package/dist/state-doctor-fix.js +196 -0
  59. package/dist/state-doctor.js +501 -0
  60. package/dist/validate-agent-skills.js +4 -3
  61. package/dist/validate-agent-sync.js +4 -3
  62. package/dist/validate-backlog-sync.js +4 -3
  63. package/dist/validate-skills-spec.js +4 -3
  64. package/dist/validate.js +4 -3
  65. package/dist/wu-block.js +3 -3
  66. package/dist/wu-claim.js +208 -98
  67. package/dist/wu-cleanup.js +5 -4
  68. package/dist/wu-create.js +71 -46
  69. package/dist/wu-delete.js +88 -60
  70. package/dist/wu-deps.js +6 -5
  71. package/dist/wu-done-check.js +34 -0
  72. package/dist/wu-done.js +39 -12
  73. package/dist/wu-edit.js +63 -28
  74. package/dist/wu-infer-lane.js +7 -6
  75. package/dist/wu-preflight.js +23 -81
  76. package/dist/wu-prep.js +125 -0
  77. package/dist/wu-prune.js +4 -3
  78. package/dist/wu-recover.js +88 -22
  79. package/dist/wu-repair.js +7 -6
  80. package/dist/wu-spawn.js +226 -270
  81. package/dist/wu-status.js +4 -3
  82. package/dist/wu-unblock.js +5 -5
  83. package/dist/wu-unlock-lane.js +4 -3
  84. package/dist/wu-validate.js +5 -4
  85. package/package.json +16 -7
  86. package/templates/core/.lumenflow/constraints.md.template +192 -0
  87. package/templates/core/.lumenflow/rules/git-safety.md.template +27 -0
  88. package/templates/core/.lumenflow/rules/wu-workflow.md.template +48 -0
  89. package/templates/core/AGENTS.md.template +60 -0
  90. package/templates/core/LUMENFLOW.md.template +255 -0
  91. package/templates/core/UPGRADING.md.template +121 -0
  92. package/templates/core/ai/onboarding/agent-safety-card.md.template +106 -0
  93. package/templates/core/ai/onboarding/first-wu-mistakes.md.template +198 -0
  94. package/templates/core/ai/onboarding/quick-ref-commands.md.template +186 -0
  95. package/templates/core/ai/onboarding/release-process.md.template +362 -0
  96. package/templates/core/ai/onboarding/troubleshooting-wu-done.md.template +159 -0
  97. package/templates/core/ai/onboarding/wu-create-checklist.md.template +117 -0
  98. package/templates/vendors/aider/.aider.conf.yml.template +27 -0
  99. package/templates/vendors/claude/.claude/CLAUDE.md.template +52 -0
  100. package/templates/vendors/claude/.claude/settings.json.template +49 -0
  101. package/templates/vendors/claude/.claude/skills/bug-classification/SKILL.md.template +192 -0
  102. package/templates/vendors/claude/.claude/skills/code-quality/SKILL.md.template +152 -0
  103. package/templates/vendors/claude/.claude/skills/context-management/SKILL.md.template +155 -0
  104. package/templates/vendors/claude/.claude/skills/execution-memory/SKILL.md.template +304 -0
  105. package/templates/vendors/claude/.claude/skills/frontend-design/SKILL.md.template +131 -0
  106. package/templates/vendors/claude/.claude/skills/initiative-management/SKILL.md.template +164 -0
  107. package/templates/vendors/claude/.claude/skills/library-first/SKILL.md.template +98 -0
  108. package/templates/vendors/claude/.claude/skills/lumenflow-gates/SKILL.md.template +87 -0
  109. package/templates/vendors/claude/.claude/skills/multi-agent-coordination/SKILL.md.template +84 -0
  110. package/templates/vendors/claude/.claude/skills/ops-maintenance/SKILL.md.template +254 -0
  111. package/templates/vendors/claude/.claude/skills/orchestration/SKILL.md.template +189 -0
  112. package/templates/vendors/claude/.claude/skills/tdd-workflow/SKILL.md.template +139 -0
  113. package/templates/vendors/claude/.claude/skills/worktree-discipline/SKILL.md.template +138 -0
  114. package/templates/vendors/claude/.claude/skills/wu-lifecycle/SKILL.md.template +106 -0
  115. package/templates/vendors/cline/.clinerules.template +53 -0
  116. package/templates/vendors/cursor/.cursor/rules/lumenflow.md.template +34 -0
  117. package/templates/vendors/cursor/.cursor/rules.md.template +28 -0
  118. package/templates/vendors/windsurf/.windsurf/rules/lumenflow.md.template +34 -0
package/dist/wu-spawn.js CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env node
2
+ /* eslint-disable no-console -- CLI tool requires console output */
2
3
  /**
3
4
  * WU Spawn Helper
4
5
  *
@@ -25,7 +26,7 @@
25
26
  * Codex Mode:
26
27
  * When --codex is used, outputs a Codex/GPT-friendly Markdown prompt (no antml/XML escaping).
27
28
  *
28
- * @see {@link docs/04-operations/_frameworks/lumenflow/agent/onboarding/agent-invocation-guide.md} - Context loading templates
29
+ * @see {@link https://lumenflow.dev/reference/agent-invocation-guide/} - Context loading templates
29
30
  */
30
31
  import { existsSync, readFileSync } from 'node:fs';
31
32
  import path from 'node:path';
@@ -43,38 +44,31 @@ import { validateSpawnArgs, generateExecutionModeSection, generateThinkToolGuida
43
44
  import { SpawnStrategyFactory } from '@lumenflow/core/dist/spawn-strategy.js';
44
45
  import { getConfig } from '@lumenflow/core/dist/lumenflow-config.js';
45
46
  import { generateClientSkillsGuidance, generateSkillsSelectionSection, resolveClientConfig, } from '@lumenflow/core/dist/wu-spawn-skills.js';
47
+ // WU-1253: Template loader for extracted prompt templates
48
+ import { loadTemplatesWithOverrides, replaceTokens } from '@lumenflow/core/dist/template-loader.js';
46
49
  import { validateSpawnDependencies, formatDependencyError, } from '@lumenflow/core/dist/dependency-validator.js';
50
+ // WU-1192: Import prompt generation from Core (single source of truth)
51
+ // WU-1203: Import generateAgentCoordinationSection from core for config-driven progress signals
52
+ // WU-1288: Import policy-based test guidance and mandatory standards generators
53
+ import { TRUNCATION_WARNING_BANNER, SPAWN_END_SENTINEL, generateTestGuidance, generateAgentCoordinationSection, generatePolicyBasedTestGuidance, generateMandatoryStandards, generateEnforcementSummary, } from '@lumenflow/core/dist/wu-spawn.js';
54
+ // WU-1288: Import resolvePolicy for methodology policy resolution
55
+ import { resolvePolicy } from '@lumenflow/core/dist/resolve-policy.js';
56
+ // WU-1240: Import memory context integration for spawn prompts
57
+ import { generateMemoryContextSection, checkMemoryLayerInitialized, getMemoryContextMaxSize, } from '@lumenflow/core/dist/wu-spawn-context.js';
58
+ // Re-export for backwards compatibility
59
+ export { TRUNCATION_WARNING_BANNER, SPAWN_END_SENTINEL, generateTestGuidance, generateAgentCoordinationSection, };
47
60
  /**
48
61
  * Mandatory agent trigger patterns.
49
- * Mirrors MANDATORY_TRIGGERS from orchestration-advisory-loader.mjs.
62
+ * Mirrors MANDATORY_TRIGGERS from orchestration.constants.ts.
63
+ *
64
+ * Note: For LumenFlow framework development, this is empty since we don't have
65
+ * application-specific concerns like PHI, auth, or RLS. Projects using LumenFlow
66
+ * should configure their own triggers based on their domain requirements.
50
67
  */
51
68
  const MANDATORY_TRIGGERS = {
52
- 'security-auditor': ['supabase/migrations/**', '**/auth/**', '**/rls/**', '**/permissions/**'],
53
- 'beacon-guardian': ['**/prompts/**', '**/classification/**', '**/detector/**', '**/llm/**'],
69
+ // No mandatory triggers for LumenFlow framework development.
54
70
  };
55
71
  const LOG_PREFIX = '[wu:spawn]';
56
- /**
57
- * WU-1131: Truncation prevention constants
58
- *
59
- * These constants help detect when spawn output has been truncated during
60
- * copy-paste operations or context loading. The warning banner alerts users
61
- * to the truncation risk, and the end sentinel allows verification that
62
- * the full output was received.
63
- */
64
- export const TRUNCATION_WARNING_BANNER = `<!-- LUMENFLOW_TRUNCATION_WARNING -->
65
- <!--
66
- ⚠️ CRITICAL: DO NOT TRUNCATE THIS OUTPUT
67
-
68
- This spawn prompt MUST be copied verbatim. Truncation causes:
69
- - Missing constraints (agents ignore safety rules)
70
- - Missing TDD directives (agents skip tests)
71
- - Degraded agent performance
72
-
73
- VERIFICATION: The output MUST end with: <!-- LUMENFLOW_SPAWN_END -->
74
- If you don't see that sentinel at the end, the output was truncated.
75
- -->
76
- `;
77
- export const SPAWN_END_SENTINEL = '<!-- LUMENFLOW_SPAWN_END -->';
78
72
  /**
79
73
  * Detect mandatory agents based on code paths.
80
74
  *
@@ -142,15 +136,6 @@ function formatManualTests(manualTests) {
142
136
  }
143
137
  return manualTests.map((test) => `- [ ] ${test}`).join('\n');
144
138
  }
145
- /**
146
- * Generate implementation context section (WU-1833)
147
- *
148
- * Includes spec_refs, notes, risks, and tests.manual if present.
149
- * Sections with no content are omitted to keep prompts lean.
150
- *
151
- * @param {object} doc - WU YAML document
152
- * @returns {string} Implementation context section or empty string
153
- */
154
139
  function generateImplementationContext(doc) {
155
140
  const sections = [];
156
141
  // References (spec_refs)
@@ -216,14 +201,16 @@ function formatInvariantForOutput(inv) {
216
201
  lines.push(`**Path:** \`${inv.path}\``);
217
202
  }
218
203
  if (inv.paths) {
219
- lines.push(`**Paths:** ${inv.paths.map((p) => `\`${p}\``).join(', ')}`);
204
+ const formattedPaths = inv.paths.map((p) => `\`${p}\``).join(', ');
205
+ lines.push(`**Paths:** ${formattedPaths}`);
220
206
  }
221
207
  // WU-2254: forbidden-import specific fields
222
208
  if (inv.from) {
223
209
  lines.push(`**From:** \`${inv.from}\``);
224
210
  }
225
211
  if (inv.cannot_import && Array.isArray(inv.cannot_import)) {
226
- lines.push(`**Cannot Import:** ${inv.cannot_import.map((m) => `\`${m}\``).join(', ')}`);
212
+ const formattedImports = inv.cannot_import.map((m) => `\`${m}\``).join(', ');
213
+ lines.push(`**Cannot Import:** ${formattedImports}`);
227
214
  }
228
215
  // WU-2254: required-pattern specific fields
229
216
  if (inv.pattern &&
@@ -232,7 +219,8 @@ function formatInvariantForOutput(inv) {
232
219
  lines.push(`**Pattern:** \`${inv.pattern}\``);
233
220
  }
234
221
  if (inv.scope && Array.isArray(inv.scope)) {
235
- lines.push(`**Scope:** ${inv.scope.map((s) => `\`${s}\``).join(', ')}`);
222
+ const formattedScope = inv.scope.map((s) => `\`${s}\``).join(', ');
223
+ lines.push(`**Scope:** ${formattedScope}`);
236
224
  }
237
225
  lines.push('');
238
226
  return lines;
@@ -281,107 +269,8 @@ function generateInvariantsPriorArtSection(codePaths) {
281
269
  ];
282
270
  return lines.join('\n');
283
271
  }
284
- /**
285
- * WU types that require TDD (failing test first)
286
- */
287
- const TDD_REQUIRED_TYPES = ['feature', 'bug', 'tooling', 'enhancement'];
288
- /**
289
- * WU types that require existing tests to pass (no new tests mandated)
290
- */
291
- const EXISTING_TESTS_TYPES = ['refactor'];
292
- /**
293
- * WU types that require smoke tests + manual QA
294
- */
295
- const SMOKE_TEST_TYPES = ['visual', 'design', 'ui'];
296
- /**
297
- * WU types that only need format checks (no TDD)
298
- */
299
- const DOCS_ONLY_TYPES = ['documentation', 'docs', 'config'];
300
- /**
301
- * Generate type-aware test guidance (WU-1142)
302
- *
303
- * Returns appropriate test guidance based on WU type:
304
- * - feature/bug/tooling: Full TDD directive
305
- * - documentation: Format check only
306
- * - visual/design: Smoke test + manual QA
307
- * - refactor: Existing tests must pass
308
- *
309
- * @param {string} wuType - WU type from YAML
310
- * @returns {string} Test guidance section
311
- */
312
- export function generateTestGuidance(wuType) {
313
- const type = (wuType || 'feature').toLowerCase();
314
- // Documentation WUs - no TDD, just format checks
315
- if (DOCS_ONLY_TYPES.includes(type)) {
316
- return `## Documentation Standards
317
-
318
- **Format check only** - No TDD required for documentation WUs.
319
-
320
- ### Requirements
321
-
322
- 1. Run \`pnpm gates --docs-only\` before completion
323
- 2. Ensure markdown formatting is correct
324
- 3. Verify links are valid
325
- 4. Check spelling and grammar`;
326
- }
327
- // Visual/Design WUs - smoke tests + manual QA
328
- if (SMOKE_TEST_TYPES.includes(type)) {
329
- return `## Visual/Design Testing
330
-
331
- **Smoke test + manual QA** - Visual WUs require different verification.
332
-
333
- ### Requirements
334
-
335
- 1. Create smoke test for component rendering (if applicable)
336
- 2. Verify visual appearance manually
337
- 3. Test responsive behavior across breakpoints
338
- 4. Check accessibility (keyboard navigation, screen reader)
339
- 5. Document manual QA results in completion notes`;
340
- }
341
- // Refactor WUs - existing tests must pass
342
- if (EXISTING_TESTS_TYPES.includes(type)) {
343
- return `## Refactor Testing
344
-
345
- **Existing tests must pass** - Refactoring must not break current behavior.
346
-
347
- ### Requirements
348
-
349
- 1. Run all existing tests BEFORE refactoring
350
- 2. Run all existing tests AFTER refactoring
351
- 3. No new tests required unless behavior changes
352
- 4. If tests fail after refactor, the refactor introduced a bug`;
353
- }
354
- // Default: TDD required (feature, bug, tooling, enhancement)
355
- return generateTDDDirective();
356
- }
357
- /**
358
- * Generate the TDD directive section (WU-1585)
359
- *
360
- * Positioned immediately after </task> preamble per "Lost in the Middle" research.
361
- * Critical instructions at START and END of prompt improve adherence.
362
- *
363
- * @returns {string} TDD directive section
364
- */
365
- function generateTDDDirective() {
366
- return `## ⛔ TDD DIRECTIVE — READ BEFORE CODING
367
-
368
- **IF YOU WRITE IMPLEMENTATION CODE BEFORE A FAILING TEST, YOU HAVE FAILED THIS WU.**
369
-
370
- ### Test-First Workflow (MANDATORY)
371
-
372
- 1. Write a failing test for the acceptance criteria
373
- 2. Run the test to confirm it fails (RED)
374
- 3. Implement the minimum code to pass the test
375
- 4. Run the test to confirm it passes (GREEN)
376
- 5. Refactor if needed, keeping tests green
377
-
378
- ### Why This Matters
379
-
380
- - Tests document expected behavior BEFORE implementation
381
- - Prevents scope creep and over-engineering
382
- - Ensures every feature has verification
383
- - Failing tests prove the test actually tests something`;
384
- }
272
+ // WU-1192: generateTestGuidance and related constants moved to @lumenflow/core
273
+ // See imports from '@lumenflow/core/dist/wu-spawn.js' above
385
274
  /**
386
275
  * Generate the context loading preamble
387
276
  *
@@ -438,7 +327,7 @@ CRITICAL RULES - ENFORCE BEFORE EVERY ACTION:
438
327
  - For ordinary errors: fix and retry autonomously (up to 3 attempts)
439
328
 
440
329
  4. VERIFY COMPLETION before reporting success
441
- - Run: node tools/lib/agent-verification.mjs ${id} (from shared checkout)
330
+ - Run: node packages/@lumenflow/agent/dist/agent-verification.js ${id} (from shared checkout)
442
331
  - Exit 0 = passed, Exit 1 = INCOMPLETE
443
332
  - Never report "done" if verification fails
444
333
 
@@ -471,7 +360,7 @@ function generateCodexConstraints(id) {
471
360
 
472
361
  1. **TDD checkpoint**: tests BEFORE implementation; never skip RED
473
362
  2. **Stop on errors**: if any command fails, report BLOCKED (never DONE) with the error
474
- 3. **Verify before success**: run \`pnpm gates\` in the worktree, then run \`node tools/lib/agent-verification.mjs ${id}\` (from the shared checkout)
363
+ 3. **Verify before success**: run \`pnpm gates\` in the worktree, then run \`node packages/@lumenflow/agent/dist/agent-verification.js ${id}\` (from the shared checkout)
475
364
  4. **No fabrication**: if blockers remain or verification fails, report INCOMPLETE
476
365
  5. **Git workflow**: avoid merge commits; let \`pnpm wu:done\` handle completion
477
366
  6. **Scope discipline**: stay within \`code_paths\`; capture out-of-scope issues via \`pnpm mem:create\`
@@ -481,10 +370,10 @@ function generateCodexConstraints(id) {
481
370
  * Generate mandatory agent advisory section
482
371
  *
483
372
  * @param {string[]} mandatoryAgents - Array of mandatory agent names
484
- * @param {string} id - WU ID
373
+ * @param {string} _id - WU ID (reserved for future use)
485
374
  * @returns {string} Mandatory agent section or empty string
486
375
  */
487
- function generateMandatoryAgentSection(mandatoryAgents, id) {
376
+ function generateMandatoryAgentSection(mandatoryAgents, _id) {
488
377
  if (mandatoryAgents.length === 0) {
489
378
  return '';
490
379
  }
@@ -496,7 +385,7 @@ Based on code_paths, the following agents MUST be invoked:
496
385
 
497
386
  ${agentList}
498
387
 
499
- Run: pnpm orchestrate:suggest --wu ${id}
388
+ Run: pnpm orchestrate:monitor to check agent status
500
389
  `;
501
390
  }
502
391
  /**
@@ -613,54 +502,8 @@ When finishing, provide structured output:
613
502
 
614
503
  This format enables orchestrator to track progress across waves.`;
615
504
  }
616
- /**
617
- * Generate agent coordination section (WU-1987)
618
- *
619
- * Provides guidance on mem:signal for parallel agent coordination,
620
- * orchestrate:status for dashboard checks, and abandoned WU handling.
621
- *
622
- * @param {string} id - WU ID
623
- * @returns {string} Agent coordination section
624
- */
625
- export function generateAgentCoordinationSection(id) {
626
- return `## Agent Coordination (Parallel Work)
627
-
628
- ### ⚠️ CRITICAL: Use mem:signal, NOT TaskOutput
629
-
630
- **DO NOT** use TaskOutput to check agent progress - it returns full transcripts
631
- and causes "prompt too long" errors. Always use the memory layer instead:
632
-
633
- \`\`\`bash
634
- # ✅ CORRECT: Compact signals (~6 lines)
635
- pnpm mem:inbox --since 30m
636
-
637
- # ❌ WRONG: Full transcripts (context explosion)
638
- # TaskOutput with block=false <-- NEVER DO THIS FOR MONITORING
639
- \`\`\`
640
-
641
- ### Automatic Completion Signals
642
-
643
- \`wu:done\` automatically broadcasts completion signals. You do not need to
644
- manually signal completion - just run \`wu:done\` and orchestrators will
645
- see your signal via \`mem:inbox\`.
646
-
647
- ### Progress Signals (Optional)
648
-
649
- For long-running work, send progress signals at milestones:
650
-
651
- \`\`\`bash
652
- pnpm mem:signal "50% complete: tests passing, implementing adapter" --wu ${id}
653
- pnpm mem:signal "Blocked: waiting for WU-XXX dependency" --wu ${id}
654
- \`\`\`
655
-
656
- ### Checking Status
657
-
658
- \`\`\`bash
659
- pnpm orchestrate:init-status -i INIT-XXX # Initiative progress (compact)
660
- pnpm mem:inbox --since 1h # Recent signals from all agents
661
- pnpm mem:inbox --lane "Experience: Web" # Lane-specific signals
662
- \`\`\``;
663
- }
505
+ // WU-1203: generateAgentCoordinationSection is now imported from @lumenflow/core
506
+ // The core version reads config and generates dynamic guidance based on progress_signals settings
664
507
  /**
665
508
  * Generate quick fix commands section (WU-1987)
666
509
  *
@@ -698,7 +541,7 @@ If you encounter a "worktree required" or "commit blocked" error:
698
541
  1. **Check existing worktrees**: \`git worktree list\`
699
542
  2. **Navigate to the worktree**: \`cd ${worktreePath || 'worktrees/<lane>-wu-xxx'}\`
700
543
  3. **Retry your operation** from within the worktree
701
- 4. **Use relative paths only** (never absolute paths like \`/home/...\`)
544
+ 4. **Use relative paths only** (never absolute paths starting with /)
702
545
 
703
546
  ### Common Causes
704
547
 
@@ -850,7 +693,7 @@ pnpm mem:triage --wu ${id} # List discoveries for this WU
850
693
  pnpm mem:triage --promote <node-id> --lane "<lane>" # Create Bug WU (human action)
851
694
  \`\`\`
852
695
 
853
- See: docs/04-operations/_frameworks/lumenflow/agent/onboarding/agent-invocation-guide.md §Bug Discovery`;
696
+ See: https://lumenflow.dev/reference/agent-invocation-guide/ §Bug Discovery`;
854
697
  }
855
698
  /**
856
699
  * Generate lane-specific guidance
@@ -949,6 +792,57 @@ pnpm wu:done --id ${id}
949
792
 
950
793
  **Do not ask** "should I run wu:done?" — just run it when gates pass.`;
951
794
  }
795
+ /**
796
+ * WU-1253: Try to load templates for spawn prompt sections.
797
+ *
798
+ * Implements shadow mode: tries templates first, returns empty map
799
+ * if templates aren't available (caller uses hardcoded fallback).
800
+ *
801
+ * @param clientName - Client name for overrides (e.g., 'claude-code', 'cursor')
802
+ * @param context - Token values for replacement
803
+ * @returns Map of template id to processed content, empty if templates unavailable
804
+ */
805
+ function tryLoadTemplates(clientName, context) {
806
+ const result = new Map();
807
+ try {
808
+ const baseDir = process.cwd();
809
+ const templates = loadTemplatesWithOverrides(baseDir, clientName);
810
+ // Process each template: replace tokens
811
+ for (const [id, template] of templates) {
812
+ const processed = replaceTokens(template.content, context);
813
+ result.set(id, processed);
814
+ }
815
+ }
816
+ catch {
817
+ // Template loading failed - return empty map for hardcoded fallback
818
+ }
819
+ return result;
820
+ }
821
+ /**
822
+ * WU-1253: Build template context from WU document.
823
+ *
824
+ * @param doc - WU YAML document
825
+ * @param id - WU ID
826
+ * @returns Context for template token replacement
827
+ */
828
+ function buildSpawnTemplateContext(doc, id) {
829
+ const lane = doc.lane || '';
830
+ const laneParent = lane.split(':')[0]?.trim() || '';
831
+ const type = (doc.type || 'feature').toLowerCase();
832
+ return {
833
+ WU_ID: id,
834
+ LANE: lane,
835
+ TYPE: type,
836
+ TITLE: doc.title || '',
837
+ DESCRIPTION: doc.description || '',
838
+ WORKTREE_PATH: doc.worktree_path || '',
839
+ laneParent,
840
+ // Lowercase aliases for condition evaluation
841
+ type,
842
+ lane,
843
+ worktreePath: doc.worktree_path || '',
844
+ };
845
+ }
952
846
  function generateClientBlocksSection(clientContext) {
953
847
  if (!clientContext?.config?.blocks?.length)
954
848
  return '';
@@ -972,38 +866,63 @@ function generateClientBlocksSection(clientContext) {
972
866
  export function generateTaskInvocation(doc, id, strategy, options = {}) {
973
867
  const codePaths = doc.code_paths || [];
974
868
  const mandatoryAgents = detectMandatoryAgents(codePaths);
869
+ // WU-1253: Try loading templates (shadow mode - falls back to hardcoded if unavailable)
870
+ const clientName = options.client?.name || 'claude-code';
871
+ const templateContext = buildSpawnTemplateContext(doc, id);
872
+ const templates = tryLoadTemplates(clientName, templateContext);
975
873
  const preamble = generatePreamble(id, strategy);
976
- // WU-1142: Use type-aware test guidance instead of hardcoded TDD directive
977
- const testGuidance = generateTestGuidance(doc.type);
978
874
  const clientContext = options.client;
979
875
  const config = options.config || getConfig();
876
+ // WU-1288: Resolve methodology policy from config
877
+ const policy = resolvePolicy(config);
878
+ // WU-1142: Use type-aware test guidance instead of hardcoded TDD directive
879
+ // WU-1288: Use policy-based test guidance that respects methodology.testing config
880
+ // WU-1253: Try template first, fall back to policy-based guidance
881
+ const testGuidance = templates.get('tdd-directive') || generatePolicyBasedTestGuidance(doc.type, policy);
882
+ // WU-1288: Generate enforcement summary from resolved policy
883
+ const enforcementSummary = generateEnforcementSummary(policy);
884
+ // WU-1288: Generate mandatory standards based on resolved policy
885
+ const mandatoryStandards = generateMandatoryStandards(policy);
980
886
  // WU-1142: Pass lane to get byLane skills
981
887
  const clientSkillsGuidance = generateClientSkillsGuidance(clientContext, doc.lane);
982
- const skillsSection = generateSkillsSelectionSection(doc, config, clientContext?.name) +
983
- (clientSkillsGuidance ? `\n${clientSkillsGuidance}` : '');
888
+ // WU-1253: Try template for skills-selection, build skills section
889
+ const skillsTemplateContent = templates.get('skills-selection');
890
+ const skillsGuidanceSuffix = clientSkillsGuidance ? '\n' + clientSkillsGuidance : '';
891
+ const skillsBaseContent = skillsTemplateContent || generateSkillsSelectionSection(doc, config, clientContext?.name);
892
+ const skillsSection = skillsBaseContent + skillsGuidanceSuffix;
984
893
  const clientBlocks = generateClientBlocksSection(clientContext);
985
894
  const mandatorySection = generateMandatoryAgentSection(mandatoryAgents, id);
986
895
  const laneGuidance = generateLaneGuidance(doc.lane);
987
- const bugDiscoverySection = generateBugDiscoverySection(id);
988
- const constraints = generateConstraints(id);
896
+ // WU-1253: Try template for bug-discovery
897
+ const bugDiscoverySection = templates.get('bug-discovery') || generateBugDiscoverySection(id);
898
+ // WU-1253: Try template for constraints
899
+ const constraints = templates.get('constraints') || generateConstraints(id);
989
900
  const implementationContext = generateImplementationContext(doc);
990
901
  // WU-2252: Generate invariants/prior-art section for code_paths
991
902
  const invariantsPriorArt = generateInvariantsPriorArtSection(codePaths);
992
903
  // WU-1986: Anthropic multi-agent best practices sections
993
- const effortScaling = generateEffortScalingRules();
994
- const parallelToolCalls = generateParallelToolCallGuidance();
995
- const searchHeuristics = generateIterativeSearchHeuristics();
996
- const tokenBudget = generateTokenBudgetAwareness(id);
904
+ // WU-1253: Try templates for these sections
905
+ const effortScaling = templates.get('effort-scaling') || generateEffortScalingRules();
906
+ const parallelToolCalls = templates.get('parallel-tool-calls') || generateParallelToolCallGuidance();
907
+ const searchHeuristics = templates.get('search-heuristics') || generateIterativeSearchHeuristics();
908
+ const tokenBudget = templates.get('token-budget') || generateTokenBudgetAwareness(id);
997
909
  const completionFormat = generateCompletionFormat(id);
998
910
  // WU-1987: Agent coordination and quick fix sections
999
911
  const agentCoordination = generateAgentCoordinationSection(id);
1000
- const quickFix = generateQuickFixCommands();
912
+ // WU-1253: Try template for quick-fix-commands
913
+ const quickFix = templates.get('quick-fix-commands') || generateQuickFixCommands();
1001
914
  // WU-2107: Lane selection guidance
1002
- const laneSelection = generateLaneSelectionSection();
915
+ // WU-1253: Try template for lane-selection
916
+ const laneSelection = templates.get('lane-selection') || generateLaneSelectionSection();
1003
917
  // WU-2362: Worktree path guidance for sub-agents
1004
918
  const worktreeGuidance = generateWorktreePathGuidance(doc.worktree_path);
1005
919
  // WU-1134: Worktree block recovery guidance
1006
- const worktreeBlockRecovery = generateWorktreeBlockRecoverySection(doc.worktree_path);
920
+ // WU-1253: Try template for worktree-recovery
921
+ const worktreeBlockRecovery = templates.get('worktree-recovery') || generateWorktreeBlockRecoverySection(doc.worktree_path);
922
+ // WU-1240: Memory context section
923
+ // Include if explicitly enabled and not disabled via noContext
924
+ const shouldIncludeMemoryContext = options.includeMemoryContext && !options.noContext;
925
+ const memoryContextSection = shouldIncludeMemoryContext ? options.memoryContextContent || '' : '';
1007
926
  // Generate thinking mode sections if applicable
1008
927
  const executionModeSection = generateExecutionModeSection(options);
1009
928
  const thinkToolGuidance = generateThinkToolGuidance(options);
@@ -1049,19 +968,13 @@ ${codePaths.length > 0 ? codePaths.map((p) => `- ${p}`).join('\n') : '- No code
1049
968
  ${mandatorySection}${invariantsPriorArt ? `---\n\n${invariantsPriorArt}\n\n` : ''}${implementationContext ? `---\n\n${implementationContext}\n\n` : ''}---
1050
969
 
1051
970
  ${thinkingBlock}${skillsSection}
1052
- ---
971
+ ${memoryContextSection ? `---\n\n${memoryContextSection}\n\n` : ''}---
972
+
973
+ ${mandatoryStandards}
1053
974
 
1054
- ## Mandatory Standards
975
+ ---
1055
976
 
1056
- - **LumenFlow**: Follow trunk-based flow, WIP=1, worktree discipline
1057
- - **TDD**: Failing test first, then implementation, then passing test. 90%+ coverage on new application code
1058
- - **Hexagonal Architecture**: Ports-first design. No application -> infrastructure imports
1059
- - **SOLID/DRY/YAGNI/KISS**: No over-engineering, no premature abstraction
1060
- - **Library-First**: Search context7 before writing custom code. No reinventing wheels
1061
- - **Code Quality**: No string literals, no magic numbers, no brittle regexes when libraries exist
1062
- - **Worktree Discipline**: ALWAYS use \`pnpm wu:claim\` to create worktrees (never \`git worktree add\` directly). Work ONLY in the worktree, never edit main
1063
- - **Documentation**: Update tooling docs if changing tools. Keep docs in sync with code
1064
- - **Sub-agents**: Use Explore agent for codebase investigation. Activate mandatory agents (security-auditor for PHI/auth, beacon-guardian for LLM/prompts)
977
+ ${enforcementSummary}
1065
978
 
1066
979
  ${clientBlocks ? `---\n\n${clientBlocks}\n\n` : ''}${worktreeGuidance ? `---\n\n${worktreeGuidance}\n\n` : ''}---
1067
980
 
@@ -1161,6 +1074,9 @@ export function generateCodexPrompt(doc, id, strategy, options = {}) {
1161
1074
  const thinkingBlock = thinkingSections ? `${thinkingSections}\n\n---\n\n` : '';
1162
1075
  // WU-1134: Worktree block recovery guidance
1163
1076
  const worktreeBlockRecovery = generateWorktreeBlockRecoverySection(doc.worktree_path);
1077
+ // WU-1240: Memory context section
1078
+ const shouldIncludeMemoryContext = options.includeMemoryContext && !options.noContext;
1079
+ const memoryContextSection = shouldIncludeMemoryContext ? options.memoryContextContent || '' : '';
1164
1080
  // WU-1131: Warning banner at start, end sentinel after constraints
1165
1081
  // WU-1142: Type-aware test guidance
1166
1082
  return `${TRUNCATION_WARNING_BANNER}# ${id}: ${doc.title || 'Untitled'}
@@ -1200,8 +1116,7 @@ ${formatAcceptance(doc.acceptance)}
1200
1116
  ---
1201
1117
 
1202
1118
  ${skillsSection}
1203
-
1204
- ---
1119
+ ${memoryContextSection ? `---\n\n${memoryContextSection}\n\n` : ''}---
1205
1120
 
1206
1121
  ## Action
1207
1122
 
@@ -1212,7 +1127,7 @@ ${action}
1212
1127
  ## Verification
1213
1128
 
1214
1129
  - Run in worktree: \`pnpm gates\`
1215
- - From shared checkout: \`node tools/lib/agent-verification.mjs ${id}\`
1130
+ - From shared checkout: \`node packages/@lumenflow/agent/dist/agent-verification.js ${id}\`
1216
1131
 
1217
1132
  ---
1218
1133
 
@@ -1256,16 +1171,7 @@ export function generateLaneOccupationWarning(lockMetadata, targetWuId, options
1256
1171
  warning += ` 3. Block ${lockMetadata.wuId} if work is stalled: pnpm wu:block --id ${lockMetadata.wuId}`;
1257
1172
  return warning;
1258
1173
  }
1259
- /**
1260
- * Main entry point
1261
- */
1262
- async function main() {
1263
- // WU-2202: Validate dependencies BEFORE any other operation
1264
- // This prevents false lane occupancy reports when yaml package is missing
1265
- const depResult = await validateSpawnDependencies();
1266
- if (!depResult.valid) {
1267
- die(formatDependencyError('wu:spawn', depResult.missing));
1268
- }
1174
+ function parseAndValidateArgs() {
1269
1175
  const args = createWUParser({
1270
1176
  name: 'wu-spawn',
1271
1177
  description: 'Generate Task tool invocation for sub-agent WU execution',
@@ -1278,6 +1184,7 @@ async function main() {
1278
1184
  WU_OPTIONS.parentWu, // WU-1945: Parent WU for spawn registry tracking
1279
1185
  WU_OPTIONS.client,
1280
1186
  WU_OPTIONS.vendor,
1187
+ WU_OPTIONS.noContext, // WU-1240: Skip memory context injection
1281
1188
  ],
1282
1189
  required: ['id'],
1283
1190
  allowPositionalId: true,
@@ -1289,42 +1196,92 @@ async function main() {
1289
1196
  catch (e) {
1290
1197
  die(e.message);
1291
1198
  }
1292
- const id = args.id.toUpperCase();
1293
- if (!PATTERNS.WU_ID.test(id)) {
1294
- die(`Invalid WU id '${args.id}'. Expected format WU-123`);
1295
- }
1296
- const WU_PATH = WU_PATHS.WU(id);
1199
+ return args;
1200
+ }
1201
+ /**
1202
+ * Load and validate WU document from YAML file
1203
+ */
1204
+ function loadWUDocument(id, wuPath) {
1297
1205
  // Check if WU file exists
1298
- if (!existsSync(WU_PATH)) {
1299
- die(`WU file not found: ${WU_PATH}\n\n` +
1206
+ if (!existsSync(wuPath)) {
1207
+ die(`WU file not found: ${wuPath}\n\n` +
1300
1208
  `Cannot spawn a sub-agent for a WU that doesn't exist.\n\n` +
1301
1209
  `Options:\n` +
1302
1210
  ` 1. Create the WU first: pnpm wu:create --id ${id} --lane <lane> --title "..."\n` +
1303
1211
  ` 2. Check if the WU ID is correct`);
1304
1212
  }
1305
- // Read and parse WU YAML
1306
- let doc;
1213
+ // Read WU file
1307
1214
  let text;
1308
1215
  try {
1309
- text = readFileSync(WU_PATH, { encoding: FILE_SYSTEM.UTF8 });
1216
+ text = readFileSync(wuPath, { encoding: FILE_SYSTEM.UTF8 });
1310
1217
  }
1311
1218
  catch (e) {
1312
- die(`Failed to read WU file: ${WU_PATH}\n\n` +
1219
+ die(`Failed to read WU file: ${wuPath}\n\n` +
1313
1220
  `Error: ${e.message}\n\n` +
1314
1221
  `Options:\n` +
1315
- ` 1. Check file permissions: ls -la ${WU_PATH}\n` +
1222
+ ` 1. Check file permissions: ls -la ${wuPath}\n` +
1316
1223
  ` 2. Ensure the file exists and is readable`);
1317
1224
  }
1225
+ // Parse YAML
1318
1226
  try {
1319
- doc = parseYAML(text);
1227
+ return parseYAML(text);
1320
1228
  }
1321
1229
  catch (e) {
1322
- die(`Failed to parse WU YAML ${WU_PATH}\n\n` +
1230
+ die(`Failed to parse WU YAML ${wuPath}\n\n` +
1323
1231
  `Error: ${e.message}\n\n` +
1324
1232
  `Options:\n` +
1325
1233
  ` 1. Validate YAML syntax: pnpm wu:validate --id ${id}\n` +
1326
1234
  ` 2. Fix YAML errors manually and retry`);
1327
1235
  }
1236
+ }
1237
+ /**
1238
+ * Resolve the client name from args and config
1239
+ */
1240
+ function resolveClientName(args, config) {
1241
+ let clientName = args.client;
1242
+ if (!clientName && args.vendor) {
1243
+ console.warn(`${LOG_PREFIX} ${EMOJI.WARNING} Warning: --vendor is deprecated. Use --client.`);
1244
+ clientName = args.vendor;
1245
+ }
1246
+ // Codex handling (deprecated legacy flag)
1247
+ if (args.codex && !clientName) {
1248
+ console.warn(`${LOG_PREFIX} ${EMOJI.WARNING} Warning: --codex is deprecated. Use --client codex-cli.`);
1249
+ clientName = 'codex-cli';
1250
+ }
1251
+ return clientName || config.agents.defaultClient || 'claude-code';
1252
+ }
1253
+ /**
1254
+ * Check lane occupation and warn if occupied by a different WU
1255
+ */
1256
+ async function checkAndWarnLaneOccupation(lane, id) {
1257
+ if (!lane)
1258
+ return;
1259
+ const existingLock = checkLaneOccupation(lane);
1260
+ if (existingLock && existingLock.wuId !== id) {
1261
+ // Lane is occupied by a different WU
1262
+ const { isLockStale } = await import('@lumenflow/core/dist/lane-lock.js');
1263
+ const isStale = isLockStale(existingLock);
1264
+ const warning = generateLaneOccupationWarning(existingLock, id, { isStale });
1265
+ console.warn(`${LOG_PREFIX} ${EMOJI.WARNING}\n${warning}\n`);
1266
+ }
1267
+ }
1268
+ /**
1269
+ * Main entry point
1270
+ */
1271
+ async function main() {
1272
+ // WU-2202: Validate dependencies BEFORE any other operation
1273
+ // This prevents false lane occupancy reports when yaml package is missing
1274
+ const depResult = await validateSpawnDependencies();
1275
+ if (!depResult.valid) {
1276
+ die(formatDependencyError('wu:spawn', depResult.missing));
1277
+ }
1278
+ const args = parseAndValidateArgs();
1279
+ const id = args.id.toUpperCase();
1280
+ if (!PATTERNS.WU_ID.test(id)) {
1281
+ die(`Invalid WU id '${args.id}'. Expected format WU-123`);
1282
+ }
1283
+ const wuPath = WU_PATHS.WU(id);
1284
+ const doc = loadWUDocument(id, wuPath);
1328
1285
  // Warn if WU is not in ready or in_progress status
1329
1286
  const validStatuses = [WU_STATUS.READY, WU_STATUS.IN_PROGRESS];
1330
1287
  if (!validStatuses.includes(doc.status)) {
@@ -1333,17 +1290,7 @@ async function main() {
1333
1290
  console.warn('');
1334
1291
  }
1335
1292
  // WU-1603: Check if lane is already occupied and warn
1336
- const lane = doc.lane;
1337
- if (lane) {
1338
- const existingLock = checkLaneOccupation(lane);
1339
- if (existingLock && existingLock.wuId !== id) {
1340
- // Lane is occupied by a different WU
1341
- const { isLockStale } = await import('@lumenflow/core/dist/lane-lock.js');
1342
- const isStale = isLockStale(existingLock);
1343
- const warning = generateLaneOccupationWarning(existingLock, id, { isStale });
1344
- console.warn(`${LOG_PREFIX} ${EMOJI.WARNING}\n${warning}\n`);
1345
- }
1346
- }
1293
+ await checkAndWarnLaneOccupation(doc.lane, id);
1347
1294
  // Build thinking mode options for task invocation
1348
1295
  const thinkingOptions = {
1349
1296
  thinking: args.thinking,
@@ -1352,21 +1299,25 @@ async function main() {
1352
1299
  };
1353
1300
  // Client Resolution
1354
1301
  const config = getConfig();
1355
- let clientName = args.client;
1356
- if (!clientName && args.vendor) {
1357
- console.warn(`${LOG_PREFIX} ${EMOJI.WARNING} Warning: --vendor is deprecated. Use --client.`);
1358
- clientName = args.vendor;
1359
- }
1360
- // Codex handling (deprecated legacy flag)
1361
- if (args.codex) {
1362
- if (!clientName) {
1363
- console.warn(`${LOG_PREFIX} ${EMOJI.WARNING} Warning: --codex is deprecated. Use --client codex-cli.`);
1364
- clientName = 'codex-cli';
1302
+ const clientName = resolveClientName(args, config);
1303
+ // WU-1240: Generate memory context if not skipped
1304
+ const baseDir = process.cwd();
1305
+ let memoryContextContent = '';
1306
+ const shouldIncludeMemoryContext = !args.noContext;
1307
+ if (shouldIncludeMemoryContext) {
1308
+ const isMemoryInitialized = await checkMemoryLayerInitialized(baseDir);
1309
+ if (isMemoryInitialized) {
1310
+ const maxSize = getMemoryContextMaxSize(config);
1311
+ memoryContextContent = await generateMemoryContextSection(baseDir, {
1312
+ wuId: id,
1313
+ lane: doc.lane,
1314
+ maxSize,
1315
+ });
1316
+ if (memoryContextContent) {
1317
+ console.log(`${LOG_PREFIX} Memory context loaded (${memoryContextContent.length} bytes)`);
1318
+ }
1365
1319
  }
1366
1320
  }
1367
- if (!clientName) {
1368
- clientName = config.agents.defaultClient || 'claude-code';
1369
- }
1370
1321
  // Create strategy
1371
1322
  const strategy = SpawnStrategyFactory.create(clientName);
1372
1323
  const clientContext = { name: clientName, config: resolveClientConfig(config, clientName) };
@@ -1386,6 +1337,11 @@ async function main() {
1386
1337
  ...thinkingOptions,
1387
1338
  client: clientContext,
1388
1339
  config,
1340
+ // WU-1240: Include memory context in spawn prompt
1341
+ baseDir,
1342
+ includeMemoryContext: shouldIncludeMemoryContext && memoryContextContent.length > 0,
1343
+ memoryContextContent,
1344
+ noContext: args.noContext,
1389
1345
  });
1390
1346
  console.log(`${LOG_PREFIX} Generated Task tool invocation for ${id}`);
1391
1347
  console.log(`${LOG_PREFIX} Copy the block below to spawn a sub-agent:\n`);
@@ -1409,5 +1365,5 @@ async function main() {
1409
1365
  // path but import.meta.url resolves to the real path - they never match
1410
1366
  import { runCLI } from './cli-entry-point.js';
1411
1367
  if (import.meta.main) {
1412
- runCLI(main);
1368
+ void runCLI(main);
1413
1369
  }