@lumenflow/cli 2.15.1 → 2.16.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.
Files changed (230) hide show
  1. package/dist/agent-issues-query.js +5 -5
  2. package/dist/agent-issues-query.js.map +1 -1
  3. package/dist/agent-log-issue.js +5 -4
  4. package/dist/agent-log-issue.js.map +1 -1
  5. package/dist/agent-session-end.js +3 -2
  6. package/dist/agent-session-end.js.map +1 -1
  7. package/dist/agent-session.js +3 -2
  8. package/dist/agent-session.js.map +1 -1
  9. package/dist/backlog-prune.js +5 -5
  10. package/dist/backlog-prune.js.map +1 -1
  11. package/dist/cli-entry-point.js +56 -3
  12. package/dist/cli-entry-point.js.map +1 -1
  13. package/dist/commands/integrate.js +4 -5
  14. package/dist/commands/integrate.js.map +1 -1
  15. package/dist/commands.js +1 -1
  16. package/dist/commands.js.map +1 -1
  17. package/dist/deps-add.js +65 -24
  18. package/dist/deps-add.js.map +1 -1
  19. package/dist/deps-remove.js +19 -11
  20. package/dist/deps-remove.js.map +1 -1
  21. package/dist/docs-sync.js +3 -2
  22. package/dist/docs-sync.js.map +1 -1
  23. package/dist/doctor.js +9 -4
  24. package/dist/doctor.js.map +1 -1
  25. package/dist/file-delete.js +1 -1
  26. package/dist/file-delete.js.map +1 -1
  27. package/dist/file-edit.js +1 -1
  28. package/dist/file-edit.js.map +1 -1
  29. package/dist/file-read.js +1 -1
  30. package/dist/file-read.js.map +1 -1
  31. package/dist/file-write.js +2 -2
  32. package/dist/file-write.js.map +1 -1
  33. package/dist/flow-bottlenecks.js +5 -6
  34. package/dist/flow-bottlenecks.js.map +1 -1
  35. package/dist/flow-report.js +4 -5
  36. package/dist/flow-report.js.map +1 -1
  37. package/dist/gate-defaults.js +149 -0
  38. package/dist/gate-defaults.js.map +1 -0
  39. package/dist/gate-registry.js +82 -0
  40. package/dist/gate-registry.js.map +1 -0
  41. package/dist/gates-types.js +10 -0
  42. package/dist/gates-types.js.map +1 -0
  43. package/dist/gates.js +163 -230
  44. package/dist/gates.js.map +1 -1
  45. package/dist/git-branch.js +1 -1
  46. package/dist/git-branch.js.map +1 -1
  47. package/dist/git-diff.js +1 -1
  48. package/dist/git-diff.js.map +1 -1
  49. package/dist/git-log.js +1 -1
  50. package/dist/git-log.js.map +1 -1
  51. package/dist/git-status.js +1 -1
  52. package/dist/git-status.js.map +1 -1
  53. package/dist/guard-locked.js +6 -7
  54. package/dist/guard-locked.js.map +1 -1
  55. package/dist/guard-main-branch.js +3 -2
  56. package/dist/guard-main-branch.js.map +1 -1
  57. package/dist/guard-worktree-commit.js +4 -5
  58. package/dist/guard-worktree-commit.js.map +1 -1
  59. package/dist/hooks/enforcement-generator.js +1 -1
  60. package/dist/hooks/enforcement-generator.js.map +1 -1
  61. package/dist/init.js +14 -6
  62. package/dist/init.js.map +1 -1
  63. package/dist/initiative-add-wu.js +12 -12
  64. package/dist/initiative-add-wu.js.map +1 -1
  65. package/dist/initiative-bulk-assign-wus.js +8 -9
  66. package/dist/initiative-bulk-assign-wus.js.map +1 -1
  67. package/dist/initiative-create.js +11 -11
  68. package/dist/initiative-create.js.map +1 -1
  69. package/dist/initiative-edit.js +9 -9
  70. package/dist/initiative-edit.js.map +1 -1
  71. package/dist/initiative-list.js +4 -4
  72. package/dist/initiative-list.js.map +1 -1
  73. package/dist/initiative-plan.js +12 -12
  74. package/dist/initiative-plan.js.map +1 -1
  75. package/dist/initiative-remove-wu.js +11 -11
  76. package/dist/initiative-remove-wu.js.map +1 -1
  77. package/dist/initiative-status.js +6 -6
  78. package/dist/initiative-status.js.map +1 -1
  79. package/dist/lane-health.js +2 -2
  80. package/dist/lane-health.js.map +1 -1
  81. package/dist/lane-suggest.js +2 -2
  82. package/dist/lane-suggest.js.map +1 -1
  83. package/dist/lifecycle-regression-harness.js +5 -5
  84. package/dist/lifecycle-regression-harness.js.map +1 -1
  85. package/dist/lumenflow-upgrade.js +4 -4
  86. package/dist/lumenflow-upgrade.js.map +1 -1
  87. package/dist/mem-checkpoint.js +8 -7
  88. package/dist/mem-checkpoint.js.map +1 -1
  89. package/dist/mem-cleanup.js +12 -14
  90. package/dist/mem-cleanup.js.map +1 -1
  91. package/dist/mem-context.js +8 -7
  92. package/dist/mem-context.js.map +1 -1
  93. package/dist/mem-create.js +9 -8
  94. package/dist/mem-create.js.map +1 -1
  95. package/dist/mem-delete.js +8 -7
  96. package/dist/mem-delete.js.map +1 -1
  97. package/dist/mem-export.js +9 -8
  98. package/dist/mem-export.js.map +1 -1
  99. package/dist/mem-inbox.js +40 -16
  100. package/dist/mem-inbox.js.map +1 -1
  101. package/dist/mem-index.js +8 -7
  102. package/dist/mem-index.js.map +1 -1
  103. package/dist/mem-init.js +8 -7
  104. package/dist/mem-init.js.map +1 -1
  105. package/dist/mem-profile.js +8 -7
  106. package/dist/mem-profile.js.map +1 -1
  107. package/dist/mem-promote.js +8 -7
  108. package/dist/mem-promote.js.map +1 -1
  109. package/dist/mem-ready.js +9 -8
  110. package/dist/mem-ready.js.map +1 -1
  111. package/dist/mem-recover.js +8 -7
  112. package/dist/mem-recover.js.map +1 -1
  113. package/dist/mem-signal.js +9 -8
  114. package/dist/mem-signal.js.map +1 -1
  115. package/dist/mem-start.js +8 -7
  116. package/dist/mem-start.js.map +1 -1
  117. package/dist/mem-summarize.js +8 -7
  118. package/dist/mem-summarize.js.map +1 -1
  119. package/dist/mem-triage.js +8 -7
  120. package/dist/mem-triage.js.map +1 -1
  121. package/dist/metrics-cli.js +5 -6
  122. package/dist/metrics-cli.js.map +1 -1
  123. package/dist/metrics-snapshot.js +6 -6
  124. package/dist/metrics-snapshot.js.map +1 -1
  125. package/dist/onboarding-smoke-test.js +3 -0
  126. package/dist/onboarding-smoke-test.js.map +1 -1
  127. package/dist/orchestrate-init-status.js +2 -2
  128. package/dist/orchestrate-init-status.js.map +1 -1
  129. package/dist/orchestrate-initiative.js +2 -2
  130. package/dist/orchestrate-initiative.js.map +1 -1
  131. package/dist/orchestrate-monitor.js +8 -1
  132. package/dist/orchestrate-monitor.js.map +1 -1
  133. package/dist/plan-create.js +8 -8
  134. package/dist/plan-create.js.map +1 -1
  135. package/dist/plan-edit.js +7 -7
  136. package/dist/plan-edit.js.map +1 -1
  137. package/dist/plan-link.js +9 -9
  138. package/dist/plan-link.js.map +1 -1
  139. package/dist/plan-promote.js +8 -8
  140. package/dist/plan-promote.js.map +1 -1
  141. package/dist/release.js +10 -9
  142. package/dist/release.js.map +1 -1
  143. package/dist/rotate-progress.js +4 -3
  144. package/dist/rotate-progress.js.map +1 -1
  145. package/dist/session-coordinator.js +2 -2
  146. package/dist/session-coordinator.js.map +1 -1
  147. package/dist/signal-cleanup.js +10 -13
  148. package/dist/signal-cleanup.js.map +1 -1
  149. package/dist/spawn-list.js +9 -10
  150. package/dist/spawn-list.js.map +1 -1
  151. package/dist/state-bootstrap.js +3 -3
  152. package/dist/state-bootstrap.js.map +1 -1
  153. package/dist/state-cleanup.js +13 -16
  154. package/dist/state-cleanup.js.map +1 -1
  155. package/dist/state-doctor-fix.js +14 -20
  156. package/dist/state-doctor-fix.js.map +1 -1
  157. package/dist/state-doctor-stamps.js +21 -0
  158. package/dist/state-doctor-stamps.js.map +1 -0
  159. package/dist/state-doctor.js +17 -26
  160. package/dist/state-doctor.js.map +1 -1
  161. package/dist/sync-templates.js +1 -0
  162. package/dist/sync-templates.js.map +1 -1
  163. package/dist/trace-gen.js +74 -10
  164. package/dist/trace-gen.js.map +1 -1
  165. package/dist/validate-agent-skills.js +6 -5
  166. package/dist/validate-agent-skills.js.map +1 -1
  167. package/dist/validate-agent-sync.js +4 -5
  168. package/dist/validate-agent-sync.js.map +1 -1
  169. package/dist/validate-backlog-sync.js +5 -6
  170. package/dist/validate-backlog-sync.js.map +1 -1
  171. package/dist/validate-skills-spec.js +6 -5
  172. package/dist/validate-skills-spec.js.map +1 -1
  173. package/dist/validate.js +6 -7
  174. package/dist/validate.js.map +1 -1
  175. package/dist/validator-defaults.js +119 -0
  176. package/dist/validator-defaults.js.map +1 -0
  177. package/dist/validator-registry.js +81 -0
  178. package/dist/validator-registry.js.map +1 -0
  179. package/dist/wu-block.js +20 -19
  180. package/dist/wu-block.js.map +1 -1
  181. package/dist/wu-claim-mode.js +1 -1
  182. package/dist/wu-claim-mode.js.map +1 -1
  183. package/dist/wu-claim.js +33 -32
  184. package/dist/wu-claim.js.map +1 -1
  185. package/dist/wu-cleanup.js +11 -11
  186. package/dist/wu-cleanup.js.map +1 -1
  187. package/dist/wu-create.js +27 -27
  188. package/dist/wu-create.js.map +1 -1
  189. package/dist/wu-delete.js +16 -17
  190. package/dist/wu-delete.js.map +1 -1
  191. package/dist/wu-deps.js +7 -7
  192. package/dist/wu-deps.js.map +1 -1
  193. package/dist/wu-done-auto-cleanup.js +46 -21
  194. package/dist/wu-done-auto-cleanup.js.map +1 -1
  195. package/dist/wu-done-check.js +3 -2
  196. package/dist/wu-done-check.js.map +1 -1
  197. package/dist/wu-done-decay.js +3 -7
  198. package/dist/wu-done-decay.js.map +1 -1
  199. package/dist/wu-done.js +132 -66
  200. package/dist/wu-done.js.map +1 -1
  201. package/dist/wu-edit.js +22 -23
  202. package/dist/wu-edit.js.map +1 -1
  203. package/dist/wu-infer-lane.js +6 -6
  204. package/dist/wu-infer-lane.js.map +1 -1
  205. package/dist/wu-preflight.js +7 -7
  206. package/dist/wu-preflight.js.map +1 -1
  207. package/dist/wu-prep.js +10 -8
  208. package/dist/wu-prep.js.map +1 -1
  209. package/dist/wu-proto.js +14 -14
  210. package/dist/wu-proto.js.map +1 -1
  211. package/dist/wu-prune.js +7 -7
  212. package/dist/wu-prune.js.map +1 -1
  213. package/dist/wu-recover.js +13 -13
  214. package/dist/wu-recover.js.map +1 -1
  215. package/dist/wu-release.js +17 -16
  216. package/dist/wu-release.js.map +1 -1
  217. package/dist/wu-repair.js +4 -4
  218. package/dist/wu-repair.js.map +1 -1
  219. package/dist/wu-spawn.js +20 -20
  220. package/dist/wu-spawn.js.map +1 -1
  221. package/dist/wu-status.js +5 -5
  222. package/dist/wu-status.js.map +1 -1
  223. package/dist/wu-unblock.js +23 -22
  224. package/dist/wu-unblock.js.map +1 -1
  225. package/dist/wu-unlock-lane.js +5 -5
  226. package/dist/wu-unlock-lane.js.map +1 -1
  227. package/dist/wu-validate.js +8 -8
  228. package/dist/wu-validate.js.map +1 -1
  229. package/package.json +7 -6
  230. package/templates/core/ai/onboarding/docs-generation.md.template +1 -1
