orbital-command 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (325) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +396 -0
  3. package/bin/orbital.js +362 -0
  4. package/dist/assets/WorkflowVisualizer-BZ21PIIF.js +84 -0
  5. package/dist/assets/WorkflowVisualizer-BZV40eAE.css +1 -0
  6. package/dist/assets/charts-D__PA1zp.js +72 -0
  7. package/dist/assets/index-D1G6i0nS.css +1 -0
  8. package/dist/assets/index-DpItvKpf.js +419 -0
  9. package/dist/assets/ui-BvF022GT.js +53 -0
  10. package/dist/assets/vendor-Dzv9lrRc.js +59 -0
  11. package/dist/index.html +19 -0
  12. package/dist/scanner-sweep.png +0 -0
  13. package/dist/server/server/adapters/index.js +34 -0
  14. package/dist/server/server/adapters/iterm2-adapter.js +29 -0
  15. package/dist/server/server/adapters/subprocess-adapter.js +21 -0
  16. package/dist/server/server/adapters/terminal-adapter.js +1 -0
  17. package/dist/server/server/config.js +156 -0
  18. package/dist/server/server/database.js +90 -0
  19. package/dist/server/server/index.js +372 -0
  20. package/dist/server/server/init.js +811 -0
  21. package/dist/server/server/parsers/event-parser.js +64 -0
  22. package/dist/server/server/parsers/scope-parser.js +188 -0
  23. package/dist/server/server/routes/config-routes.js +163 -0
  24. package/dist/server/server/routes/data-routes.js +461 -0
  25. package/dist/server/server/routes/dispatch-routes.js +215 -0
  26. package/dist/server/server/routes/git-routes.js +92 -0
  27. package/dist/server/server/routes/scope-routes.js +215 -0
  28. package/dist/server/server/routes/sprint-routes.js +116 -0
  29. package/dist/server/server/routes/version-routes.js +130 -0
  30. package/dist/server/server/routes/workflow-routes.js +185 -0
  31. package/dist/server/server/schema.js +90 -0
  32. package/dist/server/server/services/batch-orchestrator.js +253 -0
  33. package/dist/server/server/services/claude-session-service.js +352 -0
  34. package/dist/server/server/services/config-service.js +132 -0
  35. package/dist/server/server/services/deploy-service.js +51 -0
  36. package/dist/server/server/services/event-service.js +63 -0
  37. package/dist/server/server/services/gate-service.js +83 -0
  38. package/dist/server/server/services/git-service.js +309 -0
  39. package/dist/server/server/services/github-service.js +145 -0
  40. package/dist/server/server/services/readiness-service.js +184 -0
  41. package/dist/server/server/services/scope-cache.js +72 -0
  42. package/dist/server/server/services/scope-service.js +424 -0
  43. package/dist/server/server/services/sprint-orchestrator.js +312 -0
  44. package/dist/server/server/services/sprint-service.js +293 -0
  45. package/dist/server/server/services/workflow-service.js +397 -0
  46. package/dist/server/server/utils/cc-hooks-parser.js +49 -0
  47. package/dist/server/server/utils/dispatch-utils.js +305 -0
  48. package/dist/server/server/utils/logger.js +86 -0
  49. package/dist/server/server/utils/terminal-launcher.js +388 -0
  50. package/dist/server/server/utils/worktree-manager.js +98 -0
  51. package/dist/server/server/watchers/event-watcher.js +81 -0
  52. package/dist/server/server/watchers/scope-watcher.js +33 -0
  53. package/dist/server/shared/api-types.js +5 -0
  54. package/dist/server/shared/default-workflow.json +616 -0
  55. package/dist/server/shared/workflow-config.js +44 -0
  56. package/dist/server/shared/workflow-engine.js +353 -0
  57. package/index.html +15 -0
  58. package/package.json +110 -0
  59. package/postcss.config.js +6 -0
  60. package/schemas/orbital.config.schema.json +83 -0
  61. package/scripts/postinstall.js +24 -0
  62. package/scripts/start.sh +20 -0
  63. package/server/adapters/index.ts +41 -0
  64. package/server/adapters/iterm2-adapter.ts +37 -0
  65. package/server/adapters/subprocess-adapter.ts +25 -0
  66. package/server/adapters/terminal-adapter.ts +24 -0
  67. package/server/config.ts +234 -0
  68. package/server/database.ts +107 -0
  69. package/server/index.ts +452 -0
  70. package/server/init.ts +891 -0
  71. package/server/parsers/event-parser.ts +74 -0
  72. package/server/parsers/scope-parser.ts +240 -0
  73. package/server/routes/config-routes.ts +182 -0
  74. package/server/routes/data-routes.ts +548 -0
  75. package/server/routes/dispatch-routes.ts +275 -0
  76. package/server/routes/git-routes.ts +112 -0
  77. package/server/routes/scope-routes.ts +262 -0
  78. package/server/routes/sprint-routes.ts +142 -0
  79. package/server/routes/version-routes.ts +156 -0
  80. package/server/routes/workflow-routes.ts +198 -0
  81. package/server/schema.ts +90 -0
  82. package/server/services/batch-orchestrator.ts +286 -0
  83. package/server/services/claude-session-service.ts +441 -0
  84. package/server/services/config-service.ts +151 -0
  85. package/server/services/deploy-service.ts +98 -0
  86. package/server/services/event-service.ts +98 -0
  87. package/server/services/gate-service.ts +126 -0
  88. package/server/services/git-service.ts +391 -0
  89. package/server/services/github-service.ts +183 -0
  90. package/server/services/readiness-service.ts +250 -0
  91. package/server/services/scope-cache.ts +81 -0
  92. package/server/services/scope-service.ts +476 -0
  93. package/server/services/sprint-orchestrator.ts +361 -0
  94. package/server/services/sprint-service.ts +415 -0
  95. package/server/services/workflow-service.ts +461 -0
  96. package/server/utils/cc-hooks-parser.ts +70 -0
  97. package/server/utils/dispatch-utils.ts +395 -0
  98. package/server/utils/logger.ts +109 -0
  99. package/server/utils/terminal-launcher.ts +462 -0
  100. package/server/utils/worktree-manager.ts +104 -0
  101. package/server/watchers/event-watcher.ts +100 -0
  102. package/server/watchers/scope-watcher.ts +38 -0
  103. package/shared/api-types.ts +20 -0
  104. package/shared/default-workflow.json +616 -0
  105. package/shared/workflow-config.ts +170 -0
  106. package/shared/workflow-engine.ts +427 -0
  107. package/src/App.tsx +33 -0
  108. package/src/components/AgentBadge.tsx +40 -0
  109. package/src/components/BatchPreflightModal.tsx +115 -0
  110. package/src/components/CardDisplayToggle.tsx +74 -0
  111. package/src/components/ColumnHeaderActions.tsx +55 -0
  112. package/src/components/ColumnMenu.tsx +99 -0
  113. package/src/components/DeployHistory.tsx +141 -0
  114. package/src/components/DispatchModal.tsx +164 -0
  115. package/src/components/DispatchPopover.tsx +139 -0
  116. package/src/components/DragOverlay.tsx +25 -0
  117. package/src/components/DriftSidebar.tsx +140 -0
  118. package/src/components/EnvironmentStrip.tsx +88 -0
  119. package/src/components/ErrorBoundary.tsx +62 -0
  120. package/src/components/FilterChip.tsx +105 -0
  121. package/src/components/GateIndicator.tsx +33 -0
  122. package/src/components/IdeaDetailModal.tsx +190 -0
  123. package/src/components/IdeaFormDialog.tsx +113 -0
  124. package/src/components/KanbanColumn.tsx +201 -0
  125. package/src/components/MarkdownRenderer.tsx +114 -0
  126. package/src/components/NeonGrid.tsx +128 -0
  127. package/src/components/PromotionQueue.tsx +89 -0
  128. package/src/components/ScopeCard.tsx +234 -0
  129. package/src/components/ScopeDetailModal.tsx +255 -0
  130. package/src/components/ScopeFilterBar.tsx +152 -0
  131. package/src/components/SearchInput.tsx +102 -0
  132. package/src/components/SessionPanel.tsx +335 -0
  133. package/src/components/SprintContainer.tsx +303 -0
  134. package/src/components/SprintDependencyDialog.tsx +78 -0
  135. package/src/components/SprintPreflightModal.tsx +138 -0
  136. package/src/components/StatusBar.tsx +168 -0
  137. package/src/components/SwimCell.tsx +67 -0
  138. package/src/components/SwimLaneRow.tsx +94 -0
  139. package/src/components/SwimlaneBoardView.tsx +108 -0
  140. package/src/components/VersionBadge.tsx +139 -0
  141. package/src/components/ViewModeSelector.tsx +114 -0
  142. package/src/components/config/AgentChip.tsx +53 -0
  143. package/src/components/config/AgentCreateDialog.tsx +321 -0
  144. package/src/components/config/AgentEditor.tsx +175 -0
  145. package/src/components/config/DirectoryTree.tsx +582 -0
  146. package/src/components/config/FileEditor.tsx +550 -0
  147. package/src/components/config/HookChip.tsx +50 -0
  148. package/src/components/config/StageCard.tsx +198 -0
  149. package/src/components/config/TransitionZone.tsx +173 -0
  150. package/src/components/config/UnifiedWorkflowPipeline.tsx +216 -0
  151. package/src/components/config/WorkflowPipeline.tsx +161 -0
  152. package/src/components/source-control/BranchList.tsx +93 -0
  153. package/src/components/source-control/BranchPanel.tsx +105 -0
  154. package/src/components/source-control/CommitLog.tsx +100 -0
  155. package/src/components/source-control/CommitRow.tsx +47 -0
  156. package/src/components/source-control/GitHubPanel.tsx +110 -0
  157. package/src/components/source-control/GitHubSetupGuide.tsx +52 -0
  158. package/src/components/source-control/GitOverviewBar.tsx +101 -0
  159. package/src/components/source-control/PullRequestList.tsx +69 -0
  160. package/src/components/source-control/WorktreeList.tsx +80 -0
  161. package/src/components/ui/badge.tsx +41 -0
  162. package/src/components/ui/button.tsx +55 -0
  163. package/src/components/ui/card.tsx +78 -0
  164. package/src/components/ui/dialog.tsx +94 -0
  165. package/src/components/ui/popover.tsx +33 -0
  166. package/src/components/ui/scroll-area.tsx +54 -0
  167. package/src/components/ui/separator.tsx +28 -0
  168. package/src/components/ui/tabs.tsx +52 -0
  169. package/src/components/ui/toggle-switch.tsx +35 -0
  170. package/src/components/ui/tooltip.tsx +27 -0
  171. package/src/components/workflow/AddEdgeDialog.tsx +217 -0
  172. package/src/components/workflow/AddListDialog.tsx +201 -0
  173. package/src/components/workflow/ChecklistEditor.tsx +239 -0
  174. package/src/components/workflow/CommandPrefixManager.tsx +118 -0
  175. package/src/components/workflow/ConfigSettingsPanel.tsx +189 -0
  176. package/src/components/workflow/DirectionSelector.tsx +133 -0
  177. package/src/components/workflow/DispatchConfigPanel.tsx +180 -0
  178. package/src/components/workflow/EdgeDetailPanel.tsx +236 -0
  179. package/src/components/workflow/EdgePropertyEditor.tsx +251 -0
  180. package/src/components/workflow/EditToolbar.tsx +138 -0
  181. package/src/components/workflow/HookDetailPanel.tsx +250 -0
  182. package/src/components/workflow/HookExecutionLog.tsx +24 -0
  183. package/src/components/workflow/HookSourceModal.tsx +129 -0
  184. package/src/components/workflow/HooksDashboard.tsx +363 -0
  185. package/src/components/workflow/ListPropertyEditor.tsx +251 -0
  186. package/src/components/workflow/MigrationPreviewDialog.tsx +237 -0
  187. package/src/components/workflow/MovementRulesPanel.tsx +188 -0
  188. package/src/components/workflow/NodeDetailPanel.tsx +245 -0
  189. package/src/components/workflow/PresetSelector.tsx +414 -0
  190. package/src/components/workflow/SkillCommandBuilder.tsx +174 -0
  191. package/src/components/workflow/WorkflowEdgeComponent.tsx +145 -0
  192. package/src/components/workflow/WorkflowNode.tsx +147 -0
  193. package/src/components/workflow/graphLayout.ts +186 -0
  194. package/src/components/workflow/mergeHooks.ts +85 -0
  195. package/src/components/workflow/useEditHistory.ts +88 -0
  196. package/src/components/workflow/useWorkflowEditor.ts +262 -0
  197. package/src/components/workflow/validateConfig.ts +70 -0
  198. package/src/hooks/useActiveDispatches.ts +198 -0
  199. package/src/hooks/useBoardSettings.ts +170 -0
  200. package/src/hooks/useCardDisplay.ts +57 -0
  201. package/src/hooks/useCcHooks.ts +24 -0
  202. package/src/hooks/useConfigTree.ts +51 -0
  203. package/src/hooks/useEnforcementRules.ts +46 -0
  204. package/src/hooks/useEvents.ts +59 -0
  205. package/src/hooks/useFileEditor.ts +165 -0
  206. package/src/hooks/useGates.ts +57 -0
  207. package/src/hooks/useIdeaActions.ts +53 -0
  208. package/src/hooks/useKanbanDnd.ts +410 -0
  209. package/src/hooks/useOrbitalConfig.ts +54 -0
  210. package/src/hooks/usePipeline.ts +47 -0
  211. package/src/hooks/usePipelineData.ts +338 -0
  212. package/src/hooks/useReconnect.ts +25 -0
  213. package/src/hooks/useScopeFilters.ts +125 -0
  214. package/src/hooks/useScopeSessions.ts +44 -0
  215. package/src/hooks/useScopes.ts +67 -0
  216. package/src/hooks/useSearch.ts +67 -0
  217. package/src/hooks/useSettings.tsx +187 -0
  218. package/src/hooks/useSocket.ts +25 -0
  219. package/src/hooks/useSourceControl.ts +105 -0
  220. package/src/hooks/useSprintPreflight.ts +55 -0
  221. package/src/hooks/useSprints.ts +154 -0
  222. package/src/hooks/useStatusBarHighlight.ts +18 -0
  223. package/src/hooks/useSwimlaneBoardSettings.ts +104 -0
  224. package/src/hooks/useTheme.ts +9 -0
  225. package/src/hooks/useTransitionReadiness.ts +53 -0
  226. package/src/hooks/useVersion.ts +155 -0
  227. package/src/hooks/useViolations.ts +65 -0
  228. package/src/hooks/useWorkflow.tsx +125 -0
  229. package/src/hooks/useZoomModifier.ts +19 -0
  230. package/src/index.css +797 -0
  231. package/src/layouts/DashboardLayout.tsx +113 -0
  232. package/src/lib/collisionDetection.ts +20 -0
  233. package/src/lib/scope-fields.ts +61 -0
  234. package/src/lib/swimlane.ts +146 -0
  235. package/src/lib/utils.ts +15 -0
  236. package/src/main.tsx +19 -0
  237. package/src/socket.ts +11 -0
  238. package/src/types/index.ts +497 -0
  239. package/src/views/AgentFeed.tsx +339 -0
  240. package/src/views/DeployPipeline.tsx +59 -0
  241. package/src/views/EnforcementView.tsx +378 -0
  242. package/src/views/PrimitivesConfig.tsx +500 -0
  243. package/src/views/QualityGates.tsx +1012 -0
  244. package/src/views/ScopeBoard.tsx +454 -0
  245. package/src/views/SessionTimeline.tsx +516 -0
  246. package/src/views/Settings.tsx +183 -0
  247. package/src/views/SourceControl.tsx +95 -0
  248. package/src/views/WorkflowVisualizer.tsx +382 -0
  249. package/tailwind.config.js +161 -0
  250. package/templates/agents/AUTO-INVOKE.md +180 -0
  251. package/templates/agents/CONFLICT-RESOLUTION.md +128 -0
  252. package/templates/agents/QUICK-REFERENCE.md +122 -0
  253. package/templates/agents/README.md +188 -0
  254. package/templates/agents/SKILL-TRIGGERS.md +100 -0
  255. package/templates/agents/blue-team/frontend-designer.md +424 -0
  256. package/templates/agents/green-team/architect.md +526 -0
  257. package/templates/agents/green-team/rules-enforcer.md +131 -0
  258. package/templates/agents/red-team/attacker-learned.md +24 -0
  259. package/templates/agents/red-team/attacker.md +486 -0
  260. package/templates/agents/red-team/chaos.md +548 -0
  261. package/templates/agents/reference/component-registry.md +82 -0
  262. package/templates/agents/workflows/full-mode.md +218 -0
  263. package/templates/agents/workflows/quick-mode.md +118 -0
  264. package/templates/agents/workflows/security-mode.md +283 -0
  265. package/templates/anti-patterns/dangerous-shortcuts.md +427 -0
  266. package/templates/config/agent-triggers.json +92 -0
  267. package/templates/hooks/agent-team-gate.sh +31 -0
  268. package/templates/hooks/agent-trigger.sh +97 -0
  269. package/templates/hooks/block-push.sh +66 -0
  270. package/templates/hooks/block-workarounds.sh +61 -0
  271. package/templates/hooks/blocker-check.sh +28 -0
  272. package/templates/hooks/completion-checklist.sh +28 -0
  273. package/templates/hooks/decision-capture.sh +15 -0
  274. package/templates/hooks/dependency-check.sh +27 -0
  275. package/templates/hooks/end-session.sh +31 -0
  276. package/templates/hooks/exploration-logger.sh +37 -0
  277. package/templates/hooks/files-changed-summary.sh +37 -0
  278. package/templates/hooks/get-session-id.sh +49 -0
  279. package/templates/hooks/git-commit-guard.sh +34 -0
  280. package/templates/hooks/init-session.sh +93 -0
  281. package/templates/hooks/orbital-emit.sh +79 -0
  282. package/templates/hooks/orbital-report-deploy.sh +78 -0
  283. package/templates/hooks/orbital-report-gates.sh +40 -0
  284. package/templates/hooks/orbital-report-violation.sh +36 -0
  285. package/templates/hooks/orbital-scope-update.sh +53 -0
  286. package/templates/hooks/phase-verify-reminder.sh +26 -0
  287. package/templates/hooks/review-gate-check.sh +82 -0
  288. package/templates/hooks/scope-commit-logger.sh +37 -0
  289. package/templates/hooks/scope-create-cleanup.sh +36 -0
  290. package/templates/hooks/scope-create-gate.sh +80 -0
  291. package/templates/hooks/scope-create-tracker.sh +17 -0
  292. package/templates/hooks/scope-file-sync.sh +53 -0
  293. package/templates/hooks/scope-gate.sh +35 -0
  294. package/templates/hooks/scope-helpers.sh +188 -0
  295. package/templates/hooks/scope-lifecycle-gate.sh +139 -0
  296. package/templates/hooks/scope-prepare.sh +244 -0
  297. package/templates/hooks/scope-transition.sh +172 -0
  298. package/templates/hooks/session-enforcer.sh +143 -0
  299. package/templates/hooks/time-tracker.sh +33 -0
  300. package/templates/lessons-learned.md +15 -0
  301. package/templates/orbital.config.json +35 -0
  302. package/templates/presets/development.json +42 -0
  303. package/templates/presets/gitflow.json +712 -0
  304. package/templates/presets/minimal.json +23 -0
  305. package/templates/quick/rules.md +218 -0
  306. package/templates/scopes/_template.md +255 -0
  307. package/templates/settings-hooks.json +98 -0
  308. package/templates/skills/git-commit/SKILL.md +85 -0
  309. package/templates/skills/git-dev/SKILL.md +99 -0
  310. package/templates/skills/git-hotfix/SKILL.md +223 -0
  311. package/templates/skills/git-main/SKILL.md +84 -0
  312. package/templates/skills/git-production/SKILL.md +165 -0
  313. package/templates/skills/git-staging/SKILL.md +112 -0
  314. package/templates/skills/scope-create/SKILL.md +81 -0
  315. package/templates/skills/scope-fix-review/SKILL.md +168 -0
  316. package/templates/skills/scope-implement/SKILL.md +110 -0
  317. package/templates/skills/scope-post-review/SKILL.md +144 -0
  318. package/templates/skills/scope-pre-review/SKILL.md +211 -0
  319. package/templates/skills/scope-verify/SKILL.md +201 -0
  320. package/templates/skills/session-init/SKILL.md +62 -0
  321. package/templates/skills/session-resume/SKILL.md +201 -0
  322. package/templates/skills/test-checks/SKILL.md +171 -0
  323. package/templates/skills/test-code-review/SKILL.md +252 -0
  324. package/tsconfig.json +25 -0
  325. package/vite.config.ts +38 -0
