feat(frontend): topology compare/Pareto UI
ci / gates (push) Has been cancelled
ci / rust (push) Has been cancelled
ci / sandbox-k8s (push) Has been cancelled
ci / frontend (push) Has been cancelled
ci / e2e (push) Has been cancelled

Add a Compare tab to /topologies: pick a task + roles + topology kinds, build a
graph per kind, run POST /api/topologies/compare, and render a leaderboard table
+ a quality/cost Pareto scatter (SVG, no deps). Wrap Build + Compare in a tabbed
TopologyWorkbench. e2e p8 extended to run a comparison end-to-end (build×N →
compare → leaderboard + Pareto). Full suite 39 green; build + TS clean.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
Omar Sobh
2026-06-16 03:54:54 -07:00
co-authored by Claude Opus 4.8
parent 7648487a59
commit 654ec0f511
4 changed files with 254 additions and 2 deletions
@@ -0,0 +1,44 @@
"use client";
import { useState } from "react";
import type { CatalogEntry } from "@/lib/api/topology";
import { TopologyCompare } from "./TopologyCompare";
import { TopologyExplorer } from "./TopologyExplorer";
const TABS = ["build", "compare"] as const;
type Tab = (typeof TABS)[number];
/** Tabbed topology workbench: Build (catalog + visualizer) and Compare
* (run a task across topologies → leaderboard + Pareto). */
export function TopologyWorkbench({ catalog }: { catalog: CatalogEntry[] }) {
const [tab, setTab] = useState<Tab>("build");
return (
<div className="flex flex-col gap-6">
<div role="tablist" className="flex gap-1 border-b border-border">
{TABS.map((t) => (
<button
key={t}
type="button"
role="tab"
aria-selected={tab === t}
onClick={() => setTab(t)}
className={`-mb-px border-b-2 px-3 py-2 text-sm capitalize transition-colors ${
tab === t
? "border-coral text-foreground"
: "border-transparent text-muted-foreground hover:text-foreground"
}`}
>
{t}
</button>
))}
</div>
{tab === "build" ? (
<TopologyExplorer catalog={catalog} />
) : (
<TopologyCompare catalog={catalog} />
)}
</div>
);
}