@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
@@ -24,9 +24,11 @@ import { WU_PATHS } from '@lumenflow/core/dist/wu-paths.js';
24
24
  import { readWU, writeWU } from '@lumenflow/core/dist/wu-yaml.js';
25
25
  import { CONTEXT_VALIDATION, EMOJI, WU_STATUS, DEFAULTS, toKebab, } from '@lumenflow/core/dist/wu-constants.js';
26
26
  import { getGitForCwd } from '@lumenflow/core/dist/git-adapter.js';
27
- import { join } from 'node:path';
27
+ import { withMicroWorktree } from '@lumenflow/core/dist/micro-worktree.js';
28
+ import { join, relative } from 'node:path';
28
29
  const { RECOVERY_ACTIONS } = CONTEXT_VALIDATION;
29
30
  const LOG_PREFIX = '[wu:recover]';
31
+ const OPERATION_NAME = 'wu-recover';
30
32
  /**
31
33
  * Valid recovery action types
32
34
  */
@@ -107,6 +109,9 @@ function getWorktreePath(wuId, lane) {
107
109
  }
108
110
  /**
109
111
  * Execute resume action - reconcile state and continue
112
+ *
113
+ * WU-1226: Uses micro-worktree isolation for all state changes.
114
+ * Changes are pushed via merge, not direct file modification on main.
110
115
  */