package/dist/wu-done.js CHANGED
@@ -32,7 +32,7 @@
32
32
  * Full migration to thin shim pending @lumenflow/core CLI export implementation.
33
33
  */
34
34
  // WU-2542: Import from @lumenflow/core to establish shim layer dependency
35
- import { VERSION as LUMENFLOW_VERSION } from '@lumenflow/core';
35
+ import '@lumenflow/core';
36
36
  // WU-1153: wu:done guard for uncommitted code_paths is implemented in core package
37
37
  // The guard runs in executeWorktreeCompletion() before metadata transaction
38
38
  // See: packages/@lumenflow/core/src/wu-done-validation.ts
@@ -40,19 +40,19 @@ import { execSync } from 'node:child_process';
40
40
  import prettyMs from 'pretty-ms';
41
41
  import { runGates } from './gates.js';
42
42
  import { buildClaimRepairCommand } from './wu-claim-repair-guidance.js';
43
- import { getGitForCwd } from '@lumenflow/core/dist/git-adapter.js';
44
- import { die } from '@lumenflow/core/dist/error-handler.js';
43
+ import { getGitForCwd, createGitForPath } from '@lumenflow/core/git-adapter';
44
+ import { die } from '@lumenflow/core/error-handler';
45
45
  // WU-1223: Location detection for worktree check
