@lumenflow/cli 3.1.2 → 3.1.3

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 (389) hide show
  1. package/README.md +36 -35
  2. package/dist/agent-issues-query.js +13 -8
  3. package/dist/agent-log-issue.js +15 -4
  4. package/dist/agent-session-end.js +15 -4
  5. package/dist/agent-session.js +18 -6
  6. package/dist/backlog-prune.js +1 -1
  7. package/dist/commands/integrate.js +32 -18
  8. package/dist/config-get.js +27 -15
  9. package/dist/config-set.js +104 -37
  10. package/dist/delegation-list.js +1 -1
  11. package/dist/doctor.js +19 -13
  12. package/dist/file-delete.js +1 -1
  13. package/dist/file-edit.js +1 -1
  14. package/dist/file-read.js +1 -1
  15. package/dist/file-write.js +1 -1
  16. package/dist/flow-bottlenecks.js +1 -1
  17. package/dist/flow-report.js +10 -9
  18. package/dist/gates.js +3 -2
  19. package/dist/git-branch.js +1 -1
  20. package/dist/git-diff.js +1 -1
  21. package/dist/git-log.js +1 -1
  22. package/dist/init.js +238 -42
  23. package/dist/initiative-add-wu.js +1 -1
  24. package/dist/initiative-bulk-assign-wus.js +1 -1
  25. package/dist/initiative-create.js +2 -2
  26. package/dist/initiative-edit.js +1 -1
  27. package/dist/initiative-list.js +1 -1
  28. package/dist/initiative-plan.js +1 -3
  29. package/dist/initiative-status.js +47 -6
  30. package/dist/lane-edit.js +19 -10
  31. package/dist/lane-health.js +13 -24
  32. package/dist/lane-lock.js +4 -5
  33. package/dist/lane-setup.js +5 -5
  34. package/dist/lane-status.js +4 -5
  35. package/dist/lane-suggest.js +9 -7
  36. package/dist/lane-validate.js +4 -5
  37. package/dist/lumenflow-upgrade.js +17 -11
  38. package/dist/mem-checkpoint.js +1 -1
  39. package/dist/mem-cleanup.js +6 -23
  40. package/dist/mem-context.js +1 -1
  41. package/dist/mem-create.js +1 -1
  42. package/dist/mem-delete.js +1 -1
  43. package/dist/mem-export.js +1 -1
  44. package/dist/mem-inbox.js +1 -1
  45. package/dist/mem-init.js +1 -1
  46. package/dist/mem-ready.js +1 -1
  47. package/dist/mem-recover.js +1 -1
  48. package/dist/mem-signal.js +1 -1
  49. package/dist/mem-start.js +1 -1
  50. package/dist/mem-summarize.js +8 -7
  51. package/dist/mem-triage.js +7 -5
  52. package/dist/metrics-cli.js +1 -1
  53. package/dist/metrics-snapshot.js +1 -1
  54. package/dist/onboard.js +295 -120
  55. package/dist/orchestrate-init-status.js +12 -7
  56. package/dist/orchestrate-initiative.js +23 -12
  57. package/dist/orchestrate-monitor.js +20 -8
  58. package/dist/pack-scaffold.js +1 -1
  59. package/dist/plan-create.js +1 -3
  60. package/dist/plan-edit.js +1 -3
  61. package/dist/plan-link.js +1 -3
  62. package/dist/plan-promote.js +1 -3
  63. package/dist/release.js +1 -3
  64. package/dist/signal-cleanup.js +4 -18
  65. package/dist/state-bootstrap.js +11 -8
  66. package/dist/state-cleanup.js +5 -19
  67. package/dist/state-doctor.js +213 -9
  68. package/dist/task-claim.js +1 -1
  69. package/dist/validate.js +1 -1
  70. package/dist/workspace-init.js +61 -61
  71. package/dist/wu-block.js +1 -1
  72. package/dist/wu-brief.js +1 -1
  73. package/dist/wu-claim.js +1 -1
  74. package/dist/wu-cleanup.js +1 -1
  75. package/dist/wu-create.js +3 -3
  76. package/dist/wu-delegate.js +1 -1
  77. package/dist/wu-deps.js +1 -1
  78. package/dist/wu-done.js +66 -34
  79. package/dist/wu-edit.js +1 -1
  80. package/dist/wu-infer-lane.js +1 -1
  81. package/dist/wu-preflight.js +1 -1
  82. package/dist/wu-prep.js +1 -1
  83. package/dist/wu-proto.js +1 -1
  84. package/dist/wu-prune.js +1 -1
  85. package/dist/wu-recover.js +1 -1
  86. package/dist/wu-release.js +1 -1
  87. package/dist/wu-repair.js +1 -1
  88. package/dist/wu-sandbox.js +40 -27
  89. package/dist/wu-status.js +1 -1
  90. package/dist/wu-unblock.js +1 -1
  91. package/dist/wu-unlock-lane.js +1 -1
  92. package/dist/wu-validate.js +1 -1
  93. package/package.json +12 -8
  94. package/packs/software-delivery/constants.ts +10 -0
  95. package/packs/software-delivery/extensions.ts +140 -0
  96. package/packs/software-delivery/gate-policies.ts +134 -0
  97. package/packs/software-delivery/index.ts +8 -0
  98. package/packs/software-delivery/manifest-schema.ts +236 -0
  99. package/packs/software-delivery/manifest.ts +417 -0
  100. package/packs/software-delivery/manifest.yaml +711 -0
  101. package/packs/software-delivery/pack-registration.ts +113 -0
  102. package/packs/software-delivery/tool-impl/agent-tools.ts +263 -0
  103. package/packs/software-delivery/tool-impl/delegation-tools.ts +66 -0
  104. package/packs/software-delivery/tool-impl/flow-metrics-tools.ts +219 -0
  105. package/packs/software-delivery/tool-impl/git-runner.ts +113 -0
  106. package/packs/software-delivery/tool-impl/git-tools.ts +316 -0
  107. package/packs/software-delivery/tool-impl/index.ts +15 -0
  108. package/packs/software-delivery/tool-impl/initiative-orchestration-tools.ts +720 -0
  109. package/packs/software-delivery/tool-impl/lane-lock.ts +246 -0
  110. package/packs/software-delivery/tool-impl/memory-tools.ts +415 -0
  111. package/packs/software-delivery/tool-impl/pending-runtime-tools.ts +21 -0
  112. package/packs/software-delivery/tool-impl/runtime-cli-adapter.ts +328 -0
  113. package/packs/software-delivery/tool-impl/runtime-native-tools.ts +687 -0
  114. package/packs/software-delivery/tool-impl/worker-loader.ts +52 -0
  115. package/packs/software-delivery/tool-impl/worktree-tools.ts +46 -0
  116. package/packs/software-delivery/tool-impl/wu-lifecycle-tools.ts +759 -0
  117. package/packs/software-delivery/tools/delegation-tools.ts +23 -0
  118. package/packs/software-delivery/tools/git-tools.ts +55 -0
  119. package/packs/software-delivery/tools/index.ts +8 -0
  120. package/packs/software-delivery/tools/lane-lock-tool.ts +37 -0
  121. package/packs/software-delivery/tools/types.ts +71 -0
  122. package/packs/software-delivery/tools/worktree-tools.ts +49 -0
  123. package/templates/core/LUMENFLOW.md.template +3 -3
  124. package/templates/core/ai/onboarding/agent-invocation-guide.md.template +1 -1
  125. package/templates/core/ai/onboarding/lumenflow-force-usage.md.template +1 -1
  126. package/templates/core/ai/onboarding/quick-ref-commands.md.template +5 -5
  127. package/templates/core/ai/onboarding/starting-prompt.md.template +3 -3
  128. package/templates/core/ai/onboarding/vendor-support.md.template +1 -1
  129. package/templates/core/ai/onboarding/wu-create-checklist.md.template +1 -1
  130. package/dist/agent-issues-query.js.map +0 -1
  131. package/dist/agent-log-issue.js.map +0 -1
  132. package/dist/agent-session-end.js.map +0 -1
  133. package/dist/agent-session.js.map +0 -1
  134. package/dist/backlog-prune.js.map +0 -1
  135. package/dist/cli-entry-point.js +0 -149
  136. package/dist/cli-entry-point.js.map +0 -1
  137. package/dist/commands/integrate.js.map +0 -1
  138. package/dist/commands.js.map +0 -1
  139. package/dist/config-get.js.map +0 -1
  140. package/dist/config-set.js.map +0 -1
  141. package/dist/delegation-list.js.map +0 -1
  142. package/dist/deps-add.js +0 -259
  143. package/dist/deps-add.js.map +0 -1
  144. package/dist/deps-remove.js +0 -105
  145. package/dist/deps-remove.js.map +0 -1
  146. package/dist/docs-sync.js.map +0 -1
  147. package/dist/doctor.js.map +0 -1
  148. package/dist/file-delete.js.map +0 -1
  149. package/dist/file-edit.js.map +0 -1
  150. package/dist/file-read.js.map +0 -1
  151. package/dist/file-write.js.map +0 -1
  152. package/dist/flow-bottlenecks.js.map +0 -1
  153. package/dist/flow-report.js.map +0 -1
  154. package/dist/formatters.js +0 -151
  155. package/dist/formatters.js.map +0 -1
  156. package/dist/gate-defaults.js +0 -131
  157. package/dist/gate-defaults.js.map +0 -1
  158. package/dist/gate-registry.js +0 -73
  159. package/dist/gate-registry.js.map +0 -1
  160. package/dist/gates-graceful-degradation.js +0 -153
  161. package/dist/gates-graceful-degradation.js.map +0 -1
  162. package/dist/gates-plan-resolvers.js +0 -152
  163. package/dist/gates-plan-resolvers.js.map +0 -1
  164. package/dist/gates-runners.js +0 -509
  165. package/dist/gates-runners.js.map +0 -1
  166. package/dist/gates-types.js +0 -4
  167. package/dist/gates-types.js.map +0 -1
  168. package/dist/gates-utils.js +0 -323
  169. package/dist/gates-utils.js.map +0 -1
  170. package/dist/gates.js.map +0 -1
  171. package/dist/git-branch.js.map +0 -1
  172. package/dist/git-diff.js.map +0 -1
  173. package/dist/git-log.js.map +0 -1
  174. package/dist/git-status.js.map +0 -1
  175. package/dist/guard-locked.js +0 -172
  176. package/dist/guard-locked.js.map +0 -1
  177. package/dist/guard-main-branch.js +0 -217
  178. package/dist/guard-main-branch.js.map +0 -1
  179. package/dist/guard-worktree-commit.js +0 -163
  180. package/dist/guard-worktree-commit.js.map +0 -1
  181. package/dist/hooks/auto-checkpoint-utils.js +0 -54
  182. package/dist/hooks/auto-checkpoint-utils.js.map +0 -1
  183. package/dist/hooks/enforcement-checks.js +0 -399
  184. package/dist/hooks/enforcement-checks.js.map +0 -1
  185. package/dist/hooks/enforcement-generator.js +0 -139
  186. package/dist/hooks/enforcement-generator.js.map +0 -1
  187. package/dist/hooks/enforcement-sync.js +0 -385
  188. package/dist/hooks/enforcement-sync.js.map +0 -1
  189. package/dist/hooks/generators/auto-checkpoint.js +0 -125
  190. package/dist/hooks/generators/auto-checkpoint.js.map +0 -1
  191. package/dist/hooks/generators/enforce-worktree.js +0 -190
  192. package/dist/hooks/generators/enforce-worktree.js.map +0 -1
  193. package/dist/hooks/generators/index.js +0 -18
  194. package/dist/hooks/generators/index.js.map +0 -1
  195. package/dist/hooks/generators/pre-compact-checkpoint.js +0 -136
  196. package/dist/hooks/generators/pre-compact-checkpoint.js.map +0 -1
  197. package/dist/hooks/generators/require-wu.js +0 -117
  198. package/dist/hooks/generators/require-wu.js.map +0 -1
  199. package/dist/hooks/generators/session-start-recovery.js +0 -103
  200. package/dist/hooks/generators/session-start-recovery.js.map +0 -1
  201. package/dist/hooks/generators/signal-utils.js +0 -54
  202. package/dist/hooks/generators/signal-utils.js.map +0 -1
  203. package/dist/hooks/generators/warn-incomplete.js +0 -67
  204. package/dist/hooks/generators/warn-incomplete.js.map +0 -1
  205. package/dist/hooks/index.js +0 -10
  206. package/dist/hooks/index.js.map +0 -1
  207. package/dist/index.js.map +0 -1
  208. package/dist/init-detection.js +0 -232
  209. package/dist/init-detection.js.map +0 -1
  210. package/dist/init-lane-validation.js +0 -143
  211. package/dist/init-lane-validation.js.map +0 -1
  212. package/dist/init-scaffolding.js +0 -158
  213. package/dist/init-scaffolding.js.map +0 -1
  214. package/dist/init-templates.js +0 -1982
  215. package/dist/init-templates.js.map +0 -1
  216. package/dist/init.js.map +0 -1
  217. package/dist/initiative-add-wu.js.map +0 -1
  218. package/dist/initiative-bulk-assign-wus.js.map +0 -1
  219. package/dist/initiative-create.js.map +0 -1
  220. package/dist/initiative-edit.js.map +0 -1
  221. package/dist/initiative-list.js.map +0 -1
  222. package/dist/initiative-plan.js.map +0 -1
  223. package/dist/initiative-remove-wu.js.map +0 -1
  224. package/dist/initiative-status.js.map +0 -1
  225. package/dist/lane-edit.js.map +0 -1
  226. package/dist/lane-health.js.map +0 -1
  227. package/dist/lane-lifecycle-process.js +0 -366
  228. package/dist/lane-lifecycle-process.js.map +0 -1
  229. package/dist/lane-lock.js.map +0 -1
  230. package/dist/lane-setup.js.map +0 -1
  231. package/dist/lane-status.js.map +0 -1
  232. package/dist/lane-suggest.js.map +0 -1
  233. package/dist/lane-validate.js.map +0 -1
  234. package/dist/lifecycle-regression-harness.js +0 -181
  235. package/dist/lifecycle-regression-harness.js.map +0 -1
  236. package/dist/lumenflow-upgrade.js.map +0 -1
  237. package/dist/mem-checkpoint.js.map +0 -1
  238. package/dist/mem-cleanup.js.map +0 -1
  239. package/dist/mem-context.js.map +0 -1
  240. package/dist/mem-create.js.map +0 -1
  241. package/dist/mem-delete.js.map +0 -1
  242. package/dist/mem-export.js.map +0 -1
  243. package/dist/mem-inbox.js.map +0 -1
  244. package/dist/mem-index.js +0 -214
  245. package/dist/mem-index.js.map +0 -1
  246. package/dist/mem-init.js.map +0 -1
  247. package/dist/mem-profile.js +0 -210
  248. package/dist/mem-profile.js.map +0 -1
  249. package/dist/mem-promote.js +0 -257
  250. package/dist/mem-promote.js.map +0 -1
  251. package/dist/mem-ready.js.map +0 -1
  252. package/dist/mem-recover.js.map +0 -1
  253. package/dist/mem-signal.js.map +0 -1
  254. package/dist/mem-start.js.map +0 -1
  255. package/dist/mem-summarize.js.map +0 -1
  256. package/dist/mem-triage.js.map +0 -1
  257. package/dist/merge-block.js +0 -225
  258. package/dist/merge-block.js.map +0 -1
  259. package/dist/metrics-cli.js.map +0 -1
  260. package/dist/metrics-snapshot.js.map +0 -1
  261. package/dist/onboard.js.map +0 -1
  262. package/dist/onboarding-smoke-test.js +0 -418
  263. package/dist/onboarding-smoke-test.js.map +0 -1
  264. package/dist/orchestrate-init-status.js.map +0 -1
  265. package/dist/orchestrate-initiative.js.map +0 -1
  266. package/dist/orchestrate-monitor.js.map +0 -1
  267. package/dist/pack-author.js.map +0 -1
  268. package/dist/pack-hash.js.map +0 -1
  269. package/dist/pack-install.js.map +0 -1
  270. package/dist/pack-publish.js.map +0 -1
  271. package/dist/pack-scaffold.js.map +0 -1
  272. package/dist/pack-search.js.map +0 -1
  273. package/dist/pack-validate.js.map +0 -1
  274. package/dist/plan-create.js.map +0 -1
  275. package/dist/plan-edit.js.map +0 -1
  276. package/dist/plan-link.js.map +0 -1
  277. package/dist/plan-promote.js.map +0 -1
  278. package/dist/public-manifest.js +0 -920
  279. package/dist/public-manifest.js.map +0 -1
  280. package/dist/release.js.map +0 -1
  281. package/dist/rotate-progress.js +0 -253
  282. package/dist/rotate-progress.js.map +0 -1
  283. package/dist/session-coordinator.js +0 -303
  284. package/dist/session-coordinator.js.map +0 -1
  285. package/dist/shared-validators.js +0 -81
  286. package/dist/shared-validators.js.map +0 -1
  287. package/dist/signal-cleanup.js.map +0 -1
  288. package/dist/state-bootstrap.js.map +0 -1
  289. package/dist/state-cleanup.js.map +0 -1
  290. package/dist/state-doctor-fix.js +0 -226
  291. package/dist/state-doctor-fix.js.map +0 -1
  292. package/dist/state-doctor-stamps.js +0 -23
  293. package/dist/state-doctor-stamps.js.map +0 -1
  294. package/dist/state-doctor.js.map +0 -1
  295. package/dist/strict-progress.js +0 -255
  296. package/dist/strict-progress.js.map +0 -1
  297. package/dist/sync-templates.js.map +0 -1
  298. package/dist/task-claim.js.map +0 -1
  299. package/dist/trace-gen.js +0 -401
  300. package/dist/trace-gen.js.map +0 -1
  301. package/dist/validate-agent-skills.js +0 -223
  302. package/dist/validate-agent-skills.js.map +0 -1
  303. package/dist/validate-agent-sync.js +0 -151
  304. package/dist/validate-agent-sync.js.map +0 -1
  305. package/dist/validate-backlog-sync.js +0 -77
  306. package/dist/validate-backlog-sync.js.map +0 -1
  307. package/dist/validate-skills-spec.js +0 -211
  308. package/dist/validate-skills-spec.js.map +0 -1
  309. package/dist/validate.js.map +0 -1
  310. package/dist/validator-defaults.js +0 -107
  311. package/dist/validator-defaults.js.map +0 -1
  312. package/dist/validator-registry.js +0 -71
  313. package/dist/validator-registry.js.map +0 -1
  314. package/dist/workspace-init.js.map +0 -1
  315. package/dist/wu-block.js.map +0 -1
  316. package/dist/wu-brief.js.map +0 -1
  317. package/dist/wu-claim-branch.js +0 -123
  318. package/dist/wu-claim-branch.js.map +0 -1
  319. package/dist/wu-claim-cloud.js +0 -79
  320. package/dist/wu-claim-cloud.js.map +0 -1
  321. package/dist/wu-claim-mode.js +0 -82
  322. package/dist/wu-claim-mode.js.map +0 -1
  323. package/dist/wu-claim-output.js +0 -85
  324. package/dist/wu-claim-output.js.map +0 -1
  325. package/dist/wu-claim-repair-guidance.js +0 -12
  326. package/dist/wu-claim-repair-guidance.js.map +0 -1
  327. package/dist/wu-claim-resume-handler.js +0 -87
  328. package/dist/wu-claim-resume-handler.js.map +0 -1
  329. package/dist/wu-claim-state.js +0 -581
  330. package/dist/wu-claim-state.js.map +0 -1
  331. package/dist/wu-claim-validation.js +0 -457
  332. package/dist/wu-claim-validation.js.map +0 -1
  333. package/dist/wu-claim-worktree.js +0 -223
  334. package/dist/wu-claim-worktree.js.map +0 -1
  335. package/dist/wu-claim.js.map +0 -1
  336. package/dist/wu-cleanup-cloud.js +0 -78
  337. package/dist/wu-cleanup-cloud.js.map +0 -1
  338. package/dist/wu-cleanup.js.map +0 -1
  339. package/dist/wu-code-path-coverage.js +0 -83
  340. package/dist/wu-code-path-coverage.js.map +0 -1
  341. package/dist/wu-create-cloud.js +0 -30
  342. package/dist/wu-create-cloud.js.map +0 -1
  343. package/dist/wu-create-content.js +0 -264
  344. package/dist/wu-create-content.js.map +0 -1
  345. package/dist/wu-create-readiness.js +0 -59
  346. package/dist/wu-create-readiness.js.map +0 -1
  347. package/dist/wu-create-validation.js +0 -128
  348. package/dist/wu-create-validation.js.map +0 -1
  349. package/dist/wu-create.js.map +0 -1
  350. package/dist/wu-delegate.js.map +0 -1
  351. package/dist/wu-delete.js.map +0 -1
  352. package/dist/wu-deps.js.map +0 -1
  353. package/dist/wu-done-auto-cleanup.js +0 -203
  354. package/dist/wu-done-auto-cleanup.js.map +0 -1
  355. package/dist/wu-done-check.js +0 -38
  356. package/dist/wu-done-check.js.map +0 -1
  357. package/dist/wu-done-cloud.js +0 -48
  358. package/dist/wu-done-cloud.js.map +0 -1
  359. package/dist/wu-done-decay.js +0 -86
  360. package/dist/wu-done-decay.js.map +0 -1
  361. package/dist/wu-done.js.map +0 -1
  362. package/dist/wu-edit-operations.js +0 -399
  363. package/dist/wu-edit-operations.js.map +0 -1
  364. package/dist/wu-edit-validators.js +0 -282
  365. package/dist/wu-edit-validators.js.map +0 -1
  366. package/dist/wu-edit.js.map +0 -1
  367. package/dist/wu-infer-lane.js.map +0 -1
  368. package/dist/wu-preflight.js.map +0 -1
  369. package/dist/wu-prep.js.map +0 -1
  370. package/dist/wu-proto.js.map +0 -1
  371. package/dist/wu-prune.js.map +0 -1
  372. package/dist/wu-recover.js.map +0 -1
  373. package/dist/wu-release.js.map +0 -1
  374. package/dist/wu-repair.js.map +0 -1
  375. package/dist/wu-sandbox.js.map +0 -1
  376. package/dist/wu-spawn-completion.js +0 -33
  377. package/dist/wu-spawn-completion.js.map +0 -1
  378. package/dist/wu-spawn-prompt-builders.js +0 -1197
  379. package/dist/wu-spawn-prompt-builders.js.map +0 -1
  380. package/dist/wu-spawn-strategy-resolver.js +0 -322
  381. package/dist/wu-spawn-strategy-resolver.js.map +0 -1
  382. package/dist/wu-spawn.js +0 -59
  383. package/dist/wu-spawn.js.map +0 -1
  384. package/dist/wu-state-cloud.js +0 -41
  385. package/dist/wu-state-cloud.js.map +0 -1
  386. package/dist/wu-status.js.map +0 -1
  387. package/dist/wu-unblock.js.map +0 -1
  388. package/dist/wu-unlock-lane.js.map +0 -1
  389. package/dist/wu-validate.js.map +0 -1
