orbital-command 0.2.0 → 1.0.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.
- package/README.md +67 -42
- package/bin/commands/config.js +19 -0
- package/bin/commands/events.js +40 -0
- package/bin/commands/launch.js +126 -0
- package/bin/commands/manifest.js +283 -0
- package/bin/commands/registry.js +104 -0
- package/bin/commands/update.js +24 -0
- package/bin/lib/helpers.js +229 -0
- package/bin/orbital.js +147 -319
- package/dist/assets/Landing-CfQdHR0N.js +11 -0
- package/dist/assets/PrimitivesConfig-DThSipFy.js +32 -0
- package/dist/assets/QualityGates-B4kxM5UU.js +26 -0
- package/dist/assets/SessionTimeline-Bz1iZnmg.js +1 -0
- package/dist/assets/Settings-DLcZwbCT.js +12 -0
- package/dist/assets/SourceControl-BMNIz7Lt.js +36 -0
- package/dist/assets/WorkflowVisualizer-CxuSBOYu.js +69 -0
- package/dist/assets/arrow-down-DVPp6_qp.js +6 -0
- package/dist/assets/bot-NFaJBDn_.js +6 -0
- package/dist/assets/charts-LGLb8hyU.js +68 -0
- package/dist/assets/circle-x-IsFCkBZu.js +6 -0
- package/dist/assets/file-text-J1cebZXF.js +6 -0
- package/dist/assets/globe-WzeyHsUc.js +6 -0
- package/dist/assets/index-BdJ57EhC.css +1 -0
- package/dist/assets/index-o4ScMAuR.js +349 -0
- package/dist/assets/key-CKR8JJSj.js +6 -0
- package/dist/assets/minus-CHBsJyjp.js +6 -0
- package/dist/assets/radio-xqZaR-Uk.js +6 -0
- package/dist/assets/rocket-D_xvvNG6.js +6 -0
- package/dist/assets/shield-TdB1yv_a.js +6 -0
- package/dist/assets/ui-BmsSg9jU.js +53 -0
- package/dist/assets/useSocketListener-0L5yiN5i.js +1 -0
- package/dist/assets/useWorkflowEditor-CqeRWVQX.js +11 -0
- package/dist/assets/{vendor-Dzv9lrRc.js → vendor-Bqt8AJn2.js} +1 -1
- package/dist/assets/workflow-constants-Rw-GmgHZ.js +6 -0
- package/dist/assets/zap-C9wqYMpl.js +6 -0
- package/dist/favicon.svg +1 -0
- package/dist/index.html +6 -5
- package/dist/server/server/__tests__/data-routes.test.js +126 -0
- package/dist/server/server/__tests__/helpers/db.js +17 -0
- package/dist/server/server/__tests__/helpers/mock-emitter.js +8 -0
- package/dist/server/server/__tests__/scope-routes.test.js +138 -0
- package/dist/server/server/__tests__/sprint-routes.test.js +102 -0
- package/dist/server/server/__tests__/workflow-routes.test.js +107 -0
- package/dist/server/server/config-migrator.js +135 -0
- package/dist/server/server/config.js +51 -7
- package/dist/server/server/database.js +21 -28
- package/dist/server/server/global-config.js +143 -0
- package/dist/server/server/index.js +118 -276
- package/dist/server/server/init.js +243 -225
- package/dist/server/server/launch.js +29 -0
- package/dist/server/server/manifest-types.js +8 -0
- package/dist/server/server/manifest.js +454 -0
- package/dist/server/server/migrate-legacy.js +229 -0
- package/dist/server/server/parsers/event-parser.js +4 -1
- package/dist/server/server/parsers/event-parser.test.js +117 -0
- package/dist/server/server/parsers/scope-parser.js +74 -28
- package/dist/server/server/parsers/scope-parser.test.js +230 -0
- package/dist/server/server/project-context.js +265 -0
- package/dist/server/server/project-emitter.js +41 -0
- package/dist/server/server/project-manager.js +297 -0
- package/dist/server/server/routes/aggregate-routes.js +871 -0
- package/dist/server/server/routes/config-routes.js +41 -90
- package/dist/server/server/routes/data-routes.js +25 -123
- package/dist/server/server/routes/dispatch-routes.js +37 -15
- package/dist/server/server/routes/git-routes.js +74 -0
- package/dist/server/server/routes/manifest-routes.js +319 -0
- package/dist/server/server/routes/scope-routes.js +45 -28
- package/dist/server/server/routes/sync-routes.js +134 -0
- package/dist/server/server/routes/version-routes.js +1 -15
- package/dist/server/server/routes/workflow-routes.js +9 -3
- package/dist/server/server/schema.js +3 -0
- package/dist/server/server/services/batch-orchestrator.js +41 -17
- package/dist/server/server/services/claude-session-service.js +17 -14
- package/dist/server/server/services/config-service.js +10 -1
- package/dist/server/server/services/deploy-service.test.js +119 -0
- package/dist/server/server/services/event-service.js +64 -1
- package/dist/server/server/services/event-service.test.js +191 -0
- package/dist/server/server/services/gate-service.test.js +105 -0
- package/dist/server/server/services/git-service.js +108 -4
- package/dist/server/server/services/github-service.js +110 -2
- package/dist/server/server/services/readiness-service.test.js +190 -0
- package/dist/server/server/services/scope-cache.js +5 -1
- package/dist/server/server/services/scope-cache.test.js +142 -0
- package/dist/server/server/services/scope-service.js +222 -131
- package/dist/server/server/services/scope-service.test.js +137 -0
- package/dist/server/server/services/sprint-orchestrator.js +29 -15
- package/dist/server/server/services/sprint-service.js +23 -3
- package/dist/server/server/services/sprint-service.test.js +238 -0
- package/dist/server/server/services/sync-service.js +434 -0
- package/dist/server/server/services/sync-types.js +2 -0
- package/dist/server/server/services/workflow-service.js +26 -5
- package/dist/server/server/services/workflow-service.test.js +159 -0
- package/dist/server/server/settings-sync.js +284 -0
- package/dist/server/server/uninstall.js +195 -0
- package/dist/server/server/update-planner.js +279 -0
- package/dist/server/server/update.js +212 -0
- package/dist/server/server/utils/cc-hooks-parser.js +3 -0
- package/dist/server/server/utils/cc-hooks-parser.test.js +86 -0
- package/dist/server/server/utils/dispatch-utils.js +83 -24
- package/dist/server/server/utils/dispatch-utils.test.js +182 -0
- package/dist/server/server/utils/flag-builder.js +54 -0
- package/dist/server/server/utils/json-fields.js +14 -0
- package/dist/server/server/utils/json-fields.test.js +73 -0
- package/dist/server/server/utils/logger.js +37 -3
- package/dist/server/server/utils/package-info.js +30 -0
- package/dist/server/server/utils/route-helpers.js +47 -0
- package/dist/server/server/utils/route-helpers.test.js +115 -0
- package/dist/server/server/utils/terminal-launcher.js +79 -25
- package/dist/server/server/utils/worktree-manager.js +13 -4
- package/dist/server/server/validator.js +230 -0
- package/dist/server/server/watchers/event-watcher.js +28 -13
- package/dist/server/server/watchers/global-watcher.js +63 -0
- package/dist/server/server/watchers/scope-watcher.js +27 -12
- package/dist/server/server/wizard/config-editor.js +237 -0
- package/dist/server/server/wizard/detect.js +96 -0
- package/dist/server/server/wizard/doctor.js +115 -0
- package/dist/server/server/wizard/index.js +340 -0
- package/dist/server/server/wizard/phases/confirm.js +39 -0
- package/dist/server/server/wizard/phases/project-setup.js +90 -0
- package/dist/server/server/wizard/phases/setup-wizard.js +66 -0
- package/dist/server/server/wizard/phases/welcome.js +32 -0
- package/dist/server/server/wizard/phases/workflow-setup.js +22 -0
- package/dist/server/server/wizard/types.js +29 -0
- package/dist/server/server/wizard/ui.js +73 -0
- package/dist/server/shared/__fixtures__/workflow-configs.js +75 -0
- package/dist/server/shared/api-types.js +80 -1
- package/dist/server/shared/default-workflow.json +65 -0
- package/dist/server/shared/onboarding-tour.test.js +81 -0
- package/dist/server/shared/project-colors.js +24 -0
- package/dist/server/shared/workflow-config.test.js +84 -0
- package/dist/server/shared/workflow-engine.js +1 -1
- package/dist/server/shared/workflow-engine.test.js +302 -0
- package/dist/server/shared/workflow-normalizer.js +101 -0
- package/dist/server/shared/workflow-normalizer.test.js +100 -0
- package/dist/server/src/components/onboarding/tour-steps.js +84 -0
- package/package.json +34 -29
- package/schemas/orbital.config.schema.json +2 -5
- package/scripts/postinstall.js +18 -6
- package/scripts/release.sh +53 -0
- package/server/__tests__/data-routes.test.ts +151 -0
- package/server/__tests__/helpers/db.ts +19 -0
- package/server/__tests__/helpers/mock-emitter.ts +10 -0
- package/server/__tests__/scope-routes.test.ts +158 -0
- package/server/__tests__/sprint-routes.test.ts +118 -0
- package/server/__tests__/workflow-routes.test.ts +120 -0
- package/server/config-migrator.ts +160 -0
- package/server/config.ts +64 -12
- package/server/database.ts +22 -31
- package/server/global-config.ts +204 -0
- package/server/index.ts +139 -316
- package/server/init.ts +266 -234
- package/server/launch.ts +32 -0
- package/server/manifest-types.ts +145 -0
- package/server/manifest.ts +494 -0
- package/server/migrate-legacy.ts +290 -0
- package/server/parsers/event-parser.test.ts +135 -0
- package/server/parsers/event-parser.ts +4 -1
- package/server/parsers/scope-parser.test.ts +270 -0
- package/server/parsers/scope-parser.ts +79 -31
- package/server/project-context.ts +325 -0
- package/server/project-emitter.ts +50 -0
- package/server/project-manager.ts +368 -0
- package/server/routes/aggregate-routes.ts +968 -0
- package/server/routes/config-routes.ts +43 -85
- package/server/routes/data-routes.ts +34 -156
- package/server/routes/dispatch-routes.ts +46 -17
- package/server/routes/git-routes.ts +77 -0
- package/server/routes/manifest-routes.ts +388 -0
- package/server/routes/scope-routes.ts +39 -30
- package/server/routes/sync-routes.ts +175 -0
- package/server/routes/version-routes.ts +1 -16
- package/server/routes/workflow-routes.ts +9 -3
- package/server/schema.ts +3 -0
- package/server/services/batch-orchestrator.ts +41 -17
- package/server/services/claude-session-service.ts +16 -14
- package/server/services/config-service.ts +10 -1
- package/server/services/deploy-service.test.ts +145 -0
- package/server/services/deploy-service.ts +2 -2
- package/server/services/event-service.test.ts +242 -0
- package/server/services/event-service.ts +92 -3
- package/server/services/gate-service.test.ts +131 -0
- package/server/services/gate-service.ts +2 -2
- package/server/services/git-service.ts +137 -4
- package/server/services/github-service.ts +120 -2
- package/server/services/readiness-service.test.ts +217 -0
- package/server/services/scope-cache.test.ts +167 -0
- package/server/services/scope-cache.ts +4 -1
- package/server/services/scope-service.test.ts +169 -0
- package/server/services/scope-service.ts +224 -130
- package/server/services/sprint-orchestrator.ts +30 -15
- package/server/services/sprint-service.test.ts +271 -0
- package/server/services/sprint-service.ts +29 -5
- package/server/services/sync-service.ts +482 -0
- package/server/services/sync-types.ts +77 -0
- package/server/services/workflow-service.test.ts +190 -0
- package/server/services/workflow-service.ts +29 -9
- package/server/settings-sync.ts +359 -0
- package/server/uninstall.ts +214 -0
- package/server/update-planner.ts +346 -0
- package/server/update.ts +263 -0
- package/server/utils/cc-hooks-parser.test.ts +96 -0
- package/server/utils/cc-hooks-parser.ts +4 -0
- package/server/utils/dispatch-utils.test.ts +245 -0
- package/server/utils/dispatch-utils.ts +102 -30
- package/server/utils/flag-builder.ts +56 -0
- package/server/utils/json-fields.test.ts +83 -0
- package/server/utils/json-fields.ts +14 -0
- package/server/utils/logger.ts +40 -3
- package/server/utils/package-info.ts +32 -0
- package/server/utils/route-helpers.test.ts +144 -0
- package/server/utils/route-helpers.ts +50 -0
- package/server/utils/terminal-launcher.ts +85 -25
- package/server/utils/worktree-manager.ts +9 -4
- package/server/validator.ts +270 -0
- package/server/watchers/event-watcher.ts +24 -12
- package/server/watchers/global-watcher.ts +77 -0
- package/server/watchers/scope-watcher.ts +21 -9
- package/server/wizard/config-editor.ts +248 -0
- package/server/wizard/detect.ts +104 -0
- package/server/wizard/doctor.ts +114 -0
- package/server/wizard/index.ts +438 -0
- package/server/wizard/phases/confirm.ts +45 -0
- package/server/wizard/phases/project-setup.ts +106 -0
- package/server/wizard/phases/setup-wizard.ts +78 -0
- package/server/wizard/phases/welcome.ts +39 -0
- package/server/wizard/phases/workflow-setup.ts +28 -0
- package/server/wizard/types.ts +56 -0
- package/server/wizard/ui.ts +92 -0
- package/shared/__fixtures__/workflow-configs.ts +80 -0
- package/shared/api-types.ts +106 -0
- package/shared/onboarding-tour.test.ts +94 -0
- package/shared/project-colors.ts +24 -0
- package/shared/workflow-config.test.ts +111 -0
- package/shared/workflow-config.ts +7 -0
- package/shared/workflow-engine.test.ts +388 -0
- package/shared/workflow-engine.ts +1 -1
- package/shared/workflow-normalizer.test.ts +119 -0
- package/shared/workflow-normalizer.ts +118 -0
- package/templates/agents/QUICK-REFERENCE.md +1 -0
- package/templates/agents/README.md +1 -0
- package/templates/agents/SKILL-TRIGGERS.md +11 -0
- package/templates/agents/green-team/deep-dive.md +361 -0
- package/templates/hooks/end-session.sh +4 -1
- package/templates/hooks/init-session.sh +1 -0
- package/templates/hooks/orbital-emit.sh +2 -2
- package/templates/hooks/orbital-report-deploy.sh +4 -4
- package/templates/hooks/orbital-report-gates.sh +4 -4
- package/templates/hooks/orbital-scope-update.sh +1 -1
- package/templates/hooks/scope-commit-logger.sh +2 -2
- package/templates/hooks/scope-create-cleanup.sh +2 -2
- package/templates/hooks/scope-create-gate.sh +2 -5
- package/templates/hooks/scope-gate.sh +4 -6
- package/templates/hooks/scope-helpers.sh +28 -1
- package/templates/hooks/scope-lifecycle-gate.sh +14 -5
- package/templates/hooks/scope-prepare.sh +67 -12
- package/templates/hooks/scope-transition.sh +14 -6
- package/templates/hooks/time-tracker.sh +2 -5
- package/templates/migrations/renames.json +1 -0
- package/templates/orbital.config.json +8 -6
- package/{shared/default-workflow.json → templates/presets/default.json} +65 -0
- package/templates/presets/development.json +4 -4
- package/templates/presets/gitflow.json +7 -0
- package/templates/prompts/README.md +23 -0
- package/templates/prompts/deep-dive-audit.md +94 -0
- package/templates/quick/rules.md +56 -5
- package/templates/settings-hooks.json +1 -1
- package/templates/skills/git-commit/SKILL.md +27 -7
- package/templates/skills/git-dev/SKILL.md +13 -4
- package/templates/skills/git-main/SKILL.md +13 -3
- package/templates/skills/git-production/SKILL.md +9 -2
- package/templates/skills/git-staging/SKILL.md +11 -3
- package/templates/skills/scope-create/SKILL.md +17 -3
- package/templates/skills/scope-fix-review/SKILL.md +14 -7
- package/templates/skills/scope-implement/SKILL.md +15 -4
- package/templates/skills/scope-post-review/SKILL.md +77 -7
- package/templates/skills/scope-pre-review/SKILL.md +11 -4
- package/templates/skills/scope-verify/SKILL.md +5 -3
- package/templates/skills/test-code-review/SKILL.md +41 -33
- package/templates/skills/test-scaffold/SKILL.md +222 -0
- package/dist/assets/WorkflowVisualizer-BZ21PIIF.js +0 -84
- package/dist/assets/charts-D__PA1zp.js +0 -72
- package/dist/assets/index-D1G6i0nS.css +0 -1
- package/dist/assets/index-DpItvKpf.js +0 -419
- package/dist/assets/ui-BvF022GT.js +0 -53
- package/index.html +0 -15
- package/postcss.config.js +0 -6
- package/src/App.tsx +0 -33
- package/src/components/AgentBadge.tsx +0 -40
- package/src/components/BatchPreflightModal.tsx +0 -115
- package/src/components/CardDisplayToggle.tsx +0 -74
- package/src/components/ColumnHeaderActions.tsx +0 -55
- package/src/components/ColumnMenu.tsx +0 -99
- package/src/components/DeployHistory.tsx +0 -141
- package/src/components/DispatchModal.tsx +0 -164
- package/src/components/DispatchPopover.tsx +0 -139
- package/src/components/DragOverlay.tsx +0 -25
- package/src/components/DriftSidebar.tsx +0 -140
- package/src/components/EnvironmentStrip.tsx +0 -88
- package/src/components/ErrorBoundary.tsx +0 -62
- package/src/components/FilterChip.tsx +0 -105
- package/src/components/GateIndicator.tsx +0 -33
- package/src/components/IdeaDetailModal.tsx +0 -190
- package/src/components/IdeaFormDialog.tsx +0 -113
- package/src/components/KanbanColumn.tsx +0 -201
- package/src/components/MarkdownRenderer.tsx +0 -114
- package/src/components/NeonGrid.tsx +0 -128
- package/src/components/PromotionQueue.tsx +0 -89
- package/src/components/ScopeCard.tsx +0 -234
- package/src/components/ScopeDetailModal.tsx +0 -255
- package/src/components/ScopeFilterBar.tsx +0 -152
- package/src/components/SearchInput.tsx +0 -102
- package/src/components/SessionPanel.tsx +0 -335
- package/src/components/SprintContainer.tsx +0 -303
- package/src/components/SprintDependencyDialog.tsx +0 -78
- package/src/components/SprintPreflightModal.tsx +0 -138
- package/src/components/StatusBar.tsx +0 -168
- package/src/components/SwimCell.tsx +0 -67
- package/src/components/SwimLaneRow.tsx +0 -94
- package/src/components/SwimlaneBoardView.tsx +0 -108
- package/src/components/VersionBadge.tsx +0 -139
- package/src/components/ViewModeSelector.tsx +0 -114
- package/src/components/config/AgentChip.tsx +0 -53
- package/src/components/config/AgentCreateDialog.tsx +0 -321
- package/src/components/config/AgentEditor.tsx +0 -175
- package/src/components/config/DirectoryTree.tsx +0 -582
- package/src/components/config/FileEditor.tsx +0 -550
- package/src/components/config/HookChip.tsx +0 -50
- package/src/components/config/StageCard.tsx +0 -198
- package/src/components/config/TransitionZone.tsx +0 -173
- package/src/components/config/UnifiedWorkflowPipeline.tsx +0 -216
- package/src/components/config/WorkflowPipeline.tsx +0 -161
- package/src/components/source-control/BranchList.tsx +0 -93
- package/src/components/source-control/BranchPanel.tsx +0 -105
- package/src/components/source-control/CommitLog.tsx +0 -100
- package/src/components/source-control/CommitRow.tsx +0 -47
- package/src/components/source-control/GitHubPanel.tsx +0 -110
- package/src/components/source-control/GitHubSetupGuide.tsx +0 -52
- package/src/components/source-control/GitOverviewBar.tsx +0 -101
- package/src/components/source-control/PullRequestList.tsx +0 -69
- package/src/components/source-control/WorktreeList.tsx +0 -80
- package/src/components/ui/badge.tsx +0 -41
- package/src/components/ui/button.tsx +0 -55
- package/src/components/ui/card.tsx +0 -78
- package/src/components/ui/dialog.tsx +0 -94
- package/src/components/ui/popover.tsx +0 -33
- package/src/components/ui/scroll-area.tsx +0 -54
- package/src/components/ui/separator.tsx +0 -28
- package/src/components/ui/tabs.tsx +0 -52
- package/src/components/ui/toggle-switch.tsx +0 -35
- package/src/components/ui/tooltip.tsx +0 -27
- package/src/components/workflow/AddEdgeDialog.tsx +0 -217
- package/src/components/workflow/AddListDialog.tsx +0 -201
- package/src/components/workflow/ChecklistEditor.tsx +0 -239
- package/src/components/workflow/CommandPrefixManager.tsx +0 -118
- package/src/components/workflow/ConfigSettingsPanel.tsx +0 -189
- package/src/components/workflow/DirectionSelector.tsx +0 -133
- package/src/components/workflow/DispatchConfigPanel.tsx +0 -180
- package/src/components/workflow/EdgeDetailPanel.tsx +0 -236
- package/src/components/workflow/EdgePropertyEditor.tsx +0 -251
- package/src/components/workflow/EditToolbar.tsx +0 -138
- package/src/components/workflow/HookDetailPanel.tsx +0 -250
- package/src/components/workflow/HookExecutionLog.tsx +0 -24
- package/src/components/workflow/HookSourceModal.tsx +0 -129
- package/src/components/workflow/HooksDashboard.tsx +0 -363
- package/src/components/workflow/ListPropertyEditor.tsx +0 -251
- package/src/components/workflow/MigrationPreviewDialog.tsx +0 -237
- package/src/components/workflow/MovementRulesPanel.tsx +0 -188
- package/src/components/workflow/NodeDetailPanel.tsx +0 -245
- package/src/components/workflow/PresetSelector.tsx +0 -414
- package/src/components/workflow/SkillCommandBuilder.tsx +0 -174
- package/src/components/workflow/WorkflowEdgeComponent.tsx +0 -145
- package/src/components/workflow/WorkflowNode.tsx +0 -147
- package/src/components/workflow/graphLayout.ts +0 -186
- package/src/components/workflow/mergeHooks.ts +0 -85
- package/src/components/workflow/useEditHistory.ts +0 -88
- package/src/components/workflow/useWorkflowEditor.ts +0 -262
- package/src/components/workflow/validateConfig.ts +0 -70
- package/src/hooks/useActiveDispatches.ts +0 -198
- package/src/hooks/useBoardSettings.ts +0 -170
- package/src/hooks/useCardDisplay.ts +0 -57
- package/src/hooks/useCcHooks.ts +0 -24
- package/src/hooks/useConfigTree.ts +0 -51
- package/src/hooks/useEnforcementRules.ts +0 -46
- package/src/hooks/useEvents.ts +0 -59
- package/src/hooks/useFileEditor.ts +0 -165
- package/src/hooks/useGates.ts +0 -57
- package/src/hooks/useIdeaActions.ts +0 -53
- package/src/hooks/useKanbanDnd.ts +0 -410
- package/src/hooks/useOrbitalConfig.ts +0 -54
- package/src/hooks/usePipeline.ts +0 -47
- package/src/hooks/usePipelineData.ts +0 -338
- package/src/hooks/useReconnect.ts +0 -25
- package/src/hooks/useScopeFilters.ts +0 -125
- package/src/hooks/useScopeSessions.ts +0 -44
- package/src/hooks/useScopes.ts +0 -67
- package/src/hooks/useSearch.ts +0 -67
- package/src/hooks/useSettings.tsx +0 -187
- package/src/hooks/useSocket.ts +0 -25
- package/src/hooks/useSourceControl.ts +0 -105
- package/src/hooks/useSprintPreflight.ts +0 -55
- package/src/hooks/useSprints.ts +0 -154
- package/src/hooks/useStatusBarHighlight.ts +0 -18
- package/src/hooks/useSwimlaneBoardSettings.ts +0 -104
- package/src/hooks/useTheme.ts +0 -9
- package/src/hooks/useTransitionReadiness.ts +0 -53
- package/src/hooks/useVersion.ts +0 -155
- package/src/hooks/useViolations.ts +0 -65
- package/src/hooks/useWorkflow.tsx +0 -125
- package/src/hooks/useZoomModifier.ts +0 -19
- package/src/index.css +0 -797
- package/src/layouts/DashboardLayout.tsx +0 -113
- package/src/lib/collisionDetection.ts +0 -20
- package/src/lib/scope-fields.ts +0 -61
- package/src/lib/swimlane.ts +0 -146
- package/src/lib/utils.ts +0 -15
- package/src/main.tsx +0 -19
- package/src/socket.ts +0 -11
- package/src/types/index.ts +0 -497
- package/src/views/AgentFeed.tsx +0 -339
- package/src/views/DeployPipeline.tsx +0 -59
- package/src/views/EnforcementView.tsx +0 -378
- package/src/views/PrimitivesConfig.tsx +0 -500
- package/src/views/QualityGates.tsx +0 -1012
- package/src/views/ScopeBoard.tsx +0 -454
- package/src/views/SessionTimeline.tsx +0 -516
- package/src/views/Settings.tsx +0 -183
- package/src/views/SourceControl.tsx +0 -95
- package/src/views/WorkflowVisualizer.tsx +0 -382
- package/tailwind.config.js +0 -161
- package/tsconfig.json +0 -25
- package/vite.config.ts +0 -38
package/server/init.ts
CHANGED
|
@@ -1,11 +1,25 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Shared init logic — used by
|
|
3
|
-
* programmatic callers (e.g. tests).
|
|
2
|
+
* Shared init logic — used by the wizard and
|
|
3
|
+
* programmatic callers (e.g. tests, API routes).
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import fs from 'fs';
|
|
7
7
|
import path from 'path';
|
|
8
8
|
import { fileURLToPath } from 'url';
|
|
9
|
+
import { GLOBAL_PRIMITIVES_DIR, ensureOrbitalHome } from './global-config.js';
|
|
10
|
+
import {
|
|
11
|
+
saveManifest,
|
|
12
|
+
createManifest,
|
|
13
|
+
hashFile,
|
|
14
|
+
buildTemplateInventory,
|
|
15
|
+
templateFileRecord,
|
|
16
|
+
userFileRecord,
|
|
17
|
+
isSelfHosting,
|
|
18
|
+
getSymlinkTarget,
|
|
19
|
+
} from './manifest.js';
|
|
20
|
+
import type { OrbitalManifest } from './manifest-types.js';
|
|
21
|
+
import { getTemplateChecksum } from './settings-sync.js';
|
|
22
|
+
import { getPackageVersion as _getPackageVersionUtil } from './utils/package-info.js';
|
|
9
23
|
|
|
10
24
|
const __filename = fileURLToPath(import.meta.url);
|
|
11
25
|
const __dirname = path.dirname(__filename);
|
|
@@ -228,7 +242,8 @@ function generateManifest(config: Record<string, unknown>): string {
|
|
|
228
242
|
lines.push('');
|
|
229
243
|
|
|
230
244
|
lines.push('# ─── Entry point status ───');
|
|
231
|
-
|
|
245
|
+
const entryPointId = (lists.find((l) => l.isEntryPoint)?.id as string) || (lists[0]?.id as string) || 'todo';
|
|
246
|
+
lines.push(`WORKFLOW_ENTRY_STATUS="${entryPointId}"`);
|
|
232
247
|
lines.push('');
|
|
233
248
|
|
|
234
249
|
const listMap = new Map(lists.map((l) => [l.id, l]));
|
|
@@ -255,6 +270,25 @@ function generateManifest(config: Record<string, unknown>): string {
|
|
|
255
270
|
lines.push(')');
|
|
256
271
|
lines.push('');
|
|
257
272
|
|
|
273
|
+
lines.push('# ─── Commit session branch patterns (regex) ───');
|
|
274
|
+
lines.push(`WORKFLOW_COMMIT_BRANCHES="${(config.commitBranchPatterns as string) ?? ''}"`);
|
|
275
|
+
lines.push('');
|
|
276
|
+
|
|
277
|
+
lines.push('# ─── Backward-compat direction aliases (alias:from:to:sessionKey) ───');
|
|
278
|
+
lines.push('WORKFLOW_DIRECTION_ALIASES=(');
|
|
279
|
+
for (const edge of (config.edges as Array<Record<string, unknown>>) || []) {
|
|
280
|
+
if (edge.direction !== 'forward' || !edge.dispatchOnly) continue;
|
|
281
|
+
const targetList = listMap.get(edge.to as string);
|
|
282
|
+
if (!targetList) continue;
|
|
283
|
+
const group = targetList.group as string | undefined;
|
|
284
|
+
if (group?.startsWith('deploy')) {
|
|
285
|
+
const sessionKey = (targetList.sessionKey as string) ?? '';
|
|
286
|
+
lines.push(` "to-${edge.to as string}:${edge.from as string}:${edge.to as string}:${sessionKey}"`);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
lines.push(')');
|
|
290
|
+
lines.push('');
|
|
291
|
+
|
|
258
292
|
lines.push('# ─── Helper functions ──────────────────────────────');
|
|
259
293
|
lines.push('');
|
|
260
294
|
lines.push('status_to_dir() {');
|
|
@@ -489,20 +523,151 @@ function cleanEmptyDirs(dir: string): void {
|
|
|
489
523
|
}
|
|
490
524
|
}
|
|
491
525
|
|
|
526
|
+
// ─── Manifest Building ──────────────────────────────────────
|
|
527
|
+
|
|
528
|
+
/** Build a manifest by scanning .claude/ and classifying files against templates. */
|
|
529
|
+
function buildInitManifest(
|
|
530
|
+
projectRoot: string,
|
|
531
|
+
claudeDir: string,
|
|
532
|
+
preset: string,
|
|
533
|
+
): OrbitalManifest {
|
|
534
|
+
const selfHosting = isSelfHosting(projectRoot);
|
|
535
|
+
const templateInventory = buildTemplateInventory(TEMPLATES_DIR);
|
|
536
|
+
const pkg = getPackageVersion();
|
|
537
|
+
|
|
538
|
+
const manifest = createManifest(pkg, preset);
|
|
539
|
+
|
|
540
|
+
// Classify all template files
|
|
541
|
+
for (const [relPath, templateHash] of templateInventory) {
|
|
542
|
+
const absPath = path.join(claudeDir, relPath);
|
|
543
|
+
|
|
544
|
+
if (selfHosting) {
|
|
545
|
+
const symlinkTarget = getSymlinkTarget(claudeDir, relPath);
|
|
546
|
+
if (symlinkTarget) {
|
|
547
|
+
manifest.files[relPath] = templateFileRecord(templateHash, symlinkTarget);
|
|
548
|
+
continue;
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
if (fs.existsSync(absPath)) {
|
|
553
|
+
const fileHash = hashFile(absPath);
|
|
554
|
+
if (fileHash === templateHash) {
|
|
555
|
+
manifest.files[relPath] = templateFileRecord(templateHash);
|
|
556
|
+
} else {
|
|
557
|
+
// File exists but doesn't match template — classify as outdated
|
|
558
|
+
// (no prior install to compare against, so we can't know if user edited it)
|
|
559
|
+
manifest.files[relPath] = {
|
|
560
|
+
origin: 'template',
|
|
561
|
+
status: 'outdated',
|
|
562
|
+
templateHash,
|
|
563
|
+
installedHash: fileHash,
|
|
564
|
+
};
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
// File doesn't exist — it may not have been copied (e.g. skipped on non-force init)
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
// Scan managed directories for user-created files
|
|
571
|
+
for (const dir of ['hooks', 'skills', 'agents']) {
|
|
572
|
+
const dirPath = path.join(claudeDir, dir);
|
|
573
|
+
if (!fs.existsSync(dirPath)) continue;
|
|
574
|
+
|
|
575
|
+
walkDirForManifest(dirPath, dir, (relPath, absPath) => {
|
|
576
|
+
if (manifest.files[relPath]) return; // Already classified
|
|
577
|
+
const fileHash = hashFile(absPath);
|
|
578
|
+
manifest.files[relPath] = userFileRecord(fileHash);
|
|
579
|
+
});
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
// Record settings hooks checksum
|
|
583
|
+
const settingsHooksPath = path.join(TEMPLATES_DIR, 'settings-hooks.json');
|
|
584
|
+
if (fs.existsSync(settingsHooksPath)) {
|
|
585
|
+
manifest.settingsHooksChecksum = getTemplateChecksum(settingsHooksPath);
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
// Record gitignore entries
|
|
589
|
+
manifest.gitignoreEntries = [
|
|
590
|
+
'scopes/',
|
|
591
|
+
'.claude/orbital/',
|
|
592
|
+
'.claude/orbital-events/',
|
|
593
|
+
'.claude/config/workflow-manifest.sh',
|
|
594
|
+
];
|
|
595
|
+
|
|
596
|
+
return manifest;
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
function getPackageVersion(): string {
|
|
600
|
+
return _getPackageVersionUtil(PACKAGE_ROOT);
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
/** Recursively walk a directory for manifest building. */
|
|
604
|
+
function walkDirForManifest(
|
|
605
|
+
dirPath: string,
|
|
606
|
+
prefix: string,
|
|
607
|
+
fn: (relPath: string, absPath: string) => void,
|
|
608
|
+
): void {
|
|
609
|
+
if (!fs.existsSync(dirPath)) return;
|
|
610
|
+
for (const entry of fs.readdirSync(dirPath, { withFileTypes: true })) {
|
|
611
|
+
if (entry.name.startsWith('.')) continue;
|
|
612
|
+
const absPath = path.join(dirPath, entry.name);
|
|
613
|
+
const relPath = `${prefix}/${entry.name}`;
|
|
614
|
+
// Follow symlinks: use stat() to check if target is a directory
|
|
615
|
+
const stat = fs.statSync(absPath);
|
|
616
|
+
if (stat.isDirectory()) {
|
|
617
|
+
walkDirForManifest(absPath, relPath, fn);
|
|
618
|
+
} else {
|
|
619
|
+
fn(relPath, absPath);
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
|
|
492
624
|
// ─── Exports ─────────────────────────────────────────────────
|
|
493
625
|
|
|
494
|
-
|
|
626
|
+
/** Seed ~/.orbital/primitives/ from package templates. Called by init, update, and server startup. */
|
|
627
|
+
export function seedGlobalPrimitives(): void {
|
|
628
|
+
ensureOrbitalHome();
|
|
629
|
+
for (const type of ['hooks', 'skills', 'agents'] as const) {
|
|
630
|
+
const src = path.join(TEMPLATES_DIR, type);
|
|
631
|
+
const dest = path.join(GLOBAL_PRIMITIVES_DIR, type);
|
|
632
|
+
if (fs.existsSync(src)) {
|
|
633
|
+
copyDirSync(src, dest, { overwrite: true });
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
export { TEMPLATES_DIR, ensureDir, cleanEmptyDirs, chmodScripts, listTemplateFiles, writeManifest, generateIndexMd, getPackageVersion };
|
|
639
|
+
|
|
640
|
+
// Re-export manifest utilities for CLI access via loadSharedModule()
|
|
641
|
+
export { loadManifest, saveManifest, hashFile, buildTemplateInventory, refreshFileStatuses, summarizeManifest } from './manifest.js';
|
|
642
|
+
export { validate, formatValidationReport } from './validator.js';
|
|
643
|
+
|
|
644
|
+
// Re-export update and uninstall from their new homes (backward compat for loadSharedModule)
|
|
645
|
+
export { runUpdate, type UpdateOptions } from './update.js';
|
|
646
|
+
export { runUninstall, type UninstallOptions } from './uninstall.js';
|
|
495
647
|
|
|
496
648
|
export interface InitOptions {
|
|
497
649
|
force?: boolean;
|
|
650
|
+
quiet?: boolean; // suppress console output (used by wizard)
|
|
651
|
+
preset?: string; // workflow preset name (default: 'default')
|
|
652
|
+
projectName?: string; // override auto-detected project name
|
|
653
|
+
serverPort?: number; // override default server port
|
|
654
|
+
clientPort?: number; // override default client port
|
|
655
|
+
commands?: Partial<Record<string, string | null>>; // override detected commands
|
|
498
656
|
}
|
|
499
657
|
|
|
500
658
|
export function runInit(projectRoot: string, options: InitOptions = {}): void {
|
|
501
659
|
const force = options.force ?? false;
|
|
660
|
+
const quiet = options.quiet ?? false;
|
|
661
|
+
const selectedPreset = options.preset || 'default';
|
|
502
662
|
const claudeDir = path.join(projectRoot, '.claude');
|
|
503
663
|
|
|
504
|
-
|
|
505
|
-
|
|
664
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
665
|
+
const log = quiet ? (..._args: unknown[]) => {} : console.log.bind(console);
|
|
666
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
667
|
+
const warn = quiet ? (..._args: unknown[]) => {} : console.warn.bind(console);
|
|
668
|
+
|
|
669
|
+
log(`\nOrbital Command — init`);
|
|
670
|
+
log(`Project root: ${projectRoot}\n`);
|
|
506
671
|
|
|
507
672
|
// 1. Create directories
|
|
508
673
|
const dirs = [
|
|
@@ -513,24 +678,26 @@ export function runInit(projectRoot: string, options: InitOptions = {}): void {
|
|
|
513
678
|
];
|
|
514
679
|
for (const dir of dirs) {
|
|
515
680
|
const wasCreated = ensureDir(dir);
|
|
516
|
-
|
|
681
|
+
log(` ${wasCreated ? 'Created' : 'Exists '} ${path.relative(projectRoot, dir)}/`);
|
|
517
682
|
}
|
|
518
683
|
|
|
519
|
-
// 1b. Create scopes/ subdirectories from the
|
|
684
|
+
// 1b. Create scopes/ subdirectories from the selected workflow preset
|
|
685
|
+
const selectedPresetPath = path.join(TEMPLATES_DIR, 'presets', `${selectedPreset}.json`);
|
|
520
686
|
const defaultPresetPath = path.join(TEMPLATES_DIR, 'presets', 'default.json');
|
|
687
|
+
const presetPath = fs.existsSync(selectedPresetPath) ? selectedPresetPath : defaultPresetPath;
|
|
521
688
|
let scopeDirs = ['icebox'];
|
|
522
689
|
try {
|
|
523
|
-
const preset = JSON.parse(fs.readFileSync(
|
|
690
|
+
const preset = JSON.parse(fs.readFileSync(presetPath, 'utf8'));
|
|
524
691
|
if (preset.lists && Array.isArray(preset.lists)) {
|
|
525
692
|
scopeDirs = preset.lists.filter((l: Record<string, unknown>) => l.hasDirectory).map((l: Record<string, unknown>) => l.id as string);
|
|
526
693
|
}
|
|
527
694
|
} catch {
|
|
528
|
-
|
|
695
|
+
warn(' Warning: could not load preset, creating scopes/icebox/ only');
|
|
529
696
|
}
|
|
530
697
|
for (const dirId of scopeDirs) {
|
|
531
698
|
const scopeDir = path.join(projectRoot, 'scopes', dirId);
|
|
532
699
|
const wasCreated = ensureDir(scopeDir);
|
|
533
|
-
|
|
700
|
+
log(` ${wasCreated ? 'Created' : 'Exists '} scopes/${dirId}/`);
|
|
534
701
|
}
|
|
535
702
|
|
|
536
703
|
// 1c. Copy scope template
|
|
@@ -539,9 +706,9 @@ export function runInit(projectRoot: string, options: InitOptions = {}): void {
|
|
|
539
706
|
if (fs.existsSync(scopeTemplateSrc)) {
|
|
540
707
|
if (force || !fs.existsSync(scopeTemplateDest)) {
|
|
541
708
|
fs.copyFileSync(scopeTemplateSrc, scopeTemplateDest);
|
|
542
|
-
|
|
709
|
+
log(` ${force ? 'Reset ' : 'Created'} scopes/_template.md`);
|
|
543
710
|
} else {
|
|
544
|
-
|
|
711
|
+
log(` Exists scopes/_template.md`);
|
|
545
712
|
}
|
|
546
713
|
}
|
|
547
714
|
|
|
@@ -552,75 +719,97 @@ export function runInit(projectRoot: string, options: InitOptions = {}): void {
|
|
|
552
719
|
if (configIsNew) {
|
|
553
720
|
if (fs.existsSync(configSrc)) {
|
|
554
721
|
fs.copyFileSync(configSrc, configDest);
|
|
555
|
-
|
|
722
|
+
// Apply wizard-collected or auto-detected values
|
|
723
|
+
try {
|
|
724
|
+
const config = JSON.parse(fs.readFileSync(configDest, 'utf8'));
|
|
725
|
+
config.projectName = options.projectName || path.basename(projectRoot)
|
|
726
|
+
.replace(/[-_]+/g, ' ')
|
|
727
|
+
.replace(/\b\w/g, c => c.toUpperCase());
|
|
728
|
+
if (options.serverPort) config.serverPort = options.serverPort;
|
|
729
|
+
if (options.clientPort) config.clientPort = options.clientPort;
|
|
730
|
+
fs.writeFileSync(configDest, JSON.stringify(config, null, 2) + '\n', 'utf8');
|
|
731
|
+
} catch { /* leave template default */ }
|
|
732
|
+
log(` Created .claude/orbital.config.json`);
|
|
556
733
|
} else {
|
|
557
734
|
const defaultConfig = {
|
|
558
|
-
serverPort: 4444,
|
|
559
|
-
clientPort: 4445,
|
|
560
|
-
projectName: path.basename(projectRoot),
|
|
735
|
+
serverPort: options.serverPort || 4444,
|
|
736
|
+
clientPort: options.clientPort || 4445,
|
|
737
|
+
projectName: options.projectName || path.basename(projectRoot),
|
|
561
738
|
};
|
|
562
739
|
fs.writeFileSync(configDest, JSON.stringify(defaultConfig, null, 2) + '\n', 'utf8');
|
|
563
|
-
|
|
740
|
+
log(` Created .claude/orbital.config.json (default)`);
|
|
564
741
|
}
|
|
565
742
|
|
|
566
|
-
//
|
|
567
|
-
|
|
568
|
-
if (fs.existsSync(pkgJsonPath)) {
|
|
743
|
+
// Apply wizard-provided commands or auto-detect from package.json
|
|
744
|
+
if (options.commands) {
|
|
569
745
|
try {
|
|
570
|
-
const pkg = JSON.parse(fs.readFileSync(pkgJsonPath, 'utf8'));
|
|
571
|
-
const scripts = pkg.scripts || {};
|
|
572
746
|
const config = JSON.parse(fs.readFileSync(configDest, 'utf8'));
|
|
573
747
|
if (!config.commands) config.commands = {};
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
detected++;
|
|
579
|
-
}
|
|
580
|
-
if (scripts.lint) { config.commands.lint = 'npm run lint'; detected++; }
|
|
581
|
-
if (scripts.build) { config.commands.build = 'npm run build'; detected++; }
|
|
582
|
-
if (scripts.test) { config.commands.test = 'npm run test'; detected++; }
|
|
583
|
-
|
|
584
|
-
if (detected > 0) {
|
|
585
|
-
fs.writeFileSync(configDest, JSON.stringify(config, null, 2) + '\n', 'utf8');
|
|
586
|
-
console.log(` Detected ${detected} project command(s) from package.json`);
|
|
587
|
-
}
|
|
748
|
+
Object.assign(config.commands, options.commands);
|
|
749
|
+
const commandCount = Object.values(options.commands).filter(v => v !== null).length;
|
|
750
|
+
fs.writeFileSync(configDest, JSON.stringify(config, null, 2) + '\n', 'utf8');
|
|
751
|
+
if (commandCount > 0) log(` Applied ${commandCount} project command(s)`);
|
|
588
752
|
} catch { /* leave defaults */ }
|
|
753
|
+
} else {
|
|
754
|
+
// Auto-detect project commands from package.json
|
|
755
|
+
const pkgJsonPath = path.join(projectRoot, 'package.json');
|
|
756
|
+
if (fs.existsSync(pkgJsonPath)) {
|
|
757
|
+
try {
|
|
758
|
+
const pkg = JSON.parse(fs.readFileSync(pkgJsonPath, 'utf8'));
|
|
759
|
+
const scripts = pkg.scripts || {};
|
|
760
|
+
const config = JSON.parse(fs.readFileSync(configDest, 'utf8'));
|
|
761
|
+
if (!config.commands) config.commands = {};
|
|
762
|
+
let detected = 0;
|
|
763
|
+
|
|
764
|
+
if (scripts.typecheck || scripts['type-check']) {
|
|
765
|
+
config.commands.typeCheck = `npm run ${scripts.typecheck ? 'typecheck' : 'type-check'}`;
|
|
766
|
+
detected++;
|
|
767
|
+
}
|
|
768
|
+
if (scripts.lint) { config.commands.lint = 'npm run lint'; detected++; }
|
|
769
|
+
if (scripts.build) { config.commands.build = 'npm run build'; detected++; }
|
|
770
|
+
if (scripts.test) { config.commands.test = 'npm run test'; detected++; }
|
|
771
|
+
|
|
772
|
+
if (detected > 0) {
|
|
773
|
+
fs.writeFileSync(configDest, JSON.stringify(config, null, 2) + '\n', 'utf8');
|
|
774
|
+
log(` Detected ${detected} project command(s) from package.json`);
|
|
775
|
+
}
|
|
776
|
+
} catch { /* leave defaults */ }
|
|
777
|
+
}
|
|
589
778
|
}
|
|
590
779
|
} else {
|
|
591
|
-
|
|
780
|
+
log(` Exists .claude/orbital.config.json`);
|
|
592
781
|
}
|
|
593
782
|
|
|
594
783
|
// 3. Copy hooks
|
|
595
|
-
|
|
784
|
+
log('');
|
|
596
785
|
const hooksSrc = path.join(TEMPLATES_DIR, 'hooks');
|
|
597
786
|
const hooksDest = path.join(claudeDir, 'hooks');
|
|
598
787
|
if (force) {
|
|
599
788
|
const pruned = pruneStaleEntries(hooksSrc, hooksDest);
|
|
600
|
-
if (pruned > 0)
|
|
789
|
+
if (pruned > 0) log(` Pruned ${pruned} stale hook entries`);
|
|
601
790
|
}
|
|
602
791
|
const hooksResult = copyDirSync(hooksSrc, hooksDest, { overwrite: force });
|
|
603
|
-
|
|
792
|
+
log(` Hooks ${hooksResult.created.length} copied, ${hooksResult.skipped.length} skipped`);
|
|
604
793
|
|
|
605
794
|
// 4. Copy skills
|
|
606
795
|
const skillsSrc = path.join(TEMPLATES_DIR, 'skills');
|
|
607
796
|
const skillsDest = path.join(claudeDir, 'skills');
|
|
608
797
|
if (force) {
|
|
609
798
|
const pruned = pruneStaleEntries(skillsSrc, skillsDest);
|
|
610
|
-
if (pruned > 0)
|
|
799
|
+
if (pruned > 0) log(` Pruned ${pruned} stale skill entries`);
|
|
611
800
|
}
|
|
612
801
|
const skillsResult = copyDirSync(skillsSrc, skillsDest, { overwrite: force });
|
|
613
|
-
|
|
802
|
+
log(` Skills ${skillsResult.created.length} copied, ${skillsResult.skipped.length} skipped`);
|
|
614
803
|
|
|
615
804
|
// 5. Copy agents
|
|
616
805
|
const agentsSrc = path.join(TEMPLATES_DIR, 'agents');
|
|
617
806
|
const agentsDest = path.join(claudeDir, 'agents');
|
|
618
807
|
if (force) {
|
|
619
808
|
const pruned = pruneStaleEntries(agentsSrc, agentsDest);
|
|
620
|
-
if (pruned > 0)
|
|
809
|
+
if (pruned > 0) log(` Pruned ${pruned} stale agent entries`);
|
|
621
810
|
}
|
|
622
811
|
const agentsResult = copyDirSync(agentsSrc, agentsDest, { overwrite: force });
|
|
623
|
-
|
|
812
|
+
log(` Agents ${agentsResult.created.length} copied, ${agentsResult.skipped.length} skipped`);
|
|
624
813
|
|
|
625
814
|
// 6. Copy workflow presets
|
|
626
815
|
const presetsSrc = path.join(TEMPLATES_DIR, 'presets');
|
|
@@ -628,22 +817,22 @@ export function runInit(projectRoot: string, options: InitOptions = {}): void {
|
|
|
628
817
|
if (fs.existsSync(presetsSrc) && fs.readdirSync(presetsSrc).length > 0) {
|
|
629
818
|
if (force) {
|
|
630
819
|
const pruned = pruneStaleEntries(presetsSrc, presetsDest);
|
|
631
|
-
if (pruned > 0)
|
|
820
|
+
if (pruned > 0) log(` Pruned ${pruned} stale preset entries`);
|
|
632
821
|
}
|
|
633
822
|
const presetsResult = copyDirSync(presetsSrc, presetsDest, { overwrite: force });
|
|
634
|
-
|
|
823
|
+
log(` Presets ${presetsResult.created.length} copied, ${presetsResult.skipped.length} skipped`);
|
|
635
824
|
}
|
|
636
825
|
|
|
637
826
|
// 6b. Reset active workflow config when --force, or create if missing
|
|
638
827
|
const activeWorkflowDest = path.join(claudeDir, 'config', 'workflow.json');
|
|
639
828
|
if (force) {
|
|
640
|
-
fs.copyFileSync(
|
|
641
|
-
|
|
829
|
+
fs.copyFileSync(presetPath, activeWorkflowDest);
|
|
830
|
+
log(` Reset .claude/config/workflow.json (${selectedPreset} workflow)`);
|
|
642
831
|
} else if (!fs.existsSync(activeWorkflowDest)) {
|
|
643
|
-
fs.copyFileSync(
|
|
644
|
-
|
|
832
|
+
fs.copyFileSync(presetPath, activeWorkflowDest);
|
|
833
|
+
log(` Created .claude/config/workflow.json (${selectedPreset})`);
|
|
645
834
|
} else {
|
|
646
|
-
|
|
835
|
+
log(` Exists .claude/config/workflow.json`);
|
|
647
836
|
}
|
|
648
837
|
|
|
649
838
|
// 7. Copy agent-triggers.json
|
|
@@ -652,9 +841,9 @@ export function runInit(projectRoot: string, options: InitOptions = {}): void {
|
|
|
652
841
|
if (fs.existsSync(triggersSrc)) {
|
|
653
842
|
if (force || !fs.existsSync(triggersDest)) {
|
|
654
843
|
fs.copyFileSync(triggersSrc, triggersDest);
|
|
655
|
-
|
|
844
|
+
log(` Created .claude/config/agent-triggers.json`);
|
|
656
845
|
} else {
|
|
657
|
-
|
|
846
|
+
log(` Exists .claude/config/agent-triggers.json`);
|
|
658
847
|
}
|
|
659
848
|
}
|
|
660
849
|
|
|
@@ -663,7 +852,7 @@ export function runInit(projectRoot: string, options: InitOptions = {}): void {
|
|
|
663
852
|
const quickDest = path.join(claudeDir, 'quick');
|
|
664
853
|
if (fs.existsSync(quickSrc)) {
|
|
665
854
|
const quickResult = copyDirSync(quickSrc, quickDest, { overwrite: force });
|
|
666
|
-
|
|
855
|
+
log(` Quick ${quickResult.created.length} copied, ${quickResult.skipped.length} skipped`);
|
|
667
856
|
}
|
|
668
857
|
|
|
669
858
|
// 7c. Copy anti-patterns/ templates
|
|
@@ -671,7 +860,7 @@ export function runInit(projectRoot: string, options: InitOptions = {}): void {
|
|
|
671
860
|
const antiDest = path.join(claudeDir, 'anti-patterns');
|
|
672
861
|
if (fs.existsSync(antiSrc)) {
|
|
673
862
|
const antiResult = copyDirSync(antiSrc, antiDest, { overwrite: force });
|
|
674
|
-
|
|
863
|
+
log(` Anti-pat ${antiResult.created.length} copied, ${antiResult.skipped.length} skipped`);
|
|
675
864
|
}
|
|
676
865
|
|
|
677
866
|
// 7d. Copy lessons-learned.md
|
|
@@ -680,212 +869,55 @@ export function runInit(projectRoot: string, options: InitOptions = {}): void {
|
|
|
680
869
|
if (fs.existsSync(lessonsSrc)) {
|
|
681
870
|
if (force || !fs.existsSync(lessonsDest)) {
|
|
682
871
|
fs.copyFileSync(lessonsSrc, lessonsDest);
|
|
683
|
-
|
|
872
|
+
log(` Created .claude/lessons-learned.md`);
|
|
684
873
|
} else {
|
|
685
|
-
|
|
874
|
+
log(` Exists .claude/lessons-learned.md`);
|
|
686
875
|
}
|
|
687
876
|
}
|
|
688
877
|
|
|
689
878
|
// 7e. Generate workflow manifest
|
|
690
879
|
const manifestOk = writeManifest(claudeDir);
|
|
691
|
-
|
|
880
|
+
log(` ${manifestOk ? 'Created' : 'Skipped'} .claude/config/workflow-manifest.sh`);
|
|
692
881
|
|
|
693
882
|
// 7f. Generate INDEX.md
|
|
694
883
|
const indexDest = path.join(claudeDir, 'INDEX.md');
|
|
695
884
|
if (force || !fs.existsSync(indexDest)) {
|
|
696
885
|
const indexContent = generateIndexMd(projectRoot, claudeDir);
|
|
697
886
|
fs.writeFileSync(indexDest, indexContent, 'utf8');
|
|
698
|
-
|
|
887
|
+
log(` ${force ? 'Reset ' : 'Created'} .claude/INDEX.md`);
|
|
699
888
|
} else {
|
|
700
|
-
|
|
889
|
+
log(` Exists .claude/INDEX.md`);
|
|
701
890
|
}
|
|
702
891
|
|
|
703
892
|
// 8. Merge hook registrations into settings.local.json
|
|
704
|
-
|
|
893
|
+
log('');
|
|
705
894
|
const settingsTarget = path.join(claudeDir, 'settings.local.json');
|
|
706
895
|
const settingsSrc = path.join(TEMPLATES_DIR, 'settings-hooks.json');
|
|
707
896
|
mergeSettingsHooks(settingsTarget, settingsSrc);
|
|
708
|
-
|
|
897
|
+
log(` Merged hook registrations into .claude/settings.local.json`);
|
|
709
898
|
|
|
710
899
|
// 9. Update .gitignore
|
|
711
900
|
const gitignoreUpdated = updateGitignore(projectRoot);
|
|
712
|
-
|
|
901
|
+
log(` ${gitignoreUpdated ? 'Updated' : 'Exists '} .gitignore (Orbital patterns)`);
|
|
713
902
|
|
|
714
903
|
// 10. Make hook scripts executable
|
|
715
904
|
chmodScripts(hooksDest);
|
|
716
|
-
|
|
905
|
+
log(` chmod hook scripts set to executable`);
|
|
906
|
+
|
|
907
|
+
// 11. Seed global primitives from package templates
|
|
908
|
+
seedGlobalPrimitives();
|
|
909
|
+
log(` Seeded global primitives (~/.orbital/primitives/)`);
|
|
910
|
+
|
|
911
|
+
// 12. Build and save manifest
|
|
912
|
+
const manifest = buildInitManifest(projectRoot, claudeDir, selectedPreset);
|
|
913
|
+
saveManifest(projectRoot, manifest);
|
|
914
|
+
log(` Created .claude/orbital-manifest.json (${Object.keys(manifest.files).length} files tracked)`);
|
|
717
915
|
|
|
718
916
|
// Summary
|
|
719
917
|
const totalCreated = hooksResult.created.length + skillsResult.created.length + agentsResult.created.length;
|
|
720
918
|
const totalSkipped = hooksResult.skipped.length + skillsResult.skipped.length + agentsResult.skipped.length;
|
|
721
|
-
|
|
722
|
-
}
|
|
723
|
-
|
|
724
|
-
export function runUpdate(projectRoot: string): void {
|
|
725
|
-
const claudeDir = path.join(projectRoot, '.claude');
|
|
726
|
-
|
|
727
|
-
console.log(`\nOrbital Command — update`);
|
|
728
|
-
console.log(`Project root: ${projectRoot}\n`);
|
|
729
|
-
|
|
730
|
-
// 1. Copy hooks (overwrite) — prune stale entries first
|
|
731
|
-
const hooksSrc = path.join(TEMPLATES_DIR, 'hooks');
|
|
732
|
-
const hooksDest = path.join(claudeDir, 'hooks');
|
|
733
|
-
const hooksPruned = pruneStaleEntries(hooksSrc, hooksDest);
|
|
734
|
-
if (hooksPruned > 0) console.log(` Pruned ${hooksPruned} stale hook entries`);
|
|
735
|
-
const hooksResult = copyDirSync(hooksSrc, hooksDest, { overwrite: true });
|
|
736
|
-
console.log(` Hooks ${hooksResult.created.length} updated`);
|
|
737
|
-
|
|
738
|
-
// 2. Copy skills (overwrite) — prune stale entries first
|
|
739
|
-
const skillsSrc = path.join(TEMPLATES_DIR, 'skills');
|
|
740
|
-
const skillsDest = path.join(claudeDir, 'skills');
|
|
741
|
-
const skillsPruned = pruneStaleEntries(skillsSrc, skillsDest);
|
|
742
|
-
if (skillsPruned > 0) console.log(` Pruned ${skillsPruned} stale skill entries`);
|
|
743
|
-
const skillsResult = copyDirSync(skillsSrc, skillsDest, { overwrite: true });
|
|
744
|
-
console.log(` Skills ${skillsResult.created.length} updated`);
|
|
745
|
-
|
|
746
|
-
// 3. Copy agents (overwrite) — prune stale entries first
|
|
747
|
-
const agentsSrc = path.join(TEMPLATES_DIR, 'agents');
|
|
748
|
-
const agentsDest = path.join(claudeDir, 'agents');
|
|
749
|
-
const agentsPruned = pruneStaleEntries(agentsSrc, agentsDest);
|
|
750
|
-
if (agentsPruned > 0) console.log(` Pruned ${agentsPruned} stale agent entries`);
|
|
751
|
-
const agentsResult = copyDirSync(agentsSrc, agentsDest, { overwrite: true });
|
|
752
|
-
console.log(` Agents ${agentsResult.created.length} updated`);
|
|
753
|
-
|
|
754
|
-
// 4. Update workflow presets — prune stale entries first
|
|
755
|
-
const presetsSrc = path.join(TEMPLATES_DIR, 'presets');
|
|
756
|
-
const presetsDest = path.join(claudeDir, 'config', 'workflows');
|
|
757
|
-
if (fs.existsSync(presetsSrc) && fs.readdirSync(presetsSrc).length > 0) {
|
|
758
|
-
const presetsPruned = pruneStaleEntries(presetsSrc, presetsDest);
|
|
759
|
-
if (presetsPruned > 0) console.log(` Pruned ${presetsPruned} stale preset entries`);
|
|
760
|
-
const presetsResult = copyDirSync(presetsSrc, presetsDest, { overwrite: true });
|
|
761
|
-
console.log(` Presets ${presetsResult.created.length} updated`);
|
|
762
|
-
}
|
|
763
|
-
|
|
764
|
-
// 5. Update quick/, anti-patterns/, lessons-learned, scope template
|
|
765
|
-
const quickSrc = path.join(TEMPLATES_DIR, 'quick');
|
|
766
|
-
const quickDest = path.join(claudeDir, 'quick');
|
|
767
|
-
if (fs.existsSync(quickSrc)) {
|
|
768
|
-
const quickResult = copyDirSync(quickSrc, quickDest, { overwrite: true });
|
|
769
|
-
console.log(` Quick ${quickResult.created.length} updated`);
|
|
770
|
-
}
|
|
771
|
-
|
|
772
|
-
const antiSrc = path.join(TEMPLATES_DIR, 'anti-patterns');
|
|
773
|
-
const antiDest = path.join(claudeDir, 'anti-patterns');
|
|
774
|
-
if (fs.existsSync(antiSrc)) {
|
|
775
|
-
const antiResult = copyDirSync(antiSrc, antiDest, { overwrite: true });
|
|
776
|
-
console.log(` Anti-pat ${antiResult.created.length} updated`);
|
|
777
|
-
}
|
|
778
|
-
|
|
779
|
-
const lessonsSrc = path.join(TEMPLATES_DIR, 'lessons-learned.md');
|
|
780
|
-
const lessonsDest = path.join(claudeDir, 'lessons-learned.md');
|
|
781
|
-
if (fs.existsSync(lessonsSrc) && !fs.existsSync(lessonsDest)) {
|
|
782
|
-
fs.copyFileSync(lessonsSrc, lessonsDest);
|
|
783
|
-
console.log(` Created .claude/lessons-learned.md`);
|
|
784
|
-
}
|
|
785
|
-
|
|
786
|
-
const scopeTemplateSrc = path.join(TEMPLATES_DIR, 'scopes', '_template.md');
|
|
787
|
-
const scopeTemplateDest = path.join(projectRoot, 'scopes', '_template.md');
|
|
788
|
-
if (fs.existsSync(scopeTemplateSrc)) {
|
|
789
|
-
ensureDir(path.join(projectRoot, 'scopes'));
|
|
790
|
-
fs.copyFileSync(scopeTemplateSrc, scopeTemplateDest);
|
|
791
|
-
console.log(` Updated scopes/_template.md`);
|
|
792
|
-
}
|
|
793
|
-
|
|
794
|
-
// 5b. Regenerate workflow manifest
|
|
795
|
-
const manifestOk = writeManifest(claudeDir);
|
|
796
|
-
console.log(` ${manifestOk ? 'Updated' : 'Skipped'} .claude/config/workflow-manifest.sh`);
|
|
797
|
-
|
|
798
|
-
// 6. Re-merge settings hooks
|
|
799
|
-
const settingsTarget = path.join(claudeDir, 'settings.local.json');
|
|
800
|
-
const settingsSrc = path.join(TEMPLATES_DIR, 'settings-hooks.json');
|
|
801
|
-
mergeSettingsHooks(settingsTarget, settingsSrc);
|
|
802
|
-
console.log(` Merged hook registrations into .claude/settings.local.json`);
|
|
803
|
-
|
|
804
|
-
// 7. Make hook scripts executable
|
|
805
|
-
chmodScripts(hooksDest);
|
|
806
|
-
console.log(` chmod hook scripts set to executable`);
|
|
807
|
-
|
|
808
|
-
console.log(`\nUpdate complete.\n`);
|
|
919
|
+
log(`\nDone. ${totalCreated} files installed, ${totalSkipped} skipped (use --force to overwrite).`);
|
|
809
920
|
}
|
|
810
921
|
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
console.log(`\nOrbital Command — uninstall`);
|
|
815
|
-
console.log(`Project root: ${projectRoot}\n`);
|
|
816
|
-
|
|
817
|
-
let removedCount = 0;
|
|
818
|
-
|
|
819
|
-
// 1. Remove orbital hooks from settings.local.json
|
|
820
|
-
const settingsPath = path.join(claudeDir, 'settings.local.json');
|
|
821
|
-
if (fs.existsSync(settingsPath)) {
|
|
822
|
-
try {
|
|
823
|
-
const settings = JSON.parse(fs.readFileSync(settingsPath, 'utf8'));
|
|
824
|
-
if (settings.hooks) {
|
|
825
|
-
for (const [event] of Object.entries(settings.hooks)) {
|
|
826
|
-
for (const group of settings.hooks[event]) {
|
|
827
|
-
if (group.hooks) {
|
|
828
|
-
const before = group.hooks.length;
|
|
829
|
-
group.hooks = group.hooks.filter((h: HookEntry) => !h._orbital);
|
|
830
|
-
removedCount += before - group.hooks.length;
|
|
831
|
-
}
|
|
832
|
-
}
|
|
833
|
-
settings.hooks[event] = settings.hooks[event].filter(
|
|
834
|
-
(g: HookGroup) => g.hooks && g.hooks.length > 0
|
|
835
|
-
);
|
|
836
|
-
if (settings.hooks[event].length === 0) {
|
|
837
|
-
delete settings.hooks[event];
|
|
838
|
-
}
|
|
839
|
-
}
|
|
840
|
-
if (Object.keys(settings.hooks).length === 0) {
|
|
841
|
-
delete settings.hooks;
|
|
842
|
-
}
|
|
843
|
-
fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + '\n', 'utf8');
|
|
844
|
-
console.log(` Removed ${removedCount} orbital hook registrations from settings.local.json`);
|
|
845
|
-
}
|
|
846
|
-
} catch {
|
|
847
|
-
console.warn(' Warning: could not parse settings.local.json');
|
|
848
|
-
}
|
|
849
|
-
}
|
|
850
|
-
|
|
851
|
-
// 2. Delete hooks that came from templates
|
|
852
|
-
const hookFiles = listTemplateFiles(path.join(TEMPLATES_DIR, 'hooks'), path.join(claudeDir, 'hooks'));
|
|
853
|
-
let hooksRemoved = 0;
|
|
854
|
-
for (const f of hookFiles) {
|
|
855
|
-
if (fs.existsSync(f)) {
|
|
856
|
-
fs.unlinkSync(f);
|
|
857
|
-
hooksRemoved++;
|
|
858
|
-
}
|
|
859
|
-
}
|
|
860
|
-
console.log(` Removed ${hooksRemoved} hook scripts`);
|
|
861
|
-
|
|
862
|
-
// 3. Delete skills that came from templates
|
|
863
|
-
const skillFiles = listTemplateFiles(path.join(TEMPLATES_DIR, 'skills'), path.join(claudeDir, 'skills'));
|
|
864
|
-
let skillsRemoved = 0;
|
|
865
|
-
for (const f of skillFiles) {
|
|
866
|
-
if (fs.existsSync(f)) {
|
|
867
|
-
fs.unlinkSync(f);
|
|
868
|
-
skillsRemoved++;
|
|
869
|
-
}
|
|
870
|
-
}
|
|
871
|
-
const skillsDest = path.join(claudeDir, 'skills');
|
|
872
|
-
if (fs.existsSync(skillsDest)) cleanEmptyDirs(skillsDest);
|
|
873
|
-
console.log(` Removed ${skillsRemoved} skill files`);
|
|
874
|
-
|
|
875
|
-
// 4. Delete agents that came from templates
|
|
876
|
-
const agentFiles = listTemplateFiles(path.join(TEMPLATES_DIR, 'agents'), path.join(claudeDir, 'agents'));
|
|
877
|
-
let agentsRemoved = 0;
|
|
878
|
-
for (const f of agentFiles) {
|
|
879
|
-
if (fs.existsSync(f)) {
|
|
880
|
-
fs.unlinkSync(f);
|
|
881
|
-
agentsRemoved++;
|
|
882
|
-
}
|
|
883
|
-
}
|
|
884
|
-
const agentsDest = path.join(claudeDir, 'agents');
|
|
885
|
-
if (fs.existsSync(agentsDest)) cleanEmptyDirs(agentsDest);
|
|
886
|
-
console.log(` Removed ${agentsRemoved} agent files`);
|
|
887
|
-
|
|
888
|
-
const total = removedCount + hooksRemoved + skillsRemoved + agentsRemoved;
|
|
889
|
-
console.log(`\nUninstall complete. ${total} items removed.`);
|
|
890
|
-
console.log(`Note: scopes/ and .claude/orbital-events/ were preserved.\n`);
|
|
891
|
-
}
|
|
922
|
+
// runUpdate and runUninstall have been extracted to update.ts and uninstall.ts
|
|
923
|
+
// and are re-exported above for backward compatibility.
|