46
- import { resolveLocation } from '@lumenflow/core/dist/context/location-resolver.js';
46
+ import { resolveLocation } from '@lumenflow/core/context/location-resolver';
47
47
  import { existsSync, readFileSync, mkdirSync, appendFileSync, unlinkSync, statSync } from 'node:fs';
48
48
  import path from 'node:path';
49
49
  // WU-1825: Import from unified code-path-validator (consolidates 3 validators)
50
- import { validateWUCodePaths } from '@lumenflow/core/dist/code-path-validator.js';
50
+ import { validateWUCodePaths } from '@lumenflow/core/code-path-validator';
51
51
  // WU-1983: Migration deployment utilities
52
- import { discoverLocalMigrations, hasMigrationChanges, formatMigrationReport, } from '@lumenflow/core/dist/migration-deployer.js';
53
- import { validateDocsOnly, getAllowedPathsDescription, } from '@lumenflow/core/dist/docs-path-validator.js';
54
- import { scanLogForViolations, rotateLog } from '@lumenflow/core/dist/commands-logger.js';
55
- import { rollbackFiles } from '@lumenflow/core/dist/rollback-utils.js';
52
+ import { discoverLocalMigrations, hasMigrationChanges } from '@lumenflow/core/migration-deployer';
53
+ import { validateDocsOnly, getAllowedPathsDescription } from '@lumenflow/core/docs-path-validator';
54
+ import { scanLogForViolations, rotateLog } from '@lumenflow/core/commands-logger';
55
+ import { rollbackFiles } from '@lumenflow/core/rollback-utils';
56
56
  import { validateInputs, detectModeAndPaths, defaultBranchFrom, runCleanup, validateSpecCompleteness, runPreflightTasksValidation, buildPreflightErrorMessage,
57
57
  // WU-1805: Preflight code_paths validation before gates
58
58
  executePreflightCodePathValidation, buildPreflightCodePathErrorMessage,
@@ -61,47 +61,47 @@ validateAllPreCommitHooks,
61
61
  // WU-2310: Type vs code_paths preflight validation
62
62
  validateTypeVsCodePathsPreflight, buildTypeVsCodePathsErrorMessage,
63
63
  // WU-1503: Dirty-main pre-merge guard
64
- validateDirtyMain, buildDirtyMainErrorMessage, } from '@lumenflow/core/dist/wu-done-validators.js';
64
+ validateDirtyMain, buildDirtyMainErrorMessage, } from '@lumenflow/core/wu-done-validators';
65
65
  // WU-1825: validateCodePathsExist moved to unified code-path-validator
