From dfaf523029298a34fc6b38b65bfe7da3fe0ff188 Mon Sep 17 00:00:00 2001 From: zenchantlive Date: Fri, 20 Feb 2026 22:19:38 -0800 Subject: [PATCH] feat(swarm): implement Swarm View remake with Operations, Archetypes, and Templates This commit includes the new SwarmWorkspace with its 3 sub-tabs, the LeftPanel mission picker, and the comprehensive Operations Command Dashboard featuring the live interactive DAG telemetry and task assignment prep flow. --- AGENTS.md | 8 + components/ui/dialog.tsx | 122 + components/ui/label.tsx | 26 + components/ui/select.tsx | 159 + components/ui/tabs.tsx | 55 + components/ui/textarea.tsx | 24 + docs/plans/2026-02-19-swarm-page-redesign.md | 224 + docs/plans/2026-02-19-visual-truth-spec.md | 96 + .../2026-02-20-swarm-view-remake-design.md | 13 +- docs/prompts/2026-02-19-beads-cgo-fix-pr.md | 285 + docs/protocols/bead-prompting.md | 166 + eslint.config.mjs | 21 +- package-lock.json | 4879 +++++++++++++++-- package.json | 6 +- src/app/api/agents/list/route.ts | 19 + src/app/api/beads/[id]/comments/route.ts | 28 + src/app/api/mission/[id]/topology/route.ts | 31 + src/app/api/mission/assign/route.ts | 40 + src/app/api/mission/graph/route.ts | 46 + src/app/api/mission/list/route.ts | 88 + src/app/api/swarm/close/route.ts | 70 + src/app/api/swarm/create/route.ts | 78 + src/app/api/swarm/formulas/route.ts | 29 + src/app/api/swarm/graph/route.ts | 45 + src/app/api/swarm/join/route.ts | 36 + src/app/api/swarm/launch/route.ts | 42 + src/app/api/swarm/leave/route.ts | 36 + src/app/api/swarm/list/route.ts | 44 + src/app/api/swarm/prep/route.ts | 29 + src/app/api/swarm/status/route.ts | 45 + src/app/api/swarm/templates/route.ts | 7 + src/app/globals.css | 148 +- src/app/sessions/page.tsx | 79 +- src/components/activity/activity-panel.tsx | 42 +- src/components/graph/graph-view.tsx | 17 +- src/components/mission/mission-card.tsx | 148 + src/components/mission/mission-inspector.tsx | 141 + src/components/mission/swarm-graph.tsx | 107 + .../mission/team-manager-dialog.tsx | 255 + src/components/shared/left-panel.tsx | 696 ++- src/components/shared/right-panel.tsx | 60 +- src/components/shared/thread-drawer.tsx | 558 +- src/components/shared/thread-view.tsx | 60 +- src/components/shared/top-bar.tsx | 226 +- src/components/shared/unified-shell.tsx | 1 + src/components/social/social-card.tsx | 304 +- src/components/social/social-page.tsx | 320 +- src/components/swarm/archetype-inspector.tsx | 110 + src/components/swarm/convoy-stepper.tsx | 31 + src/components/swarm/launch-dialog.tsx | 172 + .../swarm/specialized-agent-dag.tsx | 210 + src/components/swarm/swarm-card.tsx | 180 +- src/components/swarm/swarm-control-card.tsx | 146 + src/components/swarm/swarm-detail.tsx | 326 +- src/components/swarm/swarm-inspector.tsx | 191 + src/components/swarm/swarm-page.tsx | 246 +- src/components/swarm/swarm-workspace.tsx | 269 +- src/components/swarm/telemetry-grid.tsx | 217 + src/components/swarm/template-inspector.tsx | 138 + src/hooks/use-agent-pool.ts | 61 + src/hooks/use-archetypes.ts | 29 + src/hooks/use-mission-graph.ts | 42 + src/hooks/use-mission-list.ts | 66 + src/hooks/use-swarm-list.ts | 86 + src/hooks/use-swarm-topology.ts | 50 + src/hooks/use-templates.ts | 29 + src/hooks/use-url-state.ts | 155 +- src/lib/agent-registry.ts | 17 +- src/lib/bridge.ts | 8 +- src/lib/server/beads-fs.ts | 106 +- src/lib/social-cards.ts | 44 +- src/lib/swarm-api.ts | 64 + src/video/Main.tsx | 2 +- tests/hooks/use-url-state.test.ts | 158 +- 74 files changed, 11066 insertions(+), 2046 deletions(-) create mode 100644 components/ui/dialog.tsx create mode 100644 components/ui/label.tsx create mode 100644 components/ui/select.tsx create mode 100644 components/ui/tabs.tsx create mode 100644 components/ui/textarea.tsx create mode 100644 docs/plans/2026-02-19-swarm-page-redesign.md create mode 100644 docs/plans/2026-02-19-visual-truth-spec.md create mode 100644 docs/prompts/2026-02-19-beads-cgo-fix-pr.md create mode 100644 docs/protocols/bead-prompting.md create mode 100644 src/app/api/agents/list/route.ts create mode 100644 src/app/api/beads/[id]/comments/route.ts create mode 100644 src/app/api/mission/[id]/topology/route.ts create mode 100644 src/app/api/mission/assign/route.ts create mode 100644 src/app/api/mission/graph/route.ts create mode 100644 src/app/api/mission/list/route.ts create mode 100644 src/app/api/swarm/close/route.ts create mode 100644 src/app/api/swarm/create/route.ts create mode 100644 src/app/api/swarm/formulas/route.ts create mode 100644 src/app/api/swarm/graph/route.ts create mode 100644 src/app/api/swarm/join/route.ts create mode 100644 src/app/api/swarm/launch/route.ts create mode 100644 src/app/api/swarm/leave/route.ts create mode 100644 src/app/api/swarm/list/route.ts create mode 100644 src/app/api/swarm/prep/route.ts create mode 100644 src/app/api/swarm/status/route.ts create mode 100644 src/app/api/swarm/templates/route.ts create mode 100644 src/components/mission/mission-card.tsx create mode 100644 src/components/mission/mission-inspector.tsx create mode 100644 src/components/mission/swarm-graph.tsx create mode 100644 src/components/mission/team-manager-dialog.tsx create mode 100644 src/components/swarm/archetype-inspector.tsx create mode 100644 src/components/swarm/convoy-stepper.tsx create mode 100644 src/components/swarm/launch-dialog.tsx create mode 100644 src/components/swarm/specialized-agent-dag.tsx create mode 100644 src/components/swarm/swarm-control-card.tsx create mode 100644 src/components/swarm/swarm-inspector.tsx create mode 100644 src/components/swarm/telemetry-grid.tsx create mode 100644 src/components/swarm/template-inspector.tsx create mode 100644 src/hooks/use-agent-pool.ts create mode 100644 src/hooks/use-archetypes.ts create mode 100644 src/hooks/use-mission-graph.ts create mode 100644 src/hooks/use-mission-list.ts create mode 100644 src/hooks/use-swarm-list.ts create mode 100644 src/hooks/use-swarm-topology.ts create mode 100644 src/hooks/use-templates.ts create mode 100644 src/lib/swarm-api.ts diff --git a/AGENTS.md b/AGENTS.md index 455e20f..87860bf 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -22,6 +22,14 @@ bd close --reason "" bd sync ``` +## Bead Prompting Standard + +1. When creating or rewriting bead details, follow `docs/protocols/bead-prompting.md`. +2. Bead descriptions must be model-facing prompts, not internal prose notes. +3. Include explicit `Scope` and `Out of Scope` in every bead. +4. Treat `Success Criteria` as the completion contract. +5. Keep dependency flow minimal and execution-correct. + ## Start-of-Task Protocol 1. Read the target bead and acceptance criteria (`bd show `). diff --git a/components/ui/dialog.tsx b/components/ui/dialog.tsx new file mode 100644 index 0000000..1647513 --- /dev/null +++ b/components/ui/dialog.tsx @@ -0,0 +1,122 @@ +"use client" + +import * as React from "react" +import * as DialogPrimitive from "@radix-ui/react-dialog" +import { X } from "lucide-react" + +import { cn } from "@/lib/utils" + +const Dialog = DialogPrimitive.Root + +const DialogTrigger = DialogPrimitive.Trigger + +const DialogPortal = DialogPrimitive.Portal + +const DialogClose = DialogPrimitive.Close + +const DialogOverlay = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DialogOverlay.displayName = DialogPrimitive.Overlay.displayName + +const DialogContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + + {children} + + + Close + + + +)) +DialogContent.displayName = DialogPrimitive.Content.displayName + +const DialogHeader = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+) +DialogHeader.displayName = "DialogHeader" + +const DialogFooter = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+) +DialogFooter.displayName = "DialogFooter" + +const DialogTitle = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DialogTitle.displayName = DialogPrimitive.Title.displayName + +const DialogDescription = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DialogDescription.displayName = DialogPrimitive.Description.displayName + +export { + Dialog, + DialogPortal, + DialogOverlay, + DialogTrigger, + DialogClose, + DialogContent, + DialogHeader, + DialogFooter, + DialogTitle, + DialogDescription, +} diff --git a/components/ui/label.tsx b/components/ui/label.tsx new file mode 100644 index 0000000..5341821 --- /dev/null +++ b/components/ui/label.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import * as LabelPrimitive from "@radix-ui/react-label" +import { cva, type VariantProps } from "class-variance-authority" + +import { cn } from "@/lib/utils" + +const labelVariants = cva( + "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70" +) + +const Label = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & + VariantProps +>(({ className, ...props }, ref) => ( + +)) +Label.displayName = LabelPrimitive.Root.displayName + +export { Label } diff --git a/components/ui/select.tsx b/components/ui/select.tsx new file mode 100644 index 0000000..4eca918 --- /dev/null +++ b/components/ui/select.tsx @@ -0,0 +1,159 @@ +"use client" + +import * as React from "react" +import * as SelectPrimitive from "@radix-ui/react-select" +import { Check, ChevronDown, ChevronUp } from "lucide-react" + +import { cn } from "@/lib/utils" + +const Select = SelectPrimitive.Root + +const SelectGroup = SelectPrimitive.Group + +const SelectValue = SelectPrimitive.Value + +const SelectTrigger = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + span]:line-clamp-1", + className + )} + {...props} + > + {children} + + + + +)) +SelectTrigger.displayName = SelectPrimitive.Trigger.displayName + +const SelectScrollUpButton = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + + + +)) +SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName + +const SelectScrollDownButton = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + + + +)) +SelectScrollDownButton.displayName = + SelectPrimitive.ScrollDownButton.displayName + +const SelectContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, position = "popper", ...props }, ref) => ( + + + + + {children} + + + + +)) +SelectContent.displayName = SelectPrimitive.Content.displayName + +const SelectLabel = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +SelectLabel.displayName = SelectPrimitive.Label.displayName + +const SelectItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + + + + + {children} + +)) +SelectItem.displayName = SelectPrimitive.Item.displayName + +const SelectSeparator = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +SelectSeparator.displayName = SelectPrimitive.Separator.displayName + +export { + Select, + SelectGroup, + SelectValue, + SelectTrigger, + SelectContent, + SelectLabel, + SelectItem, + SelectSeparator, + SelectScrollUpButton, + SelectScrollDownButton, +} diff --git a/components/ui/tabs.tsx b/components/ui/tabs.tsx new file mode 100644 index 0000000..26eb109 --- /dev/null +++ b/components/ui/tabs.tsx @@ -0,0 +1,55 @@ +"use client" + +import * as React from "react" +import * as TabsPrimitive from "@radix-ui/react-tabs" + +import { cn } from "@/lib/utils" + +const Tabs = TabsPrimitive.Root + +const TabsList = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +TabsList.displayName = TabsPrimitive.List.displayName + +const TabsTrigger = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +TabsTrigger.displayName = TabsPrimitive.Trigger.displayName + +const TabsContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +TabsContent.displayName = TabsPrimitive.Content.displayName + +export { Tabs, TabsList, TabsTrigger, TabsContent } diff --git a/components/ui/textarea.tsx b/components/ui/textarea.tsx new file mode 100644 index 0000000..9f9a6dc --- /dev/null +++ b/components/ui/textarea.tsx @@ -0,0 +1,24 @@ +import * as React from "react" + +import { cn } from "@/lib/utils" + +export interface TextareaProps + extends React.TextareaHTMLAttributes {} + +const Textarea = React.forwardRef( + ({ className, ...props }, ref) => { + return ( +