diff --git a/panel/src/components/dashboard/command-center.tsx b/panel/src/components/dashboard/command-center.tsx
index f49ebf1d..f63bdfa2 100644
--- a/panel/src/components/dashboard/command-center.tsx
+++ b/panel/src/components/dashboard/command-center.tsx
@@ -9,6 +9,7 @@ import { ActiveBlockersPanel } from "./active-blockers-panel";
import { RecentActivityFeed } from "./recent-activity-feed";
import { QuickActionsBar } from "./quick-actions-bar";
import { CeoApprovalQueue } from "./ceo-approval-queue";
+import { PrReviewQueue } from "./pr-review-queue";
import { StrategySignalsPanel } from "./strategy-signals-panel";
import type { Activity } from "./activity-item";
import { Button } from "@/components/ui/button";
@@ -77,6 +78,9 @@ export function CommandCenter() {
+ {/* External-PR review decision queue (hidden when empty) */}
+
+
{/* Metrics, Alerts, and Usage Row */}
(null);
+ const [action, setAction] = useState<"supersede" | "dismiss" | null>(null);
+
+ const { data: reviews, isLoading } = useQuery({
+ queryKey: ["tasks", "external-pr-reviews"],
+ queryFn: () => tasksApi.getExternalPrReviews(),
+ refetchInterval: 30000,
+ });
+
+ const supersedeMutation = useMutation({
+ mutationFn: (taskId: string) => tasksApi.supersedeExternalPr(taskId),
+ onSuccess: (res) => {
+ queryClient.invalidateQueries({ queryKey: ["tasks"] });
+ toast.success(
+ res.ok
+ ? "Superseding — the org is taking the PR over"
+ : "Supersede did not start",
+ );
+ close();
+ },
+ onError: (e) =>
+ toast.error(
+ `Supersede failed: ${e instanceof Error ? e.message : "Unknown error"}`,
+ ),
+ });
+
+ const dismissMutation = useMutation({
+ mutationFn: (taskId: string) => tasksApi.dismissExternalPr(taskId),
+ onSuccess: () => {
+ queryClient.invalidateQueries({ queryKey: ["tasks"] });
+ toast.success("Review dismissed");
+ close();
+ },
+ onError: (e) =>
+ toast.error(
+ `Dismiss failed: ${e instanceof Error ? e.message : "Unknown error"}`,
+ ),
+ });
+
+ const open = (task: Task, a: "supersede" | "dismiss") => {
+ setSelected(task);
+ setAction(a);
+ };
+ const close = () => {
+ setSelected(null);
+ setAction(null);
+ };
+ const confirm = () => {
+ if (!selected) return;
+ if (action === "supersede") supersedeMutation.mutate(selected.id);
+ else if (action === "dismiss") dismissMutation.mutate(selected.id);
+ };
+
+ if (isLoading) {
+ return (
+
+
+
+
+ PR Reviews
+
+
+ External PRs reviewed and awaiting your call
+
+
+
+
+ {[1, 2].map((i) => (
+
+ ))}
+
+
+
+ );
+ }
+
+ const items = reviews || [];
+ if (items.length === 0) return null; // keep the dashboard clean when there's nothing to decide
+
+ const isPending = supersedeMutation.isPending || dismissMutation.isPending;
+
+ return (
+ <>
+
+
+
+
+ PR Reviews
+
+ {items.length}
+
+
+
+ External PRs the org reviewed — supersede or dismiss
+
+
+
+
+ {items.map((task) => (
+
+
+
+ {task.title}
+
+ {task.description && (
+
+ {task.description}
+
+ )}
+
+
+ {task.pr_url && (
+
+
+
+ )}
+
+
+
+
+
+
+
+ ))}
+
+
+
+
+
+ >
+ );
+}
diff --git a/panel/src/lib/api/tasks.ts b/panel/src/lib/api/tasks.ts
index c09d2370..cc6dd2b7 100644
--- a/panel/src/lib/api/tasks.ts
+++ b/panel/src/lib/api/tasks.ts
@@ -697,4 +697,34 @@ export const tasksApi = {
});
return data;
},
+
+ // Inbound external PRs that were reviewed and await the CEO's decision
+ // (the PR-review decision queue).
+ getExternalPrReviews: async (): Promise => {
+ if (isMockMode()) return [];
+ const { data } = await api.get("/tasks/external-pr-reviews");
+ return data;
+ },
+
+ // CEO authorizes the org to take over a reviewed external PR.
+ supersedeExternalPr: async (
+ taskId: string,
+ ): Promise<{ ok: boolean; supersede_task_id?: string; branch?: string }> => {
+ const { data } = await api.post<{
+ ok: boolean;
+ supersede_task_id?: string;
+ branch?: string;
+ }>("/tasks/" + taskId + "/supersede-external-pr");
+ return data;
+ },
+
+ // CEO declines to act on a reviewed external PR (drops it from the queue).
+ dismissExternalPr: async (
+ taskId: string,
+ ): Promise<{ ok: boolean; task_id: string }> => {
+ const { data } = await api.post<{ ok: boolean; task_id: string }>(
+ "/tasks/" + taskId + "/dismiss-external-pr",
+ );
+ return data;
+ },
};