66
- import { validateCodePathsExist } from '@lumenflow/core/dist/code-path-validator.js';
67
- import { BRANCHES, REMOTES, PATTERNS, DEFAULTS, LOG_PREFIX, EMOJI, GIT, SESSION, WU_STATUS, WU_EXPOSURE, PKG_MANAGER, SCRIPTS, CLI_FLAGS, FILE_SYSTEM, STDIO, EXIT_CODES, STRING_LITERALS, MICRO_WORKTREE_OPERATIONS, TELEMETRY_STEPS, SKIP_GATES_REASONS, CHECKPOINT_MESSAGES,
66
+ import { validateCodePathsExist } from '@lumenflow/core/code-path-validator';
67
+ import { BRANCHES, REMOTES, PATTERNS, DEFAULTS, LOG_PREFIX, EMOJI, GIT, SESSION, WU_STATUS, WU_EXPOSURE, PKG_MANAGER, SCRIPTS, CLI_FLAGS, FILE_SYSTEM, EXIT_CODES, STRING_LITERALS, MICRO_WORKTREE_OPERATIONS, TELEMETRY_STEPS, SKIP_GATES_REASONS, CHECKPOINT_MESSAGES, LUMENFLOW_PATHS,
68
68
  // WU-1223: Location types for worktree detection
69
- CONTEXT_VALIDATION, } from '@lumenflow/core/dist/wu-constants.js';
70
- import { isDocumentationType } from '@lumenflow/core/dist/wu-type-helpers.js';
71
- import { printGateFailureBox, printStatusPreview } from '@lumenflow/core/dist/wu-done-ui.js';
72
- import { ensureOnMain } from '@lumenflow/core/dist/wu-helpers.js';
73
- import { WU_PATHS, createWuPaths } from '@lumenflow/core/dist/wu-paths.js';
74
- import { getConfig } from '@lumenflow/core/dist/lumenflow-config.js';
75
- import { writeWU, appendNote, parseYAML } from '@lumenflow/core/dist/wu-yaml.js';
76
- import { PLACEHOLDER_SENTINEL, validateWU, validateDoneWU, validateApprovalGates, } from '@lumenflow/core/dist/wu-schema.js';
77
- import { validateBacklogSync } from '@lumenflow/core/dist/backlog-sync-validator.js';
69
+ CONTEXT_VALIDATION, } from '@lumenflow/core/wu-constants';
70
+ import { isDocumentationType } from '@lumenflow/core/wu-type-helpers';
71
+ import { printGateFailureBox, printStatusPreview } from '@lumenflow/core/wu-done-ui';
72
+ import { ensureOnMain } from '@lumenflow/core/wu-helpers';
73
+ import { WU_PATHS } from '@lumenflow/core/wu-paths';
74
+ import { getConfig } from '@lumenflow/core/config';
75
+ import { writeWU, appendNote, parseYAML } from '@lumenflow/core/wu-yaml';
76
+ import { PLACEHOLDER_SENTINEL, validateWU, validateDoneWU, validateApprovalGates, } from '@lumenflow/core/wu-schema';
77
+ import { validateBacklogSync } from '@lumenflow/core/backlog-sync-validator';
78
78
  import { executeBranchOnlyCompletion,
79
79
  // WU-1492: Import branch-pr completion path
80
- executeBranchPRCompletion, } from '@lumenflow/core/dist/wu-done-branch-only.js';
81
- import { executeWorktreeCompletion, autoRebaseBranch, } from '@lumenflow/core/dist/wu-done-worktree.js';
82
- import { checkWUConsistency } from '@lumenflow/core/dist/wu-consistency-checker.js';
80
+ executeBranchPRCompletion, } from '@lumenflow/core/wu-done-branch-only';
81
+ import { executeWorktreeCompletion, autoRebaseBranch } from '@lumenflow/core/wu-done-worktree';
82
+ import { checkWUConsistency } from '@lumenflow/core/wu-consistency-checker';
83
83
  // WU-1542: Use blocking mode compliance check (replaces non-blocking checkMandatoryAgentsCompliance)
84
- import { checkMandatoryAgentsComplianceBlocking } from '@lumenflow/core/dist/orchestration-rules.js';
85
- import { endSessionForWU } from '@lumenflow/agent/dist/auto-session-integration.js';
86
- import { runBackgroundProcessCheck } from '@lumenflow/core/dist/process-detector.js';
87
- import { WUStateStore } from '@lumenflow/core/dist/wu-state-store.js';
84
+ import { checkMandatoryAgentsComplianceBlocking } from '@lumenflow/core/orchestration-rules';
85
+ import { endSessionForWU } from '@lumenflow/agent/auto-session';
86
+ import { runBackgroundProcessCheck } from '@lumenflow/core/process-detector';
87
+ import { WUStateStore } from '@lumenflow/core/wu-state-store';
88
88
  // WU-1588: INIT-007 memory layer integration
89
- import { createCheckpoint } from '@lumenflow/memory/dist/mem-checkpoint-core.js';
90
- import { createSignal, loadSignals } from '@lumenflow/memory/dist/mem-signal-core.js';
89
+ import { createCheckpoint } from '@lumenflow/memory/checkpoint';
90
+ import { createSignal, loadSignals } from '@lumenflow/memory/signal';
91
91
  // WU-1763: Memory store for loading discoveries (lifecycle nudges)
92
- import { loadMemory, queryByWu } from '@lumenflow/memory/dist/memory-store.js';
92
+ import { loadMemory, queryByWu } from '@lumenflow/memory/store';
93
93
  // WU-1943: Checkpoint warning helper
94
- import { hasSessionCheckpoints } from '@lumenflow/core/dist/wu-done-worktree.js';
94
+ import { hasSessionCheckpoints } from '@lumenflow/core/wu-done-worktree';
95
95
  // WU-1603: Atomic lane locking - release lock on WU completion
