@lumenflow/cli 3.1.1 → 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 +244 -61
  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 -230
  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 -1964
  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
package/dist/init.js CHANGED
@@ -19,6 +19,7 @@ import * as path from 'node:path';
19
19
  import * as yaml from 'yaml';
20
20
  import { execFileSync } from 'node:child_process';
21
21
  import { getDefaultConfig, createWUParser, WU_OPTIONS, CLAUDE_HOOKS, LUMENFLOW_CLIENT_IDS, } from '@lumenflow/core';
22
+ import { WORKSPACE_V2_KEYS } from '@lumenflow/core/config-schema';
22
23
  // WU-1067: Import GATE_PRESETS for --preset support
23
24
  import { GATE_PRESETS } from '@lumenflow/core/gates-config';
24
25
  // WU-1362: Import worktree guard utilities for branch checking
@@ -34,13 +35,14 @@ import { getPublicManifest } from './public-manifest.js';
34
35
  import { runCLI } from './cli-entry-point.js';
35
36
  import { buildInitLaneLifecycleMessage, LANE_LIFECYCLE_STATUS } from './lane-lifecycle-process.js';
36
37
  // WU-1643: Import template constants from dedicated data module
37
- import { AGENTS_MD_TEMPLATE, LUMENFLOW_MD_TEMPLATE, CONSTRAINTS_MD_TEMPLATE, CLAUDE_MD_TEMPLATE, CLAUDE_SETTINGS_TEMPLATE, CURSOR_RULES_TEMPLATE, WINDSURF_RULES_TEMPLATE, CLINE_RULES_TEMPLATE, AIDER_CONF_TEMPLATE, MCP_JSON_TEMPLATE, BACKLOG_TEMPLATE, STATUS_TEMPLATE, WU_TEMPLATE_YAML, FRAMEWORK_HINT_TEMPLATE, FRAMEWORK_OVERLAY_TEMPLATE, QUICK_REF_COMMANDS_TEMPLATE, FIRST_WU_MISTAKES_TEMPLATE, TROUBLESHOOTING_WU_DONE_TEMPLATE, AGENT_SAFETY_CARD_TEMPLATE, STARTING_PROMPT_TEMPLATE, WU_CREATE_CHECKLIST_TEMPLATE, FIRST_15_MINS_TEMPLATE, LOCAL_ONLY_TEMPLATE, LANE_INFERENCE_DOC_TEMPLATE, WU_SIZING_GUIDE_TEMPLATE, WU_LIFECYCLE_SKILL_TEMPLATE, WORKTREE_DISCIPLINE_SKILL_TEMPLATE, LUMENFLOW_GATES_SKILL_TEMPLATE, GITIGNORE_TEMPLATE, PRETTIERIGNORE_TEMPLATE, SAFE_GIT_TEMPLATE, PRE_COMMIT_TEMPLATE, GATE_STUB_SCRIPTS, SCRIPT_ARG_OVERRIDES, DEFAULT_LANE_DEFINITIONS, } from './init-templates.js';
38
+ import { AGENTS_MD_TEMPLATE, LUMENFLOW_MD_TEMPLATE, CONSTRAINTS_MD_TEMPLATE, CLAUDE_MD_TEMPLATE, CLAUDE_SETTINGS_TEMPLATE, CURSOR_RULES_TEMPLATE, WINDSURF_RULES_TEMPLATE, CLINE_RULES_TEMPLATE, AIDER_CONF_TEMPLATE, MCP_JSON_TEMPLATE, BACKLOG_TEMPLATE, STATUS_TEMPLATE, WU_TEMPLATE_YAML, FRAMEWORK_HINT_TEMPLATE, FRAMEWORK_OVERLAY_TEMPLATE, QUICK_REF_COMMANDS_TEMPLATE, FIRST_WU_MISTAKES_TEMPLATE, TROUBLESHOOTING_WU_DONE_TEMPLATE, AGENT_SAFETY_CARD_TEMPLATE, STARTING_PROMPT_TEMPLATE, WU_CREATE_CHECKLIST_TEMPLATE, FIRST_15_MINS_TEMPLATE, LOCAL_ONLY_TEMPLATE, LANE_INFERENCE_DOC_TEMPLATE, WU_SIZING_GUIDE_TEMPLATE, WU_LIFECYCLE_SKILL_TEMPLATE, WORKTREE_DISCIPLINE_SKILL_TEMPLATE, LUMENFLOW_GATES_SKILL_TEMPLATE, GITIGNORE_TEMPLATE, REQUIRED_GITIGNORE_EXCLUSIONS, PRETTIERIGNORE_TEMPLATE, SAFE_GIT_TEMPLATE, PRE_COMMIT_TEMPLATE, GATE_STUB_SCRIPTS, SCRIPT_ARG_OVERRIDES, DEFAULT_LANE_DEFINITIONS, } from './init-templates.js';
38
39
  // WU-1644: Import detection helpers from dedicated module
