@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
package/dist/onboard.js CHANGED
@@ -20,34 +20,299 @@ import * as fs from 'node:fs';
20
20
  import * as path from 'node:path';
21
21
  import { execFileSync } from 'node:child_process';
22
22
  import { createWUParser } from '@lumenflow/core';
23
- import { WORKSPACE_FILE_NAME } from '@lumenflow/kernel';
23
+ import { WorkspaceControlPlaneConfigSchema, } from '@lumenflow/kernel';
24
24
  import YAML from 'yaml';
25
- import { buildWorkspaceConfig, generateWorkspaceYaml } from './workspace-init.js';
25
+ import { buildWorkspaceConfig, CANONICAL_BOOTSTRAP_COMMAND, DEFAULT_DENY_OVERLAYS, DEFAULT_LANE_TITLE, DEFAULT_PROJECT_NAME, DEFAULT_SANDBOX_NETWORK_PROFILE, WORKSPACE_FILENAME, generateWorkspaceYaml, } from './workspace-init.js';
26
26
  import { DEFAULT_REGISTRY_URL, installPackFromRegistry } from './pack-install.js';
27
27
  import { runCLI } from './cli-entry-point.js';
28
28
  // --- Constants ---
29
29
  export const LOG_PREFIX = '[onboard]';
30
+ const LEGACY_MARKER = 'legacy';
31
+ const LEGACY_ONBOARD_ENTRYPOINT = 'onboard';
32
+ const LEGACY_ONBOARD_ALIAS = 'lumenflow-onboard';
33
+ const LEGACY_ONBOARD_CONNECT_ENTRYPOINT = `${LEGACY_ONBOARD_ENTRYPOINT} connect`;
34
+ const CANONICAL_CLOUD_CONNECT_COMMAND = 'npx lumenflow cloud connect';
35
+ const LEGACY_ONBOARD_MESSAGE_PREFIX = `${LOG_PREFIX} ${LEGACY_MARKER} entrypoint`;
30
36
  const NODE_BINARY = 'node';
31
37
  const GIT_BINARY = 'git';
32
38
  const DEFAULT_DOMAIN_PACK_VERSION = 'latest';
39
+ const DOMAIN_IDS = {
40
+ SOFTWARE_DELIVERY: 'software-delivery',
41
+ INFRA: 'infra',
42
+ CUSTOM: 'custom',
43
+ };
44
+ const DOMAIN_PACK_IDS = {
45
+ SOFTWARE_DELIVERY: 'software-delivery',
46
+ INFRA: 'infra',
47
+ };
48
+ const DEFAULT_ONBOARD_LANE_TITLE = DEFAULT_LANE_TITLE;
49
+ const DOMAIN_DEFAULT_PACKS = {
50
+ [DOMAIN_IDS.SOFTWARE_DELIVERY]: [DOMAIN_PACK_IDS.SOFTWARE_DELIVERY],
51
+ [DOMAIN_IDS.INFRA]: [DOMAIN_PACK_IDS.INFRA],
52
+ [DOMAIN_IDS.CUSTOM]: [],
53
+ };
54
+ const DOMAIN_DEFAULT_LANES = {
55
+ [DOMAIN_IDS.SOFTWARE_DELIVERY]: ['Backend', 'Frontend', 'DevOps'],
56
+ [DOMAIN_IDS.INFRA]: ['Provisioning', 'Networking', 'Security'],
57
+ [DOMAIN_IDS.CUSTOM]: [DEFAULT_ONBOARD_LANE_TITLE],
58
+ };
59
+ const DOMAIN_EMPTY_PACK_ID = 'none';
60
+ const ONBOARD_DEFAULT_DOMAIN = DOMAIN_IDS.SOFTWARE_DELIVERY;
61
+ const ONBOARD_FALLBACK_PROJECT_NAME = DEFAULT_PROJECT_NAME;
62
+ const ONBOARD_SUBCOMMAND_CONNECT = 'connect';
63
+ const CLOUD_CONNECT_LOG_PREFIX = '[cloud connect]';
64
+ const CLOUD_CONNECT_DEFAULT_TOKEN_ENV = 'LUMENFLOW_CONTROL_PLANE_TOKEN';
65
+ const CLOUD_CONNECT_DEFAULT_SYNC_INTERVAL_SECONDS = 30;
66
+ const CLOUD_CONNECT_POLICY_MODES = {
67
+ AUTHORITATIVE: 'authoritative',
68
+ TIGHTEN_ONLY: 'tighten-only',
69
+ DEV_OVERRIDE: 'dev-override',
70
+ };
71
+ const CLOUD_CONNECT_DEFAULT_POLICY_MODE = CLOUD_CONNECT_POLICY_MODES.TIGHTEN_ONLY;
72
+ const CLOUD_CONNECT_ALLOWED_POLICY_MODES = new Set([
73
+ CLOUD_CONNECT_POLICY_MODES.AUTHORITATIVE,
74
+ CLOUD_CONNECT_POLICY_MODES.TIGHTEN_ONLY,
75
+ CLOUD_CONNECT_POLICY_MODES.DEV_OVERRIDE,
76
+ ]);
77
+ const CLOUD_CONNECT_ALLOWED_POLICY_MODE_NAMES = new Set([
78
+ ...CLOUD_CONNECT_ALLOWED_POLICY_MODES,
79
+ ]);
80
+ const CLOUD_CONNECT_SECURE_PROTOCOL = 'https:';
81
+ const CLOUD_CONNECT_LOCAL_PROTOCOL = 'http:';
82
+ const CLOUD_CONNECT_LOCAL_HOSTS = new Set(['localhost', '127.0.0.1', '::1']);
83
+ const CLOUD_CONNECT_ENV_NAME_PATTERN = /^[A-Z][A-Z0-9_]*$/;
84
+ const CLOUD_CONNECT_HELP_HINT = 'Example: npx lumenflow cloud connect --endpoint https://cp.example --org-id org-1 --project-id project-1 --token-env LUMENFLOW_CONTROL_PLANE_TOKEN';
85
+ const YAML_TRAILING_NEWLINE = '\n';
86
+ export function buildLegacyOnboardGuidance(entrypoint = LEGACY_ONBOARD_ENTRYPOINT) {
87
+ return (`${LEGACY_ONBOARD_MESSAGE_PREFIX} "${entrypoint}" is retired. ` +
88
+ `Use "${CANONICAL_BOOTSTRAP_COMMAND}" for bootstrap-all onboarding.`);
89
+ }
90
+ function buildLegacyCloudConnectGuidance(entrypoint = LEGACY_ONBOARD_CONNECT_ENTRYPOINT) {
91
+ return (`${LEGACY_ONBOARD_MESSAGE_PREFIX} "${entrypoint}" is retired. ` +
92
+ `Use "${CANONICAL_CLOUD_CONNECT_COMMAND}" instead.`);
93
+ }
33
94
  /** Domain pack IDs mapped to human-readable descriptions */