96
- import { releaseLaneLock } from '@lumenflow/core/dist/lane-lock.js';
96
+ import { releaseLaneLock } from '@lumenflow/core/lane-lock';
97
97
  // WU-1747: Checkpoint and lock for concurrent load resilience
98
- import { createPreGatesCheckpoint as createWU1747Checkpoint, markGatesPassed, canSkipGates, clearCheckpoint, } from '@lumenflow/core/dist/wu-checkpoint.js';
98
+ import { createPreGatesCheckpoint as createWU1747Checkpoint, markGatesPassed, canSkipGates, clearCheckpoint, } from '@lumenflow/core/wu-checkpoint';
99
99
  // WU-1946: Spawn registry for tracking sub-agent spawns
100
- import { SpawnRegistryStore } from '@lumenflow/core/dist/spawn-registry-store.js';
101
- import { SpawnStatus } from '@lumenflow/core/dist/spawn-registry-schema.js';
100
+ import { SpawnRegistryStore } from '@lumenflow/core/spawn-registry-store';
101
+ import { SpawnStatus } from '@lumenflow/core/spawn-registry-schema';
102
102
  // WU-1999: Exposure validation for UI pairing
103
103
  // WU-2022: Feature accessibility validation (blocking)
104
- import { validateExposure, validateFeatureAccessibility, } from '@lumenflow/core/dist/wu-validation.js';
104
+ import { validateExposure, validateFeatureAccessibility } from '@lumenflow/core/wu-validation';
105
105
  import { ensureCleanWorktree } from './wu-done-check.js';
106
106
  // WU-1366: Auto cleanup after wu:done success
107
107
  // WU-1533: commitCleanupChanges auto-commits dirty state files after cleanup
@@ -120,8 +120,7 @@ const MEMORY_CHECKPOINT_NOTES = {
120
120
  PRE_GATES: 'Pre-gates checkpoint for recovery if gates fail',
121
121
  };
122
122
  const MEMORY_SIGNAL_WINDOW_MS = 60 * 60 * 1000; // 1 hour for recent signals
123
- // Path constant for wu-events.jsonl (used in multiple places)
124
- const WU_EVENTS_PATH = '.lumenflow/state/wu-events.jsonl';
123
+ // WU-1539: Use centralized LUMENFLOW_PATHS.WU_EVENTS instead of local constant
125
124
  /**
126
125
  * WU-1804: Preflight validation for claim metadata before gates.
127
126
  *
@@ -146,7 +145,7 @@ async function validateClaimMetadataBeforeGates(id, worktreePath, yamlStatus) {
146
145
  // Check 2: State store must show WU as in_progress
147
146
  const resolvedWorktreePath = path.resolve(worktreePath);
148
147
  const stateDir = path.join(resolvedWorktreePath, '.lumenflow', 'state');
149
- const eventsPath = path.join(resolvedWorktreePath, WU_EVENTS_PATH);
148
+ const eventsPath = path.join(resolvedWorktreePath, LUMENFLOW_PATHS.WU_EVENTS);
150
149
  try {
151
150
  const store = new WUStateStore(stateDir);
152
151
  await store.load();
@@ -273,10 +272,10 @@ export function buildGatesCommand(options) {
273
272
  }
274
273
  return `${PKG_MANAGER} ${SCRIPTS.GATES}`;
275
274
  }
276
- async function assertWorktreeWUInProgressInStateStore(id, worktreePath) {
275
+ async function _assertWorktreeWUInProgressInStateStore(id, worktreePath) {
277
276
  const resolvedWorktreePath = path.resolve(worktreePath);
278
277
  const stateDir = path.join(resolvedWorktreePath, '.lumenflow', 'state');
279
- const eventsPath = path.join(resolvedWorktreePath, WU_EVENTS_PATH);
278
+ const eventsPath = path.join(resolvedWorktreePath, LUMENFLOW_PATHS.WU_EVENTS);
280
279
  const store = new WUStateStore(stateDir);
281
280
  try {
282
281
  await store.load();
@@ -475,7 +474,7 @@ export async function isBranchAlreadyMerged(branch) {
475
474
  // WU-1281: isDocsOnlyByPaths removed - use shouldSkipWebTests from path-classifiers.ts
476
475
  // The validators already use shouldSkipWebTests via detectDocsOnlyByPaths wrapper.
477
476
  // Keeping the export for backward compatibility but re-exporting the canonical function.
478
- export { shouldSkipWebTests as isDocsOnlyByPaths } from '@lumenflow/core/dist/path-classifiers.js';
477
+ export { shouldSkipWebTests as isDocsOnlyByPaths } from '@lumenflow/core/path-classifiers';
479
478
  /**
480
479
  * WU-1234: Pre-flight check for backlog state consistency
481
480
  * Fails fast if the WU appears in both Done and In Progress sections.
@@ -543,7 +542,7 @@ function getCommitHeaderLimit() {
543
542
  * Context: WU-635 (multi-agent coordination)
544
543
  * See: CLAUDE.md §2.2
545
544
  */