39
- import { checkPrerequisites, getDocsPath, detectDocsStructure, detectDefaultClient, isGitRepo, hasGitCommits, detectGitStateConfig, } from './init-detection.js';
40
+ import { getDocsPath, detectDocsStructure, detectDefaultClient, isGitRepo, hasGitCommits, detectGitStateConfig, } from './init-detection.js';
40
41
  // WU-1644: Re-export detection functions for backwards compatibility
41
42
  export { detectIDEEnvironment, checkPrerequisites, getDocsPath, detectDocsStructure, } from './init-detection.js';
42
43
  // WU-1644: Import scaffolding helpers from dedicated module
43
44
  import { processTemplate, loadTemplate, createFile, createDirectory, createExecutableScript, } from './init-scaffolding.js';
45
+ import { CANONICAL_BOOTSTRAP_COMMAND, DEFAULT_PROJECT_NAME, getDefaultWorkspaceConfig, WORKSPACE_FILENAME, } from './workspace-init.js';
44
46
  /**
45
47
  * WU-1085: CLI option definitions for init command
46
48
  * WU-1171: Added --merge and --client options
@@ -84,8 +86,33 @@ const INIT_OPTIONS = {
84
86
  flags: '--preset <preset>',
85
87
  description: 'Gate preset for config (node, python, go, rust, dotnet)',
86
88
  },
89
+ bootstrapDomain: {
90
+ name: 'bootstrapDomain',
91
+ flags: '--bootstrap-domain <domain>',
92
+ description: 'Bootstrap domain: software-delivery, infra, or custom',
93
+ },
94
+ skipBootstrap: {
95
+ name: 'skipBootstrap',
96
+ flags: '--skip-bootstrap',
97
+ description: 'Skip workspace bootstrap-all flow (workspace.yaml + pack install)',
98
+ },
99
+ skipBootstrapPackInstall: {
100
+ name: 'skipBootstrapPackInstall',
101
+ flags: '--skip-bootstrap-pack-install',
102
+ description: 'Skip registry pack install during bootstrap',
103
+ },
87
104
  force: WU_OPTIONS.force,
88
105
  };
106
+ function parseBootstrapDomain(rawDomain) {
107
+ if (!rawDomain) {
108
+ return BOOTSTRAP_DEFAULT_DOMAIN;
109
+ }
110
+ if (BOOTSTRAP_VALID_DOMAINS.has(rawDomain)) {
111
+ return rawDomain;
112
+ }
113
+ const validDomains = Array.from(BOOTSTRAP_VALID_DOMAINS).join(', ');
114
+ throw new Error(`${BOOTSTRAP_ERROR_PREFIX} Invalid --bootstrap-domain "${rawDomain}". Valid values: ${validDomains}`);
115
+ }
89
116
  /**
90
117
  * WU-1085: Parse init command options using createWUParser
91
118
  * WU-1171: Added --merge, --client options
@@ -97,7 +124,8 @@ export function parseInitOptions() {
97
124
  name: 'lumenflow-init',
98
125
  description: 'Initialize LumenFlow in a project\n\n' +
99
126
  'Subcommands:\n' +
100
- ' lumenflow commands List all available CLI commands',
127
+ ' lumenflow commands List all available CLI commands\n' +
128
+ ' lumenflow cloud connect Configure cloud control-plane access',
101
129
  options: Object.values(INIT_OPTIONS),
102
130
  });
103
131
  // WU-1171: --client takes precedence, --vendor is alias
@@ -105,6 +133,7 @@ export function parseInitOptions() {
105
133
  // WU-1286: --full is now the default (true), use --minimal to disable
106
134
  // --minimal explicitly sets full to false, otherwise full defaults to true
107
135
  const fullMode = opts.minimal ? false : (opts.full ?? true);
136
+ const bootstrapDomain = parseBootstrapDomain(opts.bootstrapDomain);
108
137
  return {
109
138
  force: opts.force ?? false,
110
139
  full: fullMode,
@@ -113,10 +142,48 @@ export function parseInitOptions() {
113
142
  client: clientValue,
114
143
  vendor: clientValue,
115
144
  preset: opts.preset,
145
+ bootstrapDomain,
146
+ skipBootstrap: Boolean(opts.skipBootstrap),
147
+ skipBootstrapPackInstall: Boolean(opts.skipBootstrapPackInstall),
116
148
  };
117
149
  }
118
150
  const DEFAULT_CLIENT_CLAUDE = LUMENFLOW_CLIENT_IDS.CLAUDE_CODE;
119
- const CONFIG_FILE_NAME = '.lumenflow.config.yaml';
151
+ const BOOTSTRAP_DEFAULT_DOMAIN = 'software-delivery';
152
+ const BOOTSTRAP_INFRA_DOMAIN = 'infra';
153
+ const BOOTSTRAP_CUSTOM_DOMAIN = 'custom';
154
+ const BOOTSTRAP_VALID_DOMAINS = new Set([
155
+ BOOTSTRAP_DEFAULT_DOMAIN,
156
+ BOOTSTRAP_INFRA_DOMAIN,
157
+ BOOTSTRAP_CUSTOM_DOMAIN,
158
+ ]);
159
+ const BOOTSTRAP_SKIP_REASON_FLAG = '--skip-bootstrap';
160
+ const BOOTSTRAP_SKIP_REASON_EXISTING_WORKSPACE = `${WORKSPACE_FILENAME} already exists`;
161
+ const BOOTSTRAP_ERROR_PREFIX = '[lumenflow bootstrap]';
162
+ const INIT_SUBCOMMANDS = {
163
+ COMMANDS: 'commands',
164
+ CLOUD: 'cloud',
165
+ };
166
+ const LEGACY_SUBCOMMANDS = {
167
+ ONBOARD: 'onboard',
168
+ WORKSPACE_INIT_COLON: 'workspace:init',
169
+ WORKSPACE_INIT_DASH: 'workspace-init',
170
+ };
171
+ const CLOUD_SUBCOMMANDS = {
172
+ CONNECT: 'connect',
173
+ };
174
+ const CLOUD_CONNECT_BIN = 'cloud-connect';
175
+ const INIT_ERROR_PREFIX = '[lumenflow init]';
176
+ const INIT_CLOUD_CONNECT_HELP = 'Usage: lumenflow cloud connect --endpoint <url> --org-id <id> --project-id <id> [--token-env <name>]';
177
+ const LEGACY_SUBCOMMAND_ERROR_PREFIX = `${INIT_ERROR_PREFIX} Legacy onboarding subcommand`;
178
+ const LEGACY_SUBCOMMAND_GUIDANCE = `Use "${CANONICAL_BOOTSTRAP_COMMAND}" for bootstrap-all onboarding`;
179
+ const LEGACY_SUBCOMMAND_HELP_HINT = `Run "${CANONICAL_BOOTSTRAP_COMMAND} --help" for supported options`;
180
+ const CONFIG_FILE_NAME = WORKSPACE_FILENAME;
181
+ const SOFTWARE_DELIVERY_KEY = WORKSPACE_V2_KEYS.SOFTWARE_DELIVERY;
182
+ const SOFTWARE_DELIVERY_CONFIG_KEYS = {
183
+ AGENTS: 'agents',
184
+ CLIENTS: 'clients',
185
+ ENFORCEMENT: 'enforcement',
186
+ };
120
187
  const FRAMEWORK_HINT_FILE = '.lumenflow.framework.yaml';
121
188
  const LUMENFLOW_DIR = '.lumenflow';
122
189
  const LUMENFLOW_AGENTS_DIR = `${LUMENFLOW_DIR}/agents`;
@@ -210,30 +277,77 @@ function detectProjectTooling(targetDir) {
210
277
  return { hasTurbo: false };
211
278
  }
212
279
  }
280
+ function asRecord(value) {
281
+ return value && typeof value === 'object' && !Array.isArray(value)
282
+ ? value
283
+ : null;
284
+ }
285
+ function mergeConfigDefaults(defaults, existing) {
286
+ const merged = { ...defaults };
287
+ for (const [key, existingValue] of Object.entries(existing)) {
288
+ const defaultValue = merged[key];
289
+ const existingRecord = asRecord(existingValue);
290
+ const defaultRecord = asRecord(defaultValue);
291
+ if (defaultRecord && existingRecord) {
292
+ merged[key] = mergeConfigDefaults(defaultRecord, existingRecord);
293
+ continue;
294
+ }
295
+ merged[key] = existingValue;
296
+ }
297
+ return merged;
298
+ }
299
+ function toWorkspaceId(value) {
300
+ return value
301
+ .toLowerCase()
302
+ .replace(/[^a-z0-9]+/g, '-')
303
+ .replace(/^-+|-+$/g, '');
304
+ }
305
+ function loadWorkspaceDocument(targetDir) {
306
+ const workspacePath = path.join(targetDir, CONFIG_FILE_NAME);
307
+ if (!fs.existsSync(workspacePath)) {
308
+ const projectName = resolveBootstrapProjectName(targetDir);
309
+ const projectId = toWorkspaceId(projectName);
310
+ const workspace = {
311
+ ...getDefaultWorkspaceConfig(),
312
+ id: projectId,
313
+ name: projectName,
314
+ memory_namespace: projectId,
315
+ event_namespace: projectId,
316
+ };
317
+ return { exists: false, workspace };
318
+ }
319
+ const content = fs.readFileSync(workspacePath, 'utf-8');
320
+ const workspace = asRecord(yaml.parse(content));
321
+ if (!workspace) {
322
+ throw new Error(`${INIT_ERROR_PREFIX} ${CONFIG_FILE_NAME} exists but is not a valid YAML object. ` +
323
+ `Fix ${CONFIG_FILE_NAME} and re-run init.`);
324
+ }
325
+ return { exists: true, workspace };
326
+ }
327
+ function upsertWorkspaceSoftwareDelivery(targetDir, softwareDeliveryConfig, result) {
328
+ const workspacePath = path.join(targetDir, CONFIG_FILE_NAME);
329
+ const { exists, workspace } = loadWorkspaceDocument(targetDir);
330
+ const existingSoftwareDelivery = asRecord(workspace[SOFTWARE_DELIVERY_KEY]) ?? {};
331
+ workspace[SOFTWARE_DELIVERY_KEY] = mergeConfigDefaults(softwareDeliveryConfig, existingSoftwareDelivery);
332
+ fs.writeFileSync(workspacePath, yaml.stringify(workspace), 'utf-8');
333
+ if (exists) {
334
+ result.overwritten = result.overwritten ?? [];
335
+ if (!result.overwritten.includes(CONFIG_FILE_NAME)) {
336
+ result.overwritten.push(CONFIG_FILE_NAME);
337
+ }
338
+ return;
339
+ }
340
+ result.created.push(CONFIG_FILE_NAME);
341
+ }
213
342
  /**
214
- * Generate YAML configuration with header comment
343
+ * Build software_delivery configuration defaults
215
344
  * WU-1067: Supports --preset option for config-driven gates
216
345
  * WU-1307: Includes default lane definitions for onboarding
217
346
  * WU-1364: Supports git config overrides (requireRemote)
218
347
  * WU-1383: Adds enforcement hooks config for Claude client by default
219
348
  * WU-1965: Detects installed tooling from package.json for config defaults
220
349
  */
