diff --git a/apps/web/src/app/(authenticated)/mission-control/page.tsx b/apps/web/src/app/(authenticated)/mission-control/page.tsx
new file mode 100644
index 0000000..8ea71b9
--- /dev/null
+++ b/apps/web/src/app/(authenticated)/mission-control/page.tsx
@@ -0,0 +1,5 @@
+import { MissionControlLayout } from "@/components/mission-control/MissionControlLayout";
+
+export default function MissionControlPage(): React.JSX.Element {
+ return ;
+}
diff --git a/apps/web/src/components/layout/AppSidebar.tsx b/apps/web/src/components/layout/AppSidebar.tsx
index d0cbd97..6126c42 100644
--- a/apps/web/src/components/layout/AppSidebar.tsx
+++ b/apps/web/src/components/layout/AppSidebar.tsx
@@ -156,6 +156,26 @@ function IconTerminal(): React.JSX.Element {
);
}
+function IconMissionControl(): React.JSX.Element {
+ return (
+
+ );
+}
+
function IconSettings(): React.JSX.Element {
return (
,
},
+ {
+ href: "/mission-control",
+ label: "Mission Control",
+ icon: ,
+ },
],
},
{
diff --git a/apps/web/src/components/mission-control/GlobalAgentRoster.tsx b/apps/web/src/components/mission-control/GlobalAgentRoster.tsx
new file mode 100644
index 0000000..778d06d
--- /dev/null
+++ b/apps/web/src/components/mission-control/GlobalAgentRoster.tsx
@@ -0,0 +1,16 @@
+"use client";
+
+import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
+
+export function GlobalAgentRoster(): React.JSX.Element {
+ return (
+
+
+ Agent Roster
+
+
+ No active agents
+
+
+ );
+}
diff --git a/apps/web/src/components/mission-control/MissionControlLayout.tsx b/apps/web/src/components/mission-control/MissionControlLayout.tsx
new file mode 100644
index 0000000..135409b
--- /dev/null
+++ b/apps/web/src/components/mission-control/MissionControlLayout.tsx
@@ -0,0 +1,21 @@
+"use client";
+
+import { GlobalAgentRoster } from "@/components/mission-control/GlobalAgentRoster";
+import { MissionControlPanel } from "@/components/mission-control/MissionControlPanel";
+
+const DEFAULT_PANEL_SLOTS = ["panel-1", "panel-2", "panel-3", "panel-4"] as const;
+
+export function MissionControlLayout(): React.JSX.Element {
+ return (
+
+ );
+}
diff --git a/apps/web/src/components/mission-control/MissionControlPanel.tsx b/apps/web/src/components/mission-control/MissionControlPanel.tsx
new file mode 100644
index 0000000..f17d37a
--- /dev/null
+++ b/apps/web/src/components/mission-control/MissionControlPanel.tsx
@@ -0,0 +1,17 @@
+"use client";
+
+import { OrchestratorPanel } from "@/components/mission-control/OrchestratorPanel";
+
+interface MissionControlPanelProps {
+ panels: readonly string[];
+}
+
+export function MissionControlPanel({ panels }: MissionControlPanelProps): React.JSX.Element {
+ return (
+
+ {panels.map((panelId) => (
+
+ ))}
+
+ );
+}
diff --git a/apps/web/src/components/mission-control/OrchestratorPanel.tsx b/apps/web/src/components/mission-control/OrchestratorPanel.tsx
new file mode 100644
index 0000000..6bf841a
--- /dev/null
+++ b/apps/web/src/components/mission-control/OrchestratorPanel.tsx
@@ -0,0 +1,16 @@
+"use client";
+
+import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
+
+export function OrchestratorPanel(): React.JSX.Element {
+ return (
+
+
+ Orchestrator Panel
+
+
+ Select an agent
+
+
+ );
+}
diff --git a/apps/web/src/hooks/useMissionControl.ts b/apps/web/src/hooks/useMissionControl.ts
new file mode 100644
index 0000000..3a5a429
--- /dev/null
+++ b/apps/web/src/hooks/useMissionControl.ts
@@ -0,0 +1,10 @@
+interface UseMissionControlResult {
+ sessions: [];
+ loading: boolean;
+ error: null;
+}
+
+// Stub — will be wired in P2-002
+export function useMissionControl(): UseMissionControlResult {
+ return { sessions: [], loading: false, error: null };
+}