@@ -25,8 +25,10 @@ import { Command } from 'commander';
25
25
  import { existsSync, readdirSync, readFileSync } from 'node:fs';
26
26
  import { join } from 'node:path';
27
27
  import { EXIT_CODES, LUMENFLOW_PATHS, DelegationRegistryStore, analyzeDelegations, detectStuckDelegations, checkZombieLocks, generateSuggestions, formatMonitorOutput, formatRecoveryResults, runRecovery, processDelegationFailureSignals, formatSignalHandlerOutput, DEFAULT_THRESHOLD_MINUTES, calculateBackoff, } from '@lumenflow/core';
28
+ import { ProcessExitError } from '@lumenflow/core/error-handler';
28
29
  import chalk from 'chalk';
29
30
  import ms, {} from 'ms';
31
+ import { runCLI } from './cli-entry-point.js';
30
32
  // ============================================================================
31
33
  // WU-1242: Watch Mode Constants
32
34
  // ============================================================================
@@ -187,8 +189,9 @@ async function runDelegationMonitoring(opts) {
187
189
  const baseDir = process.cwd();
188
190
  const thresholdMinutes = parseInt(opts.threshold, 10);
189
191
  if (isNaN(thresholdMinutes) || thresholdMinutes <= 0) {
190
- console.error(chalk.red(`${LOG_PREFIX} Invalid threshold: ${opts.threshold}`));
191
- process.exit(EXIT_CODES.FAILURE);
192
+ const message = `${LOG_PREFIX} Invalid threshold: ${opts.threshold}`;
193
+ console.error(chalk.red(message));
194
+ throw new ProcessExitError(message, EXIT_CODES.FAILURE);
192
195
  }
193
196
  console.log(chalk.cyan(`${LOG_PREFIX} Analyzing delegation health...`));
194
197
  console.log(chalk.gray(` Threshold: ${thresholdMinutes} minutes`));
@@ -209,7 +212,7 @@ async function runDelegationMonitoring(opts) {
209
212
  console.log(formatSignalHandlerOutput(signalResult));
210
213
  }
211
214
  if (result.stuckDelegations.length > 0 || result.zombieLocks.length > 0) {
212
- process.exit(EXIT_CODES.ERROR);
215
+ throw new ProcessExitError(`${LOG_PREFIX} Delegation monitor detected stuck delegations or zombie locks.`, EXIT_CODES.ERROR);
213
216
  }
214
217
  }