221
- function generateLumenflowConfigYaml(gatePreset, gitConfigOverride, client, docsPaths, targetDir) {
222
- // WU-1382: Add managed file header to prevent manual edits
223
- const header = `# ============================================================================
224
- # LUMENFLOW MANAGED FILE - DO NOT EDIT MANUALLY
225
- # ============================================================================
226
- # Generated by: lumenflow init
227
- # Regenerate with: pnpm exec lumenflow init --force
228
- #
229
- # This file is managed by LumenFlow tooling. Manual edits may be overwritten.
230
- # To customize, use the CLI commands or edit the appropriate source templates.
231
- # ============================================================================
232
-
233
- # LumenFlow Configuration
234
- # Customize paths based on your project structure
235
-
236
- `;
350
+ function buildSoftwareDeliveryConfig(gatePreset, gitConfigOverride, client, docsPaths, targetDir) {
237
351
  const config = getDefaultConfig();
238
352
  config.directories.agentsDir = LUMENFLOW_AGENTS_DIR;
239
353
  // WU-1755: Override directory paths to match detected docs structure.
@@ -319,7 +433,7 @@ function generateLumenflowConfigYaml(gatePreset, gitConfigOverride, client, docs
319
433
  },
320
434
  };
321
435
  }
322
- return header + yaml.stringify(config);
436
+ return config;
323
437
  }