34
95
  export const DOMAIN_CHOICES = [
35
96
  {
36
- value: 'software-delivery',
97
+ value: DOMAIN_IDS.SOFTWARE_DELIVERY,
37
98
  label: 'Software Delivery',
38
99
  hint: 'Git tools, worktree isolation, quality gates, lane locking',
39
100
  },
40
101
  {
41
- value: 'infra',
102
+ value: DOMAIN_IDS.INFRA,
42
103
  label: 'Infrastructure',
43
104
  hint: 'Terraform, Ansible, cloud resource management',
44
105
  },
45
106
  {
46
- value: 'custom',
107
+ value: DOMAIN_IDS.CUSTOM,
47
108
  label: 'Custom (empty)',
48
109
  hint: 'Start with an empty workspace and add packs manually',
49
110
  },
50
111
  ];
112
+ const CLOUD_CONNECT_OPTIONS = {
113
+ endpoint: {
114
+ name: 'endpoint',
115
+ flags: '--endpoint <url>',
116
+ description: 'Cloud control-plane endpoint URL',
117
+ },
118
+ orgId: {
119
+ name: 'orgId',
120
+ flags: '--org-id <id>',
121
+ description: 'Cloud organization identifier',
122
+ },
123
+ projectId: {
124
+ name: 'projectId',
125
+ flags: '--project-id <id>',
126
+ description: 'Cloud project identifier',
127
+ },
128
+ tokenEnv: {
129
+ name: 'tokenEnv',
130
+ flags: '--token-env <name>',
131
+ description: `Environment variable containing cloud auth token (default: ${CLOUD_CONNECT_DEFAULT_TOKEN_ENV})`,
132
+ },
133
+ policyMode: {
134
+ name: 'policyMode',
135
+ flags: '--policy-mode <mode>',
136
+ description: 'Policy mode: authoritative, tighten-only, dev-override',
137
+ },
138
+ syncInterval: {
139
+ name: 'syncInterval',
140
+ flags: '--sync-interval <seconds>',
141
+ description: 'Control-plane sync interval in seconds (positive integer)',
142
+ },
143
+ output: {
144
+ name: 'output',
145
+ flags: '--output, -o <dir>',
146
+ description: 'Workspace root directory (default: current directory)',
147
+ },
148
+ force: {
149
+ name: 'force',
150
+ flags: '--force, -f',
151
+ description: 'Overwrite existing control_plane section in workspace.yaml',
152
+ },
153
+ };
154
+ function isRecord(value) {
155
+ return typeof value === 'object' && value !== null;
156
+ }
157
+ function parsePositiveInt(value, fieldName) {
158
+ const parsedValue = typeof value === 'number' ? value : Number(value);
159
+ if (!Number.isInteger(parsedValue) || parsedValue <= 0) {
160
+ throw new Error(`${CLOUD_CONNECT_LOG_PREFIX} Invalid ${fieldName}: expected a positive integer`);
161
+ }
162
+ return parsedValue;
163
+ }
164
+ function parsePolicyMode(value) {
165
+ if (typeof value !== 'string' || !CLOUD_CONNECT_ALLOWED_POLICY_MODE_NAMES.has(value)) {
166
+ const allowedValues = [...CLOUD_CONNECT_ALLOWED_POLICY_MODES].join(', ');
167
+ throw new Error(`${CLOUD_CONNECT_LOG_PREFIX} Invalid --policy-mode "${String(value)}". Valid values: ${allowedValues}`);
168
+ }
169
+ return value;
170
+ }
171
+ function validateEndpoint(endpoint) {
172
+ let parsedEndpoint;
173
+ try {
174
+ parsedEndpoint = new URL(endpoint);
175
+ }
176
+ catch {
177
+ throw new Error(`${CLOUD_CONNECT_LOG_PREFIX} Invalid endpoint "${endpoint}": expected a valid URL`);
178
+ }
179
+ const isSecureProtocol = parsedEndpoint.protocol === CLOUD_CONNECT_SECURE_PROTOCOL;
180
+ const isLocalHost = CLOUD_CONNECT_LOCAL_HOSTS.has(parsedEndpoint.hostname);
181
+ const isLocalHttp = parsedEndpoint.protocol === CLOUD_CONNECT_LOCAL_PROTOCOL && isLocalHost === true;
182
+ if (!isSecureProtocol && !isLocalHttp) {
183
+ throw new Error(`${CLOUD_CONNECT_LOG_PREFIX} Endpoint must use https (or http for localhost only): ${endpoint}`);
184
+ }
185
+ const normalizedEndpoint = parsedEndpoint.toString();
186
+ return normalizedEndpoint.endsWith('/')
187
+ ? normalizedEndpoint.slice(0, normalizedEndpoint.length - 1)
188
+ : normalizedEndpoint;
189
+ }
190
+ function validateTokenEnvName(tokenEnv) {
191
+ if (!CLOUD_CONNECT_ENV_NAME_PATTERN.test(tokenEnv)) {
192
+ throw new Error(`${CLOUD_CONNECT_LOG_PREFIX} Invalid --token-env "${tokenEnv}": expected an uppercase environment variable name`);
193
+ }
194
+ return tokenEnv;
195
+ }
196
+ function ensureTokenValue(tokenEnv, env) {
197
+ const tokenValue = env[tokenEnv];
198
+ if (!tokenValue || tokenValue.trim().length === 0) {
199
+ throw new Error(`${CLOUD_CONNECT_LOG_PREFIX} Missing token env "${tokenEnv}". Export it before connect. ${CLOUD_CONNECT_HELP_HINT}`);
200
+ }
201
+ return tokenValue;
202
+ }
203
+ function parseCloudConnectCliOptions() {
204
+ const opts = createWUParser({
205
+ name: 'cloud-connect',
206
+ description: 'Connect workspace.yaml to LumenFlow cloud control plane',
207
+ options: [
208
+ CLOUD_CONNECT_OPTIONS.endpoint,
209
+ CLOUD_CONNECT_OPTIONS.orgId,
210
+ CLOUD_CONNECT_OPTIONS.projectId,
211
+ CLOUD_CONNECT_OPTIONS.tokenEnv,
212
+ CLOUD_CONNECT_OPTIONS.policyMode,
213
+ CLOUD_CONNECT_OPTIONS.syncInterval,
214
+ CLOUD_CONNECT_OPTIONS.output,
215
+ CLOUD_CONNECT_OPTIONS.force,
216
+ ],
217
+ required: [
218
+ CLOUD_CONNECT_OPTIONS.endpoint.name,
219
+ CLOUD_CONNECT_OPTIONS.orgId.name,
220
+ CLOUD_CONNECT_OPTIONS.projectId.name,
221
+ ],
222
+ });
223
+ const tokenEnvRaw = opts.tokenEnv ?? CLOUD_CONNECT_DEFAULT_TOKEN_ENV;
224
+ const policyModeRaw = opts.policyMode ?? CLOUD_CONNECT_DEFAULT_POLICY_MODE;
225
+ const syncIntervalRaw = opts.syncInterval ??
226
+ CLOUD_CONNECT_DEFAULT_SYNC_INTERVAL_SECONDS;
227
+ return {
228
+ targetDir: (opts.output ?? process.cwd()).trim(),
229
+ endpoint: validateEndpoint(String(opts.endpoint)),
230
+ orgId: String(opts.orgId).trim(),
231
+ projectId: String(opts.projectId).trim(),
232
+ tokenEnv: validateTokenEnvName(tokenEnvRaw.trim()),
233
+ policyMode: parsePolicyMode(policyModeRaw),
234
+ syncInterval: parsePositiveInt(syncIntervalRaw, '--sync-interval'),
235
+ force: Boolean(opts.force),
236
+ };
237
+ }
238
+ function validateWorkspaceRootPath(targetDir) {
239
+ if (!targetDir || targetDir.trim().length === 0) {
240
+ throw new Error(`${CLOUD_CONNECT_LOG_PREFIX} Invalid --output: path must be non-empty`);
241
+ }
242
+ return path.resolve(targetDir);
243
+ }
244
+ function readWorkspaceDocument(workspacePath) {
245
+ if (!fs.existsSync(workspacePath)) {
246
+ throw new Error(`${CLOUD_CONNECT_LOG_PREFIX} ${WORKSPACE_FILENAME} not found at ${workspacePath}. Run "lumenflow init" first to bootstrap a workspace.`);
247
+ }
248
+ const rawContent = fs.readFileSync(workspacePath, 'utf-8');
249
+ const parsedYaml = YAML.parse(rawContent);
250
+ if (!isRecord(parsedYaml)) {
251
+ throw new Error(`${CLOUD_CONNECT_LOG_PREFIX} ${WORKSPACE_FILENAME} is malformed: expected YAML object at document root`);
252
+ }
253
+ return parsedYaml;
254
+ }
255
+ function buildControlPlaneConfig(input) {
256
+ const controlPlaneCandidate = {
257
+ endpoint: input.endpoint,
258
+ org_id: input.orgId,
259
+ project_id: input.projectId,
260
+ sync_interval: input.syncInterval,
261
+ policy_mode: input.policyMode,
262
+ auth: {
263
+ token_env: input.tokenEnv,
264
+ },
265
+ };
266
+ return WorkspaceControlPlaneConfigSchema.parse(controlPlaneCandidate);
267
+ }
268
+ export async function connectWorkspaceToCloud(options) {
269
+ try {
270
+ const workspaceRoot = validateWorkspaceRootPath(options.targetDir);
271
+ const workspacePath = path.join(workspaceRoot, WORKSPACE_FILENAME);
272
+ const workspaceDoc = readWorkspaceDocument(workspacePath);
273
+ const runtimeEnv = options.env ?? process.env;
274
+ ensureTokenValue(options.tokenEnv, runtimeEnv);
275
+ if (workspaceDoc.control_plane && !options.force) {
276
+ return {
277
+ success: false,
278
+ workspacePath,
279
+ error: `${CLOUD_CONNECT_LOG_PREFIX} ${WORKSPACE_FILENAME} already has control_plane configuration. ` +
280
+ 'Use --force to overwrite.',
281
+ };
282
+ }
283
+ const controlPlaneConfig = buildControlPlaneConfig(options);
284
+ workspaceDoc.control_plane = controlPlaneConfig;
285
+ const serializedWorkspace = YAML.stringify(workspaceDoc);
286
+ const normalizedYaml = serializedWorkspace.endsWith(YAML_TRAILING_NEWLINE)
287
+ ? serializedWorkspace
288
+ : `${serializedWorkspace}${YAML_TRAILING_NEWLINE}`;
289
+ fs.writeFileSync(workspacePath, normalizedYaml, 'utf-8');
290
+ return {
291
+ success: true,
292
+ workspacePath,
293
+ controlPlaneConfig,
294
+ };
295
+ }
296
+ catch (error) {
297
+ return {
298
+ success: false,
299
+ error: error instanceof Error ? error.message : String(error),
300
+ };
301
+ }
302
+ }
303
+ export async function runCloudConnectCli() {
304
+ const connectOptions = parseCloudConnectCliOptions();
305
+ const result = await connectWorkspaceToCloud(connectOptions);
306
+ if (!result.success) {
307
+ console.error(result.error ?? `${CLOUD_CONNECT_LOG_PREFIX} Cloud connect failed`);
308
+ process.exit(1);
309
+ }
310
+ console.log(`${CLOUD_CONNECT_LOG_PREFIX} Updated ${WORKSPACE_FILENAME}`);
311
+ console.log(`${CLOUD_CONNECT_LOG_PREFIX} Endpoint: ${connectOptions.endpoint}`);
312
+ console.log(`${CLOUD_CONNECT_LOG_PREFIX} Org ID: ${connectOptions.orgId}`);
313
+ console.log(`${CLOUD_CONNECT_LOG_PREFIX} Project ID: ${connectOptions.projectId}`);
314
+ console.log(`${CLOUD_CONNECT_LOG_PREFIX} Token env: ${connectOptions.tokenEnv}`);
315
+ }
51
316
  /**
52
317
  * Get version of a CLI tool by running it with a version flag.
53
318
  * Returns 'not found' if the tool is not available.
@@ -77,7 +342,7 @@ function getToolVersion(binary, args) {
77
342
  export async function detectEnvironment(targetDir) {
78
343
  const nodeVersion = getToolVersion(NODE_BINARY, ['--version']);
79
344
  const gitVersion = getToolVersion(GIT_BINARY, ['--version']);
80
- const workspacePath = path.join(targetDir, WORKSPACE_FILE_NAME);
345
+ const workspacePath = path.join(targetDir, WORKSPACE_FILENAME);
81
346
  const existingWorkspace = fs.existsSync(workspacePath);
82
347
  return {
83
348
  node: {
@@ -98,14 +363,7 @@ export async function detectEnvironment(targetDir) {
98
363
  * @returns Array of pack IDs to include
99
364
  */