215
218
  /**
@@ -378,8 +381,9 @@ async function runWatchMode(opts) {
378
381
  const baseDir = process.cwd();
379
382
  const thresholdMinutes = parseInt(opts.threshold, 10);
380
383
  if (isNaN(thresholdMinutes) || thresholdMinutes <= 0) {
381
- console.error(chalk.red(`${LOG_PREFIX} Invalid threshold: ${opts.threshold}`));
382
- process.exit(EXIT_CODES.FAILURE);
384
+ const message = `${LOG_PREFIX} Invalid threshold: ${opts.threshold}`;
385
+ console.error(chalk.red(message));
386
+ throw new ProcessExitError(message, EXIT_CODES.FAILURE);
383
387
  }
384
388
  const watchOptions = parseWatchOptions(opts);
385
389
  console.log(chalk.cyan(`${LOG_PREFIX} Starting continuous patrol mode...`));
@@ -403,7 +407,7 @@ async function runWatchMode(opts) {
403
407
  // Handle graceful shutdown
404
408
  const shutdown = () => {
405
409
  runner.stop();
406
- process.exit(0);
410
+ process.exitCode = EXIT_CODES.SUCCESS;
407
411
  };
408
412
  process.on('SIGINT', shutdown);
409
413
  process.on('SIGTERM', shutdown);
@@ -438,10 +442,18 @@ const program = new Command()
438
442
  await runDelegationMonitoring(opts);
439
443
  }
440
444
  catch (err) {
445
+ if (err instanceof ProcessExitError) {
446
+ throw err;
447
+ }
441
448
  const message = err instanceof Error ? err.message : String(err);
442
449
  console.error(chalk.red(`${LOG_PREFIX} Error: ${message}`));
443
- process.exit(EXIT_CODES.ERROR);
450
+ throw new ProcessExitError(message, EXIT_CODES.ERROR);
444
451
  }
445
452
  });
446
- program.parse();
453
+ export async function main() {
454
+ await program.parseAsync(process.argv);
455
+ }
456
+ if (import.meta.main) {
457
+ void runCLI(main);
458
+ }
447
459
  //# sourceMappingURL=orchestrate-monitor.js.map
@@ -112,7 +112,7 @@ LumenFlow domain pack - version ${version}
112
112
 
113
113
  ## Overview
114
114
 
115
- This pack provides domain-specific tools and policies for the LumenFlow kernel.
115
+ This pack provides pack-specific tools and policies for the LumenFlow kernel.
116
116
 
117
117
  ## Structure
118
118
 
@@ -139,7 +139,7 @@ export function getCommitMessage(id, title) {
139
139
  const idLower = id.toLowerCase();
140
140
  return `docs: create plan for ${idLower} - ${title}`;
141
141
  }
142
- async function main() {
142
+ export async function main() {
143
143
  const args = createWUParser({
144
144
  name: 'plan-create',
145
145
  description: 'Create a new plan file in repo plansDir',
@@ -195,6 +195,4 @@ import { runCLI } from './cli-entry-point.js';
195
195
  if (import.meta.main) {
196
196
  void runCLI(main);
197
197
  }
198
- // Export for testing
199
- export { main };
200
198
  //# sourceMappingURL=plan-create.js.map
package/dist/plan-edit.js CHANGED
@@ -164,7 +164,7 @@ export function getCommitMessage(id, section) {
164
164
  const idLower = id.toLowerCase();
165
165
  return `docs: update ${section} section in ${idLower} plan`;
166
166
  }
167
- async function main() {
167
+ export async function main() {
168
168
  const SECTION_OPTION = {
169
169
  name: 'section',
170
170
  flags: '--section <name>',
@@ -257,6 +257,4 @@ import { runCLI } from './cli-entry-point.js';
257
257
  if (import.meta.main) {
258
258
  void runCLI(main);
259
259
  }
260
- // Export for testing
261
- export { main };
262
260
  //# sourceMappingURL=plan-edit.js.map
package/dist/plan-link.js CHANGED
@@ -200,7 +200,7 @@ export function getCommitMessage(id, planUri) {
200
200
  const filename = planUri.replace(PLAN_URI_SCHEME, '');
201
201
  return `docs: link plan ${filename} to ${idLower}`;
202
202
  }
203
- async function main() {
203
+ export async function main() {
204
204
  const PLAN_OPTION = {
205
205
  name: 'plan',
206
206
  flags: '--plan <uri>',
@@ -269,6 +269,4 @@ import { runCLI } from './cli-entry-point.js';
269
269
  if (import.meta.main) {
270
270
  void runCLI(main);
271
271
  }
272
- // Export for testing
273
- export { main };
274
272
  //# sourceMappingURL=plan-link.js.map
@@ -154,7 +154,7 @@ export function getCommitMessage(id) {
154
154
  const idLower = id.toLowerCase();
155
155
  return `docs: promote ${idLower} plan to approved`;
156
156
  }
157
- async function main() {
157
+ export async function main() {
158
158
  const FORCE_OPTION = {
159
159
  name: 'force',
160
160
  flags: '-f, --force',
@@ -227,6 +227,4 @@ import { runCLI } from './cli-entry-point.js';
227
227
  if (import.meta.main) {
228
228
  void runCLI(main);
229
229
  }
230
- // Export for testing
231
- export { main };
232
230
  //# sourceMappingURL=plan-promote.js.map
package/dist/release.js CHANGED
@@ -317,7 +317,7 @@ export async function pushTagWithForce(git, tagName, reason = 'release: tag push
317
317
  * Main release function
318
318
  * WU-1085: Renamed --version to --release-version to avoid conflict with CLI --version flag
319
319
  */