546
- async function ensureCleanWorkingTree() {
545
+ async function _ensureCleanWorkingTree() {
547
546
  const status = await getGitForCwd().getStatus();
548
547
  if (status.trim()) {
549
548
  die(`Working tree is not clean. Cannot proceed with wu:done.\n\n` +
@@ -567,6 +566,17 @@ const INTERNAL_LIFECYCLE_DIRTY_FILES = new Set([
567
566
  '.lumenflow/skip-gates-audit.log',
568
567
  '.lumenflow/skip-cos-gates-audit.log',
569
568
  ]);
569
+ /**
570
+ * WU-1554: Prefixes for metadata files that wu:done manages.
571
+ * These files may be dirty after merge+rebase when wu:claim used push-only mode
572
+ * or when concurrent agents advance origin/main. Instead of blocking wu:done,
573
+ * these are auto-committed by the caller.
574
+ */
575
+ const METADATA_LIFECYCLE_PREFIXES = [
576
+ '.lumenflow/state/',
577
+ '.lumenflow/stamps/',
578
+ '.lumenflow/archive/',
579
+ ];
570
580
  function parsePorcelainPath(line) {
571
581
  if (line.length < 4)
572
582
  return null;
@@ -579,6 +589,20 @@ function parsePorcelainPath(line) {
579
589
  }
580
590
  return pathPart;
581
591
  }
592
+ /**
593
+ * WU-1554: Check if a file is a metadata lifecycle file.
594
+ * Metadata files are managed by wu:done (wu-events.jsonl, status.md, backlog.md,
595
+ * WU YAML, stamps, archives) and may be dirty after merge+rebase.
596
+ */
597
+ function isMetadataLifecycleFile(filePath, metadataDir) {
598
+ if (METADATA_LIFECYCLE_PREFIXES.some((prefix) => filePath.startsWith(prefix))) {
599
+ return true;
600
+ }
601
+ if (metadataDir && filePath.startsWith(metadataDir + '/')) {
602
+ return true;
603
+ }
604
+ return false;
605
+ }
582
606
  /**
583
607
  * WU-1084: Check for uncommitted changes on main after merge completes.
584
608
  *
@@ -586,26 +610,34 @@ function parsePorcelainPath(line) {
586
610
  * outside the WU's code_paths during worktree work. These changes survive
587
611
  * the merge and would be silently left behind when the worktree is removed.
588
612
  *
613
+ * WU-1554: Added metadataDir parameter and metadataFiles return field.
614
+ * Metadata files (wu-events.jsonl, status.md, backlog.md, WU YAML, stamps)
615
+ * may be dirty after merge+rebase when wu:claim used push-only mode.
616
+ * These are returned separately for auto-commit by the caller.
617
+ *
589
618
  * @param gitStatus - Output from git status (porcelain format)
590
619
  * @param wuId - The WU ID for error messaging
591
- * @returns Object with isDirty flag and optional error message
620
+ * @param metadataDir - Optional task directory prefix for metadata file detection
621
+ * @returns Object with isDirty flag, file categories, and optional error message
592
622
  */
593
- export function checkPostMergeDirtyState(gitStatus, wuId) {
623
+ export function checkPostMergeDirtyState(gitStatus, wuId, metadataDir) {
594
624
  // WU-1522: Split before trimming to preserve leading spaces in porcelain format.
595
625
  // Porcelain lines like ' M .lumenflow/flow.log' use the leading space as a status
596
626
  // indicator (working tree vs staging area). Trimming the whole string first strips
597
627
  // the leading space from the first line, corrupting parsePorcelainPath output.
598
628
  const lines = gitStatus.split('\n').filter((line) => line.length >= 4);
599
629
  if (lines.length === 0) {
600
- return { isDirty: false, internalOnlyFiles: [], unrelatedFiles: [] };
630
+ return { isDirty: false, internalOnlyFiles: [], metadataFiles: [], unrelatedFiles: [] };
601
631
  }
602
632
  const dirtyFiles = lines
603
633
  .map((line) => parsePorcelainPath(line))
604
634
  .filter((value) => Boolean(value));
635
+ // WU-1554: Three-category classification
605
636
  const internalOnlyFiles = dirtyFiles.filter((file) => INTERNAL_LIFECYCLE_DIRTY_FILES.has(file));
606
- const unrelatedFiles = dirtyFiles.filter((file) => !INTERNAL_LIFECYCLE_DIRTY_FILES.has(file));
637
+ const metadataFiles = dirtyFiles.filter((file) => !INTERNAL_LIFECYCLE_DIRTY_FILES.has(file) && isMetadataLifecycleFile(file, metadataDir));
638
+ const unrelatedFiles = dirtyFiles.filter((file) => !INTERNAL_LIFECYCLE_DIRTY_FILES.has(file) && !isMetadataLifecycleFile(file, metadataDir));
607
639
  if (unrelatedFiles.length === 0) {
608
- return { isDirty: false, internalOnlyFiles, unrelatedFiles: [] };
640
+ return { isDirty: false, internalOnlyFiles, metadataFiles, unrelatedFiles: [] };
609
641
  }
610
642
  const displayStatus = gitStatus.trim();
611
643
  const error = `Main branch has uncommitted changes after merge:\n\n${displayStatus}\n\n` +
@@ -616,7 +648,7 @@ export function checkPostMergeDirtyState(gitStatus, wuId) {
616
648
  ` 1. Review and commit the changes: git add . && git commit -m "format: fix formatting"\n` +
617
649
  ` 2. Discard if unwanted: git checkout -- .\n` +
618
650
  ` 3. Then re-run: pnpm wu:done --id ${wuId} --skip-worktree-completion`;
619
- return { isDirty: true, internalOnlyFiles, unrelatedFiles, error };
651
+ return { isDirty: true, internalOnlyFiles, metadataFiles, unrelatedFiles, error };
620
652
  }
621
653
  /**
622
654
  * Extract completed WU IDs from git log output.
@@ -828,9 +860,10 @@ function runTripwireCheck() {
828
860
  rotateLog();
829
861
  process.exit(EXIT_CODES.ERROR);
830
862
  }
831
- async function listStaged() {
832
- // WU-1235: Use getGitForCwd() to capture current directory (worktree after chdir)
833
- const gitCwd = getGitForCwd();
863
+ async function listStaged(gitAdapter) {
864
+ // WU-1541: Use explicit gitAdapter if provided, otherwise fall back to getGitForCwd()
865
+ // WU-1235: getGitForCwd() captures current directory (legacy behavior)
866
+ const gitCwd = gitAdapter ?? getGitForCwd();
834
867
  const raw = await gitCwd.raw(['diff', '--cached', '--name-only']);
835
868
  return raw ? raw.split(/\r?\n/).filter(Boolean) : [];
836
869
  }
@@ -1018,8 +1051,9 @@ async function runGatesInWorktree(worktreePath, id, options = {}) {
1018
1051
  die(`Gates failed in ${worktreePath}. Fix issues in the worktree and try again.`);
1019
1052
  }
1020
1053
  }
1021
- async function validateStagedFiles(id, isDocsOnly = false) {
1022
- const staged = await listStaged();
1054
+ async function validateStagedFiles(id, isDocsOnly = false, gitAdapter, options = {}) {
1055
+ // WU-1541: Accept optional gitAdapter to avoid process.chdir dependency
1056
+ const staged = await listStaged(gitAdapter);
1023
1057
  // WU-1311: Use config-based paths instead of hardcoded docs/04-operations paths
1024
1058
  const config = getConfig();
1025
1059
  const wuPath = `${config.directories.wuDir}/${id}.yaml`;
@@ -1028,8 +1062,10 @@ async function validateStagedFiles(id, isDocsOnly = false) {
1028
1062
  wuPath,
1029
1063
  config.directories.statusPath,
1030
1064
  config.directories.backlogPath,
1031
- WU_EVENTS_PATH,
1065
+ LUMENFLOW_PATHS.WU_EVENTS,
1032
1066
  ];
1067
+ const metadataAllowlist = (options.metadataAllowlist ?? []).filter((file) => typeof file === 'string' && file.length > 0);
1068
+ const whitelistSet = new Set([...whitelist, ...metadataAllowlist]);
1033
1069
  if (isDocsOnly) {
1034
1070
  // For docs-only WUs, validate that all staged files are in allowed paths
1035
1071
  const docsResult = validateDocsOnly(staged);
@@ -1041,10 +1077,10 @@ async function validateStagedFiles(id, isDocsOnly = false) {
1041
1077
  }
1042
1078
  const unexpected = staged.filter((file) => {
1043
1079
  // Whitelist exact matches
1044
- if (whitelist.includes(file))
1080
+ if (whitelistSet.has(file))
1045
1081
  return false;
1046
- // Whitelist .lumenflow/stamps/** pattern
1047
- if (file.startsWith('.lumenflow/stamps/'))
1082
+ // Whitelist stamps directory pattern
1083
+ if (file.startsWith(`${LUMENFLOW_PATHS.STAMPS_DIR}/`))
1048
1084
  return false;
1049
1085
  // WU-1072: Whitelist apps/docs/**/*.mdx for auto-generated docs from turbo docs:generate
1050
1086
  if (file.startsWith('apps/docs/') && file.endsWith('.mdx'))
@@ -1054,13 +1090,14 @@ async function validateStagedFiles(id, isDocsOnly = false) {
1054
1090
  if (unexpected.length > 0) {
1055
1091
  // WU-1311: Use config-based pattern for WU YAML detection
1056
1092
  const wuDirPattern = config.directories.wuDir.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
1093
+ // eslint-disable-next-line security/detect-non-literal-regexp -- config path escaped for regex; not user input
1057
1094
  const wuYamlRegex = new RegExp(`^${wuDirPattern}/WU-\\d+\\.yaml$`);
1058
1095
  const otherWuYamlOnly = unexpected.every((f) => wuYamlRegex.test(f));
1059
1096
  if (otherWuYamlOnly) {
1060
1097
  console.warn(`${LOG_PREFIX.DONE} Warning: other WU YAMLs are staged; proceeding and committing only current WU files.`);
1061
1098
  }
1062
1099
  else {
1063
- die(`Unexpected files staged (only current WU YAML, status.md, backlog.md, .lumenflow/stamps/<id>.done allowed):\n ${unexpected.join(`${STRING_LITERALS.NEWLINE} `)}`);
1100
+ die(`Unexpected files staged (only current WU metadata, current parent initiative YAML, and .lumenflow/stamps/<id>.done allowed):\n ${unexpected.join(`${STRING_LITERALS.NEWLINE} `)}`);
1064
1101
  }
1065
1102
  }
1066
1103
  }
@@ -1579,6 +1616,16 @@ async function executePreFlightChecks({ id, args, isBranchOnly, isDocsOnly, docM
1579
1616
  }
1580
1617
  else if (dirtyResult.relatedFiles.length > 0) {
1581
1618
  console.log(`${LOG_PREFIX.DONE} ${EMOJI.INFO} WU-1503: ${dirtyResult.relatedFiles.length} related dirty file(s) on main (allowed)`);
1619
+ // WU-1554: Auto-restore related dirty files so ff-only merge can proceed.
1620
+ // These files will be overwritten by the merge commit anyway.
1621
+ // Without this, git merge --ff-only refuses to overwrite dirty tracked files.
1622
+ try {
1623
+ await gitAdapter.raw(['checkout', '--', ...dirtyResult.relatedFiles]);
1624
+ console.log(`${LOG_PREFIX.DONE} ${EMOJI.INFO} WU-1554: Auto-restored ${dirtyResult.relatedFiles.length} related file(s) for clean merge`);
1625
+ }
1626
+ catch (restoreErr) {
1627
+ console.warn(`${LOG_PREFIX.DONE} ${EMOJI.WARNING} WU-1554: Could not auto-restore related files: ${restoreErr.message}`);
1628
+ }
1582
1629
  }
1583
1630
  }
1584
1631
  }
@@ -1589,7 +1636,7 @@ async function executePreFlightChecks({ id, args, isBranchOnly, isDocsOnly, docM
1589
1636
  // which causes the auto-rebase to fail with "You have unstaged changes"
1590
1637
  if (derivedWorktree) {
1591
1638
  try {
1592
- execSync(`git -C "${derivedWorktree}" restore "${WU_EVENTS_PATH}"`);
1639
+ execSync(`git -C "${derivedWorktree}" restore "${LUMENFLOW_PATHS.WU_EVENTS}"`);
1593
1640
  }
1594
1641
  catch {
1595
1642
  // Non-fatal: file might not exist or already clean
@@ -1812,7 +1859,7 @@ async function executeGates({ id, args, isBranchOnly, isDocsOnly, worktreePath,
1812
1859
  // This restores the file to HEAD state - checkpoint data is preserved in memory store
1813
1860
  if (worktreePath) {
1814
1861
  try {
1815
- execSync(`git -C "${worktreePath}" restore "${WU_EVENTS_PATH}"`);
1862
+ execSync(`git -C "${worktreePath}" restore "${LUMENFLOW_PATHS.WU_EVENTS}"`);
1816
1863
  }
1817
1864
  catch {
1818
1865
  // Non-fatal: file might not exist or already clean
@@ -1825,7 +1872,7 @@ async function executeGates({ id, args, isBranchOnly, isDocsOnly, worktreePath,
1825
1872
  const invariantsBaseDir = worktreePath || process.cwd();
1826
1873
  console.log(`\n${LOG_PREFIX.DONE} Running invariants check (non-bypassable)...`);
1827
1874
  console.log(`${LOG_PREFIX.DONE} Checking invariants in: ${invariantsBaseDir}`);
1828
- const { runInvariants } = await import('@lumenflow/core/dist/invariants-runner.js');
1875
+ const { runInvariants } = await import('@lumenflow/core/invariants-runner');
1829
1876
  const invariantsResult = runInvariants({ baseDir: invariantsBaseDir, silent: false, wuId: id });
1830
1877
  if (!invariantsResult.success) {
1831
1878
  emitTelemetry({
@@ -2175,9 +2222,12 @@ async function main() {
2175
2222
  else {
2176
2223
  // Worktree mode: update in worktree, commit, then merge or create PR
2177
2224
  // WU-1369: Uses atomic transaction pattern
2225
+ // WU-1541: Create worktree-aware validateStagedFiles to avoid process.chdir dependency
2226
+ const worktreeGitForValidation = createGitForPath(worktreePath);
2178
2227
  const worktreeContext = {
2179
2228
  ...baseContext,
2180
2229
  worktreePath,
2230
+ validateStagedFiles: (wuId, docsOnly, options) => validateStagedFiles(wuId, docsOnly, worktreeGitForValidation, options),
2181
2231
  };
2182
2232
  completionResult = await executeWorktreeCompletion(worktreeContext);
2183
2233
  }
@@ -2219,9 +2269,10 @@ async function main() {
2219
2269
  await ensureNoAutoStagedOrNoop([WU_PATH, STATUS_PATH, BACKLOG_PATH, STAMPS_DIR]);
2220
2270
  }
2221
2271
  // WU-1084: Check for uncommitted changes on main after merge
2222
- // This catches cases where pnpm format touched files outside code_paths
2272
+ // WU-1554: Pass metadataDir so metadata files are classified separately
2273
+ const metadataDir = path.dirname(STATUS_PATH);
2223
2274
  const postMergeStatus = await getGitForCwd().getStatus();
2224
- const dirtyCheck = checkPostMergeDirtyState(postMergeStatus, id);
2275
+ const dirtyCheck = checkPostMergeDirtyState(postMergeStatus, id, metadataDir);
2225
2276
  if (dirtyCheck.internalOnlyFiles.length > 0) {
2226
2277
  const gitMain = getGitForCwd();
2227
2278
  try {
@@ -2232,6 +2283,21 @@ async function main() {
2232
2283
  console.warn(`${LOG_PREFIX.DONE} ${EMOJI.WARNING} Could not auto-restore internal lifecycle files: ${restoreErr.message}`);
2233
2284
  }
2234
2285
  }
2286
+ // WU-1554: Auto-commit metadata files left dirty after merge+rebase
2287
+ // This handles push-only claim mode and concurrent agent advancement
2288
+ if (dirtyCheck.metadataFiles.length > 0) {
2289
+ const gitMain = getGitForCwd();
2290
+ try {
2291
+ await gitMain.add(dirtyCheck.metadataFiles);
2292
+ await gitMain.commit(`chore: post-merge metadata sync for ${id} [skip ci]`);
2293
+ await gitMain.raw(['pull', '--rebase', '--autostash', 'origin', 'main']);
2294
+ await gitMain.push('origin', 'main');
2295
+ console.log(`${LOG_PREFIX.DONE} ${EMOJI.SUCCESS} Auto-committed post-merge metadata: ${dirtyCheck.metadataFiles.join(', ')}`);
2296
+ }
2297
+ catch (commitErr) {
2298
+ console.warn(`${LOG_PREFIX.DONE} ${EMOJI.WARNING} Could not auto-commit metadata files: ${commitErr.message}`);
2299
+ }
2300
+ }
2235
2301
  if (dirtyCheck.isDirty) {
2236
2302
  die(dirtyCheck.error);
2237
2303
  }
@@ -2454,6 +2520,6 @@ async function detectChangedDocPaths(worktreePath, baseBranch) {
2454
2520
  // path but import.meta.url resolves to the real path - they never match
2455
2521
  import { runCLI } from './cli-entry-point.js';
2456
2522
  if (import.meta.main) {
2457
- runCLI(main);
2523
+ void runCLI(main);
2458
2524
  }
2459
2525
  //# sourceMappingURL=wu-done.js.map