324
438
  /**
325
439
  * Get current date in YYYY-MM-DD format
@@ -381,22 +495,29 @@ async function runClientIntegrations(targetDir, result) {
381
495
  const configPath = path.join(targetDir, CONFIG_FILE_NAME);
382
496
  if (!fs.existsSync(configPath))
383
497
  return integrationFiles;
384
- let config;
498
+ let softwareDeliveryConfig;
385
499
  try {
386
500
  const content = fs.readFileSync(configPath, 'utf-8');
387
- config = yaml.parse(content);
501
+ const workspaceConfig = asRecord(yaml.parse(content));
502
+ softwareDeliveryConfig = workspaceConfig
503
+ ? asRecord(workspaceConfig[SOFTWARE_DELIVERY_KEY])
504
+ : null;
388
505
  }
389
506
  catch {
390
507
  return integrationFiles; // Config unreadable -- skip silently
391
508
  }
392
- if (!config)
509
+ if (!softwareDeliveryConfig)
393
510
  return integrationFiles;
394
- const agents = config.agents;
395
- const clients = agents?.clients;
511
+ const agents = asRecord(softwareDeliveryConfig[SOFTWARE_DELIVERY_CONFIG_KEYS.AGENTS]);
512
+ const clients = asRecord(agents?.[SOFTWARE_DELIVERY_CONFIG_KEYS.CLIENTS]);
396
513
  if (!clients)
397
514
  return integrationFiles;
398
- for (const [clientKey, clientConfig] of Object.entries(clients)) {
399
- const enforcement = clientConfig.enforcement;
515
+ for (const [clientKey, unsafeClientConfig] of Object.entries(clients)) {
516
+ const clientConfig = asRecord(unsafeClientConfig);
517
+ if (!clientConfig) {
518
+ continue;
519
+ }
520
+ const enforcement = asRecord(clientConfig[SOFTWARE_DELIVERY_CONFIG_KEYS.ENFORCEMENT]);
400
521
  if (!enforcement?.hooks)
401
522
  continue;
402
523
  const integration = CLIENT_INTEGRATIONS[clientKey];
@@ -504,19 +625,8 @@ export async function scaffoldProject(targetDir, options) {
504
625
  DOCS_TASKS_PATH: docsPaths.tasks,
505
626
  DOCS_ONBOARDING_PATH: docsPaths.onboarding,
506
627
  };
507
- // Create .lumenflow.config.yaml (WU-1067: includes gate preset if specified)
508
- // WU-1364: Includes git config overrides (e.g., requireRemote: false for local-only)
509
- // WU-1383: Includes enforcement hooks for Claude client
510
- // Note: Config files don't use merge mode (always skip or force)
511
- const configPath = path.join(targetDir, CONFIG_FILE_NAME);
512
- // WU-1383: Warn if config already exists to discourage manual editing
513
- if (fs.existsSync(configPath) && !options.force) {
514
- result.warnings = result.warnings ?? [];
515
- result.warnings.push(`${CONFIG_FILE_NAME} already exists. ` +
516
- 'To modify configuration, use CLI commands (e.g., pnpm lumenflow:init --force) ' +
517
- 'instead of manual editing.');
518
- }
519
- await createFile(configPath, generateLumenflowConfigYaml(options.gatePreset, gitConfigOverride, client, docsPaths, targetDir), options.force ? 'force' : 'skip', result, targetDir);
628
+ // Upsert workspace.yaml software_delivery defaults (WU-2006 hard cut)
629
+ upsertWorkspaceSoftwareDelivery(targetDir, buildSoftwareDeliveryConfig(options.gatePreset, gitConfigOverride, client, docsPaths, targetDir), result);
520
630
  // WU-1171: Create AGENTS.md (universal entry point for all agents)
521
631
  try {
522
632
  const agentsTemplate = loadTemplate('core/AGENTS.md.template');
@@ -596,14 +706,8 @@ async function scaffoldGitignore(targetDir, options, result) {
596
706
  // Merge mode or skip mode with existing file: append LumenFlow exclusions if not already present
597
707
  const existingContent = fs.readFileSync(gitignorePath, 'utf-8');
598
708
  const linesToAdd = [];
599
- // Check each required exclusion
600
- // WU-1519: Replaced .lumenflow/state with .lumenflow/telemetry
601
- const requiredExclusions = [
602
- { pattern: 'node_modules', line: 'node_modules/' },
603
- { pattern: '.lumenflow/telemetry', line: '.lumenflow/telemetry/' },
604
- { pattern: 'worktrees', line: 'worktrees/' },
605
- ];
606
- for (const { pattern, line } of requiredExclusions) {
709
+ // WU-1969: Use shared constant so merge path and full template cannot drift
710
+ for (const { pattern, line } of REQUIRED_GITIGNORE_EXCLUSIONS) {
607
711
  if (!existingContent.includes(pattern)) {
608
712
  linesToAdd.push(line);
609
713
  }
@@ -970,6 +1074,56 @@ async function scaffoldClientFiles(targetDir, options, result, tokens, client) {
970
1074
  await createFile(path.join(targetDir, '.aider.conf.yml'), AIDER_CONF_TEMPLATE, fileMode, result, targetDir);
971
1075
  }
972
1076
  }
1077
+ function resolveBootstrapProjectName(targetDir) {
1078
+ const basename = path.basename(path.resolve(targetDir)).trim();
1079
+ return basename.length > 0 ? basename : DEFAULT_PROJECT_NAME;
1080
+ }
1081
+ export async function runInitBootstrap(options) {
1082
+ if (options.skipBootstrap) {
1083
+ return {
1084
+ skipped: true,
1085
+ reason: BOOTSTRAP_SKIP_REASON_FLAG,
1086
+ workspaceGenerated: false,
1087
+ packInstalled: false,
1088
+ };
1089
+ }
1090
+ const workspacePath = path.join(options.targetDir, WORKSPACE_FILENAME);
1091
+ const hasExistingWorkspace = fs.existsSync(workspacePath);
1092
+ if (hasExistingWorkspace && !options.force) {
1093
+ return {
1094
+ skipped: true,
1095
+ reason: BOOTSTRAP_SKIP_REASON_EXISTING_WORKSPACE,
1096
+ workspaceGenerated: false,
1097
+ packInstalled: false,
1098
+ };
1099
+ }
1100
+ const onboardModule = await import('./onboard.js');
1101
+ const onboardResult = (await onboardModule.runOnboard({
1102
+ targetDir: options.targetDir,
1103
+ nonInteractive: true,
1104
+ projectName: resolveBootstrapProjectName(options.targetDir),
1105
+ domain: options.bootstrapDomain,
1106
+ force: options.force,
1107
+ skipPackInstall: options.skipBootstrapPackInstall,
1108
+ skipDashboard: true,
1109
+ fetchFn: options.fetchFn ?? globalThis.fetch,
1110
+ }));
1111
+ if (!onboardResult.success) {
1112
+ const failureReason = onboardResult.errors.join('; ') || 'unknown onboarding error';
1113
+ throw new Error(`${BOOTSTRAP_ERROR_PREFIX} ${failureReason}`);
1114
+ }
1115
+ if (!options.skipBootstrapPackInstall &&
1116
+ options.bootstrapDomain !== BOOTSTRAP_CUSTOM_DOMAIN &&
1117
+ onboardResult.packInstalled !== true) {
1118
+ throw new Error(`${BOOTSTRAP_ERROR_PREFIX} failed to install ${options.bootstrapDomain} pack with integrity metadata. ` +
1119
+ `Retry after fixing registry access or rerun with --skip-bootstrap-pack-install.`);
1120
+ }
1121
+ return {
1122
+ skipped: false,
1123
+ workspaceGenerated: onboardResult.workspaceGenerated === true,
1124
+ packInstalled: onboardResult.packInstalled === true,
1125
+ };
1126
+ }
973
1127
  /**
974
1128
  * CLI entry point
975
1129
  * WU-1085: Updated to use parseInitOptions for proper --help support
@@ -978,8 +1132,14 @@ async function scaffoldClientFiles(targetDir, options, result, tokens, client) {
978
1132
  */