100
365
  function getPacksForDomain(domain) {
101
- switch (domain) {
102
- case 'software-delivery':
103
- return ['software-delivery'];
104
- case 'infra':
105
- return ['infra'];
106
- case 'custom':
107
- return [];
108
- }
366
+ return [...DOMAIN_DEFAULT_PACKS[domain]];
109
367
  }
110
368
  /**
111
369
  * Build lane configuration for a given domain.
@@ -114,14 +372,7 @@ function getPacksForDomain(domain) {
114
372
  * @returns Array of lane titles
115
373
  */
116
374
  function getLanesForDomain(domain) {
117
- switch (domain) {
118
- case 'software-delivery':
119
- return ['Backend', 'Frontend', 'DevOps'];
120
- case 'infra':
121
- return ['Provisioning', 'Networking', 'Security'];
122
- case 'custom':
123
- return ['Default'];
124
- }
375
+ return [...DOMAIN_DEFAULT_LANES[domain]];
125
376
  }
126
377
  /**
127
378
  * Convert a string to kebab-case.
@@ -140,12 +391,12 @@ function toKebabCase(input) {
140
391
  * @returns Result of workspace generation
141
392
  */
142
393
  export async function generateWorkspaceForDomain(targetDir, options) {
143
- const workspacePath = path.join(targetDir, WORKSPACE_FILE_NAME);
394
+ const workspacePath = path.join(targetDir, WORKSPACE_FILENAME);
144
395
  // Check for existing file
145
396
  if (fs.existsSync(workspacePath) && !options.force) {
146
397
  return {
147
398
  success: false,
148
- error: `${WORKSPACE_FILE_NAME} already exists at ${workspacePath}. Use --force to overwrite.`,
399
+ error: `${WORKSPACE_FILENAME} already exists at ${workspacePath}. Use --force to overwrite.`,
149
400
  };
150
401
  }
151
402
  const lanes = getLanesForDomain(options.domain);
@@ -154,8 +405,8 @@ export async function generateWorkspaceForDomain(targetDir, options) {
154
405
  const config = buildWorkspaceConfig({
155
406
  projectName: options.projectName,
156
407
  lanes,
157
- sandboxProfile: 'off',
158
- deniedPaths: ['~/.ssh', '~/.aws', '~/.gnupg', '.env'],
408
+ sandboxProfile: DEFAULT_SANDBOX_NETWORK_PROFILE,
409
+ deniedPaths: [...DEFAULT_DENY_OVERLAYS],
159
410
  cloudConnect: false,
160
411
  });
161
412
  // Installable packs are added in AC4 via installDomainPack.
@@ -191,7 +442,7 @@ export async function installDomainPack(targetDir, options) {
191
442
  const packs = getPacksForDomain(options.domain);
192
443
  if (packs.length === 0) {
193
444
  return {
194
- packId: 'none',
445
+ packId: DOMAIN_EMPTY_PACK_ID,
195
446
  skipped: true,
196
447
  reason: `No packs to install for custom domain. Add packs manually with: pnpm pack:install --id <pack-id>`,
197
448
  };
@@ -225,7 +476,7 @@ export async function installDomainPack(targetDir, options) {
225
476
  let installedVersion;
226
477
  let installedIntegrity;
227
478
  try {
228
- const workspacePath = path.join(targetDir, WORKSPACE_FILE_NAME);
479
+ const workspacePath = path.join(targetDir, WORKSPACE_FILENAME);
229
480
  const workspaceRaw = fs.readFileSync(workspacePath, 'utf-8');
230
481
  const parsed = YAML.parse(workspaceRaw);
231
482
  const installedPack = (parsed.packs ?? []).find((entry) => entry.id === packId);
@@ -284,7 +535,7 @@ export async function launchDashboard(targetDir, options = {}) {
284
535
  * @returns Onboard result
285
536
  */
286
537
  export async function runOnboard(options) {
287
- const { targetDir, projectName = 'my-project', domain = 'software-delivery', force = false, skipPackInstall = false, skipDashboard = false, registryUrl = DEFAULT_REGISTRY_URL, fetchFn = globalThis.fetch, } = options;
538
+ const { targetDir, projectName = ONBOARD_FALLBACK_PROJECT_NAME, domain = ONBOARD_DEFAULT_DOMAIN, force = false, skipPackInstall = false, skipDashboard = false, registryUrl = DEFAULT_REGISTRY_URL, fetchFn = globalThis.fetch, } = options;
288
539
  const errors = [];
289
540
  const result = {
290
541
  success: false,
@@ -344,7 +595,7 @@ export async function runOnboard(options) {
344
595
  *
345
596
  * This is the main entry point for interactive mode.
346
597
  */
347
- async function runInteractiveOnboard(targetDir, force) {
598
+ async function _runInteractiveOnboard(targetDir, force) {
348
599
  // Dynamic import to avoid loading @clack/prompts in non-interactive mode
349
600
  const clack = await import('@clack/prompts');
350
601
  clack.intro('Welcome to LumenFlow');
@@ -367,8 +618,8 @@ async function runInteractiveOnboard(targetDir, force) {
367
618
  // Step 2: Project name
368
619
  const projectName = await clack.text({
369
620
  message: 'Project name',
370
- placeholder: 'my-project',
371
- defaultValue: 'my-project',
621
+ placeholder: ONBOARD_FALLBACK_PROJECT_NAME,
622
+ defaultValue: ONBOARD_FALLBACK_PROJECT_NAME,
372
623
  validate: (value) => {
373
624
  if (!value?.trim())
374
625
  return 'Project name is required';
@@ -406,7 +657,7 @@ async function runInteractiveOnboard(targetDir, force) {
406
657
  }
407
658
  spinner.stop('workspace.yaml created');
408
659
  // Step 5: Install pack (AC4)
409
- if (domain !== 'custom') {
660
+ if (domain !== DOMAIN_IDS.CUSTOM) {
410
661
  spinner.start(`Installing ${domain} pack...`);
411
662
  const installResult = await installDomainPack(targetDir, {
412
663
  domain: domain,
@@ -422,108 +673,32 @@ async function runInteractiveOnboard(targetDir, force) {
422
673
  const dashResult = await launchDashboard(targetDir);
423
674
  // Final summary
424
675
  clack.note([
425
- `Workspace: ${WORKSPACE_FILE_NAME}`,
676
+ `Workspace: ${WORKSPACE_FILENAME}`,
426
677
  `Domain: ${domain}`,
427
678
  `Dashboard: ${dashResult.instruction}`,
428
679
  '',
429
680
  'Next steps:',
430
681
  ' 1. Run "lumenflow init" to scaffold agent config files',
431
- ' 2. Create your first task: pnpm wu:create --lane "Default" --title "My first task"',
682
+ ` 2. Create your first task: pnpm wu:create --lane "${DEFAULT_LANE_TITLE}" --title "My first task"`,
432
683
  ' 3. Claim it: pnpm wu:claim --id WU-1',
433
684
  ].join('\n'), 'Setup complete');
434
685
  clack.outro('Happy building!');
435
686
  }
436
687
  // --- CLI entry point ---
437
- const ONBOARD_OPTIONS = {
438
- yes: {
439
- name: 'yes',
440
- flags: '--yes, -y',
441
- description: 'Accept all defaults non-interactively',
442
- },
443
- domain: {
444
- name: 'domain',
445
- flags: '--domain <domain>',
446
- description: 'Domain pack: software-delivery, infra, or custom',
447
- },
448
- projectName: {
449
- name: 'projectName',
450
- flags: '--project-name <name>',
451
- description: 'Project name (default: directory name or "my-project")',
452
- },
453
- output: {
454
- name: 'output',
455
- flags: '--output, -o <dir>',
456
- description: 'Output directory (default: current directory)',
457
- },
458
- force: {
459
- name: 'force',
460
- flags: '--force, -f',
461
- description: 'Overwrite existing workspace.yaml',
462
- },
463
- skipPackInstall: {
464
- name: 'skipPackInstall',
465
- flags: '--skip-pack-install',
466
- description: 'Skip pack installation step',
467
- },
468
- skipDashboard: {
469
- name: 'skipDashboard',
470
- flags: '--skip-dashboard',
471
- description: 'Skip dashboard launch step',
472
- },
473
- };
474
688
  /**
475
689
  * CLI main entry point for lumenflow onboard
476
690
  */
477
691
  export async function main() {
478
- const opts = createWUParser({
479
- name: 'onboard',
480
- description: 'Interactive setup wizard for LumenFlow workspace',
481
- options: [
482
- ONBOARD_OPTIONS.yes,
483
- ONBOARD_OPTIONS.domain,
484
- ONBOARD_OPTIONS.projectName,
485
- ONBOARD_OPTIONS.output,
486
- ONBOARD_OPTIONS.force,
487
- ONBOARD_OPTIONS.skipPackInstall,
488
- ONBOARD_OPTIONS.skipDashboard,
489
- ],
490
- });
491
- const targetDir = opts.output ?? process.cwd();
492
- const force = Boolean(opts.force);
493
- const useDefaults = Boolean(opts.yes);
494
- const domain = opts.domain ?? 'software-delivery';
495
- const projectName = opts.projectName ?? path.basename(path.resolve(targetDir));
496
- const skipPackInstall = Boolean(opts.skipPackInstall);
497
- const skipDashboard = Boolean(opts.skipDashboard);
498
- if (useDefaults) {
499
- // Non-interactive mode
500
- const result = await runOnboard({
501
- targetDir,
502
- nonInteractive: true,
503
- projectName,
504
- domain,
505
- force,
506
- skipPackInstall,
507
- skipDashboard,
508
- });
509
- if (!result.success) {
510
- console.error(`${LOG_PREFIX} Onboarding failed:`);
511
- for (const error of result.errors) {
512
- console.error(` - ${error}`);
513
- }
514
- process.exit(1);
515
- }
516
- console.log(`${LOG_PREFIX} Workspace created at ${targetDir}/${WORKSPACE_FILE_NAME}`);
517
- console.log(`${LOG_PREFIX} Domain: ${domain}`);
518
- if (!skipPackInstall && result.packInstalled === false) {
519
- console.warn(`${LOG_PREFIX} Warning: Pack install did not complete. Retry with: pnpm pack:install --id ${domain} --source registry --version ${DEFAULT_DOMAIN_PACK_VERSION}`);
520
- }
521
- console.log(`${LOG_PREFIX} Next: run "lumenflow init" to scaffold agent config files`);
522
- }
523
- else {
524
- // Interactive mode with @clack/prompts
525
- await runInteractiveOnboard(targetDir, force);
692
+ const invokedBinary = path.basename(process.argv[1] ?? LEGACY_ONBOARD_ENTRYPOINT, '.js');
693
+ const invokedEntrypoint = invokedBinary === LEGACY_ONBOARD_ALIAS ? LEGACY_ONBOARD_ALIAS : LEGACY_ONBOARD_ENTRYPOINT;
694
+ const subcommand = process.argv[2];
695
+ if (subcommand === ONBOARD_SUBCOMMAND_CONNECT) {
696
+ console.warn(buildLegacyCloudConnectGuidance(`${invokedEntrypoint} ${ONBOARD_SUBCOMMAND_CONNECT}`));
697
+ process.argv.splice(2, 1);
698
+ await runCloudConnectCli();
699
+ return;
526
700
  }
701
+ console.warn(buildLegacyOnboardGuidance(invokedEntrypoint));
527
702
  }
528
703
  // Run if executed directly
529
704
  if (import.meta.main) {
@@ -15,11 +15,10 @@ import { existsSync, readdirSync } from 'node:fs';
15
15
  import { loadInitiativeWUs, calculateProgress, formatProgress, getLaneAvailability, resolveLaneConfigsFromConfig, } from '@lumenflow/initiatives';
16
16
  import { EXIT_CODES, LUMENFLOW_PATHS } from '@lumenflow/core/wu-constants';
17
17
  import { getConfig } from '@lumenflow/core/config';
18
+ import { getErrorMessage, ProcessExitError } from '@lumenflow/core/error-handler';
18
19
  import chalk from 'chalk';
20
+ import { runCLI } from './cli-entry-point.js';
19
21
  const LOG_PREFIX = '[orchestrate:init-status]';
20
- function getErrorMessage(error) {
21
- return error instanceof Error ? error.message : String(error);
22
- }
23
22
  function normalizeLifecycleStatus(value) {
24
23
  return typeof value === 'string' ? value.trim().toLowerCase() : '';
25
24
  }
@@ -113,12 +112,18 @@ const program = new Command()
113
112
  console.log(formatLaneAvailability(availability, laneConfigs));
114
113
  }
115
114
  catch (err) {
116
- console.error(chalk.red(`${LOG_PREFIX} Error: ${getErrorMessage(err)}`));
117
- process.exit(EXIT_CODES.ERROR);
115
+ if (err instanceof ProcessExitError) {
116
+ throw err;
117
+ }
118
+ const message = `${LOG_PREFIX} Error: ${getErrorMessage(err)}`;
119
+ console.error(chalk.red(message));
120
+ throw new ProcessExitError(message, EXIT_CODES.ERROR);
118
121
  }
119
122
  });
120
- // WU-1181 parity: avoid top-level parse when imported in tests
123
+ export async function main() {
124
+ await program.parseAsync(process.argv);
125
+ }
121
126
  if (import.meta.main) {
122
- program.parse();
127
+ void runCLI(main);
123
128
  }
124
129
  //# sourceMappingURL=orchestrate-init-status.js.map
@@ -16,9 +16,8 @@ import chalk from 'chalk';
16
16
  import { loadInitiativeWUs, loadMultipleInitiatives, buildExecutionPlanWithLockPolicy, resolveLaneConfigsFromConfig, formatExecutionPlan, formatExecutionPlanWithEmbeddedSpawns, calculateProgress, formatProgress, buildCheckpointWave, formatCheckpointOutput, validateCheckpointFlags, resolveCheckpointModeAsync, LOG_PREFIX, } from '@lumenflow/initiatives';
17
17
  import { EXIT_CODES } from '@lumenflow/core/wu-constants';
18
18
  import { getConfig } from '@lumenflow/core/config';
19
- function getErrorMessage(error) {
20
- return error instanceof Error ? error.message : String(error);
21
- }
19
+ import { getErrorMessage, ProcessExitError } from '@lumenflow/core/error-handler';
20
+ import { runCLI } from './cli-entry-point.js';
22
21
  const program = new Command()
23
22
  .name('orchestrate-initiative')
24
23
  .description('Orchestrate initiative execution with parallel agent spawning')
@@ -34,16 +33,18 @@ const program = new Command()
34
33
  validateCheckpointFlags({ checkpointPerWave, dryRun, noCheckpoint });
35
34
  }
36
35
  catch (error) {
37
- console.error(chalk.red(`${LOG_PREFIX} Error: ${getErrorMessage(error)}`));
38
- process.exit(EXIT_CODES.ERROR);
36
+ const message = `${LOG_PREFIX} Error: ${getErrorMessage(error)}`;
37
+ console.error(chalk.red(message));
38
+ throw new ProcessExitError(message, EXIT_CODES.ERROR);
39
39
  }
40
40
  if (!initIds || initIds.length === 0) {
41
- console.error(chalk.red(`${LOG_PREFIX} Error: --initiative is required`));
41
+ const message = `${LOG_PREFIX} Error: --initiative is required`;
42
+ console.error(chalk.red(message));
42
43
  console.error('');
43
44
  console.error('Usage:');
44
45
  console.error(' pnpm orchestrate:initiative --initiative INIT-001');
45
46
  console.error(' pnpm orchestrate:initiative --initiative INIT-001 --dry-run');
46
- process.exit(EXIT_CODES.ERROR);
47
+ throw new ProcessExitError(message, EXIT_CODES.ERROR);
47
48
  }
48
49
  try {
49
50
  console.log(chalk.cyan(`${LOG_PREFIX} Loading initiative(s): ${initIds.join(', ')}`));
@@ -70,8 +71,9 @@ const program = new Command()
70
71
  const checkpointDecision = await resolveCheckpointModeAsync({ checkpointPerWave, noCheckpoint, dryRun }, wus);
71
72
  if (checkpointDecision.enabled) {
72
73
  if (initIds.length > 1) {
73
- console.error(chalk.red(`${LOG_PREFIX} Error: Checkpoint mode only supports single initiative`));
74
- process.exit(EXIT_CODES.ERROR);
74
+ const message = `${LOG_PREFIX} Error: Checkpoint mode only supports single initiative`;
75
+ console.error(chalk.red(message));
76
+ throw new ProcessExitError(message, EXIT_CODES.ERROR);
75
77
  }
76
78
  const waveData = buildCheckpointWave(initIds[0], { dryRun });
77
79
  if (!waveData) {
@@ -139,9 +141,18 @@ const program = new Command()
139
141
  console.log(chalk.cyan('Copy the spawn XML above to execute agents.'));
140
142
  }
141
143
  catch (error) {
142
- console.error(chalk.red(`${LOG_PREFIX} Error: ${getErrorMessage(error)}`));
143
- process.exit(EXIT_CODES.ERROR);
144
+ if (error instanceof ProcessExitError) {
145
+ throw error;
146
+ }
147
+ const message = `${LOG_PREFIX} Error: ${getErrorMessage(error)}`;
148
+ console.error(chalk.red(message));
149
+ throw new ProcessExitError(message, EXIT_CODES.ERROR);
144
150
  }
145
151
  });
146
- program.parse();
152
+ export async function main() {
153
+ await program.parseAsync(process.argv);
154
+ }
155
+ if (import.meta.main) {
156
+ void runCLI(main);
157
+ }
147
158
  //# sourceMappingURL=orchestrate-initiative.js.map