core/workbench-ui/src/app/App.tsx
Shay af0b4f707b feat(workbench): CORE-Logos Studio LG-2 — /logos route shell + Overview/Identity/Safety
Read-only /logos frontend route (Wave M CORE-Logos read-only wave, LG-2):
- route registered via WORKBENCH_ROUTES + lazy ROUTE_ELEMENTS (Substrate section)
- Overview / Identity / Safety tabs over live /logos/packs, /{id}, /safety only
  (no /contents or /alignment — those are LG-3 / LG-4)
- 10 Logos* TS interfaces mirrored; NOT_YET_MIRRORED shrunk back to empty
- SafetyVerdict UI badge + dump-enums.py source + enum-snapshot + coverage test
- logos_pack evidence subject (logos:<pack_id>) + round-trip
- bottom strip "proposal mode: none — read-only"; holonomy rendered as
  missing_evidence (no tab, no proof card); invalid alignment targets surfaced
  honestly in Safety; verdict never mapped to "clear" for warning/unknown

Depends on LG-1 (#737). No mutation endpoints, no engine math in the UI.
2026-06-14 12:12:47 -07:00

119 lines
4.1 KiB
TypeScript

import { BrowserRouter, Routes, Route, Navigate } from "react-router-dom";
import { QueryClientProvider } from "@tanstack/react-query";
import { Suspense, lazy, type ReactElement } from "react";
import { queryClient } from "../api/queries";
import { Shell } from "./Shell";
import { LoadingState } from "../design/components/states/LoadingState";
import { getWorkbenchPrefs } from "./workbenchPrefs";
import { WORKBENCH_ROUTES, type RouteElementMap } from "./routes";
const ChatRoute = lazy(() =>
import("../routes/ChatRoute").then((module) => ({ default: module.ChatRoute })),
);
const TraceRoute = lazy(() =>
import("./trace/TraceRoute").then((module) => ({ default: module.TraceRoute })),
);
const ContemplationRoute = lazy(() =>
import("./contemplation/ContemplationRoute").then((module) => ({
default: module.ContemplationRoute,
})),
);
const ReplayRoute = lazy(() =>
import("./replay/ReplayRoute").then((module) => ({ default: module.ReplayRoute })),
);
const TourRoute = lazy(() =>
import("./tour/TourRoute").then((module) => ({ default: module.TourRoute })),
);
const DemoTheaterRoute = lazy(() =>
import("./demos/DemoTheaterRoute").then((module) => ({
default: module.DemoTheaterRoute,
})),
);
const ProposalsRoute = lazy(() =>
import("./proposals/ProposalsRoute").then((module) => ({
default: module.ProposalsRoute,
})),
);
const RunsRoute = lazy(() =>
import("./runs/RunsRoute").then((module) => ({ default: module.RunsRoute })),
);
const VaultRoute = lazy(() =>
import("./vault/VaultRoute").then((module) => ({ default: module.VaultRoute })),
);
const AuditRoute = lazy(() =>
import("./audit/AuditRoute").then((module) => ({ default: module.AuditRoute })),
);
const EvalsRoute = lazy(() =>
import("./evals/EvalsRoute").then((module) => ({ default: module.EvalsRoute })),
);
const CalibrationRoute = lazy(() =>
import("./calibration/CalibrationRoute").then((module) => ({
default: module.CalibrationRoute,
})),
);
const PacksRoute = lazy(() =>
import("./packs/PacksRoute").then((module) => ({ default: module.PacksRoute })),
);
const LogosRoute = lazy(() =>
import("./logos/LogosRoute").then((module) => ({ default: module.LogosRoute })),
);
const SettingsRoute = lazy(() =>
import("./settings/SettingsRoute").then((module) => ({
default: module.SettingsRoute,
})),
);
const PreviewPage = lazy(() =>
import("../preview/PreviewPage").then((module) => ({ default: module.PreviewPage })),
);
function lazyRoute(element: ReactElement): ReactElement {
return (
<Suspense fallback={<LoadingState label="Loading route..." />}>
{element}
</Suspense>
);
}
// The one place route id → element is bound (App owns the route-component
// imports). Every WORKBENCH_ROUTES id must have an entry here; routes.test
// asserts it, so a registry route without an element fails the suite instead
// of rendering `undefined`.
export const ROUTE_ELEMENTS: RouteElementMap = {
chat: lazyRoute(<ChatRoute />),
trace: lazyRoute(<TraceRoute />),
contemplation: lazyRoute(<ContemplationRoute />),
tour: lazyRoute(<TourRoute />),
replay: lazyRoute(<ReplayRoute />),
demos: lazyRoute(<DemoTheaterRoute />),
proposals: lazyRoute(<ProposalsRoute />),
runs: lazyRoute(<RunsRoute />),
vault: lazyRoute(<VaultRoute />),
audit: lazyRoute(<AuditRoute />),
evals: lazyRoute(<EvalsRoute />),
calibration: lazyRoute(<CalibrationRoute />),
packs: lazyRoute(<PacksRoute />),
logos: lazyRoute(<LogosRoute />),
settings: lazyRoute(<SettingsRoute />),
};
export function App() {
return (
<QueryClientProvider client={queryClient}>
<BrowserRouter>
<Routes>
<Route path="/" element={<Shell />}>
<Route index element={<Navigate to={`/${getWorkbenchPrefs().landingRoute}`} replace />} />
{WORKBENCH_ROUTES.map((route) => (
<Route
key={route.id}
path={route.routePattern}
element={ROUTE_ELEMENTS[route.id]}
/>
))}
</Route>
<Route path="/preview" element={lazyRoute(<PreviewPage />)} />
</Routes>
</BrowserRouter>
</QueryClientProvider>
);
}