diff --git a/packages/dashboard/app/components/command-center/CommandCenter.tsx b/packages/dashboard/app/components/command-center/CommandCenter.tsx index de79c42486..ff26fd0d5e 100644 --- a/packages/dashboard/app/components/command-center/CommandCenter.tsx +++ b/packages/dashboard/app/components/command-center/CommandCenter.tsx @@ -217,6 +217,9 @@ function OverviewTab({ range }: { range: DateRange }) { }, ]; + // FNXC:CommandCenter 2026-06-19-00:00: + // Throughput funnel now renders first in every overview branch (loading/error/empty/populated) + // so the SDLC throughput card is top-of-page; mobile scroll owner and data-testid anchors unchanged. // The throughput funnel reads its own data (activityLog transitions) and shows // its own empty state, so it renders even when the stat-card aggregates have no // data yet. @@ -229,11 +232,11 @@ function OverviewTab({ range }: { range: DateRange }) { if (isInitialLoading) { return (
+ {throughputSection}

{t("commandCenter.loading", "Loading command center...")}

- {throughputSection}
); } @@ -241,11 +244,11 @@ function OverviewTab({ range }: { range: DateRange }) { if (coreError !== null && !hasData) { return (
+ {throughputSection}

{coreError}

- {throughputSection}
); } @@ -253,17 +256,18 @@ function OverviewTab({ range }: { range: DateRange }) { if (!hasData) { return (
+ {throughputSection}

{t("commandCenter.empty", "No usage data yet. Run some agents to populate the Command Center.")}

- {throughputSection}
); } return (
+ {throughputSection}
{cards.map((card) => (
@@ -370,7 +374,6 @@ function OverviewTab({ range }: { range: DateRange }) { ) : null} ) : null} - {throughputSection}
); } diff --git a/packages/dashboard/app/components/command-center/__tests__/CommandCenter.test.tsx b/packages/dashboard/app/components/command-center/__tests__/CommandCenter.test.tsx index b322ff4c7b..86c7359502 100644 --- a/packages/dashboard/app/components/command-center/__tests__/CommandCenter.test.tsx +++ b/packages/dashboard/app/components/command-center/__tests__/CommandCenter.test.tsx @@ -291,6 +291,17 @@ function liveMetricValue(testId = "command-center-live-tasks-in-progress") { return screen.getByTestId(testId).querySelector(".cc-live-metric-value")?.textContent ?? null; } +function expectThroughputFirstBefore(...followingTestIds: string[]) { + const throughput = screen.getByTestId("command-center-throughput"); + expect(throughput.parentElement?.classList.contains("cc-overview")).toBe(true); + expect(throughput.parentElement?.firstElementChild).toBe(throughput); + + for (const testId of followingTestIds) { + const followingNode = screen.getByTestId(testId); + expect(Boolean(throughput.compareDocumentPosition(followingNode) & Node.DOCUMENT_POSITION_FOLLOWING)).toBe(true); + } +} + beforeEach(() => { apiMock.mockReset(); mockEmptyOverviewApi(); @@ -308,6 +319,13 @@ describe("CommandCenter shell", () => { expect(screen.getByTestId("command-center-panel-overview")).toBeTruthy(); }); + it("renders throughput first while the Overview branch is loading", () => { + mockEmptyOverviewApi(); + render(); + expect(screen.getByTestId("command-center-overview-loading")).toBeTruthy(); + expectThroughputFirstBefore("command-center-overview-loading"); + }); + it("renders the documented empty state when there is no data (no crash)", async () => { mockEmptyOverviewApi(); render(); @@ -317,6 +335,7 @@ describe("CommandCenter shell", () => { expect(screen.queryByTestId("cc-overview-pie")).toBeNull(); expect(screen.queryByTestId("cc-overview-line")).toBeNull(); await screen.findByTestId("command-center-empty"); + expectThroughputFirstBefore("command-center-empty"); expect(screen.queryByTestId("command-center-overview-charts")).toBeNull(); expect(screen.queryByTestId("cc-overview-pie")).toBeNull(); expect(screen.queryByTestId("cc-overview-line")).toBeNull(); @@ -352,6 +371,7 @@ describe("CommandCenter shell", () => { expect(statValue("command-center-stat-models")).toBe("2"); expect(statValue("command-center-stat-signals")).toBe("2"); expect(screen.getByTestId("command-center-live-strip")).toBeTruthy(); + expectThroughputFirstBefore("command-center-stat-tokens", "command-center-live-strip"); expect(screen.getByTestId("command-center-live-snapshot")).toBeTruthy(); await waitFor(() => expect(liveMetricValue()).toBe("3")); expect(screen.getByTestId("command-center-live-agents-working").textContent).toContain("2"); @@ -561,6 +581,7 @@ describe("CommandCenter shell", () => { render(); await screen.findByTestId("command-center-overview-error"); + expectThroughputFirstBefore("command-center-overview-error"); expect(screen.getByTestId("command-center-overview-error").textContent).toContain("tokens failed"); expect(screen.queryByTestId("command-center-overview-loading")).toBeNull(); expect(screen.queryByTestId("command-center-empty")).toBeNull();