320
- async function main() {
320
+ export async function main() {
321
321
  const program = new Command()
322
322
  .name('lumenflow-release')
323
323
  .description('Release @lumenflow/* packages to npm with version bump, tag, and publish')
@@ -468,8 +468,6 @@ async function main() {
468
468
  console.log(` - Verify packages: npm view @lumenflow/cli version`);
469
469
  }
470
470
  }
471
- // Export for testing
472
- export { main };
473
471
  // Guard main() for testability
474
472
  if (import.meta.main) {
475
473
  void runCLI(main);
@@ -29,6 +29,7 @@ import { cleanupSignals } from '@lumenflow/memory/signal-cleanup-core';
29
29
  import { createWUParser } from '@lumenflow/core/arg-parser';
30
30
  import { EXIT_CODES, LUMENFLOW_PATHS, PROTECTED_WU_STATUSES } from '@lumenflow/core/wu-constants';
31
31
  import { getConfig } from '@lumenflow/core/config';
32
+ import { formatBytes } from './constants.js';
32
33
  import { runCLI } from './cli-entry-point.js';
33
34
  /**
34
35
  * Log prefix for signal:cleanup output
@@ -38,10 +39,7 @@ const LOG_PREFIX = '[signal:cleanup]';
38
39
  * Tool name for audit logging
39
40
  */
40
41
  const TOOL_NAME = 'signal:cleanup';
41
- /**
42
- * Bytes per KB for formatting
43
- */
44
- const BYTES_PER_KB = 1024;
42
+ // WU-2044: BYTES_PER_KB imported from ./constants.js
45
43
  /**
46
44
  * CLI argument options specific to signal:cleanup
47
45
  */
@@ -100,19 +98,7 @@ async function writeAuditLog(baseDir, entry) {
100
98
  // Audit logging is non-fatal - silently ignore errors
101
99
  }
102
100
  }
103
- /**
104
- * Format bytes as human-readable string
105
- *
106
- * @param bytes - Number of bytes
107
- * @returns Formatted string (e.g., "1.5 KB")
108
- */
109
- function formatBytes(bytes) {
110
- if (bytes < BYTES_PER_KB) {
111
- return `${bytes} B`;
112
- }
113
- const kb = (bytes / BYTES_PER_KB).toFixed(1);
114
- return `${kb} KB`;
115
- }
101
+ // WU-2044: formatBytes imported from ./constants.js
116
102
  /**
117
103
  * Format compaction ratio as percentage
118
104
  *
@@ -227,7 +213,7 @@ function printResult(result, quiet) {
227
213
  /**
228
214
  * Main CLI entry point
229
215
  */
230
- async function main() {
216
+ export async function main() {
231
217
  const args = parseArguments();
232
218
  const baseDir = args.baseDir || process.cwd();
233
219
  const startedAt = new Date().toISOString();
@@ -18,7 +18,8 @@ import path from 'node:path';
18
18
  import { parse as parseYaml } from 'yaml';
19
19
  import { readFileSync } from 'node:fs';
20
20
  import { WU_PATHS } from '@lumenflow/core/wu-paths';
21
- import { CLI_FLAGS, EXIT_CODES, EMOJI, STRING_LITERALS } from '@lumenflow/core/wu-constants';
21
+ import { CLI_FLAGS, EXIT_CODES, EMOJI, STRING_LITERALS, WU_STATUS, } from '@lumenflow/core/wu-constants';
22
+ import { WU_EVENT_TYPE } from '@lumenflow/core/wu-state-schema';
22
23
  /** Log prefix for consistent output */
23
24
  const LOG_PREFIX = '[state-bootstrap]';
24
25
  /**
@@ -99,36 +100,38 @@ function toTimestamp(dateStr, fallback) {
99
100
  export function inferEventsFromWu(wu) {
100
101
  const events = [];
101
102
  // Ready WUs have no events (not yet in the lifecycle)
102
- if (wu.status === 'ready' || wu.status === 'backlog' || wu.status === 'todo') {
103
+ if (wu.status === WU_STATUS.READY ||
104
+ wu.status === WU_STATUS.BACKLOG ||
105
+ wu.status === WU_STATUS.TODO) {
103
106
  return events;
104
107
  }
105
108
  // All other states start with a claim event
106
109
  const claimTimestamp = toTimestamp(wu.claimed_at, wu.created);
107
110
  events.push({
108
- type: 'claim',
111
+ type: WU_EVENT_TYPE.CLAIM,
109
112
  wuId: wu.id,
110
113
  lane: wu.lane,
111
114
  title: wu.title,
112
115
  timestamp: claimTimestamp,
113
116
  });
114
117
  // Handle completed/done status
115
- if (wu.status === 'done' || wu.status === 'completed') {
118
+ if (wu.status === WU_STATUS.DONE || wu.status === WU_STATUS.COMPLETED) {
116
119
  const completeTimestamp = toTimestamp(wu.completed_at, wu.created);
117
120
  events.push({
118
- type: 'complete',
121
+ type: WU_EVENT_TYPE.COMPLETE,
119
122
  wuId: wu.id,
120
123
  timestamp: completeTimestamp,
121
124
  });
122
125
  return events;
123
126
  }
124
127
  // Handle blocked status
125
- if (wu.status === 'blocked') {
128
+ if (wu.status === WU_STATUS.BLOCKED) {
126
129
  // Block event timestamp should be after claim
127
130
  // We don't have exact block time, so use claim time + 1 second
128
131
  const claimDate = new Date(claimTimestamp);
129
132
  claimDate.setSeconds(claimDate.getSeconds() + 1);
130
133
  events.push({
131
- type: 'block',
134
+ type: WU_EVENT_TYPE.BLOCK,
132
135
  wuId: wu.id,
133
136
  timestamp: claimDate.toISOString(),
134
137
  reason: 'Bootstrapped from WU YAML (original reason unknown)',
@@ -266,7 +269,7 @@ Supported WU statuses:
266
269
  /**
267
270
  * Main function
268
271
  */
269
- async function main() {
272
+ export async function main() {
270
273
  const args = parseStateBootstrapArgs(process.argv);
271
274
  if (args.help) {
272
275
  printHelp();
@@ -12,7 +12,7 @@
12
12
  * Cleanup order: signals -> memory -> events (dependency order)
13
13
  *
14
14
  * Features:
15
- * - Respects config from .lumenflow.config.yaml
15
+ * - Respects config from workspace.yaml
16
16
  * - Supports --dry-run for preview
17
17
  * - Supports --signals-only, --memory-only, --events-only for selective cleanup
18
18
  * - Non-fatal: warns on errors but continues with other cleanups
@@ -40,6 +40,7 @@ import { EXIT_CODES, LUMENFLOW_PATHS, PROTECTED_WU_STATUSES } from '@lumenflow/c
40
40
  import { getConfig } from '@lumenflow/core/config';
41
41
  import fg from 'fast-glob';
42
42
  import { parse as parseYaml } from 'yaml';
43
+ import { formatBytes } from './constants.js';
43
44
  import { runCLI } from './cli-entry-point.js';
44
45
  /**
45
46
  * Log prefix for state:cleanup output
@@ -49,10 +50,7 @@ const LOG_PREFIX = '[state:cleanup]';
49
50
  * Tool name for audit logging
50
51
  */
51
52
  const TOOL_NAME = 'state:cleanup';
52
- /**
53
- * Bytes per KB for formatting
54
- */
55
- const BYTES_PER_KB = 1024;
53
+ // WU-2044: BYTES_PER_KB imported from ./constants.js
56
54
  /**
57
55
  * Labels for output formatting
58
56
  */
@@ -117,19 +115,7 @@ async function writeAuditLog(baseDir, entry) {
117
115
  // Audit logging is non-fatal - silently ignore errors
118
116
  }
119
117
  }
120
- /**
121
- * Format bytes as human-readable string
122
- *
123
- * @param bytes - Number of bytes
124
- * @returns Formatted string (e.g., "1.5 KB")
125
- */
126
- function formatBytes(bytes) {
127
- if (bytes < BYTES_PER_KB) {
128
- return `${bytes} B`;
129
- }
130
- const kb = (bytes / BYTES_PER_KB).toFixed(1);
131
- return `${kb} KB`;
132
- }
118
+ // WU-2044: formatBytes imported from ./constants.js
133
119
  /**
134
120
  * Get active WU IDs (in_progress or blocked) by scanning WU YAML files.
135
121
  *
@@ -264,7 +250,7 @@ function printResult(result, quiet) {
264
250
  /**
265
251
  * Main CLI entry point
266
252
  */
267
- async function main() {
253
+ export async function main() {
268
254
  const args = parseArguments();
269
255
  const baseDir = args.baseDir || process.cwd();
270
256
  const startedAt = new Date().toISOString();
@@ -30,20 +30,28 @@
30
30
  import fs from 'node:fs/promises';
31
31
  import path from 'node:path';
32
32
  import fg from 'fast-glob';
33
- import { parse as parseYaml } from 'yaml';
33
+ import { parse as parseYaml, stringify as stringifyYaml } from 'yaml';
34
34
  import { diagnoseState, ISSUE_TYPES, ISSUE_SEVERITY, } from '@lumenflow/core/state-doctor-core';
35
35
  import { createWUParser } from '@lumenflow/core/arg-parser';
36
- import { EXIT_CODES, LUMENFLOW_PATHS } from '@lumenflow/core/wu-constants';
37
- import { getConfig, getResolvedPaths } from '@lumenflow/core/config';
36
+ import { EXIT_CODES, LUMENFLOW_PATHS, WU_STATUS } from '@lumenflow/core/wu-constants';
37
+ import { getConfig, getResolvedPaths, getConfigFilePresence, WORKSPACE_CONFIG_FILE_NAME, } from '@lumenflow/core/config';
38
38
  import { existsSync } from 'node:fs';
39
39
  import { createStamp } from '@lumenflow/core/stamp-utils';
40
+ import { withMicroWorktree } from '@lumenflow/core/micro-worktree';
40
41
  import { createStateDoctorFixDeps } from './state-doctor-fix.js';
41
42
  import { runCLI } from './cli-entry-point.js';
42
43
  import { resolveStateDoctorStampIds } from './state-doctor-stamps.js';
44
+ import { deriveInitiativeLifecycleStatus } from './initiative-status.js';
43
45
  /**
44
46
  * Log prefix for state:doctor output
45
47
  */
46
48
  const LOG_PREFIX = '[state:doctor]';
49
+ const WORKSPACE_INIT_COMMAND = 'pnpm workspace-init --yes';
50
+ const INITIATIVE_FILE_GLOB = 'INIT-*.yaml';
51
+ const WU_FILE_GLOB = 'WU-*.yaml';
52
+ const STATUS_RECONCILIATION_OPERATION_ID = 'reconcile-initiative-status';
53
+ const STATUS_RECONCILIATION_COMMIT_MESSAGE = 'fix(state-doctor): reconcile stale initiative lifecycle statuses';
54
+ const INITIATIVE_STATUS_RECONCILIATION_SUGGESTION = 'Run with --fix to reconcile initiative status';
47
55
  // WU-1539/WU-1548: Use centralized LUMENFLOW_PATHS.MEMORY_SIGNALS and LUMENFLOW_PATHS.WU_EVENTS
48
56
  /**
49
57
  * Tool name for audit logging
@@ -89,6 +97,161 @@ const CLI_OPTIONS = {
89
97
  description: 'Base directory (defaults to current directory)',
90
98
  },
91
99
  };
100
+ function normalizeLifecycleStatus(value) {
101
+ return typeof value === 'string' ? value.trim().toLowerCase() : '';
102
+ }
103
+ function toInitiativePhases(value) {
104
+ if (!Array.isArray(value)) {
105
+ return [];
106
+ }
107
+ return value
108
+ .filter((phase) => phase != null && typeof phase === 'object')
109
+ .flatMap((phase) => {
110
+ if (typeof phase.id !== 'number') {
111
+ return [];
112
+ }
113
+ const status = typeof phase.status === 'string' ? phase.status : undefined;
114
+ return [{ id: phase.id, status }];
115
+ });
116
+ }
117
+ function createInitiativeStatusMismatchIssue(mismatch) {
118
+ return {
119
+ type: ISSUE_TYPES.STATUS_MISMATCH,
120
+ severity: ISSUE_SEVERITY.WARNING,
121
+ wuId: mismatch.initiativeId,
122
+ description: `Initiative ${mismatch.initiativeId} metadata status is '${mismatch.currentStatus}' but linked WUs derive '${mismatch.derivedStatus}'`,
123
+ suggestion: INITIATIVE_STATUS_RECONCILIATION_SUGGESTION,
124
+ canAutoFix: true,
125
+ statusMismatch: {
126
+ yamlStatus: mismatch.currentStatus,
127
+ derivedStatus: mismatch.derivedStatus,
128
+ },
129
+ };
130
+ }
131
+ export async function collectInitiativeLifecycleStatusMismatches(baseDir) {
132
+ const config = getConfig({ projectRoot: baseDir, strictWorkspace: true });
133
+ const initiativesDir = path.join(baseDir, config.directories.initiativesDir);
134
+ const wuDir = path.join(baseDir, config.directories.wuDir);
135
+ const [initiativeFiles, wuFiles] = await Promise.all([
136
+ fg(INITIATIVE_FILE_GLOB, { cwd: initiativesDir }),
137
+ fg(WU_FILE_GLOB, { cwd: wuDir }),
138
+ ]);
139
+ if (initiativeFiles.length === 0) {
140
+ return [];
141
+ }
142
+ const initiatives = [];
143
+ const initiativeIdByReference = new Map();
144
+ const progressByInitiativeId = new Map();
145
+ for (const file of initiativeFiles) {
146
+ const relativePath = path.join(config.directories.initiativesDir, file);
147
+ const fullPath = path.join(initiativesDir, file);
148
+ try {
149
+ const content = await fs.readFile(fullPath, 'utf-8');
150
+ const doc = parseYaml(content);
151
+ const initiativeId = typeof doc.id === 'string' && doc.id.length > 0 ? doc.id : '';
152
+ if (!initiativeId) {
153
+ continue;
154
+ }
155
+ const slug = typeof doc.slug === 'string' ? doc.slug : '';
156
+ const status = normalizeLifecycleStatus(doc.status);
157
+ const phases = toInitiativePhases(doc.phases);
158
+ initiatives.push({
159
+ id: initiativeId,
160
+ slug,
161
+ status,
162
+ phases,
163
+ relativePath,
164
+ });
165
+ initiativeIdByReference.set(initiativeId, initiativeId);
166
+ if (slug.length > 0) {
167
+ initiativeIdByReference.set(slug, initiativeId);
168
+ }
169
+ progressByInitiativeId.set(initiativeId, { done: 0, total: 0 });
170
+ }
171
+ catch {
172
+ // Skip malformed initiative YAML files during diagnosis.
173
+ }
174
+ }
175
+ for (const file of wuFiles) {
176
+ const fullPath = path.join(wuDir, file);
177
+ try {
178
+ const content = await fs.readFile(fullPath, 'utf-8');
179
+ const doc = parseYaml(content);
180
+ const initiativeRef = typeof doc.initiative === 'string' ? doc.initiative : '';
181
+ if (!initiativeRef) {
182
+ continue;
183
+ }
184
+ const initiativeId = initiativeIdByReference.get(initiativeRef);
185
+ if (!initiativeId) {
186
+ continue;
187
+ }
188
+ const current = progressByInitiativeId.get(initiativeId) || { done: 0, total: 0 };
189
+ current.total += 1;
190
+ if (normalizeLifecycleStatus(doc.status) === WU_STATUS.DONE) {
191
+ current.done += 1;
192
+ }
193
+ progressByInitiativeId.set(initiativeId, current);
194
+ }
195
+ catch {
196
+ // Skip malformed WU YAML files during diagnosis.
197
+ }
198
+ }
199
+ const mismatches = [];
200
+ for (const initiative of initiatives) {
201
+ if (![WU_STATUS.IN_PROGRESS, WU_STATUS.DONE].includes(initiative.status)) {
202
+ continue;
203
+ }
204
+ const progress = progressByInitiativeId.get(initiative.id);
205
+ const derivedStatus = deriveInitiativeLifecycleStatus(initiative.status, initiative.phases, progress);
206
+ if (derivedStatus !== initiative.status) {
207
+ mismatches.push({
208
+ initiativeId: initiative.id,
209
+ relativePath: initiative.relativePath,
210
+ currentStatus: initiative.status,
211
+ derivedStatus,
212
+ });
213
+ }
214
+ }
215
+ return mismatches;
216
+ }
217
+ export async function applyInitiativeLifecycleStatusFixes(baseDir, mismatches) {
218
+ if (mismatches.length === 0) {
219
+ return;
220
+ }
221
+ const uniqueMismatches = Array.from(new Map(mismatches.map((mismatch) => [mismatch.relativePath, mismatch])).values());
222
+ await withMicroWorktree({
223
+ operation: TOOL_NAME,
224
+ id: STATUS_RECONCILIATION_OPERATION_ID,
225
+ logPrefix: LOG_PREFIX,
226
+ pushOnly: true,
227
+ execute: async ({ worktreePath }) => {
228
+ const modifiedFiles = [];
229
+ for (const mismatch of uniqueMismatches) {
230
+ const initiativePath = path.join(worktreePath, mismatch.relativePath);
231
+ const content = await fs.readFile(initiativePath, 'utf-8');
232
+ const doc = parseYaml(content);
233
+ doc.status = mismatch.derivedStatus;
234
+ await fs.writeFile(initiativePath, stringifyYaml(doc), 'utf-8');
235
+ modifiedFiles.push(mismatch.relativePath);
236
+ }
237
+ return {
238
+ commitMessage: STATUS_RECONCILIATION_COMMIT_MESSAGE,
239
+ files: modifiedFiles,
240
+ };
241
+ },
242
+ });
243
+ }
244
+ function appendInitiativeStatusMismatchIssues(result, mismatches) {
245
+ if (mismatches.length === 0) {
246
+ return [];
247
+ }
248
+ const issues = mismatches.map((mismatch) => createInitiativeStatusMismatchIssue(mismatch));
249
+ result.issues.push(...issues);
250
+ result.summary.statusMismatches += issues.length;
251
+ result.summary.totalIssues += issues.length;
252
+ result.healthy = false;
253
+ return issues;
254
+ }
92
255
  /**
93
256
  * Write audit log entry for tool execution
94
257
  */
@@ -126,7 +289,7 @@ function parseArguments() {
126
289
  * Create dependencies for state doctor from filesystem
127
290
  */
128
291
  async function createDeps(baseDir) {
129
- const config = getConfig({ projectRoot: baseDir });
292
+ const config = getConfig({ projectRoot: baseDir, strictWorkspace: true });
130
293
  return {
131
294
  /**
132
295
  * List all WU YAML files
@@ -289,6 +452,19 @@ async function createDeps(baseDir) {
289
452
  },
290
453
  };
291
454
  }
455
+ /**
456
+ * Enforce canonical workspace config before running state-doctor checks.
457
+ *
458
+ * @param baseDir - Target repository directory
459
+ * @throws Error when workspace.yaml is missing
460
+ */
461
+ function assertCanonicalWorkspace(baseDir) {
462
+ const { workspaceConfigExists } = getConfigFilePresence(baseDir);
463
+ if (workspaceConfigExists) {
464
+ return;
465
+ }
466
+ throw new Error(`${LOG_PREFIX} Missing ${WORKSPACE_CONFIG_FILE_NAME}. Run \`${WORKSPACE_INIT_COMMAND}\`.`);
467
+ }
292
468
  /**
293
469
  * Get emoji for issue severity
294
470
  */
@@ -433,7 +609,7 @@ function buildAuditOutput(result) {
433
609
  function warnMissingPaths(baseDir, quiet) {
434
610
  if (quiet)
435
611
  return;
436
- const paths = getResolvedPaths({ projectRoot: baseDir });
612
+ const paths = getResolvedPaths({ projectRoot: baseDir, strictWorkspace: true });
437
613
  const missing = [];
438
614
  if (!existsSync(paths.wuDir)) {
439
615
  missing.push(`WU directory: ${paths.wuDir}`);
@@ -449,22 +625,24 @@ function warnMissingPaths(baseDir, quiet) {
449
625
  for (const p of missing) {
450
626
  console.warn(` - ${p}`);
451
627
  }
452
- console.warn(' Tip: Run `pnpm setup` or check .lumenflow.config.yaml');
628
+ console.warn(` Tip: Run \`${WORKSPACE_INIT_COMMAND}\` and verify ${WORKSPACE_CONFIG_FILE_NAME}`);
453
629
  }
454
630
  }
455
631
  /**
456
632
  * Main CLI entry point
457
633
  */
458
- async function main() {
634
+ export async function main() {
459
635
  const args = parseArguments();
460
636
  const baseDir = args.baseDir || process.cwd();
461
637
  const startedAt = new Date().toISOString();
462
638
  const startTime = Date.now();
463
- // WU-1301: Warn about missing configured paths
464
- warnMissingPaths(baseDir, args.quiet ?? false);
465
639
  let result = null;
466
640
  let error = null;
467
641
  try {
642
+ // Hard-cut enforcement: require canonical workspace configuration.
643
+ assertCanonicalWorkspace(baseDir);
644
+ // WU-1301: Warn about missing configured paths
645
+ warnMissingPaths(baseDir, args.quiet ?? false);
468
646
  // Create base deps for read operations
469
647
  const baseDeps = await createDeps(baseDir);
470
648
  // WU-1230: When --fix is enabled, use micro-worktree isolation for all
@@ -480,6 +658,32 @@ async function main() {
480
658
  fix: args.fix,
481
659
  dryRun: args.dryRun,
482
660
  });
661
+ const initiativeMismatches = await collectInitiativeLifecycleStatusMismatches(baseDir);
662
+ const initiativeIssues = appendInitiativeStatusMismatchIssues(result, initiativeMismatches);
663
+ if (initiativeIssues.length > 0) {
664
+ if (args.fix && args.dryRun) {
665
+ result.dryRun = true;
666
+ const existingWouldFix = result.wouldFix || [];
667
+ result.wouldFix = [...existingWouldFix, ...initiativeIssues];
668
+ }
669
+ else if (args.fix) {
670
+ try {
671
+ await applyInitiativeLifecycleStatusFixes(baseDir, initiativeMismatches);
672
+ result.fixed.push(...initiativeIssues);
673
+ }
674
+ catch (fixErr) {
675
+ const message = fixErr instanceof Error ? fixErr.message : String(fixErr);
676
+ for (const issue of initiativeIssues) {
677
+ result.fixErrors.push({
678
+ type: issue.type,
679
+ wuId: issue.wuId,
680
+ signalId: issue.signalId,
681
+ error: message,
682
+ });
683
+ }
684
+ }
685
+ }
686
+ }
483
687
  }
484
688
  catch (err) {
485
689
  error = err.message;
@@ -57,7 +57,7 @@ const TASK_CLAIM_OPTIONS = {
57
57
  domainData: {
58
58
  name: 'domainData',
59
59
  flags: '--domain-data <json>',
60
- description: 'Optional JSON object payload for domain-specific metadata',
60
+ description: 'Optional JSON object payload for task-scoped metadata',
61
61
  },
62
62
  workspaceRoot: {
63
63
  name: 'workspaceRoot',
package/dist/validate.js CHANGED
@@ -30,7 +30,7 @@ export { validateSingleWU, validateAllWUs };
30
30
  /**
31
31
  * Main CLI entry point
32
32
  */
33
- async function main() {
33
+ export async function main() {
34
34
  const args = process.argv.slice(2);
35
35
  // Parse arguments
36
36
  let wuId;