orbital-command 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (380) hide show
  1. package/bin/orbital.js +640 -37
  2. package/dist/assets/PrimitivesConfig-CrmQXYh4.js +32 -0
  3. package/dist/assets/QualityGates-BbasOsF3.js +21 -0
  4. package/dist/assets/SessionTimeline-CGeJsVvy.js +1 -0
  5. package/dist/assets/Settings-oiM496mc.js +12 -0
  6. package/dist/assets/SourceControl-B1fP2nJL.js +41 -0
  7. package/dist/assets/WorkflowVisualizer-CWLYf-f0.js +74 -0
  8. package/dist/assets/arrow-down-CPy85_J6.js +6 -0
  9. package/dist/assets/charts-DbDg0Psc.js +68 -0
  10. package/dist/assets/circle-x-Cwz6ZQDV.js +6 -0
  11. package/dist/assets/file-text-C46Xr65c.js +6 -0
  12. package/dist/assets/formatDistanceToNow-BMqsSP44.js +1 -0
  13. package/dist/assets/globe-Cn2yNZUD.js +6 -0
  14. package/dist/assets/index-Aj4sV8Al.css +1 -0
  15. package/dist/assets/index-Bc9dK3MW.js +354 -0
  16. package/dist/assets/key-OPaNTWJ5.js +6 -0
  17. package/dist/assets/minus-GMsbpKym.js +6 -0
  18. package/dist/assets/shield-DwAFkDYI.js +6 -0
  19. package/dist/assets/ui-BmsSg9jU.js +53 -0
  20. package/dist/assets/useWorkflowEditor-BJkTX_NR.js +16 -0
  21. package/dist/assets/{vendor-Dzv9lrRc.js → vendor-Bqt8AJn2.js} +1 -1
  22. package/dist/assets/zap-DfbUoOty.js +11 -0
  23. package/dist/favicon.svg +1 -0
  24. package/dist/index.html +6 -5
  25. package/dist/server/server/__tests__/data-routes.test.js +124 -0
  26. package/dist/server/server/__tests__/helpers/db.js +17 -0
  27. package/dist/server/server/__tests__/helpers/mock-emitter.js +8 -0
  28. package/dist/server/server/__tests__/scope-routes.test.js +137 -0
  29. package/dist/server/server/__tests__/sprint-routes.test.js +102 -0
  30. package/dist/server/server/__tests__/workflow-routes.test.js +107 -0
  31. package/dist/server/server/config-migrator.js +138 -0
  32. package/dist/server/server/config.js +17 -2
  33. package/dist/server/server/database.js +27 -12
  34. package/dist/server/server/global-config.js +143 -0
  35. package/dist/server/server/index.js +882 -252
  36. package/dist/server/server/init.js +579 -194
  37. package/dist/server/server/launch.js +29 -0
  38. package/dist/server/server/manifest-types.js +8 -0
  39. package/dist/server/server/manifest.js +454 -0
  40. package/dist/server/server/migrate-legacy.js +229 -0
  41. package/dist/server/server/parsers/event-parser.test.js +117 -0
  42. package/dist/server/server/parsers/scope-parser.js +74 -28
  43. package/dist/server/server/parsers/scope-parser.test.js +230 -0
  44. package/dist/server/server/project-context.js +255 -0
  45. package/dist/server/server/project-emitter.js +41 -0
  46. package/dist/server/server/project-manager.js +297 -0
  47. package/dist/server/server/routes/config-routes.js +1 -3
  48. package/dist/server/server/routes/data-routes.js +22 -110
  49. package/dist/server/server/routes/dispatch-routes.js +15 -9
  50. package/dist/server/server/routes/git-routes.js +74 -0
  51. package/dist/server/server/routes/manifest-routes.js +319 -0
  52. package/dist/server/server/routes/scope-routes.js +37 -23
  53. package/dist/server/server/routes/sync-routes.js +134 -0
  54. package/dist/server/server/routes/version-routes.js +1 -15
  55. package/dist/server/server/routes/workflow-routes.js +9 -3
  56. package/dist/server/server/schema.js +2 -0
  57. package/dist/server/server/services/batch-orchestrator.js +26 -16
  58. package/dist/server/server/services/claude-session-service.js +17 -14
  59. package/dist/server/server/services/deploy-service.test.js +119 -0
  60. package/dist/server/server/services/event-service.js +64 -1
  61. package/dist/server/server/services/event-service.test.js +191 -0
  62. package/dist/server/server/services/gate-service.test.js +105 -0
  63. package/dist/server/server/services/git-service.js +108 -4
  64. package/dist/server/server/services/github-service.js +110 -2
  65. package/dist/server/server/services/readiness-service.test.js +190 -0
  66. package/dist/server/server/services/scope-cache.js +5 -1
  67. package/dist/server/server/services/scope-cache.test.js +142 -0
  68. package/dist/server/server/services/scope-service.js +217 -126
  69. package/dist/server/server/services/scope-service.test.js +137 -0
  70. package/dist/server/server/services/sprint-orchestrator.js +7 -6
  71. package/dist/server/server/services/sprint-service.js +21 -1
  72. package/dist/server/server/services/sprint-service.test.js +238 -0
  73. package/dist/server/server/services/sync-service.js +434 -0
  74. package/dist/server/server/services/sync-types.js +2 -0
  75. package/dist/server/server/services/telemetry-service.js +143 -0
  76. package/dist/server/server/services/workflow-service.js +26 -5
  77. package/dist/server/server/services/workflow-service.test.js +159 -0
  78. package/dist/server/server/settings-sync.js +284 -0
  79. package/dist/server/server/update-planner.js +279 -0
  80. package/dist/server/server/utils/cc-hooks-parser.js +3 -0
  81. package/dist/server/server/utils/cc-hooks-parser.test.js +86 -0
  82. package/dist/server/server/utils/dispatch-utils.js +77 -20
  83. package/dist/server/server/utils/dispatch-utils.test.js +182 -0
  84. package/dist/server/server/utils/logger.js +37 -3
  85. package/dist/server/server/utils/package-info.js +30 -0
  86. package/dist/server/server/utils/route-helpers.js +10 -0
  87. package/dist/server/server/utils/terminal-launcher.js +79 -25
  88. package/dist/server/server/utils/worktree-manager.js +13 -4
  89. package/dist/server/server/validator.js +230 -0
  90. package/dist/server/server/watchers/global-watcher.js +63 -0
  91. package/dist/server/server/watchers/scope-watcher.js +27 -12
  92. package/dist/server/server/wizard/config-editor.js +237 -0
  93. package/dist/server/server/wizard/detect.js +96 -0
  94. package/dist/server/server/wizard/doctor.js +115 -0
  95. package/dist/server/server/wizard/index.js +155 -0
  96. package/dist/server/server/wizard/phases/confirm.js +39 -0
  97. package/dist/server/server/wizard/phases/project-setup.js +90 -0
  98. package/dist/server/server/wizard/phases/setup-wizard.js +66 -0
  99. package/dist/server/server/wizard/phases/welcome.js +35 -0
  100. package/dist/server/server/wizard/phases/workflow-setup.js +22 -0
  101. package/dist/server/server/wizard/types.js +29 -0
  102. package/dist/server/server/wizard/ui.js +74 -0
  103. package/dist/server/shared/__fixtures__/workflow-configs.js +75 -0
  104. package/dist/server/shared/default-workflow.json +65 -0
  105. package/dist/server/shared/onboarding-tour.test.js +81 -0
  106. package/dist/server/shared/project-colors.js +24 -0
  107. package/dist/server/shared/workflow-config.test.js +84 -0
  108. package/dist/server/shared/workflow-engine.test.js +302 -0
  109. package/dist/server/shared/workflow-normalizer.js +101 -0
  110. package/dist/server/shared/workflow-normalizer.test.js +100 -0
  111. package/dist/server/src/components/onboarding/tour-steps.js +84 -0
  112. package/package.json +20 -15
  113. package/schemas/orbital.config.schema.json +16 -1
  114. package/scripts/postinstall.js +55 -7
  115. package/server/__tests__/data-routes.test.ts +149 -0
  116. package/server/__tests__/helpers/db.ts +19 -0
  117. package/server/__tests__/helpers/mock-emitter.ts +10 -0
  118. package/server/__tests__/scope-routes.test.ts +157 -0
  119. package/server/__tests__/sprint-routes.test.ts +118 -0
  120. package/server/__tests__/workflow-routes.test.ts +120 -0
  121. package/server/config-migrator.ts +163 -0
  122. package/server/config.ts +26 -2
  123. package/server/database.ts +35 -18
  124. package/server/global-config.ts +200 -0
  125. package/server/index.ts +975 -287
  126. package/server/init.ts +625 -182
  127. package/server/launch.ts +32 -0
  128. package/server/manifest-types.ts +145 -0
  129. package/server/manifest.ts +494 -0
  130. package/server/migrate-legacy.ts +290 -0
  131. package/server/parsers/event-parser.test.ts +135 -0
  132. package/server/parsers/scope-parser.test.ts +270 -0
  133. package/server/parsers/scope-parser.ts +79 -31
  134. package/server/project-context.ts +309 -0
  135. package/server/project-emitter.ts +50 -0
  136. package/server/project-manager.ts +369 -0
  137. package/server/routes/config-routes.ts +3 -5
  138. package/server/routes/data-routes.ts +28 -141
  139. package/server/routes/dispatch-routes.ts +19 -11
  140. package/server/routes/git-routes.ts +77 -0
  141. package/server/routes/manifest-routes.ts +388 -0
  142. package/server/routes/scope-routes.ts +29 -25
  143. package/server/routes/sync-routes.ts +175 -0
  144. package/server/routes/version-routes.ts +1 -16
  145. package/server/routes/workflow-routes.ts +9 -3
  146. package/server/schema.ts +2 -0
  147. package/server/services/batch-orchestrator.ts +24 -16
  148. package/server/services/claude-session-service.ts +16 -14
  149. package/server/services/deploy-service.test.ts +145 -0
  150. package/server/services/deploy-service.ts +2 -2
  151. package/server/services/event-service.test.ts +242 -0
  152. package/server/services/event-service.ts +92 -3
  153. package/server/services/gate-service.test.ts +131 -0
  154. package/server/services/gate-service.ts +2 -2
  155. package/server/services/git-service.ts +137 -4
  156. package/server/services/github-service.ts +120 -2
  157. package/server/services/readiness-service.test.ts +217 -0
  158. package/server/services/scope-cache.test.ts +167 -0
  159. package/server/services/scope-cache.ts +4 -1
  160. package/server/services/scope-service.test.ts +169 -0
  161. package/server/services/scope-service.ts +220 -126
  162. package/server/services/sprint-orchestrator.ts +7 -7
  163. package/server/services/sprint-service.test.ts +271 -0
  164. package/server/services/sprint-service.ts +27 -3
  165. package/server/services/sync-service.ts +482 -0
  166. package/server/services/sync-types.ts +77 -0
  167. package/server/services/telemetry-service.ts +195 -0
  168. package/server/services/workflow-service.test.ts +190 -0
  169. package/server/services/workflow-service.ts +29 -9
  170. package/server/settings-sync.ts +359 -0
  171. package/server/update-planner.ts +346 -0
  172. package/server/utils/cc-hooks-parser.test.ts +96 -0
  173. package/server/utils/cc-hooks-parser.ts +4 -0
  174. package/server/utils/dispatch-utils.test.ts +245 -0
  175. package/server/utils/dispatch-utils.ts +97 -27
  176. package/server/utils/logger.ts +40 -3
  177. package/server/utils/package-info.ts +32 -0
  178. package/server/utils/route-helpers.ts +12 -0
  179. package/server/utils/terminal-launcher.ts +85 -25
  180. package/server/utils/worktree-manager.ts +9 -4
  181. package/server/validator.ts +270 -0
  182. package/server/watchers/global-watcher.ts +77 -0
  183. package/server/watchers/scope-watcher.ts +21 -9
  184. package/server/wizard/config-editor.ts +248 -0
  185. package/server/wizard/detect.ts +104 -0
  186. package/server/wizard/doctor.ts +114 -0
  187. package/server/wizard/index.ts +187 -0
  188. package/server/wizard/phases/confirm.ts +45 -0
  189. package/server/wizard/phases/project-setup.ts +106 -0
  190. package/server/wizard/phases/setup-wizard.ts +78 -0
  191. package/server/wizard/phases/welcome.ts +43 -0
  192. package/server/wizard/phases/workflow-setup.ts +28 -0
  193. package/server/wizard/types.ts +56 -0
  194. package/server/wizard/ui.ts +93 -0
  195. package/shared/__fixtures__/workflow-configs.ts +80 -0
  196. package/shared/default-workflow.json +65 -0
  197. package/shared/onboarding-tour.test.ts +94 -0
  198. package/shared/project-colors.ts +24 -0
  199. package/shared/workflow-config.test.ts +111 -0
  200. package/shared/workflow-config.ts +7 -0
  201. package/shared/workflow-engine.test.ts +388 -0
  202. package/shared/workflow-normalizer.test.ts +119 -0
  203. package/shared/workflow-normalizer.ts +118 -0
  204. package/templates/hooks/end-session.sh +3 -1
  205. package/templates/hooks/orbital-emit.sh +2 -2
  206. package/templates/hooks/orbital-report-deploy.sh +4 -4
  207. package/templates/hooks/orbital-report-gates.sh +4 -4
  208. package/templates/hooks/orbital-scope-update.sh +1 -1
  209. package/templates/hooks/scope-create-cleanup.sh +2 -2
  210. package/templates/hooks/scope-create-gate.sh +0 -1
  211. package/templates/hooks/scope-helpers.sh +18 -0
  212. package/templates/hooks/scope-prepare.sh +66 -11
  213. package/templates/migrations/renames.json +1 -0
  214. package/templates/orbital.config.json +7 -2
  215. package/templates/settings-hooks.json +1 -1
  216. package/templates/skills/git-commit/SKILL.md +9 -4
  217. package/templates/skills/git-dev/SKILL.md +8 -3
  218. package/templates/skills/git-main/SKILL.md +8 -2
  219. package/templates/skills/git-production/SKILL.md +6 -2
  220. package/templates/skills/git-staging/SKILL.md +8 -3
  221. package/templates/skills/scope-create/SKILL.md +17 -3
  222. package/templates/skills/scope-fix-review/SKILL.md +6 -3
  223. package/templates/skills/scope-implement/SKILL.md +4 -1
  224. package/templates/skills/scope-post-review/SKILL.md +63 -5
  225. package/templates/skills/scope-pre-review/SKILL.md +5 -2
  226. package/templates/skills/scope-verify/SKILL.md +5 -3
  227. package/templates/skills/test-code-review/SKILL.md +41 -33
  228. package/templates/skills/test-scaffold/SKILL.md +222 -0
  229. package/dist/assets/WorkflowVisualizer-BZ21PIIF.js +0 -84
  230. package/dist/assets/charts-D__PA1zp.js +0 -72
  231. package/dist/assets/index-D1G6i0nS.css +0 -1
  232. package/dist/assets/index-DpItvKpf.js +0 -419
  233. package/dist/assets/ui-BvF022GT.js +0 -53
  234. package/index.html +0 -15
  235. package/postcss.config.js +0 -6
  236. package/src/App.tsx +0 -33
  237. package/src/components/AgentBadge.tsx +0 -40
  238. package/src/components/BatchPreflightModal.tsx +0 -115
  239. package/src/components/CardDisplayToggle.tsx +0 -74
  240. package/src/components/ColumnHeaderActions.tsx +0 -55
  241. package/src/components/ColumnMenu.tsx +0 -99
  242. package/src/components/DeployHistory.tsx +0 -141
  243. package/src/components/DispatchModal.tsx +0 -164
  244. package/src/components/DispatchPopover.tsx +0 -139
  245. package/src/components/DragOverlay.tsx +0 -25
  246. package/src/components/DriftSidebar.tsx +0 -140
  247. package/src/components/EnvironmentStrip.tsx +0 -88
  248. package/src/components/ErrorBoundary.tsx +0 -62
  249. package/src/components/FilterChip.tsx +0 -105
  250. package/src/components/GateIndicator.tsx +0 -33
  251. package/src/components/IdeaDetailModal.tsx +0 -190
  252. package/src/components/IdeaFormDialog.tsx +0 -113
  253. package/src/components/KanbanColumn.tsx +0 -201
  254. package/src/components/MarkdownRenderer.tsx +0 -114
  255. package/src/components/NeonGrid.tsx +0 -128
  256. package/src/components/PromotionQueue.tsx +0 -89
  257. package/src/components/ScopeCard.tsx +0 -234
  258. package/src/components/ScopeDetailModal.tsx +0 -255
  259. package/src/components/ScopeFilterBar.tsx +0 -152
  260. package/src/components/SearchInput.tsx +0 -102
  261. package/src/components/SessionPanel.tsx +0 -335
  262. package/src/components/SprintContainer.tsx +0 -303
  263. package/src/components/SprintDependencyDialog.tsx +0 -78
  264. package/src/components/SprintPreflightModal.tsx +0 -138
  265. package/src/components/StatusBar.tsx +0 -168
  266. package/src/components/SwimCell.tsx +0 -67
  267. package/src/components/SwimLaneRow.tsx +0 -94
  268. package/src/components/SwimlaneBoardView.tsx +0 -108
  269. package/src/components/VersionBadge.tsx +0 -139
  270. package/src/components/ViewModeSelector.tsx +0 -114
  271. package/src/components/config/AgentChip.tsx +0 -53
  272. package/src/components/config/AgentCreateDialog.tsx +0 -321
  273. package/src/components/config/AgentEditor.tsx +0 -175
  274. package/src/components/config/DirectoryTree.tsx +0 -582
  275. package/src/components/config/FileEditor.tsx +0 -550
  276. package/src/components/config/HookChip.tsx +0 -50
  277. package/src/components/config/StageCard.tsx +0 -198
  278. package/src/components/config/TransitionZone.tsx +0 -173
  279. package/src/components/config/UnifiedWorkflowPipeline.tsx +0 -216
  280. package/src/components/config/WorkflowPipeline.tsx +0 -161
  281. package/src/components/source-control/BranchList.tsx +0 -93
  282. package/src/components/source-control/BranchPanel.tsx +0 -105
  283. package/src/components/source-control/CommitLog.tsx +0 -100
  284. package/src/components/source-control/CommitRow.tsx +0 -47
  285. package/src/components/source-control/GitHubPanel.tsx +0 -110
  286. package/src/components/source-control/GitHubSetupGuide.tsx +0 -52
  287. package/src/components/source-control/GitOverviewBar.tsx +0 -101
  288. package/src/components/source-control/PullRequestList.tsx +0 -69
  289. package/src/components/source-control/WorktreeList.tsx +0 -80
  290. package/src/components/ui/badge.tsx +0 -41
  291. package/src/components/ui/button.tsx +0 -55
  292. package/src/components/ui/card.tsx +0 -78
  293. package/src/components/ui/dialog.tsx +0 -94
  294. package/src/components/ui/popover.tsx +0 -33
  295. package/src/components/ui/scroll-area.tsx +0 -54
  296. package/src/components/ui/separator.tsx +0 -28
  297. package/src/components/ui/tabs.tsx +0 -52
  298. package/src/components/ui/toggle-switch.tsx +0 -35
  299. package/src/components/ui/tooltip.tsx +0 -27
  300. package/src/components/workflow/AddEdgeDialog.tsx +0 -217
  301. package/src/components/workflow/AddListDialog.tsx +0 -201
  302. package/src/components/workflow/ChecklistEditor.tsx +0 -239
  303. package/src/components/workflow/CommandPrefixManager.tsx +0 -118
  304. package/src/components/workflow/ConfigSettingsPanel.tsx +0 -189
  305. package/src/components/workflow/DirectionSelector.tsx +0 -133
  306. package/src/components/workflow/DispatchConfigPanel.tsx +0 -180
  307. package/src/components/workflow/EdgeDetailPanel.tsx +0 -236
  308. package/src/components/workflow/EdgePropertyEditor.tsx +0 -251
  309. package/src/components/workflow/EditToolbar.tsx +0 -138
  310. package/src/components/workflow/HookDetailPanel.tsx +0 -250
  311. package/src/components/workflow/HookExecutionLog.tsx +0 -24
  312. package/src/components/workflow/HookSourceModal.tsx +0 -129
  313. package/src/components/workflow/HooksDashboard.tsx +0 -363
  314. package/src/components/workflow/ListPropertyEditor.tsx +0 -251
  315. package/src/components/workflow/MigrationPreviewDialog.tsx +0 -237
  316. package/src/components/workflow/MovementRulesPanel.tsx +0 -188
  317. package/src/components/workflow/NodeDetailPanel.tsx +0 -245
  318. package/src/components/workflow/PresetSelector.tsx +0 -414
  319. package/src/components/workflow/SkillCommandBuilder.tsx +0 -174
  320. package/src/components/workflow/WorkflowEdgeComponent.tsx +0 -145
  321. package/src/components/workflow/WorkflowNode.tsx +0 -147
  322. package/src/components/workflow/graphLayout.ts +0 -186
  323. package/src/components/workflow/mergeHooks.ts +0 -85
  324. package/src/components/workflow/useEditHistory.ts +0 -88
  325. package/src/components/workflow/useWorkflowEditor.ts +0 -262
  326. package/src/components/workflow/validateConfig.ts +0 -70
  327. package/src/hooks/useActiveDispatches.ts +0 -198
  328. package/src/hooks/useBoardSettings.ts +0 -170
  329. package/src/hooks/useCardDisplay.ts +0 -57
  330. package/src/hooks/useCcHooks.ts +0 -24
  331. package/src/hooks/useConfigTree.ts +0 -51
  332. package/src/hooks/useEnforcementRules.ts +0 -46
  333. package/src/hooks/useEvents.ts +0 -59
  334. package/src/hooks/useFileEditor.ts +0 -165
  335. package/src/hooks/useGates.ts +0 -57
  336. package/src/hooks/useIdeaActions.ts +0 -53
  337. package/src/hooks/useKanbanDnd.ts +0 -410
  338. package/src/hooks/useOrbitalConfig.ts +0 -54
  339. package/src/hooks/usePipeline.ts +0 -47
  340. package/src/hooks/usePipelineData.ts +0 -338
  341. package/src/hooks/useReconnect.ts +0 -25
  342. package/src/hooks/useScopeFilters.ts +0 -125
  343. package/src/hooks/useScopeSessions.ts +0 -44
  344. package/src/hooks/useScopes.ts +0 -67
  345. package/src/hooks/useSearch.ts +0 -67
  346. package/src/hooks/useSettings.tsx +0 -187
  347. package/src/hooks/useSocket.ts +0 -25
  348. package/src/hooks/useSourceControl.ts +0 -105
  349. package/src/hooks/useSprintPreflight.ts +0 -55
  350. package/src/hooks/useSprints.ts +0 -154
  351. package/src/hooks/useStatusBarHighlight.ts +0 -18
  352. package/src/hooks/useSwimlaneBoardSettings.ts +0 -104
  353. package/src/hooks/useTheme.ts +0 -9
  354. package/src/hooks/useTransitionReadiness.ts +0 -53
  355. package/src/hooks/useVersion.ts +0 -155
  356. package/src/hooks/useViolations.ts +0 -65
  357. package/src/hooks/useWorkflow.tsx +0 -125
  358. package/src/hooks/useZoomModifier.ts +0 -19
  359. package/src/index.css +0 -797
  360. package/src/layouts/DashboardLayout.tsx +0 -113
  361. package/src/lib/collisionDetection.ts +0 -20
  362. package/src/lib/scope-fields.ts +0 -61
  363. package/src/lib/swimlane.ts +0 -146
  364. package/src/lib/utils.ts +0 -15
  365. package/src/main.tsx +0 -19
  366. package/src/socket.ts +0 -11
  367. package/src/types/index.ts +0 -497
  368. package/src/views/AgentFeed.tsx +0 -339
  369. package/src/views/DeployPipeline.tsx +0 -59
  370. package/src/views/EnforcementView.tsx +0 -378
  371. package/src/views/PrimitivesConfig.tsx +0 -500
  372. package/src/views/QualityGates.tsx +0 -1012
  373. package/src/views/ScopeBoard.tsx +0 -454
  374. package/src/views/SessionTimeline.tsx +0 -516
  375. package/src/views/Settings.tsx +0 -183
  376. package/src/views/SourceControl.tsx +0 -95
  377. package/src/views/WorkflowVisualizer.tsx +0 -382
  378. package/tailwind.config.js +0 -161
  379. package/tsconfig.json +0 -25
  380. package/vite.config.ts +0 -38