@@ -0,0 +1,139 @@
1
+ import { RefreshCw, Download, Check, AlertCircle, GitBranch, GitCommit, Loader2 } from 'lucide-react';
2
+ import { Badge } from '@/components/ui/badge';
3
+ import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';
4
+ import { useVersion } from '@/hooks/useVersion';
5
+ import { cn } from '@/lib/utils';
6
+
7
+ export function VersionBadge() {
8
+ const {
9
+ version,
10
+ updateAvailable,
11
+ behindCount,
12
+ updateStage,
13
+ updateError,
14
+ loading,
15
+ checkForUpdate,
16
+ performUpdate,
17
+ } = useVersion();
18
+
19
+ if (loading) return null;
20
+ if (!version) {
21
+ return (
22
+ <button className="version-badge flex items-center gap-1.5 rounded-lg px-2 py-1 text-[10px] font-mono text-muted-foreground/50">
23
+ <span>v?</span>
24
+ </button>
25
+ );
26
+ }
27
+
28
+ const isWorking = updateStage === 'checking' || updateStage === 'pulling' || updateStage === 'installing';
29
+
30
+ return (
31
+ <Popover>
32
+ <PopoverTrigger asChild>
33
+ <button className="relative cursor-pointer">
34
+ <Badge
35
+ variant={updateAvailable ? 'warning' : 'success'}
36
+ className="version-badge font-mono text-[10px] transition-colors"
37
+ >
38
+ v{version.version}
39
+ </Badge>
40
+ {updateAvailable && (
41
+ <span className="version-pulse-dot absolute -top-1 -right-1 h-2 w-2 rounded-full bg-emerald-400" />
42
+ )}
43
+ </button>
44
+ </PopoverTrigger>
45
+
46
+ <PopoverContent
47
+ side="top"
48
+ align="end"
49
+ sideOffset={8}
50
+ className="w-64 filter-popover-glass"
51
+ >
52
+ <div className="space-y-3">
53
+ {/* Version header */}
54
+ <div className="flex items-center justify-between">
55
+ <span className="text-xs font-medium text-foreground">Orbital Command</span>
56
+ <Badge variant="outline" className="font-mono text-[10px]">
57
+ v{version.version}
58
+ </Badge>
59
+ </div>
60
+
61
+ {/* Git info */}
62
+ <div className="space-y-1.5 text-[11px] text-muted-foreground">
63
+ <div className="flex items-center gap-1.5">
64
+ <GitCommit className="h-3 w-3" />
65
+ <span className="font-mono">{version.commitSha}</span>
66
+ </div>
67
+ <div className="flex items-center gap-1.5">
68
+ <GitBranch className="h-3 w-3" />
69
+ <span className="font-mono">{version.branch}</span>
70
+ </div>
71
+ </div>
72
+
73
+ {/* Update status */}
74
+ {updateAvailable && updateStage !== 'done' && (
75
+ <div className="rounded-md border border-emerald-500/20 bg-emerald-500/5 px-2 py-1.5 text-[11px] text-emerald-400">
76
+ {behindCount} commit{behindCount !== 1 ? 's' : ''} behind remote
77
+ </div>
78
+ )}
79
+
80
+ {updateStage === 'done' && (
81
+ <div className="flex items-center gap-1.5 rounded-md border border-emerald-500/20 bg-emerald-500/5 px-2 py-1.5 text-[11px] text-emerald-400">
82
+ <Check className="h-3 w-3" />
83
+ Updated. Restart server to apply.
84
+ </div>
85
+ )}
86
+
87
+ {updateStage === 'error' && (
88
+ <div className="flex items-start gap-1.5 rounded-md border border-destructive/20 bg-destructive/5 px-2 py-1.5 text-[11px] text-destructive">
89
+ <AlertCircle className="h-3 w-3 mt-0.5 shrink-0" />
90
+ <span>{updateError ?? 'An unknown error occurred'}</span>
91
+ </div>
92
+ )}
93
+
94
+ {isWorking && (
95
+ <div className="flex items-center gap-1.5 text-[11px] text-muted-foreground">
96
+ <Loader2 className="h-3 w-3 animate-spin" />
97
+ <span>
98
+ {updateStage === 'checking' && 'Checking for updates...'}
99
+ {updateStage === 'pulling' && 'Pulling latest changes...'}
100
+ {updateStage === 'installing' && 'Installing dependencies...'}
101
+ </span>
102
+ </div>
103
+ )}
104
+
105
+ {/* Actions */}
106
+ <div className="flex gap-2 pt-1">
107
+ <button
108
+ onClick={checkForUpdate}
109
+ disabled={isWorking}
110
+ className={cn(
111
+ 'flex flex-1 items-center justify-center gap-1.5 rounded-md border border-border px-2 py-1 text-[11px]',
112
+ 'text-muted-foreground hover:text-foreground hover:bg-surface-light transition-colors',
113
+ 'disabled:opacity-40 disabled:cursor-not-allowed',
114
+ )}
115
+ >
116
+ <RefreshCw className={cn('h-3 w-3', updateStage === 'checking' && 'animate-spin')} />
117
+ Check
118
+ </button>
119
+ {updateAvailable && updateStage !== 'done' && (
120
+ <button
121
+ onClick={performUpdate}
122
+ disabled={isWorking}
123
+ className={cn(
124
+ 'flex flex-1 items-center justify-center gap-1.5 rounded-md px-2 py-1 text-[11px]',
125
+ 'bg-emerald-500/10 border border-emerald-500/20 text-emerald-400',
126
+ 'hover:bg-emerald-500/20 transition-colors',
127
+ 'disabled:opacity-40 disabled:cursor-not-allowed',
128
+ )}
129
+ >
130
+ <Download className="h-3 w-3" />
131
+ Update
132
+ </button>
133
+ )}
134
+ </div>
135
+ </div>
136
+ </PopoverContent>
137
+ </Popover>
138
+ );
139
+ }
@@ -0,0 +1,114 @@
1
+ import { Columns3, Rows3 } from 'lucide-react';
2
+ import { Popover, PopoverTrigger, PopoverContent } from '@/components/ui/popover';
3
+ import { Button } from '@/components/ui/button';
4
+ import { cn } from '@/lib/utils';
5
+ import type { ViewMode, SwimGroupField } from '@/types';
6
+
7
+ interface ViewModeSelectorProps {
8
+ viewMode: ViewMode;
9
+ groupField: SwimGroupField;
10
+ onViewModeChange: (mode: ViewMode) => void;
11
+ onGroupFieldChange: (field: SwimGroupField) => void;
12
+ }
13
+
14
+ const VIEW_MODES: { value: ViewMode; label: string; Icon: typeof Columns3 }[] = [
15
+ { value: 'kanban', label: 'Kanban', Icon: Columns3 },
16
+ { value: 'swimlane', label: 'Swimlane', Icon: Rows3 },
17
+ ];
18
+
19
+ const GROUP_FIELDS: { value: SwimGroupField; label: string }[] = [
20
+ { value: 'priority', label: 'Priority' },
21
+ { value: 'category', label: 'Category' },
22
+ { value: 'tags', label: 'Tags' },
23
+ { value: 'effort', label: 'Effort' },
24
+ { value: 'dependencies', label: 'Dependencies' },
25
+ ];
26
+
27
+ export function ViewModeSelector({
28
+ viewMode,
29
+ groupField,
30
+ onViewModeChange,
31
+ onGroupFieldChange,
32
+ }: ViewModeSelectorProps) {
33
+ const ActiveIcon = viewMode === 'swimlane' ? Rows3 : Columns3;
34
+
35
+ return (
36
+ <Popover>
37
+ <PopoverTrigger asChild>
38
+ <Button
39
+ variant="outline"
40
+ size="sm"
41
+ className="gap-1.5 backdrop-blur-sm bg-white/[0.03] border-white/10"
42
+ aria-label="Toggle view mode"
43
+ >
44
+ <ActiveIcon className="h-3 w-3" />
45
+ {viewMode === 'swimlane' ? 'Swimlane' : 'Kanban'}
46
+ </Button>
47
+ </PopoverTrigger>
48
+
49
+ <PopoverContent align="end" className="filter-popover-glass !bg-transparent w-44">
50
+ {/* View mode selection */}
51
+ <div className="space-y-0.5">
52
+ <p className="px-2 pb-1 text-[10px] uppercase tracking-wider text-muted-foreground">View</p>
53
+ {VIEW_MODES.map(({ value, label, Icon }) => (
54
+ <button
55
+ key={value}
56
+ onClick={() => onViewModeChange(value)}
57
+ className={cn(
58
+ 'flex w-full items-center gap-2 rounded px-2 py-1.5 text-xs transition-colors',
59
+ 'hover:bg-white/[0.06]',
60
+ viewMode === value && 'bg-white/[0.06]',
61
+ )}
62
+ >
63
+ <span
64
+ className={cn(
65
+ 'flex h-3.5 w-3.5 shrink-0 items-center justify-center rounded-full border',
66
+ viewMode === value ? 'border-primary bg-primary' : 'border-white/15',
67
+ )}
68
+ >
69
+ {viewMode === value && (
70
+ <span className="h-1.5 w-1.5 rounded-full bg-primary-foreground" />
71
+ )}
72
+ </span>
73
+ <Icon className="h-3 w-3 text-muted-foreground" />
74
+ <span className={cn(viewMode === value && 'text-foreground')}>{label}</span>
75
+ </button>
76
+ ))}
77
+ </div>
78
+
79
+ {/* Group-by field — only visible in swimlane mode */}
80
+ {viewMode === 'swimlane' && (
81
+ <>
82
+ <div className="my-2 border-t border-white/[0.06]" />
83
+ <div className="space-y-0.5">
84
+ <p className="px-2 pb-1 text-[10px] uppercase tracking-wider text-muted-foreground">Group by</p>
85
+ {GROUP_FIELDS.map(({ value, label }) => (
86
+ <button
87
+ key={value}
88
+ onClick={() => onGroupFieldChange(value)}
89
+ className={cn(
90
+ 'flex w-full items-center gap-2 rounded px-2 py-1.5 text-xs transition-colors',
91
+ 'hover:bg-white/[0.06]',
92
+ groupField === value && 'bg-white/[0.06]',
93
+ )}
94
+ >
95
+ <span
96
+ className={cn(
97
+ 'flex h-3.5 w-3.5 shrink-0 items-center justify-center rounded-full border',
98
+ groupField === value ? 'border-primary bg-primary' : 'border-white/15',
99
+ )}
100
+ >
101
+ {groupField === value && (
102
+ <span className="h-1.5 w-1.5 rounded-full bg-primary-foreground" />
103
+ )}
104
+ </span>
105
+ <span className={cn(groupField === value && 'text-foreground')}>{label}</span>
106
+ </button>
107
+ ))}
108
+ </div>
109
+ </>
110
+ )}
111
+ </PopoverContent>
112
+ </Popover>
113
+ );
114
+ }
@@ -0,0 +1,53 @@
1
+ import { Bot, X } from 'lucide-react';
2
+ import { cn } from '@/lib/utils';
3
+ import type { ResolvedAgent } from '@/types';
4
+
5
+ interface AgentChipProps {
6
+ agent: ResolvedAgent;
7
+ mode?: 'always-on' | 'review';
8
+ selected?: boolean;
9
+ onClick?: () => void;
10
+ onRemove?: () => void;
11
+ }
12
+
13
+ export function AgentChip({ agent, mode, selected, onClick, onRemove }: AgentChipProps) {
14
+ const color = agent.color || '#8B5CF6';
15
+
16
+ return (
17
+ <button
18
+ type="button"
19
+ onClick={onClick}
20
+ data-pipeline-path={agent.filePath ?? undefined}
21
+ className={cn(
22
+ 'inline-flex items-center gap-1.5 rounded-md border px-2 py-0.5 text-[11px] font-medium transition-colors',
23
+ 'hover:brightness-125 cursor-pointer',
24
+ selected && 'glow-selected-pulse',
25
+ )}
26
+ style={{
27
+ color,
28
+ borderColor: `${color}4D`,
29
+ backgroundColor: `${color}1A`,
30
+ ...(selected ? { '--glow-color': `${color}A0`, '--glow-color-wide': `${color}40` } as React.CSSProperties : {}),
31
+ }}
32
+ >
33
+ {agent.emoji ? (
34
+ <span className="text-xs">{agent.emoji}</span>
35
+ ) : (
36
+ <Bot className="h-3 w-3 shrink-0" />
37
+ )}
38
+ <span className="truncate max-w-[100px]">{agent.label}</span>
39
+ {mode === 'always-on' && (
40
+ <span className="ml-0.5 h-1.5 w-1.5 rounded-full bg-green-500 shrink-0" title="Auto-invoke" />
41
+ )}
42
+ {onRemove && (
43
+ <span
44
+ role="button"
45
+ onClick={(e) => { e.stopPropagation(); onRemove(); }}
46
+ className="ml-0.5 rounded-full p-0.5 hover:bg-red-500/20"
47
+ >
48
+ <X className="h-2.5 w-2.5" />
49
+ </span>
50
+ )}
51
+ </button>
52
+ );
53
+ }
@@ -0,0 +1,321 @@
1
+ import { useState, useCallback } from 'react';
2
+ import { Plus, Bot, Shield, Eye, Wrench, Search, Sparkles } from 'lucide-react';
3
+ import { Button } from '@/components/ui/button';
4
+ import {
5
+ Dialog,
6
+ DialogContent,
7
+ DialogDescription,
8
+ DialogHeader,
9
+ DialogTitle,
10
+ DialogTrigger,
11
+ } from '@/components/ui/dialog';
12
+ import { Badge } from '@/components/ui/badge';
13
+ import { cn } from '@/lib/utils';
14
+
15
+ interface AgentCreateDialogProps {
16
+ onCreated: () => void;
17
+ }
18
+
19
+ interface Template {
20
+ id: string;
21
+ label: string;
22
+ icon: typeof Shield;
23
+ description: string;
24
+ scaffold: string;
25
+ defaultFolder: string;
26
+ }
27
+
28
+ const TEMPLATES: Template[] = [
29
+ {
30
+ id: 'security',
31
+ label: 'Security',
32
+ icon: Shield,
33
+ description: 'Adversarial security review agent',
34
+ defaultFolder: 'red-team',
35
+ scaffold: `# {name}
36
+
37
+ {description}
38
+
39
+ ## Role
40
+
41
+ You are a security-focused review agent. Your goal is to identify vulnerabilities, insecure patterns, and potential attack vectors in the code under review.
42
+
43
+ ## Auto-triggered for:
44
+ - Security-sensitive file changes
45
+ - Authentication/authorization code
46
+ - Input handling and validation
47
+
48
+ ## Review Checklist
49
+ - [ ] Input validation and sanitization
50
+ - [ ] Authentication/authorization checks
51
+ - [ ] Secrets and credential handling
52
+ - [ ] SQL/command injection risks
53
+ - [ ] XSS and CSRF protections
54
+ `,
55
+ },
56
+ {
57
+ id: 'reliability',
58
+ label: 'Reliability',
59
+ icon: Eye,
60
+ description: 'Production reliability review agent',
61
+ defaultFolder: 'blue-team',
62
+ scaffold: `# {name}
63
+
64
+ {description}
65
+
66
+ ## Role
67
+
68
+ You are a reliability-focused review agent. Your goal is to ensure code changes are production-safe with proper error handling, observability, and graceful degradation.
69
+
70
+ ## Auto-triggered for:
71
+ - Error handling changes
72
+ - Service boundary code
73
+ - Database operations
74
+
75
+ ## Review Checklist
76
+ - [ ] Error handling completeness
77
+ - [ ] Timeout and retry logic
78
+ - [ ] Logging and observability
79
+ - [ ] Graceful degradation
80
+ `,
81
+ },
82
+ {
83
+ id: 'domain-expert',
84
+ label: 'Domain Expert',
85
+ icon: Search,
86
+ description: 'Domain-specific expertise agent',
87
+ defaultFolder: 'green-team',
88
+ scaffold: `# {name}
89
+
90
+ {description}
91
+
92
+ ## Role
93
+
94
+ You are a domain expert review agent. Your goal is to ensure code changes correctly implement business logic and domain-specific requirements.
95
+
96
+ ## Auto-triggered for:
97
+ - Business logic changes
98
+ - Domain model modifications
99
+ - API contract changes
100
+
101
+ ## Review Checklist
102
+ - [ ] Business rule correctness
103
+ - [ ] Domain model integrity
104
+ - [ ] API contract compliance
105
+ `,
106
+ },
107
+ {
108
+ id: 'guardian',
109
+ label: 'Guardian',
110
+ icon: Wrench,
111
+ description: 'Code quality and standards agent',
112
+ defaultFolder: 'blue-team',
113
+ scaffold: `# {name}
114
+
115
+ {description}
116
+
117
+ ## Role
118
+
119
+ You are a code quality guardian agent. Your goal is to ensure code follows project conventions, maintains consistency, and upholds quality standards.
120
+
121
+ ## Auto-triggered for:
122
+ - All code changes
123
+
124
+ ## Review Checklist
125
+ - [ ] Code style and conventions
126
+ - [ ] Test coverage
127
+ - [ ] Documentation completeness
128
+ - [ ] Performance implications
129
+ `,
130
+ },
131
+ {
132
+ id: 'custom',
133
+ label: 'Custom',
134
+ icon: Sparkles,
135
+ description: 'Start from a blank template',
136
+ defaultFolder: '',
137
+ scaffold: `# {name}
138
+
139
+ {description}
140
+
141
+ ## Role
142
+
143
+ Describe this agent's role and responsibilities.
144
+
145
+ ## Review Checklist
146
+ - [ ] Add review criteria here
147
+ `,
148
+ },
149
+ ];
150
+
151
+ export function AgentCreateDialog({ onCreated }: AgentCreateDialogProps) {
152
+ const [open, setOpen] = useState(false);
153
+ const [selectedTemplate, setSelectedTemplate] = useState<string>('security');
154
+ const [name, setName] = useState('');
155
+ const [description, setDescription] = useState('');
156
+ const [folder, setFolder] = useState('');
157
+ const [creating, setCreating] = useState(false);
158
+ const [error, setError] = useState<string | null>(null);
159
+
160
+ const template = TEMPLATES.find(t => t.id === selectedTemplate) ?? TEMPLATES[0];
161
+
162
+ const handleCreate = useCallback(async () => {
163
+ if (!name.trim()) {
164
+ setError('Agent name is required');
165
+ return;
166
+ }
167
+
168
+ const slug = name.trim().toLowerCase().replace(/\s+/g, '-');
169
+ const folderPath = folder.trim() || template.defaultFolder;
170
+ const filePath = folderPath ? `${folderPath}/${slug}.md` : `${slug}.md`;
171
+
172
+ const content = `---\nname: ${name.trim()}\ndescription: ${description.trim() || template.description}\n---\n${template.scaffold
173
+ .replace(/\{name\}/g, name.trim())
174
+ .replace(/\{description\}/g, description.trim() || template.description)}`;
175
+
176
+ setCreating(true);
177
+ setError(null);
178
+
179
+ try {
180
+ const res = await fetch('/api/orbital/config/agents/file', {
181
+ method: 'POST',
182
+ headers: { 'Content-Type': 'application/json' },
183
+ body: JSON.stringify({ path: filePath, content }),
184
+ });
185
+ if (!res.ok) {
186
+ const json = await res.json().catch(() => ({ error: 'Create failed' }));
187
+ throw new Error(json.error ?? `HTTP ${res.status}`);
188
+ }
189
+ setOpen(false);
190
+ setName('');
191
+ setDescription('');
192
+ setFolder('');
193
+ onCreated();
194
+ } catch (err) {
195
+ setError(err instanceof Error ? err.message : 'Create failed');
196
+ } finally {
197
+ setCreating(false);
198
+ }
199
+ }, [name, description, folder, template, onCreated]);
200
+
201
+ return (
202
+ <Dialog open={open} onOpenChange={setOpen}>
203
+ <DialogTrigger asChild>
204
+ <Button variant="outline" size="sm" className="gap-1.5">
205
+ <Plus className="h-3.5 w-3.5" />
206
+ <Bot className="h-3.5 w-3.5" />
207
+ New Agent
208
+ </Button>
209
+ </DialogTrigger>
210
+ <DialogContent className="sm:max-w-[480px]">
211
+ <DialogHeader>
212
+ <DialogTitle className="flex items-center gap-2">
213
+ <Bot className="h-5 w-5" /> Create Agent
214
+ </DialogTitle>
215
+ <DialogDescription>
216
+ Choose a template and configure your new review agent.
217
+ </DialogDescription>
218
+ </DialogHeader>
219
+
220
+ <div className="space-y-4 py-2">
221
+ {/* Template selector */}
222
+ <div className="space-y-2">
223
+ <label className="text-xs font-medium text-muted-foreground">Template</label>
224
+ <div className="grid grid-cols-5 gap-1.5">
225
+ {TEMPLATES.map(t => {
226
+ const Icon = t.icon;
227
+ return (
228
+ <button
229
+ key={t.id}
230
+ type="button"
231
+ onClick={() => {
232
+ setSelectedTemplate(t.id);
233
+ setFolder(t.defaultFolder);
234
+ }}
235
+ className={cn(
236
+ 'flex flex-col items-center gap-1 rounded-md border p-2 text-[10px] transition-colors',
237
+ selectedTemplate === t.id
238
+ ? 'border-primary bg-primary/10 text-primary'
239
+ : 'border-border text-muted-foreground hover:border-muted-foreground/40',
240
+ )}
241
+ >
242
+ <Icon className="h-4 w-4" />
243
+ {t.label}
244
+ </button>
245
+ );
246
+ })}
247
+ </div>
248
+ </div>
249
+
250
+ {/* Name */}
251
+ <div className="space-y-1">
252
+ <label className="text-xs font-medium text-muted-foreground">Name</label>
253
+ <input
254
+ value={name}
255
+ onChange={(e) => setName(e.target.value)}
256
+ placeholder="e.g., API Security Reviewer"
257
+ className={cn(
258
+ 'w-full rounded border border-border bg-surface px-2.5 py-1.5 text-sm text-foreground',
259
+ 'outline-none focus:border-accent-blue/50 transition-colors',
260
+ )}
261
+ />
262
+ </div>
263
+
264
+ {/* Description */}
265
+ <div className="space-y-1">
266
+ <label className="text-xs font-medium text-muted-foreground">Description</label>
267
+ <input
268
+ value={description}
269
+ onChange={(e) => setDescription(e.target.value)}
270
+ placeholder={template.description}
271
+ className={cn(
272
+ 'w-full rounded border border-border bg-surface px-2.5 py-1.5 text-sm text-foreground',
273
+ 'outline-none focus:border-accent-blue/50 transition-colors',
274
+ )}
275
+ />
276
+ </div>
277
+
278
+ {/* Folder */}
279
+ <div className="space-y-1">
280
+ <label className="text-xs font-medium text-muted-foreground">
281
+ Team Folder
282
+ <span className="ml-1 text-muted-foreground/50">(optional)</span>
283
+ </label>
284
+ <input
285
+ value={folder}
286
+ onChange={(e) => setFolder(e.target.value)}
287
+ placeholder={template.defaultFolder || 'root'}
288
+ className={cn(
289
+ 'w-full rounded border border-border bg-surface px-2.5 py-1.5 text-sm text-foreground font-mono',
290
+ 'outline-none focus:border-accent-blue/50 transition-colors',
291
+ )}
292
+ />
293
+ <div className="flex gap-1.5 mt-1">
294
+ {['red-team', 'blue-team', 'green-team'].map(f => (
295
+ <Badge
296
+ key={f}
297
+ variant={folder === f ? 'default' : 'secondary'}
298
+ className="text-[10px] cursor-pointer"
299
+ onClick={() => setFolder(f)}
300
+ >
301
+ {f}
302
+ </Badge>
303
+ ))}
304
+ </div>
305
+ </div>
306
+
307
+ {error && (
308
+ <p className="text-xs text-destructive">{error}</p>
309
+ )}
310
+ </div>
311
+
312
+ <div className="flex justify-end gap-2 pt-2">
313
+ <Button variant="ghost" onClick={() => setOpen(false)}>Cancel</Button>
314
+ <Button onClick={handleCreate} disabled={creating}>
315
+ {creating ? 'Creating...' : 'Create Agent'}
316
+ </Button>
317
+ </div>
318
+ </DialogContent>
319
+ </Dialog>
320
+ );
321
+ }