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
|
@@ -1,10 +1,14 @@
|
|
|
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
|
import fs from 'fs';
|
|
6
6
|
import path from 'path';
|
|
7
7
|
import { fileURLToPath } from 'url';
|
|
8
|
+
import { GLOBAL_PRIMITIVES_DIR, ensureOrbitalHome } from './global-config.js';
|
|
9
|
+
import { saveManifest, createManifest, hashFile, buildTemplateInventory, templateFileRecord, userFileRecord, isSelfHosting, getSymlinkTarget, } from './manifest.js';
|
|
10
|
+
import { getTemplateChecksum } from './settings-sync.js';
|
|
11
|
+
import { getPackageVersion as _getPackageVersionUtil } from './utils/package-info.js';
|
|
8
12
|
const __filename = fileURLToPath(import.meta.url);
|
|
9
13
|
const __dirname = path.dirname(__filename);
|
|
10
14
|
// Walk up from __dirname until we find the package root (identified by templates/).
|
|
@@ -182,7 +186,8 @@ function generateManifest(config) {
|
|
|
182
186
|
lines.push(`WORKFLOW_TERMINAL_STATUSES="${terminalStatuses.join(' ')}"`);
|
|
183
187
|
lines.push('');
|
|
184
188
|
lines.push('# ─── Entry point status ───');
|
|
185
|
-
|
|
189
|
+
const entryPointId = lists.find((l) => l.isEntryPoint)?.id || lists[0]?.id || 'todo';
|
|
190
|
+
lines.push(`WORKFLOW_ENTRY_STATUS="${entryPointId}"`);
|
|
186
191
|
lines.push('');
|
|
187
192
|
const listMap = new Map(lists.map((l) => [l.id, l]));
|
|
188
193
|
lines.push('# ─── Transition edges (from:to:sessionKey) ───');
|
|
@@ -205,6 +210,25 @@ function generateManifest(config) {
|
|
|
205
210
|
}
|
|
206
211
|
lines.push(')');
|
|
207
212
|
lines.push('');
|
|
213
|
+
lines.push('# ─── Commit session branch patterns (regex) ───');
|
|
214
|
+
lines.push(`WORKFLOW_COMMIT_BRANCHES="${config.commitBranchPatterns ?? ''}"`);
|
|
215
|
+
lines.push('');
|
|
216
|
+
lines.push('# ─── Backward-compat direction aliases (alias:from:to:sessionKey) ───');
|
|
217
|
+
lines.push('WORKFLOW_DIRECTION_ALIASES=(');
|
|
218
|
+
for (const edge of config.edges || []) {
|
|
219
|
+
if (edge.direction !== 'forward' || !edge.dispatchOnly)
|
|
220
|
+
continue;
|
|
221
|
+
const targetList = listMap.get(edge.to);
|
|
222
|
+
if (!targetList)
|
|
223
|
+
continue;
|
|
224
|
+
const group = targetList.group;
|
|
225
|
+
if (group?.startsWith('deploy')) {
|
|
226
|
+
const sessionKey = targetList.sessionKey ?? '';
|
|
227
|
+
lines.push(` "to-${edge.to}:${edge.from}:${edge.to}:${sessionKey}"`);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
lines.push(')');
|
|
231
|
+
lines.push('');
|
|
208
232
|
lines.push('# ─── Helper functions ──────────────────────────────');
|
|
209
233
|
lines.push('');
|
|
210
234
|
lines.push('status_to_dir() {');
|
|
@@ -431,13 +455,119 @@ function cleanEmptyDirs(dir) {
|
|
|
431
455
|
fs.rmdirSync(dir);
|
|
432
456
|
}
|
|
433
457
|
}
|
|
458
|
+
// ─── Manifest Building ──────────────────────────────────────
|
|
459
|
+
/** Build a manifest by scanning .claude/ and classifying files against templates. */
|
|
460
|
+
function buildInitManifest(projectRoot, claudeDir, preset) {
|
|
461
|
+
const selfHosting = isSelfHosting(projectRoot);
|
|
462
|
+
const templateInventory = buildTemplateInventory(TEMPLATES_DIR);
|
|
463
|
+
const pkg = getPackageVersion();
|
|
464
|
+
const manifest = createManifest(pkg, preset);
|
|
465
|
+
// Classify all template files
|
|
466
|
+
for (const [relPath, templateHash] of templateInventory) {
|
|
467
|
+
const absPath = path.join(claudeDir, relPath);
|
|
468
|
+
if (selfHosting) {
|
|
469
|
+
const symlinkTarget = getSymlinkTarget(claudeDir, relPath);
|
|
470
|
+
if (symlinkTarget) {
|
|
471
|
+
manifest.files[relPath] = templateFileRecord(templateHash, symlinkTarget);
|
|
472
|
+
continue;
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
if (fs.existsSync(absPath)) {
|
|
476
|
+
const fileHash = hashFile(absPath);
|
|
477
|
+
if (fileHash === templateHash) {
|
|
478
|
+
manifest.files[relPath] = templateFileRecord(templateHash);
|
|
479
|
+
}
|
|
480
|
+
else {
|
|
481
|
+
// File exists but doesn't match template — classify as outdated
|
|
482
|
+
// (no prior install to compare against, so we can't know if user edited it)
|
|
483
|
+
manifest.files[relPath] = {
|
|
484
|
+
origin: 'template',
|
|
485
|
+
status: 'outdated',
|
|
486
|
+
templateHash,
|
|
487
|
+
installedHash: fileHash,
|
|
488
|
+
};
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
// File doesn't exist — it may not have been copied (e.g. skipped on non-force init)
|
|
492
|
+
}
|
|
493
|
+
// Scan managed directories for user-created files
|
|
494
|
+
for (const dir of ['hooks', 'skills', 'agents']) {
|
|
495
|
+
const dirPath = path.join(claudeDir, dir);
|
|
496
|
+
if (!fs.existsSync(dirPath))
|
|
497
|
+
continue;
|
|
498
|
+
walkDirForManifest(dirPath, dir, (relPath, absPath) => {
|
|
499
|
+
if (manifest.files[relPath])
|
|
500
|
+
return; // Already classified
|
|
501
|
+
const fileHash = hashFile(absPath);
|
|
502
|
+
manifest.files[relPath] = userFileRecord(fileHash);
|
|
503
|
+
});
|
|
504
|
+
}
|
|
505
|
+
// Record settings hooks checksum
|
|
506
|
+
const settingsHooksPath = path.join(TEMPLATES_DIR, 'settings-hooks.json');
|
|
507
|
+
if (fs.existsSync(settingsHooksPath)) {
|
|
508
|
+
manifest.settingsHooksChecksum = getTemplateChecksum(settingsHooksPath);
|
|
509
|
+
}
|
|
510
|
+
// Record gitignore entries
|
|
511
|
+
manifest.gitignoreEntries = [
|
|
512
|
+
'scopes/',
|
|
513
|
+
'.claude/orbital/',
|
|
514
|
+
'.claude/orbital-events/',
|
|
515
|
+
'.claude/config/workflow-manifest.sh',
|
|
516
|
+
];
|
|
517
|
+
return manifest;
|
|
518
|
+
}
|
|
519
|
+
function getPackageVersion() {
|
|
520
|
+
return _getPackageVersionUtil(PACKAGE_ROOT);
|
|
521
|
+
}
|
|
522
|
+
/** Recursively walk a directory for manifest building. */
|
|
523
|
+
function walkDirForManifest(dirPath, prefix, fn) {
|
|
524
|
+
if (!fs.existsSync(dirPath))
|
|
525
|
+
return;
|
|
526
|
+
for (const entry of fs.readdirSync(dirPath, { withFileTypes: true })) {
|
|
527
|
+
if (entry.name.startsWith('.'))
|
|
528
|
+
continue;
|
|
529
|
+
const absPath = path.join(dirPath, entry.name);
|
|
530
|
+
const relPath = `${prefix}/${entry.name}`;
|
|
531
|
+
// Follow symlinks: use stat() to check if target is a directory
|
|
532
|
+
const stat = fs.statSync(absPath);
|
|
533
|
+
if (stat.isDirectory()) {
|
|
534
|
+
walkDirForManifest(absPath, relPath, fn);
|
|
535
|
+
}
|
|
536
|
+
else {
|
|
537
|
+
fn(relPath, absPath);
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
}
|
|
434
541
|
// ─── Exports ─────────────────────────────────────────────────
|
|
435
|
-
|
|
542
|
+
/** Seed ~/.orbital/primitives/ from package templates. Called by init, update, and server startup. */
|
|
543
|
+
export function seedGlobalPrimitives() {
|
|
544
|
+
ensureOrbitalHome();
|
|
545
|
+
for (const type of ['hooks', 'skills', 'agents']) {
|
|
546
|
+
const src = path.join(TEMPLATES_DIR, type);
|
|
547
|
+
const dest = path.join(GLOBAL_PRIMITIVES_DIR, type);
|
|
548
|
+
if (fs.existsSync(src)) {
|
|
549
|
+
copyDirSync(src, dest, { overwrite: true });
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
export { TEMPLATES_DIR, ensureDir, cleanEmptyDirs, chmodScripts, listTemplateFiles, writeManifest, generateIndexMd, getPackageVersion };
|
|
554
|
+
// Re-export manifest utilities for CLI access via loadSharedModule()
|
|
555
|
+
export { loadManifest, saveManifest, hashFile, buildTemplateInventory, refreshFileStatuses, summarizeManifest } from './manifest.js';
|
|
556
|
+
export { validate, formatValidationReport } from './validator.js';
|
|
557
|
+
// Re-export update and uninstall from their new homes (backward compat for loadSharedModule)
|
|
558
|
+
export { runUpdate } from './update.js';
|
|
559
|
+
export { runUninstall } from './uninstall.js';
|
|
436
560
|
export function runInit(projectRoot, options = {}) {
|
|
437
561
|
const force = options.force ?? false;
|
|
562
|
+
const quiet = options.quiet ?? false;
|
|
563
|
+
const selectedPreset = options.preset || 'default';
|
|
438
564
|
const claudeDir = path.join(projectRoot, '.claude');
|
|
439
|
-
|
|
440
|
-
|
|
565
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
566
|
+
const log = quiet ? (..._args) => { } : console.log.bind(console);
|
|
567
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
568
|
+
const warn = quiet ? (..._args) => { } : console.warn.bind(console);
|
|
569
|
+
log(`\nOrbital Command — init`);
|
|
570
|
+
log(`Project root: ${projectRoot}\n`);
|
|
441
571
|
// 1. Create directories
|
|
442
572
|
const dirs = [
|
|
443
573
|
path.join(claudeDir, 'orbital-events'),
|
|
@@ -447,24 +577,26 @@ export function runInit(projectRoot, options = {}) {
|
|
|
447
577
|
];
|
|
448
578
|
for (const dir of dirs) {
|
|
449
579
|
const wasCreated = ensureDir(dir);
|
|
450
|
-
|
|
580
|
+
log(` ${wasCreated ? 'Created' : 'Exists '} ${path.relative(projectRoot, dir)}/`);
|
|
451
581
|
}
|
|
452
|
-
// 1b. Create scopes/ subdirectories from the
|
|
582
|
+
// 1b. Create scopes/ subdirectories from the selected workflow preset
|
|
583
|
+
const selectedPresetPath = path.join(TEMPLATES_DIR, 'presets', `${selectedPreset}.json`);
|
|
453
584
|
const defaultPresetPath = path.join(TEMPLATES_DIR, 'presets', 'default.json');
|
|
585
|
+
const presetPath = fs.existsSync(selectedPresetPath) ? selectedPresetPath : defaultPresetPath;
|
|
454
586
|
let scopeDirs = ['icebox'];
|
|
455
587
|
try {
|
|
456
|
-
const preset = JSON.parse(fs.readFileSync(
|
|
588
|
+
const preset = JSON.parse(fs.readFileSync(presetPath, 'utf8'));
|
|
457
589
|
if (preset.lists && Array.isArray(preset.lists)) {
|
|
458
590
|
scopeDirs = preset.lists.filter((l) => l.hasDirectory).map((l) => l.id);
|
|
459
591
|
}
|
|
460
592
|
}
|
|
461
593
|
catch {
|
|
462
|
-
|
|
594
|
+
warn(' Warning: could not load preset, creating scopes/icebox/ only');
|
|
463
595
|
}
|
|
464
596
|
for (const dirId of scopeDirs) {
|
|
465
597
|
const scopeDir = path.join(projectRoot, 'scopes', dirId);
|
|
466
598
|
const wasCreated = ensureDir(scopeDir);
|
|
467
|
-
|
|
599
|
+
log(` ${wasCreated ? 'Created' : 'Exists '} scopes/${dirId}/`);
|
|
468
600
|
}
|
|
469
601
|
// 1c. Copy scope template
|
|
470
602
|
const scopeTemplateSrc = path.join(TEMPLATES_DIR, 'scopes', '_template.md');
|
|
@@ -472,10 +604,10 @@ export function runInit(projectRoot, options = {}) {
|
|
|
472
604
|
if (fs.existsSync(scopeTemplateSrc)) {
|
|
473
605
|
if (force || !fs.existsSync(scopeTemplateDest)) {
|
|
474
606
|
fs.copyFileSync(scopeTemplateSrc, scopeTemplateDest);
|
|
475
|
-
|
|
607
|
+
log(` ${force ? 'Reset ' : 'Created'} scopes/_template.md`);
|
|
476
608
|
}
|
|
477
609
|
else {
|
|
478
|
-
|
|
610
|
+
log(` Exists scopes/_template.md`);
|
|
479
611
|
}
|
|
480
612
|
}
|
|
481
613
|
// 2. Copy orbital.config.json template
|
|
@@ -485,85 +617,114 @@ export function runInit(projectRoot, options = {}) {
|
|
|
485
617
|
if (configIsNew) {
|
|
486
618
|
if (fs.existsSync(configSrc)) {
|
|
487
619
|
fs.copyFileSync(configSrc, configDest);
|
|
488
|
-
|
|
620
|
+
// Apply wizard-collected or auto-detected values
|
|
621
|
+
try {
|
|
622
|
+
const config = JSON.parse(fs.readFileSync(configDest, 'utf8'));
|
|
623
|
+
config.projectName = options.projectName || path.basename(projectRoot)
|
|
624
|
+
.replace(/[-_]+/g, ' ')
|
|
625
|
+
.replace(/\b\w/g, c => c.toUpperCase());
|
|
626
|
+
if (options.serverPort)
|
|
627
|
+
config.serverPort = options.serverPort;
|
|
628
|
+
if (options.clientPort)
|
|
629
|
+
config.clientPort = options.clientPort;
|
|
630
|
+
fs.writeFileSync(configDest, JSON.stringify(config, null, 2) + '\n', 'utf8');
|
|
631
|
+
}
|
|
632
|
+
catch { /* leave template default */ }
|
|
633
|
+
log(` Created .claude/orbital.config.json`);
|
|
489
634
|
}
|
|
490
635
|
else {
|
|
491
636
|
const defaultConfig = {
|
|
492
|
-
serverPort: 4444,
|
|
493
|
-
clientPort: 4445,
|
|
494
|
-
projectName: path.basename(projectRoot),
|
|
637
|
+
serverPort: options.serverPort || 4444,
|
|
638
|
+
clientPort: options.clientPort || 4445,
|
|
639
|
+
projectName: options.projectName || path.basename(projectRoot),
|
|
495
640
|
};
|
|
496
641
|
fs.writeFileSync(configDest, JSON.stringify(defaultConfig, null, 2) + '\n', 'utf8');
|
|
497
|
-
|
|
642
|
+
log(` Created .claude/orbital.config.json (default)`);
|
|
498
643
|
}
|
|
499
|
-
//
|
|
500
|
-
|
|
501
|
-
if (fs.existsSync(pkgJsonPath)) {
|
|
644
|
+
// Apply wizard-provided commands or auto-detect from package.json
|
|
645
|
+
if (options.commands) {
|
|
502
646
|
try {
|
|
503
|
-
const pkg = JSON.parse(fs.readFileSync(pkgJsonPath, 'utf8'));
|
|
504
|
-
const scripts = pkg.scripts || {};
|
|
505
647
|
const config = JSON.parse(fs.readFileSync(configDest, 'utf8'));
|
|
506
648
|
if (!config.commands)
|
|
507
649
|
config.commands = {};
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
if (scripts.lint) {
|
|
514
|
-
config.commands.lint = 'npm run lint';
|
|
515
|
-
detected++;
|
|
516
|
-
}
|
|
517
|
-
if (scripts.build) {
|
|
518
|
-
config.commands.build = 'npm run build';
|
|
519
|
-
detected++;
|
|
520
|
-
}
|
|
521
|
-
if (scripts.test) {
|
|
522
|
-
config.commands.test = 'npm run test';
|
|
523
|
-
detected++;
|
|
524
|
-
}
|
|
525
|
-
if (detected > 0) {
|
|
526
|
-
fs.writeFileSync(configDest, JSON.stringify(config, null, 2) + '\n', 'utf8');
|
|
527
|
-
console.log(` Detected ${detected} project command(s) from package.json`);
|
|
528
|
-
}
|
|
650
|
+
Object.assign(config.commands, options.commands);
|
|
651
|
+
const commandCount = Object.values(options.commands).filter(v => v !== null).length;
|
|
652
|
+
fs.writeFileSync(configDest, JSON.stringify(config, null, 2) + '\n', 'utf8');
|
|
653
|
+
if (commandCount > 0)
|
|
654
|
+
log(` Applied ${commandCount} project command(s)`);
|
|
529
655
|
}
|
|
530
656
|
catch { /* leave defaults */ }
|
|
531
657
|
}
|
|
658
|
+
else {
|
|
659
|
+
// Auto-detect project commands from package.json
|
|
660
|
+
const pkgJsonPath = path.join(projectRoot, 'package.json');
|
|
661
|
+
if (fs.existsSync(pkgJsonPath)) {
|
|
662
|
+
try {
|
|
663
|
+
const pkg = JSON.parse(fs.readFileSync(pkgJsonPath, 'utf8'));
|
|
664
|
+
const scripts = pkg.scripts || {};
|
|
665
|
+
const config = JSON.parse(fs.readFileSync(configDest, 'utf8'));
|
|
666
|
+
if (!config.commands)
|
|
667
|
+
config.commands = {};
|
|
668
|
+
let detected = 0;
|
|
669
|
+
if (scripts.typecheck || scripts['type-check']) {
|
|
670
|
+
config.commands.typeCheck = `npm run ${scripts.typecheck ? 'typecheck' : 'type-check'}`;
|
|
671
|
+
detected++;
|
|
672
|
+
}
|
|
673
|
+
if (scripts.lint) {
|
|
674
|
+
config.commands.lint = 'npm run lint';
|
|
675
|
+
detected++;
|
|
676
|
+
}
|
|
677
|
+
if (scripts.build) {
|
|
678
|
+
config.commands.build = 'npm run build';
|
|
679
|
+
detected++;
|
|
680
|
+
}
|
|
681
|
+
if (scripts.test) {
|
|
682
|
+
config.commands.test = 'npm run test';
|
|
683
|
+
detected++;
|
|
684
|
+
}
|
|
685
|
+
if (detected > 0) {
|
|
686
|
+
fs.writeFileSync(configDest, JSON.stringify(config, null, 2) + '\n', 'utf8');
|
|
687
|
+
log(` Detected ${detected} project command(s) from package.json`);
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
catch { /* leave defaults */ }
|
|
691
|
+
}
|
|
692
|
+
}
|
|
532
693
|
}
|
|
533
694
|
else {
|
|
534
|
-
|
|
695
|
+
log(` Exists .claude/orbital.config.json`);
|
|
535
696
|
}
|
|
536
697
|
// 3. Copy hooks
|
|
537
|
-
|
|
698
|
+
log('');
|
|
538
699
|
const hooksSrc = path.join(TEMPLATES_DIR, 'hooks');
|
|
539
700
|
const hooksDest = path.join(claudeDir, 'hooks');
|
|
540
701
|
if (force) {
|
|
541
702
|
const pruned = pruneStaleEntries(hooksSrc, hooksDest);
|
|
542
703
|
if (pruned > 0)
|
|
543
|
-
|
|
704
|
+
log(` Pruned ${pruned} stale hook entries`);
|
|
544
705
|
}
|
|
545
706
|
const hooksResult = copyDirSync(hooksSrc, hooksDest, { overwrite: force });
|
|
546
|
-
|
|
707
|
+
log(` Hooks ${hooksResult.created.length} copied, ${hooksResult.skipped.length} skipped`);
|
|
547
708
|
// 4. Copy skills
|
|
548
709
|
const skillsSrc = path.join(TEMPLATES_DIR, 'skills');
|
|
549
710
|
const skillsDest = path.join(claudeDir, 'skills');
|
|
550
711
|
if (force) {
|
|
551
712
|
const pruned = pruneStaleEntries(skillsSrc, skillsDest);
|
|
552
713
|
if (pruned > 0)
|
|
553
|
-
|
|
714
|
+
log(` Pruned ${pruned} stale skill entries`);
|
|
554
715
|
}
|
|
555
716
|
const skillsResult = copyDirSync(skillsSrc, skillsDest, { overwrite: force });
|
|
556
|
-
|
|
717
|
+
log(` Skills ${skillsResult.created.length} copied, ${skillsResult.skipped.length} skipped`);
|
|
557
718
|
// 5. Copy agents
|
|
558
719
|
const agentsSrc = path.join(TEMPLATES_DIR, 'agents');
|
|
559
720
|
const agentsDest = path.join(claudeDir, 'agents');
|
|
560
721
|
if (force) {
|
|
561
722
|
const pruned = pruneStaleEntries(agentsSrc, agentsDest);
|
|
562
723
|
if (pruned > 0)
|
|
563
|
-
|
|
724
|
+
log(` Pruned ${pruned} stale agent entries`);
|
|
564
725
|
}
|
|
565
726
|
const agentsResult = copyDirSync(agentsSrc, agentsDest, { overwrite: force });
|
|
566
|
-
|
|
727
|
+
log(` Agents ${agentsResult.created.length} copied, ${agentsResult.skipped.length} skipped`);
|
|
567
728
|
// 6. Copy workflow presets
|
|
568
729
|
const presetsSrc = path.join(TEMPLATES_DIR, 'presets');
|
|
569
730
|
const presetsDest = path.join(claudeDir, 'config', 'workflows');
|
|
@@ -571,23 +732,23 @@ export function runInit(projectRoot, options = {}) {
|
|
|
571
732
|
if (force) {
|
|
572
733
|
const pruned = pruneStaleEntries(presetsSrc, presetsDest);
|
|
573
734
|
if (pruned > 0)
|
|
574
|
-
|
|
735
|
+
log(` Pruned ${pruned} stale preset entries`);
|
|
575
736
|
}
|
|
576
737
|
const presetsResult = copyDirSync(presetsSrc, presetsDest, { overwrite: force });
|
|
577
|
-
|
|
738
|
+
log(` Presets ${presetsResult.created.length} copied, ${presetsResult.skipped.length} skipped`);
|
|
578
739
|
}
|
|
579
740
|
// 6b. Reset active workflow config when --force, or create if missing
|
|
580
741
|
const activeWorkflowDest = path.join(claudeDir, 'config', 'workflow.json');
|
|
581
742
|
if (force) {
|
|
582
|
-
fs.copyFileSync(
|
|
583
|
-
|
|
743
|
+
fs.copyFileSync(presetPath, activeWorkflowDest);
|
|
744
|
+
log(` Reset .claude/config/workflow.json (${selectedPreset} workflow)`);
|
|
584
745
|
}
|
|
585
746
|
else if (!fs.existsSync(activeWorkflowDest)) {
|
|
586
|
-
fs.copyFileSync(
|
|
587
|
-
|
|
747
|
+
fs.copyFileSync(presetPath, activeWorkflowDest);
|
|
748
|
+
log(` Created .claude/config/workflow.json (${selectedPreset})`);
|
|
588
749
|
}
|
|
589
750
|
else {
|
|
590
|
-
|
|
751
|
+
log(` Exists .claude/config/workflow.json`);
|
|
591
752
|
}
|
|
592
753
|
// 7. Copy agent-triggers.json
|
|
593
754
|
const triggersSrc = path.join(TEMPLATES_DIR, 'config', 'agent-triggers.json');
|
|
@@ -595,10 +756,10 @@ export function runInit(projectRoot, options = {}) {
|
|
|
595
756
|
if (fs.existsSync(triggersSrc)) {
|
|
596
757
|
if (force || !fs.existsSync(triggersDest)) {
|
|
597
758
|
fs.copyFileSync(triggersSrc, triggersDest);
|
|
598
|
-
|
|
759
|
+
log(` Created .claude/config/agent-triggers.json`);
|
|
599
760
|
}
|
|
600
761
|
else {
|
|
601
|
-
|
|
762
|
+
log(` Exists .claude/config/agent-triggers.json`);
|
|
602
763
|
}
|
|
603
764
|
}
|
|
604
765
|
// 7b. Copy quick/ templates
|
|
@@ -606,14 +767,14 @@ export function runInit(projectRoot, options = {}) {
|
|
|
606
767
|
const quickDest = path.join(claudeDir, 'quick');
|
|
607
768
|
if (fs.existsSync(quickSrc)) {
|
|
608
769
|
const quickResult = copyDirSync(quickSrc, quickDest, { overwrite: force });
|
|
609
|
-
|
|
770
|
+
log(` Quick ${quickResult.created.length} copied, ${quickResult.skipped.length} skipped`);
|
|
610
771
|
}
|
|
611
772
|
// 7c. Copy anti-patterns/ templates
|
|
612
773
|
const antiSrc = path.join(TEMPLATES_DIR, 'anti-patterns');
|
|
613
774
|
const antiDest = path.join(claudeDir, 'anti-patterns');
|
|
614
775
|
if (fs.existsSync(antiSrc)) {
|
|
615
776
|
const antiResult = copyDirSync(antiSrc, antiDest, { overwrite: force });
|
|
616
|
-
|
|
777
|
+
log(` Anti-pat ${antiResult.created.length} copied, ${antiResult.skipped.length} skipped`);
|
|
617
778
|
}
|
|
618
779
|
// 7d. Copy lessons-learned.md
|
|
619
780
|
const lessonsSrc = path.join(TEMPLATES_DIR, 'lessons-learned.md');
|
|
@@ -621,191 +782,48 @@ export function runInit(projectRoot, options = {}) {
|
|
|
621
782
|
if (fs.existsSync(lessonsSrc)) {
|
|
622
783
|
if (force || !fs.existsSync(lessonsDest)) {
|
|
623
784
|
fs.copyFileSync(lessonsSrc, lessonsDest);
|
|
624
|
-
|
|
785
|
+
log(` Created .claude/lessons-learned.md`);
|
|
625
786
|
}
|
|
626
787
|
else {
|
|
627
|
-
|
|
788
|
+
log(` Exists .claude/lessons-learned.md`);
|
|
628
789
|
}
|
|
629
790
|
}
|
|
630
791
|
// 7e. Generate workflow manifest
|
|
631
792
|
const manifestOk = writeManifest(claudeDir);
|
|
632
|
-
|
|
793
|
+
log(` ${manifestOk ? 'Created' : 'Skipped'} .claude/config/workflow-manifest.sh`);
|
|
633
794
|
// 7f. Generate INDEX.md
|
|
634
795
|
const indexDest = path.join(claudeDir, 'INDEX.md');
|
|
635
796
|
if (force || !fs.existsSync(indexDest)) {
|
|
636
797
|
const indexContent = generateIndexMd(projectRoot, claudeDir);
|
|
637
798
|
fs.writeFileSync(indexDest, indexContent, 'utf8');
|
|
638
|
-
|
|
799
|
+
log(` ${force ? 'Reset ' : 'Created'} .claude/INDEX.md`);
|
|
639
800
|
}
|
|
640
801
|
else {
|
|
641
|
-
|
|
802
|
+
log(` Exists .claude/INDEX.md`);
|
|
642
803
|
}
|
|
643
804
|
// 8. Merge hook registrations into settings.local.json
|
|
644
|
-
|
|
805
|
+
log('');
|
|
645
806
|
const settingsTarget = path.join(claudeDir, 'settings.local.json');
|
|
646
807
|
const settingsSrc = path.join(TEMPLATES_DIR, 'settings-hooks.json');
|
|
647
808
|
mergeSettingsHooks(settingsTarget, settingsSrc);
|
|
648
|
-
|
|
809
|
+
log(` Merged hook registrations into .claude/settings.local.json`);
|
|
649
810
|
// 9. Update .gitignore
|
|
650
811
|
const gitignoreUpdated = updateGitignore(projectRoot);
|
|
651
|
-
|
|
812
|
+
log(` ${gitignoreUpdated ? 'Updated' : 'Exists '} .gitignore (Orbital patterns)`);
|
|
652
813
|
// 10. Make hook scripts executable
|
|
653
814
|
chmodScripts(hooksDest);
|
|
654
|
-
|
|
815
|
+
log(` chmod hook scripts set to executable`);
|
|
816
|
+
// 11. Seed global primitives from package templates
|
|
817
|
+
seedGlobalPrimitives();
|
|
818
|
+
log(` Seeded global primitives (~/.orbital/primitives/)`);
|
|
819
|
+
// 12. Build and save manifest
|
|
820
|
+
const manifest = buildInitManifest(projectRoot, claudeDir, selectedPreset);
|
|
821
|
+
saveManifest(projectRoot, manifest);
|
|
822
|
+
log(` Created .claude/orbital-manifest.json (${Object.keys(manifest.files).length} files tracked)`);
|
|
655
823
|
// Summary
|
|
656
824
|
const totalCreated = hooksResult.created.length + skillsResult.created.length + agentsResult.created.length;
|
|
657
825
|
const totalSkipped = hooksResult.skipped.length + skillsResult.skipped.length + agentsResult.skipped.length;
|
|
658
|
-
|
|
659
|
-
}
|
|
660
|
-
export function runUpdate(projectRoot) {
|
|
661
|
-
const claudeDir = path.join(projectRoot, '.claude');
|
|
662
|
-
console.log(`\nOrbital Command — update`);
|
|
663
|
-
console.log(`Project root: ${projectRoot}\n`);
|
|
664
|
-
// 1. Copy hooks (overwrite) — prune stale entries first
|
|
665
|
-
const hooksSrc = path.join(TEMPLATES_DIR, 'hooks');
|
|
666
|
-
const hooksDest = path.join(claudeDir, 'hooks');
|
|
667
|
-
const hooksPruned = pruneStaleEntries(hooksSrc, hooksDest);
|
|
668
|
-
if (hooksPruned > 0)
|
|
669
|
-
console.log(` Pruned ${hooksPruned} stale hook entries`);
|
|
670
|
-
const hooksResult = copyDirSync(hooksSrc, hooksDest, { overwrite: true });
|
|
671
|
-
console.log(` Hooks ${hooksResult.created.length} updated`);
|
|
672
|
-
// 2. Copy skills (overwrite) — prune stale entries first
|
|
673
|
-
const skillsSrc = path.join(TEMPLATES_DIR, 'skills');
|
|
674
|
-
const skillsDest = path.join(claudeDir, 'skills');
|
|
675
|
-
const skillsPruned = pruneStaleEntries(skillsSrc, skillsDest);
|
|
676
|
-
if (skillsPruned > 0)
|
|
677
|
-
console.log(` Pruned ${skillsPruned} stale skill entries`);
|
|
678
|
-
const skillsResult = copyDirSync(skillsSrc, skillsDest, { overwrite: true });
|
|
679
|
-
console.log(` Skills ${skillsResult.created.length} updated`);
|
|
680
|
-
// 3. Copy agents (overwrite) — prune stale entries first
|
|
681
|
-
const agentsSrc = path.join(TEMPLATES_DIR, 'agents');
|
|
682
|
-
const agentsDest = path.join(claudeDir, 'agents');
|
|
683
|
-
const agentsPruned = pruneStaleEntries(agentsSrc, agentsDest);
|
|
684
|
-
if (agentsPruned > 0)
|
|
685
|
-
console.log(` Pruned ${agentsPruned} stale agent entries`);
|
|
686
|
-
const agentsResult = copyDirSync(agentsSrc, agentsDest, { overwrite: true });
|
|
687
|
-
console.log(` Agents ${agentsResult.created.length} updated`);
|
|
688
|
-
// 4. Update workflow presets — prune stale entries first
|
|
689
|
-
const presetsSrc = path.join(TEMPLATES_DIR, 'presets');
|
|
690
|
-
const presetsDest = path.join(claudeDir, 'config', 'workflows');
|
|
691
|
-
if (fs.existsSync(presetsSrc) && fs.readdirSync(presetsSrc).length > 0) {
|
|
692
|
-
const presetsPruned = pruneStaleEntries(presetsSrc, presetsDest);
|
|
693
|
-
if (presetsPruned > 0)
|
|
694
|
-
console.log(` Pruned ${presetsPruned} stale preset entries`);
|
|
695
|
-
const presetsResult = copyDirSync(presetsSrc, presetsDest, { overwrite: true });
|
|
696
|
-
console.log(` Presets ${presetsResult.created.length} updated`);
|
|
697
|
-
}
|
|
698
|
-
// 5. Update quick/, anti-patterns/, lessons-learned, scope template
|
|
699
|
-
const quickSrc = path.join(TEMPLATES_DIR, 'quick');
|
|
700
|
-
const quickDest = path.join(claudeDir, 'quick');
|
|
701
|
-
if (fs.existsSync(quickSrc)) {
|
|
702
|
-
const quickResult = copyDirSync(quickSrc, quickDest, { overwrite: true });
|
|
703
|
-
console.log(` Quick ${quickResult.created.length} updated`);
|
|
704
|
-
}
|
|
705
|
-
const antiSrc = path.join(TEMPLATES_DIR, 'anti-patterns');
|
|
706
|
-
const antiDest = path.join(claudeDir, 'anti-patterns');
|
|
707
|
-
if (fs.existsSync(antiSrc)) {
|
|
708
|
-
const antiResult = copyDirSync(antiSrc, antiDest, { overwrite: true });
|
|
709
|
-
console.log(` Anti-pat ${antiResult.created.length} updated`);
|
|
710
|
-
}
|
|
711
|
-
const lessonsSrc = path.join(TEMPLATES_DIR, 'lessons-learned.md');
|
|
712
|
-
const lessonsDest = path.join(claudeDir, 'lessons-learned.md');
|
|
713
|
-
if (fs.existsSync(lessonsSrc) && !fs.existsSync(lessonsDest)) {
|
|
714
|
-
fs.copyFileSync(lessonsSrc, lessonsDest);
|
|
715
|
-
console.log(` Created .claude/lessons-learned.md`);
|
|
716
|
-
}
|
|
717
|
-
const scopeTemplateSrc = path.join(TEMPLATES_DIR, 'scopes', '_template.md');
|
|
718
|
-
const scopeTemplateDest = path.join(projectRoot, 'scopes', '_template.md');
|
|
719
|
-
if (fs.existsSync(scopeTemplateSrc)) {
|
|
720
|
-
ensureDir(path.join(projectRoot, 'scopes'));
|
|
721
|
-
fs.copyFileSync(scopeTemplateSrc, scopeTemplateDest);
|
|
722
|
-
console.log(` Updated scopes/_template.md`);
|
|
723
|
-
}
|
|
724
|
-
// 5b. Regenerate workflow manifest
|
|
725
|
-
const manifestOk = writeManifest(claudeDir);
|
|
726
|
-
console.log(` ${manifestOk ? 'Updated' : 'Skipped'} .claude/config/workflow-manifest.sh`);
|
|
727
|
-
// 6. Re-merge settings hooks
|
|
728
|
-
const settingsTarget = path.join(claudeDir, 'settings.local.json');
|
|
729
|
-
const settingsSrc = path.join(TEMPLATES_DIR, 'settings-hooks.json');
|
|
730
|
-
mergeSettingsHooks(settingsTarget, settingsSrc);
|
|
731
|
-
console.log(` Merged hook registrations into .claude/settings.local.json`);
|
|
732
|
-
// 7. Make hook scripts executable
|
|
733
|
-
chmodScripts(hooksDest);
|
|
734
|
-
console.log(` chmod hook scripts set to executable`);
|
|
735
|
-
console.log(`\nUpdate complete.\n`);
|
|
736
|
-
}
|
|
737
|
-
export function runUninstall(projectRoot) {
|
|
738
|
-
const claudeDir = path.join(projectRoot, '.claude');
|
|
739
|
-
console.log(`\nOrbital Command — uninstall`);
|
|
740
|
-
console.log(`Project root: ${projectRoot}\n`);
|
|
741
|
-
let removedCount = 0;
|
|
742
|
-
// 1. Remove orbital hooks from settings.local.json
|
|
743
|
-
const settingsPath = path.join(claudeDir, 'settings.local.json');
|
|
744
|
-
if (fs.existsSync(settingsPath)) {
|
|
745
|
-
try {
|
|
746
|
-
const settings = JSON.parse(fs.readFileSync(settingsPath, 'utf8'));
|
|
747
|
-
if (settings.hooks) {
|
|
748
|
-
for (const [event] of Object.entries(settings.hooks)) {
|
|
749
|
-
for (const group of settings.hooks[event]) {
|
|
750
|
-
if (group.hooks) {
|
|
751
|
-
const before = group.hooks.length;
|
|
752
|
-
group.hooks = group.hooks.filter((h) => !h._orbital);
|
|
753
|
-
removedCount += before - group.hooks.length;
|
|
754
|
-
}
|
|
755
|
-
}
|
|
756
|
-
settings.hooks[event] = settings.hooks[event].filter((g) => g.hooks && g.hooks.length > 0);
|
|
757
|
-
if (settings.hooks[event].length === 0) {
|
|
758
|
-
delete settings.hooks[event];
|
|
759
|
-
}
|
|
760
|
-
}
|
|
761
|
-
if (Object.keys(settings.hooks).length === 0) {
|
|
762
|
-
delete settings.hooks;
|
|
763
|
-
}
|
|
764
|
-
fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + '\n', 'utf8');
|
|
765
|
-
console.log(` Removed ${removedCount} orbital hook registrations from settings.local.json`);
|
|
766
|
-
}
|
|
767
|
-
}
|
|
768
|
-
catch {
|
|
769
|
-
console.warn(' Warning: could not parse settings.local.json');
|
|
770
|
-
}
|
|
771
|
-
}
|
|
772
|
-
// 2. Delete hooks that came from templates
|
|
773
|
-
const hookFiles = listTemplateFiles(path.join(TEMPLATES_DIR, 'hooks'), path.join(claudeDir, 'hooks'));
|
|
774
|
-
let hooksRemoved = 0;
|
|
775
|
-
for (const f of hookFiles) {
|
|
776
|
-
if (fs.existsSync(f)) {
|
|
777
|
-
fs.unlinkSync(f);
|
|
778
|
-
hooksRemoved++;
|
|
779
|
-
}
|
|
780
|
-
}
|
|
781
|
-
console.log(` Removed ${hooksRemoved} hook scripts`);
|
|
782
|
-
// 3. Delete skills that came from templates
|
|
783
|
-
const skillFiles = listTemplateFiles(path.join(TEMPLATES_DIR, 'skills'), path.join(claudeDir, 'skills'));
|
|
784
|
-
let skillsRemoved = 0;
|
|
785
|
-
for (const f of skillFiles) {
|
|
786
|
-
if (fs.existsSync(f)) {
|
|
787
|
-
fs.unlinkSync(f);
|
|
788
|
-
skillsRemoved++;
|
|
789
|
-
}
|
|
790
|
-
}
|
|
791
|
-
const skillsDest = path.join(claudeDir, 'skills');
|
|
792
|
-
if (fs.existsSync(skillsDest))
|
|
793
|
-
cleanEmptyDirs(skillsDest);
|
|
794
|
-
console.log(` Removed ${skillsRemoved} skill files`);
|
|
795
|
-
// 4. Delete agents that came from templates
|
|
796
|
-
const agentFiles = listTemplateFiles(path.join(TEMPLATES_DIR, 'agents'), path.join(claudeDir, 'agents'));
|
|
797
|
-
let agentsRemoved = 0;
|
|
798
|
-
for (const f of agentFiles) {
|
|
799
|
-
if (fs.existsSync(f)) {
|
|
800
|
-
fs.unlinkSync(f);
|
|
801
|
-
agentsRemoved++;
|
|
802
|
-
}
|
|
803
|
-
}
|
|
804
|
-
const agentsDest = path.join(claudeDir, 'agents');
|
|
805
|
-
if (fs.existsSync(agentsDest))
|
|
806
|
-
cleanEmptyDirs(agentsDest);
|
|
807
|
-
console.log(` Removed ${agentsRemoved} agent files`);
|
|
808
|
-
const total = removedCount + hooksRemoved + skillsRemoved + agentsRemoved;
|
|
809
|
-
console.log(`\nUninstall complete. ${total} items removed.`);
|
|
810
|
-
console.log(`Note: scopes/ and .claude/orbital-events/ were preserved.\n`);
|
|
826
|
+
log(`\nDone. ${totalCreated} files installed, ${totalSkipped} skipped (use --force to overwrite).`);
|
|
811
827
|
}
|
|
828
|
+
// runUpdate and runUninstall have been extracted to update.ts and uninstall.ts
|
|
829
|
+
// and are re-exported above for backward compatibility.
|