package/bin/orbital.js CHANGED
@@ -31,6 +31,11 @@ function resolveBin(name) {
31
31
  // CLI Helpers
32
32
  // ---------------------------------------------------------------------------
33
33
 
34
+ function getFlagValue(args, flag) {
35
+ const idx = args.indexOf(flag);
36
+ return idx !== -1 && idx + 1 < args.length ? args[idx + 1] : undefined;
37
+ }
38
+
34
39
  function detectProjectRoot() {
35
40
  try {
36
41
  return execFileSync('git', ['rev-parse', '--show-toplevel'], { encoding: 'utf8' }).trim();
@@ -131,34 +136,110 @@ async function loadSharedModule() {
131
136
  }
132
137
  }
133
138
 
139
+ /**
140
+ * Load the interactive wizard module.
141
+ */
142
+ async function loadWizardModule() {
143
+ try {
144
+ return await import('../dist/server/server/wizard/index.js');
145
+ } catch {
146
+ try {
147
+ return await import('../server/wizard/index.js');
148
+ } catch {
149
+ console.error('Error: Wizard module not found.');
150
+ console.error('Try reinstalling: npm install -g orbital-command');
151
+ process.exit(1);
152
+ }
153
+ }
154
+ }
155
+
134
156
  // ---------------------------------------------------------------------------
135
157
  // Commands
136
158
  // ---------------------------------------------------------------------------
137
159
 
160
+ function orbitalSetupDone() {
161
+ return fs.existsSync(path.join(ORBITAL_HOME, 'config.json'));
162
+ }
163
+
164
+ function autoRegisterProject(projectRoot) {
165
+ if (!fs.existsSync(ORBITAL_HOME)) fs.mkdirSync(ORBITAL_HOME, { recursive: true });
166
+ const registry = loadRegistry();
167
+ if (!(registry.projects || []).some(p => p.path === projectRoot)) {
168
+ cmdRegister([projectRoot]);
169
+ }
170
+ }
171
+
138
172
  async function cmdInit(args) {
139
- const force = args.includes('--force');
173
+ const isYes = args.includes('--yes') || args.includes('-y');
174
+ const isInteractive = process.stdout.isTTY && !process.env.CI && !isYes;
140
175
  const projectRoot = detectProjectRoot();
141
176
 
142
- const { runInit } = await loadSharedModule();
143
- runInit(projectRoot, { force });
177
+ if (isInteractive) {
178
+ const wiz = await loadWizardModule();
179
+ const version = getPackageVersion();
180
+
181
+ // If Orbital hasn't been set up yet, run Phase 1 first
182
+ if (!orbitalSetupDone()) {
183
+ await wiz.runSetupWizard(version);
184
+ }
185
+
186
+ // Phase 2: project setup for current directory
187
+ await wiz.runProjectSetup(projectRoot, version, args);
188
+ stampTemplateVersion(projectRoot);
189
+ return;
190
+ }
191
+
192
+ // Non-interactive / --yes fallback (existing behavior preserved)
193
+ const force = args.includes('--force');
194
+ const globalPrivate = loadRegistry().privateMode === true;
195
+ const isPrivate = args.includes('--private') || globalPrivate;
196
+ const preset = getFlagValue(args, '--preset');
197
+ const projectName = getFlagValue(args, '--project-name');
198
+ const serverPort = getFlagValue(args, '--server-port');
199
+ const clientPort = getFlagValue(args, '--client-port');
144
200
 
201
+ const { runInit } = await loadSharedModule();
202
+ runInit(projectRoot, {
203
+ force,
204
+ preset: preset || undefined,
205
+ projectName: projectName || undefined,
206
+ serverPort: serverPort ? Number(serverPort) : undefined,
207
+ clientPort: clientPort ? Number(clientPort) : undefined,
208
+ });
145
209
  stampTemplateVersion(projectRoot);
146
- console.log(`Run \`orbital dev\` to start the development server.\n`);
210
+
211
+ if (isPrivate) {
212
+ const configPath = path.join(projectRoot, '.claude', 'orbital.config.json');
213
+ if (fs.existsSync(configPath)) {
214
+ try {
215
+ const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
216
+ if (!config.telemetry) config.telemetry = {};
217
+ config.telemetry.enabled = false;
218
+ fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + '\n', 'utf8');
219
+
220
+ } catch { /* leave config as-is */ }
221
+ }
222
+ }
223
+
224
+ autoRegisterProject(projectRoot);
225
+ console.log(`Run \`orbital launch\` to start the dashboard.\n`);
147
226
  }
148
227
 
149
- function cmdDev() {
228
+ function cmdLaunchOrDev(forceViteFlag) {
150
229
  const shouldOpen = process.argv.includes('--open');
151
- const forceVite = process.argv.includes('--vite');
230
+ const forceVite = forceViteFlag || process.argv.includes('--vite');
152
231
  const projectRoot = detectProjectRoot();
153
232
  const config = loadConfig(projectRoot);
154
233
  const serverPort = config.serverPort || 4444;
155
234
  const clientPort = config.clientPort || 4445;
156
235
 
236
+ autoRegisterProject(projectRoot);
237
+
157
238
  // Detect packaged mode: dist/index.html exists → serve pre-built frontend
158
239
  const hasPrebuiltFrontend = fs.existsSync(path.join(PACKAGE_ROOT, 'dist', 'index.html'));
159
240
  const useVite = forceVite || !hasPrebuiltFrontend;
160
241
 
161
- console.log(`\nOrbital Command — dev`);
242
+ console.log(`\nOrbital Command — ${useVite ? 'dev' : 'launch'}`);
162
243
  console.log(`Project root: ${projectRoot}`);
163
244
  if (useVite) {
164
245
  console.log(`Server: http://localhost:${serverPort}`);
@@ -171,22 +252,22 @@ function cmdDev() {
171
252
 
172
253
  const env = {
173
254
  ...process.env,
174
- ORBITAL_PROJECT_ROOT: projectRoot,
255
+ ORBITAL_LAUNCH_MODE: 'central',
256
+ ORBITAL_AUTO_REGISTER: projectRoot,
175
257
  ORBITAL_SERVER_PORT: String(serverPort),
176
258
  };
177
259
 
178
- // Start the API server (serves pre-built frontend from dist/ when available)
260
+ const serverScript = path.join(PACKAGE_ROOT, 'server', 'launch.ts');
179
261
  const tsxBin = resolveBin('tsx');
180
262
  const serverProcess = tsxBin
181
- ? spawn(tsxBin, ['watch', path.join(PACKAGE_ROOT, 'server', 'index.ts')],
263
+ ? spawn(tsxBin, ['watch', serverScript],
182
264
  { stdio: 'inherit', env, cwd: PACKAGE_ROOT })
183
- : spawn('npx', ['tsx', 'watch', path.join(PACKAGE_ROOT, 'server', 'index.ts')],
265
+ : spawn('npx', ['tsx', 'watch', serverScript],
184
266
  { stdio: 'inherit', env, cwd: PACKAGE_ROOT });
185
267
 
186
268
  let viteProcess = null;
187
269
 
188
270
  if (useVite) {
189
- // Development mode: spawn Vite for HMR
190
271
  const viteBin = resolveBin('vite');
191
272
  viteProcess = viteBin
192
273
  ? spawn(viteBin, ['--config', path.join(PACKAGE_ROOT, 'vite.config.ts'), '--port', String(clientPort)],
@@ -284,20 +365,442 @@ function cmdEmit(args) {
284
365
  console.log(` File: ${path.relative(projectRoot, filePath)}`);
285
366
  }
286
367
 
287
- async function cmdUpdate() {
368
+ async function cmdUpdate(args) {
288
369
  const projectRoot = detectProjectRoot();
370
+ const dryRun = args.includes('--dry-run');
289
371
 
290
372
  const { runUpdate } = await loadSharedModule();
291
- runUpdate(projectRoot);
373
+ runUpdate(projectRoot, { dryRun });
292
374
 
293
- stampTemplateVersion(projectRoot);
375
+ if (!dryRun) stampTemplateVersion(projectRoot);
294
376
  }
295
377
 
296
- async function cmdUninstall() {
378
+ async function cmdUninstall(args) {
297
379
  const projectRoot = detectProjectRoot();
380
+ const dryRun = args.includes('--dry-run');
381
+ const keepConfig = args.includes('--keep-config');
298
382
 
299
383
  const { runUninstall } = await loadSharedModule();
300
- runUninstall(projectRoot);
384
+ runUninstall(projectRoot, { dryRun, keepConfig });
385
+ }
386
+
387
+ // ---------------------------------------------------------------------------
388
+ // Manifest management commands
389
+ // ---------------------------------------------------------------------------
390
+
391
+ async function cmdValidate() {
392
+ const projectRoot = detectProjectRoot();
393
+
394
+ const mod = await loadSharedModule();
395
+ const report = mod.validate(projectRoot, getPackageVersion());
396
+ console.log(mod.formatValidationReport(report));
397
+ process.exit(report.errors > 0 ? 1 : 0);
398
+ }
399
+
400
+ async function cmdStatus() {
401
+ const projectRoot = detectProjectRoot();
402
+
403
+ const mod = await loadSharedModule();
404
+ const manifest = mod.loadManifest(projectRoot);
405
+
406
+ if (!manifest) {
407
+ console.log('\nNo manifest found. Run `orbital init` or `orbital update` to create one.\n');
408
+ return;
409
+ }
410
+
411
+ const claudeDir = path.join(projectRoot, '.claude');
412
+ mod.refreshFileStatuses(manifest, claudeDir);
413
+
414
+ const summary = mod.summarizeManifest(manifest);
415
+ const packageVersion = getPackageVersion();
416
+ const needsUpdate = manifest.packageVersion !== packageVersion;
417
+
418
+ console.log(`\nOrbital Command v${packageVersion}${needsUpdate ? ` (installed: ${manifest.packageVersion} → needs update)` : ''}\n`);
419
+
420
+ for (const [type, counts] of Object.entries(summary.byType)) {
421
+ const parts = [];
422
+ if (counts.synced) parts.push(`${counts.synced} synced`);
423
+ if (counts.outdated) parts.push(`${counts.outdated} outdated`);
424
+ if (counts.modified) parts.push(`${counts.modified} modified`);
425
+ if (counts.pinned) parts.push(`${counts.pinned} pinned`);
426
+ if (counts.userOwned) parts.push(`${counts.userOwned} user-owned`);
427
+ console.log(` ${type.padEnd(16)} ${parts.join(', ')}`);
428
+ }
429
+
430
+ // Show outdated files (template moved ahead, user hasn't touched)
431
+ const outdated = Object.entries(manifest.files)
432
+ .filter(([, r]) => r.status === 'outdated');
433
+ if (outdated.length > 0) {
434
+ console.log('\n Outdated files (safe to update):');
435
+ for (const [file] of outdated) {
436
+ console.log(` ${file}`);
437
+ }
438
+ }
439
+
440
+ // Show modified files (user edited)
441
+ const modified = Object.entries(manifest.files)
442
+ .filter(([, r]) => r.status === 'modified');
443
+ if (modified.length > 0) {
444
+ console.log('\n Modified files (user edited):');
445
+ for (const [file] of modified) {
446
+ console.log(` ${file} (run 'orbital diff ${file}')`);
447
+ }
448
+ }
449
+
450
+ // Show pinned files
451
+ const pinned = Object.entries(manifest.files)
452
+ .filter(([, r]) => r.status === 'pinned');
453
+ if (pinned.length > 0) {
454
+ console.log('\n Pinned files:');
455
+ for (const [file, record] of pinned) {
456
+ const reason = record.pinnedReason ? `"${record.pinnedReason}"` : '';
457
+ console.log(` ${file} ${reason}`);
458
+ }
459
+ }
460
+
461
+ console.log();
462
+ }
463
+
464
+ async function cmdPin(args) {
465
+ const projectRoot = detectProjectRoot();
466
+ const filePath = args.find(a => !a.startsWith('--'));
467
+ const reasonIdx = args.indexOf('--reason');
468
+ const reason = reasonIdx !== -1 ? args[reasonIdx + 1] : undefined;
469
+
470
+ if (!filePath) {
471
+ console.error('Usage: orbital pin <relative-path> [--reason "..."]');
472
+ process.exit(1);
473
+ }
474
+
475
+ const mod = await loadSharedModule();
476
+ const manifest = mod.loadManifest(projectRoot);
477
+ if (!manifest) {
478
+ console.error('No manifest found. Run `orbital init` first.');
479
+ process.exit(1);
480
+ }
481
+
482
+ const record = manifest.files[filePath];
483
+ if (!record) {
484
+ console.error(`File not tracked: ${filePath}`);
485
+ process.exit(1);
486
+ }
487
+ if (record.origin === 'user') {
488
+ console.error(`Cannot pin user-owned file: ${filePath}`);
489
+ process.exit(1);
490
+ }
491
+
492
+ record.status = 'pinned';
493
+ record.pinnedAt = new Date().toISOString();
494
+ if (reason) record.pinnedReason = reason;
495
+
496
+ mod.saveManifest(projectRoot, manifest);
497
+ console.log(`Pinned: ${filePath}${reason ? ` (${reason})` : ''}`);
498
+ }
499
+
500
+ async function cmdUnpin(args) {
501
+ const projectRoot = detectProjectRoot();
502
+ const filePath = args[0];
503
+
504
+ if (!filePath) {
505
+ console.error('Usage: orbital unpin <relative-path>');
506
+ process.exit(1);
507
+ }
508
+
509
+ const mod = await loadSharedModule();
510
+ const manifest = mod.loadManifest(projectRoot);
511
+ if (!manifest) {
512
+ console.error('No manifest found. Run `orbital init` first.');
513
+ process.exit(1);
514
+ }
515
+
516
+ const record = manifest.files[filePath];
517
+ if (!record || record.status !== 'pinned') {
518
+ console.error(`File is not pinned: ${filePath}`);
519
+ process.exit(1);
520
+ }
521
+
522
+ // Clear pinned state, then recompute
523
+ record.status = 'synced';
524
+ delete record.pinnedAt;
525
+ delete record.pinnedReason;
526
+
527
+ const absPath = path.join(projectRoot, '.claude', filePath);
528
+ if (fs.existsSync(absPath)) {
529
+ const currentHash = mod.hashFile(absPath);
530
+ record.status = mod.computeFileStatus(record, currentHash);
531
+ } else {
532
+ record.status = 'synced';
533
+ }
534
+
535
+ mod.saveManifest(projectRoot, manifest);
536
+ console.log(`Unpinned: ${filePath} (now ${record.status})`);
537
+ }
538
+
539
+ async function cmdPins() {
540
+ const projectRoot = detectProjectRoot();
541
+
542
+ const mod = await loadSharedModule();
543
+ const manifest = mod.loadManifest(projectRoot);
544
+ if (!manifest) {
545
+ console.error('No manifest found. Run `orbital init` first.');
546
+ process.exit(1);
547
+ }
548
+
549
+ const pinned = Object.entries(manifest.files)
550
+ .filter(([, r]) => r.status === 'pinned');
551
+
552
+ if (pinned.length === 0) {
553
+ console.log('No pinned files.');
554
+ return;
555
+ }
556
+
557
+ console.log(`\n Pinned files:\n`);
558
+ for (const [file, record] of pinned) {
559
+ const reason = record.pinnedReason || '(no reason)';
560
+ const date = record.pinnedAt ? new Date(record.pinnedAt).toLocaleDateString() : '';
561
+ console.log(` ${file}`);
562
+ console.log(` Reason: ${reason} Pinned: ${date}`);
563
+ if (record.templateHash !== record.installedHash) {
564
+ console.log(` Template has changed since pin — run 'orbital diff ${file}' to compare`);
565
+ }
566
+ }
567
+ console.log();
568
+ }
569
+
570
+ async function cmdDiff(args) {
571
+ const projectRoot = detectProjectRoot();
572
+ const filePath = args[0];
573
+
574
+ if (!filePath) {
575
+ console.error('Usage: orbital diff <relative-path>');
576
+ process.exit(1);
577
+ }
578
+
579
+ const mod = await loadSharedModule();
580
+ const manifest = mod.loadManifest(projectRoot);
581
+ if (!manifest) {
582
+ console.error('No manifest found. Run `orbital init` first.');
583
+ process.exit(1);
584
+ }
585
+
586
+ const record = manifest.files[filePath];
587
+ if (!record || record.origin !== 'template') {
588
+ console.error(`Not a template file: ${filePath}`);
589
+ process.exit(1);
590
+ }
591
+
592
+ // Resolve template path
593
+ let templateRelPath = filePath;
594
+ if (filePath.startsWith('config/workflows/')) {
595
+ templateRelPath = filePath.replace('config/workflows/', 'presets/');
596
+ }
597
+
598
+ const templatePath = path.join(PACKAGE_ROOT, 'templates', templateRelPath);
599
+ const localPath = path.join(projectRoot, '.claude', filePath);
600
+
601
+ if (!fs.existsSync(templatePath)) {
602
+ console.error(`Template file not found: ${templateRelPath}`);
603
+ process.exit(1);
604
+ }
605
+ if (!fs.existsSync(localPath)) {
606
+ console.log('Local file does not exist. Template content:');
607
+ console.log(fs.readFileSync(templatePath, 'utf-8'));
608
+ return;
609
+ }
610
+
611
+ // Use git diff for nice formatting (safe: no user input in arguments)
612
+ const { execFileSync } = await import('child_process');
613
+ try {
614
+ const output = execFileSync(
615
+ 'git', ['diff', '--no-index', '--color', '--', templatePath, localPath],
616
+ { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] }
617
+ );
618
+ console.log(output);
619
+ } catch (e) {
620
+ // git diff exits 1 when files differ — that's expected
621
+ if (e.stdout) console.log(e.stdout);
622
+ else console.log('Files differ but git diff is unavailable.');
623
+ }
624
+ }
625
+
626
+ async function cmdReset(args) {
627
+ const projectRoot = detectProjectRoot();
628
+ const filePath = args[0];
629
+
630
+ if (!filePath) {
631
+ console.error('Usage: orbital reset <relative-path>');
632
+ process.exit(1);
633
+ }
634
+
635
+ const mod = await loadSharedModule();
636
+ const manifest = mod.loadManifest(projectRoot);
637
+ if (!manifest) {
638
+ console.error('No manifest found. Run `orbital init` first.');
639
+ process.exit(1);
640
+ }
641
+
642
+ const record = manifest.files[filePath];
643
+ if (!record || record.origin !== 'template') {
644
+ console.error(`Not a template file: ${filePath}`);
645
+ process.exit(1);
646
+ }
647
+
648
+ // Resolve and copy template file
649
+ let templateRelPath = filePath;
650
+ if (filePath.startsWith('config/workflows/')) {
651
+ templateRelPath = filePath.replace('config/workflows/', 'presets/');
652
+ }
653
+
654
+ const templatePath = path.join(PACKAGE_ROOT, 'templates', templateRelPath);
655
+ const localPath = path.join(projectRoot, '.claude', filePath);
656
+
657
+ if (!fs.existsSync(templatePath)) {
658
+ console.error(`Template file not found: ${templateRelPath}`);
659
+ process.exit(1);
660
+ }
661
+
662
+ fs.copyFileSync(templatePath, localPath);
663
+ const newHash = mod.hashFile(localPath);
664
+ record.status = 'synced';
665
+ record.templateHash = newHash;
666
+ record.installedHash = newHash;
667
+ delete record.pinnedAt;
668
+ delete record.pinnedReason;
669
+
670
+ mod.saveManifest(projectRoot, manifest);
671
+ console.log(`Reset: ${filePath} → synced with template`);
672
+ }
673
+
674
+ // ---------------------------------------------------------------------------
675
+ // Multi-project commands
676
+ // ---------------------------------------------------------------------------
677
+
678
+ const ORBITAL_HOME = path.join(process.env.HOME || process.env.USERPROFILE || '~', '.orbital');
679
+ const REGISTRY_PATH = path.join(ORBITAL_HOME, 'config.json');
680
+
681
+ function loadRegistry() {
682
+ if (!fs.existsSync(REGISTRY_PATH)) return { version: 1, projects: [] };
683
+ try {
684
+ return JSON.parse(fs.readFileSync(REGISTRY_PATH, 'utf8'));
685
+ } catch {
686
+ return { version: 1, projects: [] };
687
+ }
688
+ }
689
+
690
+ // cmdLaunch removed — merged into cmdLaunchOrDev() above
691
+
692
+ function cmdRegister(args) {
693
+ const targetPath = args[0] ? path.resolve(args[0]) : detectProjectRoot();
694
+ const nameFlag = args.indexOf('--alias');
695
+ const name = nameFlag >= 0 ? args[nameFlag + 1] : path.basename(targetPath);
696
+
697
+ // Ensure ~/.orbital/ exists
698
+ if (!fs.existsSync(ORBITAL_HOME)) fs.mkdirSync(ORBITAL_HOME, { recursive: true });
699
+
700
+ // Check the project has been initialized
701
+ if (!fs.existsSync(path.join(targetPath, '.claude'))) {
702
+ console.error(`Error: ${targetPath} has not been initialized with Orbital Command.`);
703
+ console.error(`Run \`orbital init\` in that directory first.`);
704
+ process.exit(1);
705
+ }
706
+
707
+ const registry = loadRegistry();
708
+
709
+ // Check if already registered
710
+ if (registry.projects?.some(p => p.path === targetPath)) {
711
+ console.log(`Project already registered: ${targetPath}`);
712
+ return;
713
+ }
714
+
715
+ // Color palette
716
+ const COLORS = [
717
+ '210 80% 55%', '340 75% 55%', '160 60% 45%', '30 90% 55%',
718
+ '270 65% 55%', '50 85% 50%', '180 55% 45%', '0 70% 55%',
719
+ '120 50% 42%', '300 60% 50%', '200 70% 50%', '15 80% 55%',
720
+ ];
721
+ const usedColors = (registry.projects || []).map(p => p.color);
722
+ const color = COLORS.find(c => !usedColors.includes(c)) || COLORS[0];
723
+
724
+ // Generate slug
725
+ const baseSlug = path.basename(targetPath).toLowerCase().replace(/[^a-z0-9-]/g, '-').replace(/-+/g, '-').replace(/^-|-$/g, '') || 'project';
726
+ const existingIds = (registry.projects || []).map(p => p.id);
727
+ const slug = existingIds.includes(baseSlug)
728
+ ? `${baseSlug}-${crypto.createHash('sha256').update(targetPath).digest('hex').slice(0, 4)}`
729
+ : baseSlug;
730
+
731
+ const project = {
732
+ id: slug,
733
+ path: targetPath,
734
+ name,
735
+ color,
736
+ registeredAt: new Date().toISOString(),
737
+ enabled: true,
738
+ };
739
+
740
+ if (!registry.projects) registry.projects = [];
741
+ registry.projects.push(project);
742
+ fs.writeFileSync(REGISTRY_PATH, JSON.stringify(registry, null, 2), 'utf8');
743
+
744
+ console.log(`Registered project: ${name}`);
745
+ console.log(` ID: ${slug}`);
746
+ console.log(` Path: ${targetPath}`);
747
+ console.log(` Color: ${color}`);
748
+ }
749
+
750
+ function cmdUnregister(args) {
751
+ const idOrPath = args[0];
752
+ if (!idOrPath) {
753
+ console.error('Usage: orbital unregister <id-or-path>');
754
+ process.exit(1);
755
+ }
756
+
757
+ const absPath = path.isAbsolute(idOrPath) ? idOrPath : path.resolve(idOrPath);
758
+ const registry = loadRegistry();
759
+ const idx = (registry.projects || []).findIndex(p => p.id === idOrPath || p.path === absPath);
760
+
761
+ if (idx === -1) {
762
+ console.error(`Project not found: ${idOrPath}`);
763
+ process.exit(1);
764
+ }
765
+
766
+ const removed = registry.projects.splice(idx, 1)[0];
767
+ fs.writeFileSync(REGISTRY_PATH, JSON.stringify(registry, null, 2), 'utf8');
768
+
769
+ console.log(`Unregistered project: ${removed.name} (${removed.id})`);
770
+ console.log(` Project files in ${removed.path} are preserved.`);
771
+ }
772
+
773
+ function cmdProjects() {
774
+ const registry = loadRegistry();
775
+ const projects = registry.projects || [];
776
+
777
+ if (projects.length === 0) {
778
+ console.log('\nNo projects registered.');
779
+ console.log('Use `orbital register` or `orbital init` to add a project.\n');
780
+ return;
781
+ }
782
+
783
+ console.log(`\n ${'ID'.padEnd(22)} ${'NAME'.padEnd(22)} ${'STATUS'.padEnd(10)} PATH`);
784
+ console.log(` ${'─'.repeat(22)} ${'─'.repeat(22)} ${'─'.repeat(10)} ${'─'.repeat(30)}`);
785
+ for (const p of projects) {
786
+ const status = p.enabled ? (fs.existsSync(p.path) ? 'active' : 'offline') : 'disabled';
787
+ console.log(` ${p.id.padEnd(22)} ${p.name.padEnd(22)} ${status.padEnd(10)} ${p.path}`);
788
+ }
789
+ console.log();
790
+ }
791
+
792
+ async function cmdConfig(args) {
793
+ const { runConfigEditor } = await loadWizardModule();
794
+ const projectRoot = detectProjectRoot();
795
+ const version = getPackageVersion();
796
+ await runConfigEditor(projectRoot, version, args);
797
+ }
798
+
799
+ async function cmdDoctor() {
800
+ const { runDoctor } = await loadWizardModule();
801
+ const projectRoot = detectProjectRoot();
802
+ const version = getPackageVersion();
803
+ await runDoctor(projectRoot, version);
301
804
  }
302
805
 
303
806
  function printHelp() {
@@ -308,30 +811,66 @@ Usage:
308
811
  orbital <command> [options]
309
812
 
310
813
  Commands:
311
- init Scaffold Orbital Command into the current project
312
- dev Start the Orbital Command dashboard
313
- build Production build of the dashboard
814
+ init Set up Orbital Command (interactive wizard)
815
+ launch Start the dashboard
816
+ config Modify project settings interactively
817
+ doctor Health check and version diagnostics
818
+ update Sync templates and apply migrations
819
+ status Show template sync status
820
+
821
+ Aliases:
822
+ setup Same as init
823
+ dev Same as launch --vite (development with HMR)
824
+
825
+ Config Subcommands:
826
+ config show Print current config as JSON
827
+ config set <k> <v> Set a config value non-interactively
828
+
829
+ Template Management:
830
+ validate Check cross-references and consistency
831
+ pin <path> Lock a file from updates
832
+ unpin <path> Unlock a pinned file
833
+ pins List all pinned files
834
+ diff <path> Show diff between template and local file
835
+ reset <path> Restore a file from the current template
836
+
837
+ Project Management:
838
+ register [path] Register a project with the dashboard
839
+ unregister <id> Remove a project from the dashboard
840
+ projects List all registered projects
841
+
842
+ Other:
843
+ build Production build of the dashboard frontend
314
844
  emit <TYPE> <JSON> Emit an orbital event
315
- update Re-copy hooks/skills/agents from package templates
316
845
  uninstall Remove Orbital artifacts from the project
317
846
 
318
847
  Init Options:
319
- --force Overwrite existing hooks, skills, and agents
320
- --skip-plugins Skip plugin installation
321
- --yes, -y Auto-accept all prompts
848
+ --force Overwrite existing hooks, skills, and agents
849
+ --yes, -y Skip the wizard, use auto-detected defaults
850
+ --private Disable telemetry for this project
851
+ --preset <name> Workflow preset (default/minimal/development/gitflow)
852
+ --project-name <n> Override auto-detected project name
853
+ --server-port <n> Override default server port (4444)
854
+ --client-port <n> Override default client port (4445)
855
+
856
+ Launch Options:
857
+ --open Open the dashboard in the browser
858
+ --vite Force Vite dev server for HMR
322
859
 
323
- Dev Options:
324
- --open Open the dashboard in the default browser
325
- --vite Force Vite dev server (for local development with HMR)
860
+ Update Options:
861
+ --dry-run Preview changes without applying them
862
+
863
+ Uninstall Options:
864
+ --dry-run Preview removal without applying
865
+ --keep-config Keep orbital.config.json for re-initialization
326
866
 
327
867
  Examples:
328
868
  orbital init
329
- orbital init --force
330
- orbital dev
331
- orbital dev --open
332
- orbital emit SCOPE_TRANSITION '{"scope":"042","from":"implementing","to":"review"}'
333
- orbital update
334
- orbital uninstall
869
+ orbital launch --open
870
+ orbital config
871
+ orbital doctor
872
+ orbital update --dry-run
873
+ orbital status
335
874
  `);
336
875
  }
337
876
 
@@ -343,11 +882,30 @@ const [command, ...args] = process.argv.slice(2);
343
882
 
344
883
  async function main() {
345
884
  switch (command) {
885
+ case 'launch':
886
+ cmdLaunchOrDev(false);
887
+ break;
346
888
  case 'init':
889
+ case 'setup':
347
890
  await cmdInit(args);
348
891
  break;
892
+ case 'config':
893
+ await cmdConfig(args);
894
+ break;
895
+ case 'doctor':
896
+ await cmdDoctor();
897
+ break;
349
898
  case 'dev':
350
- cmdDev();
899
+ cmdLaunchOrDev(true);
900
+ break;
901
+ case 'register':
902
+ cmdRegister(args);
903
+ break;
904
+ case 'unregister':
905
+ cmdUnregister(args);
906
+ break;
907
+ case 'projects':
908
+ cmdProjects();
351
909
  break;
352
910
  case 'build':
353
911
  cmdBuild();
@@ -356,18 +914,63 @@ async function main() {
356
914
  cmdEmit(args);
357
915
  break;
358
916
  case 'update':
359
- await cmdUpdate();
917
+ await cmdUpdate(args);
360
918
  break;
361
919
  case 'uninstall':
362
- await cmdUninstall();
920
+ await cmdUninstall(args);
921
+ break;
922
+ case 'status':
923
+ await cmdStatus();
924
+ break;
925
+ case 'validate':
926
+ await cmdValidate();
927
+ break;
928
+ case 'pin':
929
+ await cmdPin(args);
930
+ break;
931
+ case 'unpin':
932
+ await cmdUnpin(args);
933
+ break;
934
+ case 'pins':
935
+ await cmdPins();
363
936
  break;
937
+ case 'diff':
938
+ await cmdDiff(args);
939
+ break;
940
+ case 'reset':
941
+ await cmdReset(args);
942
+ break;
943
+ case 'private': {
944
+ const registry = loadRegistry();
945
+ const enable = args[0] !== 'off';
946
+ registry.privateMode = enable;
947
+ if (!fs.existsSync(ORBITAL_HOME)) fs.mkdirSync(ORBITAL_HOME, { recursive: true });
948
+ fs.writeFileSync(REGISTRY_PATH, JSON.stringify(registry, null, 2), 'utf8');
949
+ console.log(`Private mode ${enable ? 'enabled' : 'disabled'} globally.`);
950
+
951
+ break;
952
+ }
364
953
  case 'help':
365
954
  case '--help':
366
955
  case '-h':
367
956
  printHelp();
368
957
  break;
369
958
  case undefined:
370
- printHelp();
959
+ if (process.stdout.isTTY && !process.env.CI) {
960
+ const wiz = await loadWizardModule();
961
+ const version = getPackageVersion();
962
+ if (!orbitalSetupDone()) {
963
+ // First time — run Phase 1 setup
964
+ await wiz.runSetupWizard(version);
965
+ } else {
966
+ // Already set up — run Phase 2 for current directory
967
+ const projectRoot = detectProjectRoot();
968
+ await wiz.runProjectSetup(projectRoot, version, []);
969
+ stampTemplateVersion(projectRoot);
970
+ }
971
+ } else {
972
+ printHelp();
973
+ }
371
974
  break;
372
975
  default:
373
976
  console.error(`Unknown command: ${command}`);