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,237 +0,0 @@
|
|
|
1
|
-
import { useState, useMemo, useCallback } from 'react';
|
|
2
|
-
import * as Dialog from '@radix-ui/react-dialog';
|
|
3
|
-
import { X, AlertTriangle, ArrowRight, CheckCircle2, Loader2 } from 'lucide-react';
|
|
4
|
-
import type { WorkflowConfig } from '../../../shared/workflow-config';
|
|
5
|
-
|
|
6
|
-
// ─── Types ──────────────────────────────────────────────
|
|
7
|
-
|
|
8
|
-
interface MigrationPlan {
|
|
9
|
-
valid: boolean;
|
|
10
|
-
validationErrors: string[];
|
|
11
|
-
removedLists: string[];
|
|
12
|
-
addedLists: string[];
|
|
13
|
-
dirsToCreate: string[];
|
|
14
|
-
dirsToRemove: string[];
|
|
15
|
-
orphanedScopes: Array<{ listId: string; scopeFiles: string[] }>;
|
|
16
|
-
lostEdges: Array<{ from: string; to: string }>;
|
|
17
|
-
suggestedMappings: Record<string, string>;
|
|
18
|
-
impactSummary: string;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
interface MigrationPreviewDialogProps {
|
|
22
|
-
open: boolean;
|
|
23
|
-
onOpenChange: (open: boolean) => void;
|
|
24
|
-
config: WorkflowConfig;
|
|
25
|
-
plan: MigrationPlan | null;
|
|
26
|
-
loading: boolean;
|
|
27
|
-
error: string | null;
|
|
28
|
-
onApply: (orphanMappings: Record<string, string>) => void;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
// ─── Component ──────────────────────────────────────────
|
|
32
|
-
|
|
33
|
-
export function MigrationPreviewDialog({
|
|
34
|
-
open,
|
|
35
|
-
onOpenChange,
|
|
36
|
-
config,
|
|
37
|
-
plan,
|
|
38
|
-
loading,
|
|
39
|
-
error,
|
|
40
|
-
onApply,
|
|
41
|
-
}: MigrationPreviewDialogProps) {
|
|
42
|
-
const [orphanMappings, setOrphanMappings] = useState<Record<string, string>>({});
|
|
43
|
-
|
|
44
|
-
// Initialize mappings from suggestions when plan changes
|
|
45
|
-
useMemo(() => {
|
|
46
|
-
if (plan?.suggestedMappings) {
|
|
47
|
-
setOrphanMappings({ ...plan.suggestedMappings });
|
|
48
|
-
}
|
|
49
|
-
}, [plan?.suggestedMappings]);
|
|
50
|
-
|
|
51
|
-
const listIds = useMemo(() => config.lists.map((l) => l.id), [config.lists]);
|
|
52
|
-
|
|
53
|
-
const allOrphansMapped = useMemo(() => {
|
|
54
|
-
if (!plan) return true;
|
|
55
|
-
return plan.orphanedScopes.every((o) => orphanMappings[o.listId]);
|
|
56
|
-
}, [plan, orphanMappings]);
|
|
57
|
-
|
|
58
|
-
const handleApply = useCallback(() => {
|
|
59
|
-
if (!allOrphansMapped) return;
|
|
60
|
-
onApply(orphanMappings);
|
|
61
|
-
}, [allOrphansMapped, orphanMappings, onApply]);
|
|
62
|
-
|
|
63
|
-
return (
|
|
64
|
-
<Dialog.Root open={open} onOpenChange={onOpenChange}>
|
|
65
|
-
<Dialog.Portal>
|
|
66
|
-
<Dialog.Overlay className="fixed inset-0 z-40 bg-black/60 backdrop-blur-sm" />
|
|
67
|
-
<Dialog.Content className="fixed left-1/2 top-1/2 z-50 max-h-[80vh] w-[520px] -translate-x-1/2 -translate-y-1/2 overflow-hidden rounded-lg border border-zinc-800 bg-zinc-900 shadow-xl">
|
|
68
|
-
{/* Header */}
|
|
69
|
-
<div className="flex items-center justify-between border-b border-zinc-800 px-5 py-4">
|
|
70
|
-
<Dialog.Title className="flex items-center gap-2 text-sm font-medium text-zinc-100">
|
|
71
|
-
<AlertTriangle className="h-4 w-4 text-amber-400" />
|
|
72
|
-
Migration Preview
|
|
73
|
-
</Dialog.Title>
|
|
74
|
-
<Dialog.Close className="rounded p-1 text-zinc-500 hover:bg-zinc-800 hover:text-zinc-300">
|
|
75
|
-
<X className="h-4 w-4" />
|
|
76
|
-
</Dialog.Close>
|
|
77
|
-
</div>
|
|
78
|
-
|
|
79
|
-
{/* Content */}
|
|
80
|
-
<div className="max-h-[60vh] overflow-y-auto p-5 text-xs">
|
|
81
|
-
{loading && (
|
|
82
|
-
<div className="flex items-center justify-center gap-2 py-8 text-zinc-500">
|
|
83
|
-
<Loader2 className="h-4 w-4 animate-spin" />
|
|
84
|
-
<span>Computing migration impact...</span>
|
|
85
|
-
</div>
|
|
86
|
-
)}
|
|
87
|
-
|
|
88
|
-
{error && (
|
|
89
|
-
<div className="rounded border border-red-500/30 bg-red-500/10 p-3 text-red-400">
|
|
90
|
-
{error}
|
|
91
|
-
</div>
|
|
92
|
-
)}
|
|
93
|
-
|
|
94
|
-
{plan && !loading && (
|
|
95
|
-
<div className="space-y-4">
|
|
96
|
-
{/* Validation errors */}
|
|
97
|
-
{!plan.valid && (
|
|
98
|
-
<div className="rounded border border-red-500/30 bg-red-500/10 p-3">
|
|
99
|
-
<p className="mb-2 font-semibold text-red-400">Validation Errors</p>
|
|
100
|
-
{plan.validationErrors.map((e) => (
|
|
101
|
-
<p key={e} className="text-red-400">{e}</p>
|
|
102
|
-
))}
|
|
103
|
-
</div>
|
|
104
|
-
)}
|
|
105
|
-
|
|
106
|
-
{plan.valid && (
|
|
107
|
-
<>
|
|
108
|
-
{/* Summary */}
|
|
109
|
-
<div className="rounded border border-zinc-800 bg-zinc-950/50 p-3">
|
|
110
|
-
<p className="text-zinc-300">{plan.impactSummary}</p>
|
|
111
|
-
</div>
|
|
112
|
-
|
|
113
|
-
{/* Added lists */}
|
|
114
|
-
{plan.addedLists.length > 0 && (
|
|
115
|
-
<Section title={`Added Lists (${plan.addedLists.length})`}>
|
|
116
|
-
<div className="flex flex-wrap gap-1.5">
|
|
117
|
-
{plan.addedLists.map((id) => (
|
|
118
|
-
<span key={id} className="rounded bg-emerald-500/15 px-2 py-1 font-mono text-emerald-400">
|
|
119
|
-
+ {id}
|
|
120
|
-
</span>
|
|
121
|
-
))}
|
|
122
|
-
</div>
|
|
123
|
-
</Section>
|
|
124
|
-
)}
|
|
125
|
-
|
|
126
|
-
{/* Removed lists */}
|
|
127
|
-
{plan.removedLists.length > 0 && (
|
|
128
|
-
<Section title={`Removed Lists (${plan.removedLists.length})`}>
|
|
129
|
-
<div className="flex flex-wrap gap-1.5">
|
|
130
|
-
{plan.removedLists.map((id) => (
|
|
131
|
-
<span key={id} className="rounded bg-red-500/15 px-2 py-1 font-mono text-red-400">
|
|
132
|
-
- {id}
|
|
133
|
-
</span>
|
|
134
|
-
))}
|
|
135
|
-
</div>
|
|
136
|
-
</Section>
|
|
137
|
-
)}
|
|
138
|
-
|
|
139
|
-
{/* Lost edges */}
|
|
140
|
-
{plan.lostEdges.length > 0 && (
|
|
141
|
-
<Section title={`Lost Edges (${plan.lostEdges.length})`}>
|
|
142
|
-
<div className="space-y-1">
|
|
143
|
-
{plan.lostEdges.map((e) => (
|
|
144
|
-
<div key={`${e.from}:${e.to}`} className="flex items-center gap-2 text-zinc-400">
|
|
145
|
-
<span className="font-mono">{e.from}</span>
|
|
146
|
-
<ArrowRight className="h-3 w-3 text-zinc-600" />
|
|
147
|
-
<span className="font-mono">{e.to}</span>
|
|
148
|
-
</div>
|
|
149
|
-
))}
|
|
150
|
-
</div>
|
|
151
|
-
</Section>
|
|
152
|
-
)}
|
|
153
|
-
|
|
154
|
-
{/* Orphaned scopes */}
|
|
155
|
-
{plan.orphanedScopes.length > 0 && (
|
|
156
|
-
<Section title="Orphaned Scopes — Reassignment Required">
|
|
157
|
-
<div className="space-y-3">
|
|
158
|
-
{plan.orphanedScopes.map((o) => (
|
|
159
|
-
<div key={o.listId} className="rounded border border-amber-500/30 bg-amber-500/5 p-3">
|
|
160
|
-
<div className="flex items-center justify-between">
|
|
161
|
-
<span className="font-mono text-amber-400">{o.listId}</span>
|
|
162
|
-
<span className="text-zinc-500">{o.scopeFiles.length} scope(s)</span>
|
|
163
|
-
</div>
|
|
164
|
-
<div className="mt-2 flex items-center gap-2">
|
|
165
|
-
<span className="text-zinc-500">Move to:</span>
|
|
166
|
-
<select
|
|
167
|
-
value={orphanMappings[o.listId] ?? ''}
|
|
168
|
-
onChange={(e) => setOrphanMappings((prev) => ({ ...prev, [o.listId]: e.target.value }))}
|
|
169
|
-
className="flex-1 rounded border border-zinc-700 bg-zinc-800 px-2 py-1.5 text-zinc-200 outline-none focus:border-zinc-500"
|
|
170
|
-
>
|
|
171
|
-
<option value="">Select destination...</option>
|
|
172
|
-
{listIds.map((id) => (
|
|
173
|
-
<option key={id} value={id}>{id}</option>
|
|
174
|
-
))}
|
|
175
|
-
</select>
|
|
176
|
-
</div>
|
|
177
|
-
{o.scopeFiles.length <= 5 && (
|
|
178
|
-
<div className="mt-2 space-y-0.5">
|
|
179
|
-
{o.scopeFiles.map((f) => (
|
|
180
|
-
<p key={f} className="font-mono text-[10px] text-zinc-500">{f}</p>
|
|
181
|
-
))}
|
|
182
|
-
</div>
|
|
183
|
-
)}
|
|
184
|
-
</div>
|
|
185
|
-
))}
|
|
186
|
-
</div>
|
|
187
|
-
</Section>
|
|
188
|
-
)}
|
|
189
|
-
|
|
190
|
-
{/* No impact */}
|
|
191
|
-
{plan.removedLists.length === 0 &&
|
|
192
|
-
plan.addedLists.length === 0 &&
|
|
193
|
-
plan.lostEdges.length === 0 &&
|
|
194
|
-
plan.orphanedScopes.length === 0 && (
|
|
195
|
-
<div className="flex items-center gap-2 rounded border border-emerald-500/30 bg-emerald-500/10 p-3 text-emerald-400">
|
|
196
|
-
<CheckCircle2 className="h-4 w-4" />
|
|
197
|
-
<span>No migration needed — configs are compatible</span>
|
|
198
|
-
</div>
|
|
199
|
-
)}
|
|
200
|
-
</>
|
|
201
|
-
)}
|
|
202
|
-
</div>
|
|
203
|
-
)}
|
|
204
|
-
</div>
|
|
205
|
-
|
|
206
|
-
{/* Footer */}
|
|
207
|
-
<div className="flex items-center justify-end gap-2 border-t border-zinc-800 px-5 py-4">
|
|
208
|
-
<Dialog.Close className="rounded px-3 py-1.5 text-xs text-zinc-400 hover:bg-zinc-800 hover:text-zinc-200">
|
|
209
|
-
Cancel
|
|
210
|
-
</Dialog.Close>
|
|
211
|
-
{plan?.valid && (
|
|
212
|
-
<button
|
|
213
|
-
onClick={handleApply}
|
|
214
|
-
disabled={!allOrphansMapped}
|
|
215
|
-
className="flex items-center gap-1.5 rounded bg-emerald-600 px-4 py-1.5 text-xs font-medium text-white hover:bg-emerald-500 disabled:opacity-40"
|
|
216
|
-
>
|
|
217
|
-
<CheckCircle2 className="h-3.5 w-3.5" />
|
|
218
|
-
Apply Migration
|
|
219
|
-
</button>
|
|
220
|
-
)}
|
|
221
|
-
</div>
|
|
222
|
-
</Dialog.Content>
|
|
223
|
-
</Dialog.Portal>
|
|
224
|
-
</Dialog.Root>
|
|
225
|
-
);
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
// ─── Sub-components ─────────────────────────────────────
|
|
229
|
-
|
|
230
|
-
function Section({ title, children }: { title: string; children: React.ReactNode }) {
|
|
231
|
-
return (
|
|
232
|
-
<div>
|
|
233
|
-
<h4 className="mb-2 text-[10px] font-semibold uppercase tracking-wider text-zinc-500">{title}</h4>
|
|
234
|
-
{children}
|
|
235
|
-
</div>
|
|
236
|
-
);
|
|
237
|
-
}
|
|
@@ -1,188 +0,0 @@
|
|
|
1
|
-
import { useMemo } from 'react';
|
|
2
|
-
import { ArrowRight, ArrowLeft, CornerRightDown, Info } from 'lucide-react';
|
|
3
|
-
import type { WorkflowEdge, WorkflowList } from '../../../shared/workflow-config';
|
|
4
|
-
|
|
5
|
-
// ─── Types ──────────────────────────────────────────────
|
|
6
|
-
|
|
7
|
-
interface MovementRulesPanelProps {
|
|
8
|
-
edge: WorkflowEdge;
|
|
9
|
-
lists: WorkflowList[];
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
// ─── Component ──────────────────────────────────────────
|
|
13
|
-
|
|
14
|
-
export function MovementRulesPanel({ edge, lists }: MovementRulesPanelProps) {
|
|
15
|
-
const sortedLists = useMemo(
|
|
16
|
-
() => [...lists].sort((a, b) => a.order - b.order),
|
|
17
|
-
[lists],
|
|
18
|
-
);
|
|
19
|
-
|
|
20
|
-
const fromList = lists.find((l) => l.id === edge.from);
|
|
21
|
-
const toList = lists.find((l) => l.id === edge.to);
|
|
22
|
-
const fromOrder = fromList?.order ?? -1;
|
|
23
|
-
const toOrder = toList?.order ?? -1;
|
|
24
|
-
|
|
25
|
-
if (edge.direction === 'shortcut') {
|
|
26
|
-
return <ShortcutRules sortedLists={sortedLists} fromOrder={fromOrder} toOrder={toOrder} edge={edge} />;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
if (edge.direction === 'backward') {
|
|
30
|
-
return <BackwardRules edge={edge} fromLabel={fromList?.label ?? edge.from} toLabel={toList?.label ?? edge.to} />;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
return <ForwardRules edge={edge} fromLabel={fromList?.label ?? edge.from} toLabel={toList?.label ?? edge.to} />;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
// ─── Sub-panels ─────────────────────────────────────────
|
|
37
|
-
|
|
38
|
-
function ShortcutRules({ sortedLists, fromOrder, toOrder, edge }: {
|
|
39
|
-
sortedLists: WorkflowList[];
|
|
40
|
-
fromOrder: number;
|
|
41
|
-
toOrder: number;
|
|
42
|
-
edge: WorkflowEdge;
|
|
43
|
-
}) {
|
|
44
|
-
const skippedLists = sortedLists.filter(
|
|
45
|
-
(l) => l.order > Math.min(fromOrder, toOrder) && l.order < Math.max(fromOrder, toOrder),
|
|
46
|
-
);
|
|
47
|
-
|
|
48
|
-
return (
|
|
49
|
-
<div className="space-y-2">
|
|
50
|
-
<RuleHeader icon={CornerRightDown} color="#6366f1" label="Shortcut — Skip Rules" />
|
|
51
|
-
{/* Mini diagram */}
|
|
52
|
-
<div className="flex items-center gap-1 rounded border border-zinc-800 bg-zinc-950/50 px-2.5 py-2 overflow-x-auto">
|
|
53
|
-
{sortedLists.map((list, i) => {
|
|
54
|
-
const isFrom = list.id === edge.from;
|
|
55
|
-
const isTo = list.id === edge.to;
|
|
56
|
-
const isSkipped = skippedLists.some((s) => s.id === list.id);
|
|
57
|
-
return (
|
|
58
|
-
<div key={list.id} className="flex items-center gap-1">
|
|
59
|
-
<span
|
|
60
|
-
className="rounded px-1.5 py-0.5 text-[8px] font-medium whitespace-nowrap"
|
|
61
|
-
style={{
|
|
62
|
-
backgroundColor: isFrom || isTo ? '#6366f120' : isSkipped ? '#27272a' : '#18181b',
|
|
63
|
-
color: isFrom || isTo ? '#818cf8' : isSkipped ? '#52525b' : '#71717a',
|
|
64
|
-
border: isFrom || isTo ? '1px solid #6366f140' : '1px solid transparent',
|
|
65
|
-
textDecoration: isSkipped ? 'line-through' : 'none',
|
|
66
|
-
}}
|
|
67
|
-
>
|
|
68
|
-
{list.label}
|
|
69
|
-
</span>
|
|
70
|
-
{i < sortedLists.length - 1 && (
|
|
71
|
-
<span className="text-[8px] text-zinc-700">›</span>
|
|
72
|
-
)}
|
|
73
|
-
</div>
|
|
74
|
-
);
|
|
75
|
-
})}
|
|
76
|
-
</div>
|
|
77
|
-
{skippedLists.length > 0 ? (
|
|
78
|
-
<p className="text-[9px] text-zinc-500">
|
|
79
|
-
<span className="text-indigo-400">{edge.from}</span>
|
|
80
|
-
{' → '}
|
|
81
|
-
<span className="text-indigo-400">{edge.to}</span>
|
|
82
|
-
{' skips '}
|
|
83
|
-
<span className="text-zinc-400">{skippedLists.map((l) => l.label).join(', ')}</span>
|
|
84
|
-
</p>
|
|
85
|
-
) : (
|
|
86
|
-
<p className="text-[9px] text-zinc-500">No intermediate lists are skipped.</p>
|
|
87
|
-
)}
|
|
88
|
-
</div>
|
|
89
|
-
);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
function BackwardRules({ edge, fromLabel, toLabel }: {
|
|
93
|
-
edge: WorkflowEdge;
|
|
94
|
-
fromLabel: string;
|
|
95
|
-
toLabel: string;
|
|
96
|
-
}) {
|
|
97
|
-
const suggestedItems = [
|
|
98
|
-
'Issue documented',
|
|
99
|
-
'Fix scope created',
|
|
100
|
-
'Root cause identified',
|
|
101
|
-
];
|
|
102
|
-
|
|
103
|
-
return (
|
|
104
|
-
<div className="space-y-2">
|
|
105
|
-
<RuleHeader icon={ArrowLeft} color="#f59e0b" label="Backward — Revert Rules" />
|
|
106
|
-
<div className="flex items-center gap-2 rounded border border-amber-500/20 bg-amber-500/5 px-2.5 py-2">
|
|
107
|
-
<span className="rounded bg-amber-500/20 px-1.5 py-0.5 text-[9px] font-medium text-amber-400">
|
|
108
|
-
{fromLabel}
|
|
109
|
-
</span>
|
|
110
|
-
<svg width="24" height="12" viewBox="0 0 24 12" className="shrink-0">
|
|
111
|
-
<line x1="20" y1="6" x2="4" y2="6" stroke="#f59e0b" strokeWidth="1.5" strokeDasharray="2 2" />
|
|
112
|
-
<polygon points="4,6 8,3 8,9" fill="#f59e0b" />
|
|
113
|
-
</svg>
|
|
114
|
-
<span className="rounded bg-amber-500/20 px-1.5 py-0.5 text-[9px] font-medium text-amber-400">
|
|
115
|
-
{toLabel}
|
|
116
|
-
</span>
|
|
117
|
-
<span className="ml-auto rounded bg-amber-500/15 px-1.5 py-0.5 text-[8px] font-semibold text-amber-400">
|
|
118
|
-
REPAIR
|
|
119
|
-
</span>
|
|
120
|
-
</div>
|
|
121
|
-
<p className="text-[9px] text-zinc-500">
|
|
122
|
-
{fromLabel} → {toLabel} is a <span className="text-amber-400">repair</span> operation.
|
|
123
|
-
Scopes move backward for rework.
|
|
124
|
-
</p>
|
|
125
|
-
{/* Suggested checklist items */}
|
|
126
|
-
{(!edge.checklist || edge.checklist.length === 0) && (
|
|
127
|
-
<div className="rounded border border-zinc-800 bg-zinc-950/50 p-2">
|
|
128
|
-
<div className="flex items-center gap-1 mb-1.5">
|
|
129
|
-
<Info className="h-3 w-3 text-zinc-600" />
|
|
130
|
-
<span className="text-[9px] font-medium text-zinc-500">Suggested checklist items</span>
|
|
131
|
-
</div>
|
|
132
|
-
<ul className="space-y-0.5">
|
|
133
|
-
{suggestedItems.map((item) => (
|
|
134
|
-
<li key={item} className="text-[9px] text-zinc-600 flex items-center gap-1.5">
|
|
135
|
-
<span className="h-1 w-1 rounded-full bg-zinc-700 shrink-0" />
|
|
136
|
-
{item}
|
|
137
|
-
</li>
|
|
138
|
-
))}
|
|
139
|
-
</ul>
|
|
140
|
-
</div>
|
|
141
|
-
)}
|
|
142
|
-
</div>
|
|
143
|
-
);
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
function ForwardRules({ edge, fromLabel, toLabel }: {
|
|
147
|
-
edge: WorkflowEdge;
|
|
148
|
-
fromLabel: string;
|
|
149
|
-
toLabel: string;
|
|
150
|
-
}) {
|
|
151
|
-
return (
|
|
152
|
-
<div className="space-y-2">
|
|
153
|
-
<RuleHeader icon={ArrowRight} color="#22c55e" label="Forward — Progression" />
|
|
154
|
-
<div className="flex items-center gap-2 rounded border border-emerald-500/20 bg-emerald-500/5 px-2.5 py-2">
|
|
155
|
-
<span className="rounded bg-emerald-500/20 px-1.5 py-0.5 text-[9px] font-medium text-emerald-400">
|
|
156
|
-
{fromLabel}
|
|
157
|
-
</span>
|
|
158
|
-
<svg width="24" height="12" viewBox="0 0 24 12" className="shrink-0">
|
|
159
|
-
<line x1="4" y1="6" x2="20" y2="6" stroke="#22c55e" strokeWidth="1.5" />
|
|
160
|
-
<polygon points="20,6 16,3 16,9" fill="#22c55e" />
|
|
161
|
-
</svg>
|
|
162
|
-
<span className="rounded bg-emerald-500/20 px-1.5 py-0.5 text-[9px] font-medium text-emerald-400">
|
|
163
|
-
{toLabel}
|
|
164
|
-
</span>
|
|
165
|
-
</div>
|
|
166
|
-
{edge.dispatchOnly && (
|
|
167
|
-
<p className="text-[9px] text-zinc-500">
|
|
168
|
-
This transition requires a <span className="text-cyan-400">skill command</span> to trigger.
|
|
169
|
-
</p>
|
|
170
|
-
)}
|
|
171
|
-
</div>
|
|
172
|
-
);
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
// ─── Shared ─────────────────────────────────────────────
|
|
176
|
-
|
|
177
|
-
function RuleHeader({ icon: Icon, color, label }: {
|
|
178
|
-
icon: React.ComponentType<{ className?: string; style?: React.CSSProperties }>;
|
|
179
|
-
color: string;
|
|
180
|
-
label: string;
|
|
181
|
-
}) {
|
|
182
|
-
return (
|
|
183
|
-
<div className="flex items-center gap-1.5">
|
|
184
|
-
<Icon className="h-3 w-3" style={{ color }} />
|
|
185
|
-
<span className="text-[10px] font-semibold" style={{ color }}>{label}</span>
|
|
186
|
-
</div>
|
|
187
|
-
);
|
|
188
|
-
}
|
|
@@ -1,245 +0,0 @@
|
|
|
1
|
-
import { useMemo } from 'react';
|
|
2
|
-
import { X, Star, Package, Zap, GitBranch, Key, Shield, Terminal, Radio, Globe, ShieldCheck, AlertTriangle, Cog, Eye } from 'lucide-react';
|
|
3
|
-
import type { WorkflowList, WorkflowHook, WorkflowEdge, HookCategory, HookEnforcement } from '../../../shared/workflow-config';
|
|
4
|
-
import { getHookEnforcement } from '../../../shared/workflow-config';
|
|
5
|
-
|
|
6
|
-
interface NodeDetailPanelProps {
|
|
7
|
-
list: WorkflowList | null;
|
|
8
|
-
hooks: WorkflowHook[];
|
|
9
|
-
connectedEdges: WorkflowEdge[];
|
|
10
|
-
onClose: () => void;
|
|
11
|
-
onHookClick?: (hook: WorkflowHook) => void;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
const CATEGORY_CONFIG: Record<HookCategory, { icon: typeof Shield; color: string; label: string }> = {
|
|
15
|
-
guard: { icon: ShieldCheck, color: '#ef4444', label: 'Guards' },
|
|
16
|
-
gate: { icon: AlertTriangle, color: '#f59e0b', label: 'Gates' },
|
|
17
|
-
lifecycle: { icon: Cog, color: '#3b82f6', label: 'Lifecycle' },
|
|
18
|
-
observer: { icon: Eye, color: '#6b7280', label: 'Observers' },
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
const CATEGORY_ORDER: HookCategory[] = ['guard', 'gate', 'lifecycle', 'observer'];
|
|
22
|
-
|
|
23
|
-
const ENFORCEMENT_COLORS: Record<HookEnforcement, string> = {
|
|
24
|
-
blocker: '#ef4444',
|
|
25
|
-
advisor: '#f59e0b',
|
|
26
|
-
operator: '#3b82f6',
|
|
27
|
-
silent: '#6b7280',
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
export function NodeDetailPanel({ list, hooks, connectedEdges, onClose, onHookClick }: NodeDetailPanelProps) {
|
|
31
|
-
if (!list) return null;
|
|
32
|
-
|
|
33
|
-
const inbound = connectedEdges.filter((e) => e.to === list.id);
|
|
34
|
-
const outbound = connectedEdges.filter((e) => e.from === list.id);
|
|
35
|
-
|
|
36
|
-
// Group hooks by category
|
|
37
|
-
const grouped = useMemo(() => {
|
|
38
|
-
const groups = new Map<HookCategory, WorkflowHook[]>();
|
|
39
|
-
for (const hook of hooks) {
|
|
40
|
-
const existing = groups.get(hook.category);
|
|
41
|
-
if (existing) existing.push(hook);
|
|
42
|
-
else groups.set(hook.category, [hook]);
|
|
43
|
-
}
|
|
44
|
-
return groups;
|
|
45
|
-
}, [hooks]);
|
|
46
|
-
|
|
47
|
-
return (
|
|
48
|
-
<div className="flex h-full w-80 shrink-0 flex-col rounded-lg border border-zinc-800 bg-zinc-900/95 backdrop-blur">
|
|
49
|
-
{/* Header */}
|
|
50
|
-
<div className="flex items-center justify-between border-b border-zinc-800 px-4 py-3">
|
|
51
|
-
<div className="flex items-center gap-2">
|
|
52
|
-
<div className="h-3 w-3 rounded-full" style={{ backgroundColor: list.hex }} />
|
|
53
|
-
<span className="text-sm font-medium">{list.label}</span>
|
|
54
|
-
</div>
|
|
55
|
-
<button onClick={onClose} className="rounded p-1 text-zinc-500 hover:bg-zinc-800 hover:text-zinc-300">
|
|
56
|
-
<X className="h-4 w-4" />
|
|
57
|
-
</button>
|
|
58
|
-
</div>
|
|
59
|
-
|
|
60
|
-
{/* Content */}
|
|
61
|
-
<div className="flex-1 space-y-4 overflow-y-auto p-4 text-xs">
|
|
62
|
-
{/* Properties */}
|
|
63
|
-
<Section title="Properties">
|
|
64
|
-
<PropRow label="ID" value={list.id} />
|
|
65
|
-
<PropRow label="Order" value={String(list.order)} />
|
|
66
|
-
{list.group && <PropRow label="Group" value={list.group} />}
|
|
67
|
-
<PropRow label="Color" value={list.hex} />
|
|
68
|
-
</Section>
|
|
69
|
-
|
|
70
|
-
{/* Flags */}
|
|
71
|
-
<Section title="Flags">
|
|
72
|
-
<div className="flex flex-wrap gap-2">
|
|
73
|
-
{list.isEntryPoint && <FlagBadge icon={Star} label="Entry Point" color={list.hex} />}
|
|
74
|
-
{list.supportsBatch && <FlagBadge icon={Package} label="Batch" color="#22c55e" />}
|
|
75
|
-
{list.supportsSprint && <FlagBadge icon={Zap} label="Sprint" color="#6366f1" />}
|
|
76
|
-
{list.gitBranch && <FlagBadge icon={GitBranch} label={list.gitBranch} color="#f59e0b" />}
|
|
77
|
-
{list.sessionKey && <FlagBadge icon={Key} label={list.sessionKey} color="#8b5cf6" />}
|
|
78
|
-
</div>
|
|
79
|
-
{!list.isEntryPoint && !list.supportsBatch && !list.supportsSprint && !list.gitBranch && !list.sessionKey && (
|
|
80
|
-
<span className="text-zinc-600">None</span>
|
|
81
|
-
)}
|
|
82
|
-
</Section>
|
|
83
|
-
|
|
84
|
-
{/* Inbound edges */}
|
|
85
|
-
<Section title={`Inbound (${inbound.length})`}>
|
|
86
|
-
{inbound.length === 0 ? (
|
|
87
|
-
<span className="text-zinc-600">None</span>
|
|
88
|
-
) : (
|
|
89
|
-
inbound.map((e) => <EdgeRow key={`${e.from}:${e.to}`} edge={e} showField="from" />)
|
|
90
|
-
)}
|
|
91
|
-
</Section>
|
|
92
|
-
|
|
93
|
-
{/* Outbound edges */}
|
|
94
|
-
<Section title={`Outbound (${outbound.length})`}>
|
|
95
|
-
{outbound.length === 0 ? (
|
|
96
|
-
<span className="text-zinc-600">None</span>
|
|
97
|
-
) : (
|
|
98
|
-
outbound.map((e) => <EdgeRow key={`${e.from}:${e.to}`} edge={e} showField="to" />)
|
|
99
|
-
)}
|
|
100
|
-
</Section>
|
|
101
|
-
|
|
102
|
-
{/* Hooks grouped by category */}
|
|
103
|
-
{hooks.length > 0 && (
|
|
104
|
-
<Section title={`Hooks (${hooks.length})`}>
|
|
105
|
-
<div className="space-y-3">
|
|
106
|
-
{CATEGORY_ORDER.map((cat) => {
|
|
107
|
-
const catHooks = grouped.get(cat);
|
|
108
|
-
if (!catHooks?.length) return null;
|
|
109
|
-
const config = CATEGORY_CONFIG[cat];
|
|
110
|
-
const CatIcon = config.icon;
|
|
111
|
-
return (
|
|
112
|
-
<div key={cat}>
|
|
113
|
-
<div className="mb-1.5 flex items-center gap-1.5">
|
|
114
|
-
<CatIcon className="h-2.5 w-2.5" style={{ color: config.color }} />
|
|
115
|
-
<span className="text-[9px] font-semibold uppercase tracking-wider" style={{ color: config.color }}>
|
|
116
|
-
{config.label}
|
|
117
|
-
</span>
|
|
118
|
-
</div>
|
|
119
|
-
{catHooks.map((h) => (
|
|
120
|
-
<NodeHookDetail key={h.id} hook={h} onClick={onHookClick} />
|
|
121
|
-
))}
|
|
122
|
-
</div>
|
|
123
|
-
);
|
|
124
|
-
})}
|
|
125
|
-
</div>
|
|
126
|
-
</Section>
|
|
127
|
-
)}
|
|
128
|
-
</div>
|
|
129
|
-
</div>
|
|
130
|
-
);
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
// ─── Sub-components ─────────────────────────────────────
|
|
134
|
-
|
|
135
|
-
function Section({ title, children }: { title: string; children: React.ReactNode }) {
|
|
136
|
-
return (
|
|
137
|
-
<div>
|
|
138
|
-
<h4 className="mb-2 text-[10px] font-semibold uppercase tracking-wider text-zinc-500">{title}</h4>
|
|
139
|
-
<div className="space-y-1.5">{children}</div>
|
|
140
|
-
</div>
|
|
141
|
-
);
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
function PropRow({ label, value }: { label: string; value: string }) {
|
|
145
|
-
return (
|
|
146
|
-
<div className="flex items-center justify-between">
|
|
147
|
-
<span className="text-zinc-500">{label}</span>
|
|
148
|
-
<span className="font-mono text-zinc-300">{value}</span>
|
|
149
|
-
</div>
|
|
150
|
-
);
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
function FlagBadge({ icon: Icon, label, color }: { icon: React.ComponentType<{ className?: string }>; label: string; color: string }) {
|
|
154
|
-
return (
|
|
155
|
-
<span className="flex items-center gap-1 rounded px-1.5 py-0.5 text-[10px]" style={{ backgroundColor: `${color}15`, color }}>
|
|
156
|
-
<Icon className="h-3 w-3" />
|
|
157
|
-
{label}
|
|
158
|
-
</span>
|
|
159
|
-
);
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
const TIMING_COLORS: Record<string, string> = {
|
|
163
|
-
before: '#eab308',
|
|
164
|
-
after: '#3b82f6',
|
|
165
|
-
};
|
|
166
|
-
|
|
167
|
-
const TYPE_COLORS: Record<string, string> = {
|
|
168
|
-
shell: '#22c55e',
|
|
169
|
-
event: '#a855f7',
|
|
170
|
-
webhook: '#f97316',
|
|
171
|
-
};
|
|
172
|
-
|
|
173
|
-
const TYPE_ICONS: Record<string, typeof Terminal> = {
|
|
174
|
-
shell: Terminal,
|
|
175
|
-
event: Radio,
|
|
176
|
-
webhook: Globe,
|
|
177
|
-
};
|
|
178
|
-
|
|
179
|
-
function NodeHookDetail({ hook, onClick }: { hook: WorkflowHook; onClick?: (hook: WorkflowHook) => void }) {
|
|
180
|
-
const timingColor = TIMING_COLORS[hook.timing] ?? '#3b82f6';
|
|
181
|
-
const typeColor = TYPE_COLORS[hook.type] ?? '#22c55e';
|
|
182
|
-
const TypeIcon = TYPE_ICONS[hook.type] ?? Terminal;
|
|
183
|
-
const enforcement = getHookEnforcement(hook);
|
|
184
|
-
const enforcementColor = ENFORCEMENT_COLORS[enforcement];
|
|
185
|
-
const catConfig = CATEGORY_CONFIG[hook.category];
|
|
186
|
-
const CatIcon = catConfig.icon;
|
|
187
|
-
|
|
188
|
-
return (
|
|
189
|
-
<button
|
|
190
|
-
onClick={() => onClick?.(hook)}
|
|
191
|
-
className="w-full rounded border bg-zinc-950/50 p-2 text-left transition-colors hover:border-zinc-600 hover:bg-zinc-900/70"
|
|
192
|
-
style={{ borderColor: hook.blocking ? '#ef444466' : '#27272a' }}
|
|
193
|
-
>
|
|
194
|
-
<div className="flex items-center gap-2">
|
|
195
|
-
<CatIcon className="h-2.5 w-2.5" style={{ color: catConfig.color }} />
|
|
196
|
-
<span className="text-zinc-300">{hook.label}</span>
|
|
197
|
-
<span
|
|
198
|
-
className="ml-auto rounded px-1 py-0.5 text-[8px] font-bold uppercase"
|
|
199
|
-
style={{ backgroundColor: `${enforcementColor}20`, color: enforcementColor }}
|
|
200
|
-
>
|
|
201
|
-
{enforcement}
|
|
202
|
-
</span>
|
|
203
|
-
</div>
|
|
204
|
-
<div className="mt-1.5 flex flex-wrap items-center gap-1">
|
|
205
|
-
<span
|
|
206
|
-
className="rounded px-1.5 py-0.5 text-[9px] font-semibold uppercase"
|
|
207
|
-
style={{ backgroundColor: `${timingColor}20`, color: timingColor }}
|
|
208
|
-
>
|
|
209
|
-
{hook.timing}
|
|
210
|
-
</span>
|
|
211
|
-
<span
|
|
212
|
-
className="flex items-center gap-0.5 rounded px-1.5 py-0.5 text-[9px] font-semibold uppercase"
|
|
213
|
-
style={{ backgroundColor: `${typeColor}20`, color: typeColor }}
|
|
214
|
-
>
|
|
215
|
-
<TypeIcon className="h-2.5 w-2.5" />
|
|
216
|
-
{hook.type}
|
|
217
|
-
</span>
|
|
218
|
-
</div>
|
|
219
|
-
<div className="mt-1.5 flex items-center gap-1.5 rounded border border-zinc-800 bg-zinc-900 px-2 py-1 font-mono text-[10px] text-zinc-400">
|
|
220
|
-
<TypeIcon className="h-3 w-3 shrink-0 text-zinc-600" />
|
|
221
|
-
<span className="truncate">{hook.target}</span>
|
|
222
|
-
</div>
|
|
223
|
-
{hook.description && <p className="mt-1 text-zinc-500">{hook.description}</p>}
|
|
224
|
-
</button>
|
|
225
|
-
);
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
const DIRECTION_COLORS: Record<string, string> = {
|
|
229
|
-
forward: '#22c55e',
|
|
230
|
-
backward: '#f59e0b',
|
|
231
|
-
shortcut: '#6366f1',
|
|
232
|
-
};
|
|
233
|
-
|
|
234
|
-
function EdgeRow({ edge, showField }: { edge: WorkflowEdge; showField: 'from' | 'to' }) {
|
|
235
|
-
const color = DIRECTION_COLORS[edge.direction] ?? '#22c55e';
|
|
236
|
-
return (
|
|
237
|
-
<div className="flex items-center gap-2 rounded border border-zinc-800/50 bg-zinc-950/30 px-2 py-1.5">
|
|
238
|
-
<span className="rounded px-1 py-0.5 text-[9px] uppercase" style={{ backgroundColor: `${color}20`, color }}>
|
|
239
|
-
{edge.direction}
|
|
240
|
-
</span>
|
|
241
|
-
<span className="text-zinc-400">{showField === 'from' ? edge.from : edge.to}</span>
|
|
242
|
-
<span className="ml-auto text-zinc-600">{edge.label}</span>
|
|
243
|
-
</div>
|
|
244
|
-
);
|
|
245
|
-
}
|