111
116
  async function executeResume(wuId) {
112
117
  console.log(`${LOG_PREFIX} Executing resume action for ${wuId}...`);
@@ -116,17 +121,46 @@ async function executeResume(wuId) {
116
121
  return false;
117
122
  }
118
123
  const doc = readWU(wuPath, wuId);
119
- // Update status to in_progress if it was ready
120
- if (doc.status === WU_STATUS.READY) {
121
- doc.status = WU_STATUS.IN_PROGRESS;
122
- writeWU(wuPath, doc);
124
+ // If status is already in_progress, nothing to do
125
+ if (doc.status !== WU_STATUS.READY) {
126
+ console.log(`${LOG_PREFIX} ${EMOJI.SUCCESS} Resume completed - WU already has status '${doc.status}'`);
127
+ return true;
128
+ }
129
+ // WU-1226: Use micro-worktree isolation for state changes
130
+ try {
131
+ await withMicroWorktree({
132
+ operation: OPERATION_NAME,
133
+ id: wuId,
134
+ logPrefix: LOG_PREFIX,
135
+ pushOnly: true, // Don't modify local main
136
+ execute: async ({ worktreePath }) => {
137
+ // Read WU in micro-worktree context
138
+ const microWuPath = join(worktreePath, relative(process.cwd(), wuPath));
139
+ const microDoc = readWU(microWuPath, wuId);
140
+ // Update status to in_progress
141
+ microDoc.status = WU_STATUS.IN_PROGRESS;
142
+ writeWU(microWuPath, microDoc);
143
+ return {
144
+ commitMessage: `fix(wu-recover): resume ${wuId} - set status to in_progress`,
145
+ files: [relative(process.cwd(), wuPath)],
146
+ };
147
+ },
148
+ });
123
149
  console.log(`${LOG_PREFIX} ${EMOJI.SUCCESS} Updated ${wuId} status to in_progress`);
150
+ console.log(`${LOG_PREFIX} ${EMOJI.SUCCESS} Resume completed - you can continue working in the worktree`);
151
+ return true;
152
+ }
153
+ catch (err) {
154
+ console.error(`${LOG_PREFIX} ${EMOJI.FAILURE} Micro-worktree operation failed: ${err.message}`);
155
+ return false;
124
156
  }
125
- console.log(`${LOG_PREFIX} ${EMOJI.SUCCESS} Resume completed - you can continue working in the worktree`);
126
- return true;
127
157
  }
128
158
  /**
129
159
  * Execute reset action - discard worktree and reset to ready
160
+ *
161
+ * WU-1226: Uses micro-worktree isolation for WU YAML state changes.
162
+ * Worktree removal still happens directly (git operation, not file write).
163
+ * Changes are pushed via merge, not direct file modification on main.
130
164
  */
131
165
  async function executeReset(wuId) {
132
166
  console.log(`${LOG_PREFIX} Executing reset action for ${wuId}...`);
@@ -137,7 +171,7 @@ async function executeReset(wuId) {
137
171
  }
138
172
  const doc = readWU(wuPath, wuId);
139
173
  const worktreePath = getWorktreePath(wuId, doc.lane || '');
140
- // Remove worktree if exists
174
+ // Remove worktree if exists (git operation, safe to do directly)
141
175
  // WU-1097: Use worktreeRemove() instead of deprecated run() with shell strings
142
176
  // This properly handles paths with spaces and special characters
143
177
  if (existsSync(worktreePath)) {
@@ -146,7 +180,7 @@ async function executeReset(wuId) {
146
180
  await git.worktreeRemove(worktreePath, { force: true });
147
181
  console.log(`${LOG_PREFIX} Removed worktree: ${worktreePath}`);
148
182
  }
149
- catch (e) {
183
+ catch {
150
184
  // Try manual removal if git command fails
151
185
  try {
152
186
  rmSync(worktreePath, { recursive: true, force: true });
@@ -158,14 +192,38 @@ async function executeReset(wuId) {
158
192
  }
159
193
  }
160
194
  }
161
- // Reset WU status to ready
162
- doc.status = WU_STATUS.READY;
163
- delete doc.worktree_path;
164
- delete doc.claimed_at;
165
- delete doc.session_id;
166
- writeWU(wuPath, doc);
167
- console.log(`${LOG_PREFIX} ${EMOJI.SUCCESS} Reset completed - ${wuId} is now ready for re-claiming`);
168
- return true;
195
+ // WU-1226: Use micro-worktree isolation for WU YAML state changes
196
+ try {
197
+ await withMicroWorktree({
198
+ operation: OPERATION_NAME,
199
+ id: wuId,
200
+ logPrefix: LOG_PREFIX,
201
+ pushOnly: true, // Don't modify local main
202
+ execute: async ({ worktreePath: microPath }) => {
203
+ // Read WU in micro-worktree context
204
+ const microWuPath = join(microPath, relative(process.cwd(), wuPath));
205
+ const microDoc = readWU(microWuPath, wuId);
206
+ // Reset WU status to ready and clear claim fields
207
+ microDoc.status = WU_STATUS.READY;
208
+ // Use Reflect.deleteProperty to satisfy sonarjs/no-delete rule
209
+ Reflect.deleteProperty(microDoc, 'worktree_path');
210
+ Reflect.deleteProperty(microDoc, 'claimed_at');
211
+ Reflect.deleteProperty(microDoc, 'session_id');
212
+ Reflect.deleteProperty(microDoc, 'baseline_main_sha');
213
+ writeWU(microWuPath, microDoc);
214
+ return {
215
+ commitMessage: `fix(wu-recover): reset ${wuId} - clear claim and set status to ready`,
216
+ files: [relative(process.cwd(), wuPath)],
217
+ };
218
+ },
219
+ });
220
+ console.log(`${LOG_PREFIX} ${EMOJI.SUCCESS} Reset completed - ${wuId} is now ready for re-claiming`);
221
+ return true;
222
+ }
223
+ catch (err) {
224
+ console.error(`${LOG_PREFIX} ${EMOJI.FAILURE} Micro-worktree operation failed: ${err.message}`);
225
+ return false;
226
+ }
169
227
  }
170
228
  /**
171
229
  * Execute nuke action - remove all artifacts completely
@@ -241,8 +299,15 @@ async function executeCleanup(wuId) {
241
299
  }
242
300
  /**
243
301
  * Execute recovery action
302
+ *
303
+ * WU-1226: All state-modifying actions (resume, reset) now use micro-worktree
304
+ * isolation. Changes are pushed via merge, not direct file modification on main.
305
+ *
306
+ * @param action - Recovery action type
307
+ * @param wuId - WU ID to recover
308
+ * @returns Promise<boolean> - true if action succeeded
244
309
  */
245
- async function executeAction(action, wuId) {
310
+ export async function executeRecoveryAction(action, wuId) {
246
311
  switch (action) {
247
312
  case RECOVERY_ACTIONS.RESUME:
248
313
  return executeResume(wuId);
@@ -314,16 +379,17 @@ async function main() {
314
379
  die(`Action '${action}' requires --force flag`);
315
380
  }
316
381
  // Execute action
317
- const success = await executeAction(action, id);
382
+ const success = await executeRecoveryAction(action, id);
318
383
  if (!success) {
319
384
  console.error(`${LOG_PREFIX} ${EMOJI.FAILURE} Recovery action failed`);
320
385
  process.exit(1);
321
386
  }
322
387
  process.exit(0);
323
388
  }
324
- // Guard main() for testability
325
- import { fileURLToPath } from 'node:url';
389
+ // WU-1181: Use import.meta.main instead of process.argv[1] comparison
390
+ // The old pattern fails with pnpm symlinks because process.argv[1] is the symlink
391
+ // path but import.meta.url resolves to the real path - they never match
326
392
  import { runCLI } from './cli-entry-point.js';
327
- if (process.argv[1] === fileURLToPath(import.meta.url)) {
393
+ if (import.meta.main) {
328
394
  runCLI(main);
329
395
  }
package/dist/wu-repair.js CHANGED
@@ -41,9 +41,9 @@
41
41
  * - pnpm wu:repair-claim is deprecated. Use: pnpm wu:repair --claim
42
42
  * - pnpm wu:admin-repair is deprecated. Use: pnpm wu:repair --admin
43
43
  *
44
- * @see {@link tools/lib/wu-repair-core.mjs} - Core repair logic
45
- * @see {@link tools/lib/wu-consistency-checker.mjs} - Consistency detection/repair
46
- * @see {@link tools/lib/wu-state-store.mjs} - State file repair (repairStateFile)
44
+ * @see {@link packages/@lumenflow/cli/src/lib/wu-repair-core.ts} - Core repair logic
45
+ * @see {@link packages/@lumenflow/cli/src/lib/wu-consistency-checker.ts} - Consistency detection/repair
46
+ * @see {@link packages/@lumenflow/cli/src/lib/wu-state-store.ts} - State file repair (repairStateFile)
47
47
  */
48
48
  import { Command } from 'commander';
49
49
  import path from 'node:path';
@@ -217,10 +217,11 @@ async function main() {
217
217
  const result = await routeToRepairMode(options);
218
218
  process.exit(result.exitCode);
219
219
  }
220
- // Guard main() for testability (WU-1366)
221
- import { fileURLToPath } from 'node:url';
220
+ // WU-1181: Use import.meta.main instead of process.argv[1] comparison
221
+ // The old pattern fails with pnpm symlinks because process.argv[1] is the symlink
222
+ // path but import.meta.url resolves to the real path - they never match
222
223
  import { runCLI } from './cli-entry-point.js';
223
- if (process.argv[1] === fileURLToPath(import.meta.url)) {
224
+ if (import.meta.main) {
224
225
  runCLI(main);
225
226
  }
226
227
  // Export for testing