979
1133
  export async function main() {
980
1134
  // WU-1378: Check for subcommands before parsing init options
1135
+ const invokedBinary = path.basename(process.argv[1] ?? '', '.js');
981
1136
  const subcommand = process.argv[2];
982
- if (subcommand === 'commands') {
1137
+ if (invokedBinary === CLOUD_CONNECT_BIN) {
1138
+ const { runCloudConnectCli } = await import('./onboard.js');
1139
+ await runCloudConnectCli();
1140
+ return;
1141
+ }
1142
+ if (subcommand === INIT_SUBCOMMANDS.COMMANDS) {
983
1143
  // Route to commands subcommand
984
1144
  const { main: commandsMain } = await import('./commands.js');
985
1145
  // Remove 'commands' from argv so the subcommand parser sees clean args
@@ -987,6 +1147,21 @@ export async function main() {
987
1147
  await commandsMain();
988
1148
  return;
989
1149
  }
1150
+ if (subcommand === LEGACY_SUBCOMMANDS.ONBOARD ||
1151
+ subcommand === LEGACY_SUBCOMMANDS.WORKSPACE_INIT_COLON ||
1152
+ subcommand === LEGACY_SUBCOMMANDS.WORKSPACE_INIT_DASH) {
1153
+ throw new Error(`${LEGACY_SUBCOMMAND_ERROR_PREFIX} "${subcommand}". ${LEGACY_SUBCOMMAND_GUIDANCE}. ${LEGACY_SUBCOMMAND_HELP_HINT}.`);
1154
+ }
1155
+ if (subcommand === INIT_SUBCOMMANDS.CLOUD) {
1156
+ const cloudSubcommand = process.argv[3];
1157
+ if (cloudSubcommand !== CLOUD_SUBCOMMANDS.CONNECT) {
1158
+ throw new Error(`${INIT_ERROR_PREFIX} Unknown cloud subcommand "${cloudSubcommand ?? ''}". ${INIT_CLOUD_CONNECT_HELP}`);
1159
+ }
1160
+ const { runCloudConnectCli } = await import('./onboard.js');
1161
+ process.argv.splice(2, 2);
1162
+ await runCloudConnectCli();
1163
+ return;
1164
+ }
990
1165
  const opts = parseInitOptions();
991
1166
  const targetDir = process.cwd();
992
1167
  console.log('[lumenflow init] Scaffolding LumenFlow project...');
@@ -994,15 +1169,23 @@ export async function main() {
994
1169
  console.log(` Framework: ${opts.framework ?? 'none'}`);
995
1170
  console.log(` Client: ${opts.client ?? 'auto'}`);
996
1171
  console.log(` Gate preset: ${opts.preset ?? 'none (manual config)'}`);
997
- // WU-1177: Check prerequisites (non-blocking)
998
- const prereqs = checkPrerequisites();
999
- const failingPrereqs = Object.entries(prereqs)
1000
- .filter(([, check]) => !check.passed)
1001
- .map(([name, check]) => `${name}: ${check.version} (requires ${check.required})`);
1002
- if (failingPrereqs.length > 0) {
1003
- console.log('\nPrerequisite warnings (non-blocking):');
1004
- failingPrereqs.forEach((msg) => console.log(` ! ${msg}`));
1005
- console.log(' Run "lumenflow doctor" for details.\n');
1172
+ console.log(` Bootstrap domain: ${opts.bootstrapDomain}`);
1173
+ console.log(` Bootstrap pack install: ${opts.skipBootstrapPackInstall ? 'skipped (--skip-bootstrap-pack-install)' : 'required'}`);
1174
+ // WU-1968: Removed separate checkPrerequisites() call here.
1175
+ // runDoctorForInit() (called after scaffolding) already checks prerequisites
1176
+ // and displays results, avoiding duplicate output.
1177
+ const bootstrapResult = await runInitBootstrap({
1178
+ targetDir,
1179
+ force: opts.force,
1180
+ bootstrapDomain: opts.bootstrapDomain,
1181
+ skipBootstrap: opts.skipBootstrap,
1182
+ skipBootstrapPackInstall: opts.skipBootstrapPackInstall,
1183
+ });
1184
+ if (bootstrapResult.skipped) {
1185
+ console.log(` Bootstrap: skipped (${bootstrapResult.reason})`);
1186
+ }
1187
+ else {
1188
+ console.log(` Bootstrap: workspace=${bootstrapResult.workspaceGenerated ? 'created' : 'unchanged'}, pack=${bootstrapResult.packInstalled ? 'installed' : 'skipped'}`);
1006
1189
  }
1007
1190
  const result = await scaffoldProject(targetDir, {
1008
1191
  force: opts.force,
@@ -1051,7 +1234,7 @@ export async function main() {
1051
1234
  // WU-1576: Show enforcement hooks status -- vendor-agnostic (UnsafeAny adapter that produced files)
1052
1235
  console.log('\n[lumenflow init] Done! Next steps:');
1053
1236
  console.log(' 1. Review AGENTS.md and LUMENFLOW.md for workflow documentation');
1054
- console.log(` 2. Edit ${CONFIG_FILE_NAME} to match your project structure`);
1237
+ console.log(` 2. Review ${CONFIG_FILE_NAME} ${SOFTWARE_DELIVERY_KEY} settings for project defaults`);
1055
1238
  console.log('');
1056
1239
  console.log(` ${buildInitLaneLifecycleMessage(LANE_LIFECYCLE_STATUS.UNCONFIGURED)}`);
1057
1240
  if (result.integrationFiles && result.integrationFiles.length > 0) {
@@ -384,7 +384,7 @@ export function buildAddWuMicroWorktreeOptions(wuArg, initId) {
384
384
  },
385
385
  };
386
386
  }
387
- async function main() {
387
+ export async function main() {
388
388
  const args = createWUParser({
389
389
  name: 'initiative-add-wu',
390
390
  description: 'Link one or more WUs to an initiative bidirectionally',
@@ -242,7 +242,7 @@ function printSummary(stats) {
242
242
  /**
243
243
  * Main function
244
244
  */
245
- async function main() {
245
+ export async function main() {
246
246
  const args = createWUParser({
247
247
  name: 'initiative-bulk-assign-wus',
248
248
  description: 'Bulk-assign orphaned WUs to initiatives based on lane prefix rules',
@@ -117,14 +117,14 @@ function createInitiativeYamlInWorktree(worktreePath, id, slug, title, options =
117
117
  }
118
118
  /**
119
119
  * Resolve lane lifecycle classification for initiative:create without mutating
120
- * .lumenflow.config.yaml.
120
+ * workspace.yaml.
121
121
  *
122
122
  * WU-1751: initiative:create guidance should be read-only.
123
123
  */
124
124
  export function resolveLaneLifecycleForInitiativeCreate(projectRoot) {
125
125
  return ensureLaneLifecycleForProject(projectRoot, { persist: false });
126
126
  }
127
- async function main() {
127
+ export async function main() {
128
128
  const args = createWUParser({
129
129
  name: 'initiative-create',
130
130
  description: 'Create a new Initiative with micro-worktree isolation (race-safe)',
@@ -469,7 +469,7 @@ export function buildNoEditsMessage() {
469
469
  /**
470
470
  * Main entry point
471
471
  */
472
- async function main() {
472
+ export async function main() {
473
473
  const opts = parseArgs();
474
474
  const { id } = opts;
475
475
  console.log(`${PREFIX} Starting Initiative edit for ${id}`);
@@ -73,7 +73,7 @@ function truncate(str, maxLen) {
73
73
  return '';
74
74
  return str.length > maxLen ? `${str.substring(0, maxLen - 3)}...` : str;
75
75
  }
76
- async function main() {
76
+ export async function main() {
77
77
  const args = createWUParser({
78
78
  name: 'initiative-list',
79
79
  description: 'List all initiatives with progress percentages',
@@ -252,7 +252,7 @@ export function getCommitMessage(initId, planUri) {
252
252
  const filename = planUri.replace(PLAN_URI_SCHEME, '');
253
253
  return `docs: link plan ${filename} to ${initId.toLowerCase()}`;
254
254
  }
255
- async function main() {
255
+ export async function main() {
256
256
  const args = createWUParser({
257
257
  name: 'init-plan',
258
258
  description: 'Link a plan file to an initiative',
@@ -377,6 +377,4 @@ import { runCLI } from './cli-entry-point.js';
377
377
  if (import.meta.main) {
378
378
  void runCLI(main);
379
379
  }
380
- // Export for testing
381
- export { main };
382
380
  //# sourceMappingURL=initiative-plan.js.map
@@ -40,11 +40,29 @@ function hasIncompletePhase(phases) {
40
40
  return normalizeLifecycleStatus(phase.status) !== WU_STATUS.DONE;
41
41
  });
42
42
  }
43
- export function deriveInitiativeLifecycleStatus(status, phases) {
43
+ function hasAllLinkedWUsDone(progress) {
44
+ if (!progress) {
45
+ return false;
46
+ }
47
+ return progress.total > 0 && progress.done === progress.total;
48
+ }
49
+ function hasIncompleteLinkedWUs(progress) {
50
+ if (!progress) {
51
+ return false;
52
+ }
53
+ return progress.total > 0 && progress.done < progress.total;
54
+ }
55
+ export function deriveInitiativeLifecycleStatus(status, phases, progress) {
44
56
  const normalizedStatus = normalizeLifecycleStatus(status);
57
+ if (hasAllLinkedWUsDone(progress)) {
58
+ return WU_STATUS.DONE;
59
+ }
45
60
  if (normalizedStatus === WU_STATUS.DONE && hasIncompletePhase(phases)) {
46
61
  return WU_STATUS.IN_PROGRESS;
47
62
  }
63
+ if (normalizedStatus === WU_STATUS.DONE && hasIncompleteLinkedWUs(progress)) {
64
+ return WU_STATUS.IN_PROGRESS;
65
+ }
48
66
  return normalizedStatus || WU_STATUS.IN_PROGRESS;
49
67
  }
50
68
  function getWUBlockers(doc) {
@@ -54,6 +72,28 @@ function getWUBlockers(doc) {
54
72
  }
55
73
  return asStringArray(doc.dependencies);
56
74
  }
75
+ function hasPhaseWUStatus(phaseWUs, status) {
76
+ return phaseWUs.some((wu) => normalizeLifecycleStatus(wu.doc.status) === status);
77
+ }
78
+ function areAllPhaseWUsDone(phaseWUs) {
79
+ return (phaseWUs.length > 0 &&
80
+ phaseWUs.every((wu) => normalizeLifecycleStatus(wu.doc.status) === WU_STATUS.DONE));
81
+ }
82
+ export function deriveInitiativePhaseStatus(status, phaseWUs) {
83
+ if (areAllPhaseWUsDone(phaseWUs)) {
84
+ return WU_STATUS.DONE;
85
+ }
86
+ if (hasPhaseWUStatus(phaseWUs, WU_STATUS.IN_PROGRESS)) {
87
+ return WU_STATUS.IN_PROGRESS;
88
+ }
89
+ if (hasPhaseWUStatus(phaseWUs, WU_STATUS.BLOCKED)) {
90
+ return WU_STATUS.BLOCKED;
91
+ }
92
+ if (hasPhaseWUStatus(phaseWUs, WU_STATUS.READY)) {
93
+ return WU_STATUS.READY;
94
+ }
95
+ return normalizeLifecycleStatus(status) || WU_STATUS.IN_PROGRESS;
96
+ }
57
97
  function priorityRank(priority) {
58
98
  const p = String(priority || '').toUpperCase();
59
99
  const map = { P0: 0, P1: 1, P2: 2, P3: 3 };
@@ -75,7 +115,7 @@ function renderDetailed(initiative, useColor) {
75
115
  const wuById = new Map(wus.map((wu) => [wu.id, wu]));
76
116
  const phaseGroups = getInitiativePhases(id);
77
117
  const phases = toInitiativePhases(doc);
78
- const status = deriveInitiativeLifecycleStatus(doc.status, phases);
118
+ const status = deriveInitiativeLifecycleStatus(doc.status, phases, progress);
79
119
  const docTitle = asString(doc.title);
80
120
  const rawStatus = asString(doc.status);
81
121
  const normalizedRawStatus = normalizeLifecycleStatus(rawStatus);
@@ -129,7 +169,7 @@ function renderDetailed(initiative, useColor) {
129
169
  console.log('\nPhases:');
130
170
  for (const phase of phases) {
131
171
  const phaseWUs = phaseGroups.get(phase.id) || [];
132
- const phaseStatus = formatStatus(normalizeLifecycleStatus(phase.status), useColor);
172
+ const phaseStatus = formatStatus(deriveInitiativePhaseStatus(phase.status, phaseWUs), useColor);
133
173
  const phaseTitle = asString(phase.title) || `Phase ${phase.id}`;
134
174
  console.log(` ${phase.id}. ${phaseTitle.padEnd(30)} [${phaseStatus}] ${phaseWUs.length} WUs`);
135
175
  }
@@ -169,7 +209,7 @@ function renderJSON(initiative) {
169
209
  const wus = getInitiativeWUs(id);
170
210
  const phaseGroups = getInitiativePhases(id);
171
211
  const phases = toInitiativePhases(doc);
172
- const status = deriveInitiativeLifecycleStatus(doc.status, phases);
212
+ const status = deriveInitiativeLifecycleStatus(doc.status, phases, progress);
173
213
  const output = {
174
214
  id,
175
215
  slug: asString(doc.slug),
@@ -191,10 +231,11 @@ function renderJSON(initiative) {
191
231
  },
192
232
  phases: phases.map((phase) => {
193
233
  const phaseWUs = phaseGroups.get(phase.id) || [];
234
+ const phaseStatus = deriveInitiativePhaseStatus(phase.status, phaseWUs);
194
235
  return {
195
236
  id: phase.id,
196
237
  title: asString(phase.title),
197
- status: normalizeLifecycleStatus(phase.status),
238
+ status: phaseStatus,
198
239
  wuCount: phaseWUs.length,
199
240
  wus: phaseWUs.map((w) => ({
200
241
  id: w.id,
@@ -258,7 +299,7 @@ function truncate(str, maxLen) {
258
299
  function capitalizeFirst(str) {
259
300
  return str.charAt(0).toUpperCase() + str.slice(1).replace(/_/g, ' ');
260
301
  }
261
- async function main() {
302
+ export async function main() {
262
303
  const args = createWUParser({
263
304
  name: 'initiative-status',
264
305
  description: 'Show detailed initiative view with phases and WUs',