From ceac43121e283d83df71b7e4bcb47d228ee7dbf3 Mon Sep 17 00:00:00 2001 From: Wibias <37517432+Wibias@users.noreply.github.com> Date: Mon, 10 Aug 2026 01:34:31 +0200 Subject: [PATCH 01/16] feat(lab): CL-05 compatibility matrix UI Add GUI compatibility matrix page with lab API integration, i18n, tests, and docs. --- .../001_pr_stack_status.md | 6 +- .../005_cl05_compatibility_matrix_ui.md | 50 +++ gui/src/App.tsx | 6 +- gui/src/app-routing.ts | 2 + gui/src/i18n/de.ts | 40 ++ gui/src/i18n/en.ts | 42 +++ gui/src/i18n/ja.ts | 40 ++ gui/src/i18n/ko.ts | 41 +++ gui/src/i18n/ru.ts | 40 ++ gui/src/i18n/tr.ts | 40 ++ gui/src/i18n/zh.ts | 40 ++ gui/src/icons.tsx | 1 + gui/src/pages/CompatibilityMatrix.tsx | 344 ++++++++++++++++++ gui/src/pages/compatibility-matrix-api.ts | 82 +++++ gui/src/pages/compatibility-matrix-shared.ts | 186 ++++++++++ gui/src/styles-compatibility-matrix.css | 229 ++++++++++++ gui/src/styles.css | 1 + gui/tests/compatibility-matrix-layout.test.ts | 27 ++ gui/tests/compatibility-matrix.test.tsx | 196 ++++++++++ structure/09_compatibility-lab.md | 4 + 20 files changed, 1414 insertions(+), 3 deletions(-) create mode 100644 devlog/_plan/260807_compatibility_lab/005_cl05_compatibility_matrix_ui.md create mode 100644 gui/src/pages/CompatibilityMatrix.tsx create mode 100644 gui/src/pages/compatibility-matrix-api.ts create mode 100644 gui/src/pages/compatibility-matrix-shared.ts create mode 100644 gui/src/styles-compatibility-matrix.css create mode 100644 gui/tests/compatibility-matrix-layout.test.ts create mode 100644 gui/tests/compatibility-matrix.test.tsx diff --git a/devlog/_plan/260807_compatibility_lab/001_pr_stack_status.md b/devlog/_plan/260807_compatibility_lab/001_pr_stack_status.md index 2fde00f849..60d03393aa 100644 --- a/devlog/_plan/260807_compatibility_lab/001_pr_stack_status.md +++ b/devlog/_plan/260807_compatibility_lab/001_pr_stack_status.md @@ -23,7 +23,8 @@ independent review, blockers, and whether a later phase is authorized. | CL-01 | `feat/cl-01-conformance-harness` | `c2113ca47b8a05c5a5f90679e4eaa640ca2c6a66` | `22d608c82d82e2746c0cef9cd761db19a8e465ee` | [#1320](https://github.com/lidge-jun/opencodex/pull/1320) | MERGED TO `dev` at `4bb249b756abd468c675d2d92fffe4da95ad3e2a` | | CL-02 | `feat/cl-02-evidence-ledger` | `4bb249b756abd468c675d2d92fffe4da95ad3e2a` | NOT RECORDED | [#1333](https://github.com/lidge-jun/opencodex/pull/1333) | MERGED TO `dev` at `025c37916225dd685d9217e5b40190600f06d278`; POST-MERGE HARDENING [#1343](https://github.com/lidge-jun/opencodex/pull/1343) MERGED at `eee2dab4d1bbacefce56057adad51d734f346702`; FINAL CLOSURE GATE [#1348](https://github.com/lidge-jun/opencodex/pull/1348) | | CL-03 | `feat/cl-03-live-route-probes` | `4f746d13799888ea0a8c7a111aa2ad61c2126ea0` | `003f7402f49bfe8dd710a7beba52f717051bfadf` | [#1352](https://github.com/lidge-jun/opencodex/pull/1352) | MERGED TO `dev` at `68c71a4e9cdf882d812f09fd94783a28749db629`; ACCEPTED/CLOSED | -| CL-04 | `feat/cl-04-lab-read-surfaces` | `68c71a4e9cdf882d812f09fd94783a28749db629` | NOT RECORDED | DRAFT PENDING | IMPLEMENTATION IN PROGRESS (not accepted) | +| CL-04 | `feat/cl-04-lab-read-surfaces` | `68c71a4e9cdf882d812f09fd94783a28749db629` | NOT RECORDED | [#1378](https://github.com/lidge-jun/opencodex/pull/1378) | MERGED TO `dev` at `d517161aeaa3a974ad3c0360ff0c97b03b4c4520` | +| CL-05 | `feat/cl-05-compatibility-matrix-ui` | `d517161aeaa3a974ad3c0360ff0c97b03b4c4520` | NOT RECORDED | DRAFT PENDING | IMPLEMENTATION IN PROGRESS (not accepted) | The CL-01 starting SHA is the exact CL-00 tip recorded when CL-01 began. Its moving base-ref name is not a substitute for that historical SHA. @@ -158,7 +159,8 @@ Claims cannot produce `PROBED`/`VERIFIED`. - CL-01: **MERGED** via #1320 at `4bb249b756abd468c675d2d92fffe4da95ad3e2a`. - CL-02: **MERGED** via #1333 at `025c37916225dd685d9217e5b40190600f06d278`; post-merge hardening #1343 is also **MERGED** at `eee2dab4d1bbacefce56057adad51d734f346702`; final closure is tracked in #1348. - CL-03: **ACCEPTED/CLOSED** via [#1352](https://github.com/lidge-jun/opencodex/pull/1352), merged to `dev` at `68c71a4e9cdf882d812f09fd94783a28749db629`. -- CL-04: **IMPLEMENTATION IN PROGRESS**, authorized from accepted CL-03 merge `68c71a4e9cdf882d812f09fd94783a28749db629`. +- CL-04: **MERGED** via #1378 at `d517161aeaa3a974ad3c0360ff0c97b03b4c4520`. +- CL-05: **IMPLEMENTATION IN PROGRESS**, authorized from CL-04 merge `d517161aeaa3a974ad3c0360ff0c97b03b4c4520`. ## CL-03 implementation log (2026-08-09) diff --git a/devlog/_plan/260807_compatibility_lab/005_cl05_compatibility_matrix_ui.md b/devlog/_plan/260807_compatibility_lab/005_cl05_compatibility_matrix_ui.md new file mode 100644 index 0000000000..efa090d69f --- /dev/null +++ b/devlog/_plan/260807_compatibility_lab/005_cl05_compatibility_matrix_ui.md @@ -0,0 +1,50 @@ +# CL-05 implementation record — Compatibility Matrix UI + +## Programme position + +- **Phase:** CL-05 (read-only GUI) +- **Starting `upstream/dev` SHA:** `d517161aeaa3a974ad3c0360ff0c97b03b4c4520` (merge #1378 / CL-04) +- **Branch:** `feat/cl-05-compatibility-matrix-ui` +- **PR:** DRAFT PENDING → `lidge-jun/opencodex:dev` +- **CL-06:** not started + +## Scope delivered + +### GUI (`gui/src/pages/`) + +- New sidebar route `#lab` — **Compatibility Lab** +- `CompatibilityMatrix.tsx` — read-only verdict matrix over CL-04 management APIs +- `compatibility-matrix-api.ts` — paginated fetch helpers for `/api/lab/status`, `/api/lab/verdicts`, `/api/lab/subjects` +- `compatibility-matrix-shared.ts` — DTO parsing, matrix grouping, filters +- `styles-compatibility-matrix.css` — scrollable matrix + detail tables (api-auth-matrix pattern) +- i18n keys in all seven locales (`en`, `de`, `ko`, `zh`, `ru`, `ja`, `tr`) +- Component/layout tests under `gui/tests/compatibility-matrix*.test.*` + +### Behaviour + +- Projection status cards (subjects, verdicts, observations, events, built-at) +- Subject × evidence-layer matrix with per-suite verdict badges +- Filterable verdict detail table (layer, verdict, subject id) +- Empty/unavailable/incompatible projection states via existing data-surface contract +- No probe execution, projection rebuild, or evidence mutation + +## Validation (local) + +- `bun x tsc --noEmit` — pending +- `bun test tests/lab-read-surfaces.test.ts` — pending +- `cd gui && bun test tests/compatibility-matrix.test.tsx tests/compatibility-matrix-layout.test.ts` — pending +- `cd gui && bun run lint` — pending +- `cd gui && bun run build` — pending +- `bun run privacy:scan` — pending + +## Acceptance blockers + +- Draft PR requires cross-platform CI green +- GUI screenshot in PR body (or `gui-screenshot-waived` label) +- Independent acceptance review not performed + +## Out of scope (confirmed) + +- CL-06 routing profile compatibility fields, CL-07 fabric, CL-08 shadow/automatic/public publish +- New management APIs or CLI changes (CL-04 read surfaces are sufficient) +- Probe execution, projection rebuild triggers, raw artifact download in GUI diff --git a/gui/src/App.tsx b/gui/src/App.tsx index e2afbb4f84..fa8ae94b04 100644 --- a/gui/src/App.tsx +++ b/gui/src/App.tsx @@ -9,10 +9,11 @@ import Usage from "./pages/Usage"; import Storage from "./pages/Storage"; import CodexAuth from "./pages/CodexAuth"; import Integrations from "./pages/Integrations"; +import CompatibilityMatrix from "./pages/CompatibilityMatrix"; import Startup from "./pages/Startup"; import ErrorBoundary from "./components/ErrorBoundary"; import { SidebarGithubRow } from "./components/sidebar-github-row"; -import { IconGrid, IconServer, IconBoxes, IconBot, IconList, IconActivity, IconHardDrive, IconKey, IconMenu, IconSun, IconMoon, IconMonitor, IconGlobe, IconPower, IconX } from "./icons"; +import { IconGrid, IconServer, IconBoxes, IconBot, IconList, IconActivity, IconLab, IconHardDrive, IconKey, IconMenu, IconSun, IconMoon, IconMonitor, IconGlobe, IconPower, IconX } from "./icons"; import { useI18n, useT, LOCALES, localeDisplayName, type Locale, type TKey } from "./i18n/shared"; import { Select } from "./ui"; import { installApiAuthFetch } from "./api"; @@ -33,6 +34,7 @@ const PAGE_TKEY: Record = { subagents: "nav.subagents", logs: "nav.logs", usage: "nav.usage", + lab: "nav.lab", storage: "nav.storage", "codex-auth": "nav.codexAuth", integrations: "nav.integrations", @@ -63,6 +65,7 @@ const NAV: NavEntry[] = [ { id: "subagents", tkey: "nav.subagents", Icon: IconBot }, { id: "logs", tkey: "nav.logs", Icon: IconList }, { id: "usage", tkey: "nav.usage", Icon: IconActivity }, + { id: "lab", tkey: "nav.lab", Icon: IconLab }, { id: "storage", tkey: "nav.storage", Icon: IconHardDrive }, { id: "integrations", tkey: "nav.integrations", Icon: IconGlobe }, ]; @@ -305,6 +308,7 @@ export default function App() { {page === "subagents" && } {page === "logs" && } {page === "usage" && } + {page === "lab" && } {page === "storage" && } {page === "codex-auth" && } {page === "integrations" && } diff --git a/gui/src/app-routing.ts b/gui/src/app-routing.ts index 55b59af85b..20dcba2698 100644 --- a/gui/src/app-routing.ts +++ b/gui/src/app-routing.ts @@ -10,6 +10,7 @@ export type Page = | "subagents" | "logs" | "usage" + | "lab" | "storage" | "codex-auth" | "integrations"; @@ -22,6 +23,7 @@ export const VALID_PAGES = new Set([ "subagents", "logs", "usage", + "lab", "storage", "codex-auth", "integrations", diff --git a/gui/src/i18n/de.ts b/gui/src/i18n/de.ts index ad073d31a4..034c4a0831 100644 --- a/gui/src/i18n/de.ts +++ b/gui/src/i18n/de.ts @@ -64,6 +64,7 @@ export const de: Record = { "routing.analyticsEmpty": "Noch keine Analysen – senden Sie zuerst einige Anfragen.", "nav.logs": "Protokolle & Diagnose", "nav.usage": "Nutzung", + "nav.lab": "Kompatibilitäts-Labor", "common.github": "GitHub", "sidebar.star": "Auf GitHub mit Stern markieren", "sidebar.starred": "Auf GitHub markiert", @@ -1908,4 +1909,43 @@ export const de: Record = { "sub.delegation.modelHint": "Das Modell, zu dem Codex zuerst greift, wenn es Arbeit übergibt. Oben steht, wen es überhaupt aufrufen darf; hier wählst du den Ersten davon.", "dash.syncModelsHint": "Schreibt Codex' Modellkatalog anhand deiner verbundenen Provider neu.", "dash.syncRun": "Jetzt synchronisieren", + "lab.title": "Kompatibilitäts-Labor", + "lab.subtitle": "Schreibgeschützte Kompatibilitätsmatrix aus der Lab-Projektion.", + "lab.loadFailed": "Kompatibilitäts-Lab-Daten konnten nicht geladen werden", + "lab.projectionUnavailable": "Lab-Projektion ist nicht verfügbar. Führen Sie zuerst Konformitäts- oder Live-Probes aus.", + "lab.projectionIncompatible": "Lab-Projektionsschema ist inkompatibel. Projektion neu aufbauen.", + "lab.statusTitle": "Projektionsstatus", + "lab.matrixTitle": "Kompatibilitätsmatrix", + "lab.verdictsTitle": "Urteilsdatensätze", + "lab.filter.layer": "Evidenzschicht", + "lab.filter.verdict": "Urteil", + "lab.filter.subject": "Subject-ID", + "lab.filter.all": "Alle", + "lab.col.subject": "Subject", + "lab.col.layer": "Schicht", + "lab.col.suite": "Suite", + "lab.col.verdict": "Urteil", + "lab.col.asOf": "Stand", + "lab.col.protocol": "Protokollkonformität", + "lab.col.live": "Live-Route-Kompatibilität", + "lab.col.task": "Aufgabenwirksamkeit", + "lab.empty": "Noch keine Kompatibilitätsurteile in der Projektion.", + "lab.subjectKind": "Art", + "lab.observationCount": "Beobachtungen", + "lab.eventCount": "Ereignisse", + "lab.verdictCount": "Urteile", + "lab.subjectCount": "Subjects", + "lab.builtAt": "Erstellt", + "lab.loading": "Kompatibilitätsevidenz wird geladen…", + "lab.refresh": "Aktualisieren", + "lab.verdict.UNKNOWN": "Unbekannt", + "lab.verdict.CLAIMED": "Behauptet", + "lab.verdict.PROBED": "Geprüft", + "lab.verdict.VERIFIED": "Verifiziert", + "lab.verdict.DEGRADED": "Eingeschränkt", + "lab.verdict.BLOCKED": "Blockiert", + "lab.verdict.UNSUPPORTED": "Nicht unterstützt", + "lab.layer.protocol_conformance": "Protokollkonformität", + "lab.layer.live_route_compatibility": "Live-Route-Kompatibilität", + "lab.layer.task_effectiveness": "Aufgabenwirksamkeit", }; diff --git a/gui/src/i18n/en.ts b/gui/src/i18n/en.ts index 1b8c25bf3b..3cef5e1487 100644 --- a/gui/src/i18n/en.ts +++ b/gui/src/i18n/en.ts @@ -19,6 +19,7 @@ export const en = { "nav.subagents": "Subagents", "nav.logs": "Logs & Debug", "nav.usage": "Usage", + "nav.lab": "Compatibility Lab", "common.github": "GitHub", "sidebar.star": "Star on GitHub", "sidebar.starred": "Starred on GitHub", @@ -1936,6 +1937,47 @@ export const en = { "claudeDesktop.effort.supported": "effort", "claudeDesktop.effort.displayOnly": "effort (display only)", + // compatibility lab (CL-05) + "lab.title": "Compatibility Lab", + "lab.subtitle": "Read-only compatibility verdict matrix from lab projection evidence.", + "lab.loadFailed": "Could not load compatibility lab data", + "lab.projectionUnavailable": "Lab projection is not available. Run conformance or live probes first.", + "lab.projectionIncompatible": "Lab projection schema is incompatible. Rebuild the projection.", + "lab.statusTitle": "Projection status", + "lab.matrixTitle": "Compatibility matrix", + "lab.verdictsTitle": "Verdict records", + "lab.filter.layer": "Evidence layer", + "lab.filter.verdict": "Verdict", + "lab.filter.subject": "Subject ID", + "lab.filter.all": "All", + "lab.col.subject": "Subject", + "lab.col.layer": "Layer", + "lab.col.suite": "Suite", + "lab.col.verdict": "Verdict", + "lab.col.asOf": "As of", + "lab.col.protocol": "Protocol conformance", + "lab.col.live": "Live route compatibility", + "lab.col.task": "Task effectiveness", + "lab.empty": "No compatibility verdicts in the projection yet.", + "lab.subjectKind": "Kind", + "lab.observationCount": "Observations", + "lab.eventCount": "Events", + "lab.verdictCount": "Verdicts", + "lab.subjectCount": "Subjects", + "lab.builtAt": "Built", + "lab.loading": "Loading compatibility evidence…", + "lab.refresh": "Refresh", + "lab.verdict.UNKNOWN": "Unknown", + "lab.verdict.CLAIMED": "Claimed", + "lab.verdict.PROBED": "Probed", + "lab.verdict.VERIFIED": "Verified", + "lab.verdict.DEGRADED": "Degraded", + "lab.verdict.BLOCKED": "Blocked", + "lab.verdict.UNSUPPORTED": "Unsupported", + "lab.layer.protocol_conformance": "Protocol conformance", + "lab.layer.live_route_compatibility": "Live route compatibility", + "lab.layer.task_effectiveness": "Task effectiveness", + } as const; export type TKey = keyof typeof en; diff --git a/gui/src/i18n/ja.ts b/gui/src/i18n/ja.ts index 6a163d1618..f58d21e95a 100644 --- a/gui/src/i18n/ja.ts +++ b/gui/src/i18n/ja.ts @@ -64,6 +64,7 @@ export const ja: Record = { "routing.analyticsEmpty": "分析はまだありません。まずリクエストを送信してください。", "nav.logs": "ログ & デバッグ", "nav.usage": "使用量", + "nav.lab": "互換性ラボ", "common.github": "GitHub", "sidebar.star": "GitHub でスターを付ける", "sidebar.starred": "GitHub でスター済み", @@ -1929,4 +1930,43 @@ export const ja: Record = { "sub.delegation.modelHint": "Codex が作業を任せるとき、最初に呼ぶモデルです。上のおすすめが呼べる候補で、ここで選んだものがその中の第一候補になります。", "dash.syncModelsHint": "接続済みのプロバイダーをもとに Codex のモデルカタログを書き直します。", "dash.syncRun": "今すぐ同期", + "lab.title": "Compatibility Lab", + "lab.subtitle": "Read-only compatibility verdict matrix from lab projection evidence.", + "lab.loadFailed": "Could not load compatibility lab data", + "lab.projectionUnavailable": "Lab projection is not available. Run conformance or live probes first.", + "lab.projectionIncompatible": "Lab projection schema is incompatible. Rebuild the projection.", + "lab.statusTitle": "Projection status", + "lab.matrixTitle": "Compatibility matrix", + "lab.verdictsTitle": "Verdict records", + "lab.filter.layer": "Evidence layer", + "lab.filter.verdict": "Verdict", + "lab.filter.subject": "Subject ID", + "lab.filter.all": "All", + "lab.col.subject": "Subject", + "lab.col.layer": "Layer", + "lab.col.suite": "Suite", + "lab.col.verdict": "Verdict", + "lab.col.asOf": "As of", + "lab.col.protocol": "Protocol conformance", + "lab.col.live": "Live route compatibility", + "lab.col.task": "Task effectiveness", + "lab.empty": "No compatibility verdicts in the projection yet.", + "lab.subjectKind": "Kind", + "lab.observationCount": "Observations", + "lab.eventCount": "Events", + "lab.verdictCount": "Verdicts", + "lab.subjectCount": "Subjects", + "lab.builtAt": "Built", + "lab.loading": "Loading compatibility evidence…", + "lab.refresh": "Refresh", + "lab.verdict.UNKNOWN": "Unknown", + "lab.verdict.CLAIMED": "Claimed", + "lab.verdict.PROBED": "Probed", + "lab.verdict.VERIFIED": "Verified", + "lab.verdict.DEGRADED": "Degraded", + "lab.verdict.BLOCKED": "Blocked", + "lab.verdict.UNSUPPORTED": "Unsupported", + "lab.layer.protocol_conformance": "Protocol conformance", + "lab.layer.live_route_compatibility": "Live route compatibility", + "lab.layer.task_effectiveness": "Task effectiveness", }; diff --git a/gui/src/i18n/ko.ts b/gui/src/i18n/ko.ts index 30097ac458..f49d8c0560 100644 --- a/gui/src/i18n/ko.ts +++ b/gui/src/i18n/ko.ts @@ -64,6 +64,7 @@ export const ko: Record = { "routing.analyticsEmpty": "분석이 아직 없습니다. 먼저 요청을 보내세요.", "nav.logs": "로그&디버그", "nav.usage": "사용량", + "nav.lab": "호환성 랩", "common.github": "GitHub", "sidebar.star": "GitHub에서 스타 누르기", "sidebar.starred": "GitHub 스타 완료", @@ -1929,4 +1930,44 @@ export const ko: Record = { "claudeDesktop.effort.supported": "effort", "claudeDesktop.effort.displayOnly": "effort (표시만)", + "lab.title": "Compatibility Lab", + "lab.subtitle": "Read-only compatibility verdict matrix from lab projection evidence.", + "lab.loadFailed": "Could not load compatibility lab data", + "lab.projectionUnavailable": "Lab projection is not available. Run conformance or live probes first.", + "lab.projectionIncompatible": "Lab projection schema is incompatible. Rebuild the projection.", + "lab.statusTitle": "Projection status", + "lab.matrixTitle": "Compatibility matrix", + "lab.verdictsTitle": "Verdict records", + "lab.filter.layer": "Evidence layer", + "lab.filter.verdict": "Verdict", + "lab.filter.subject": "Subject ID", + "lab.filter.all": "All", + "lab.col.subject": "Subject", + "lab.col.layer": "Layer", + "lab.col.suite": "Suite", + "lab.col.verdict": "Verdict", + "lab.col.asOf": "As of", + "lab.col.protocol": "Protocol conformance", + "lab.col.live": "Live route compatibility", + "lab.col.task": "Task effectiveness", + "lab.empty": "No compatibility verdicts in the projection yet.", + "lab.subjectKind": "Kind", + "lab.observationCount": "Observations", + "lab.eventCount": "Events", + "lab.verdictCount": "Verdicts", + "lab.subjectCount": "Subjects", + "lab.builtAt": "Built", + "lab.loading": "Loading compatibility evidence…", + "lab.refresh": "Refresh", + "lab.verdict.UNKNOWN": "Unknown", + "lab.verdict.CLAIMED": "Claimed", + "lab.verdict.PROBED": "Probed", + "lab.verdict.VERIFIED": "Verified", + "lab.verdict.DEGRADED": "Degraded", + "lab.verdict.BLOCKED": "Blocked", + "lab.verdict.UNSUPPORTED": "Unsupported", + "lab.layer.protocol_conformance": "Protocol conformance", + "lab.layer.live_route_compatibility": "Live route compatibility", + "lab.layer.task_effectiveness": "Task effectiveness", + }; diff --git a/gui/src/i18n/ru.ts b/gui/src/i18n/ru.ts index d462a81adb..886d0691d1 100644 --- a/gui/src/i18n/ru.ts +++ b/gui/src/i18n/ru.ts @@ -64,6 +64,7 @@ export const ru: Record = { "routing.analyticsEmpty": "Аналитики пока нет — сначала отправьте несколько запросов.", "nav.logs": "Логи и отладка", "nav.usage": "Использование", + "nav.lab": "Лаборатория совместимости", "common.github": "GitHub", "sidebar.star": "Поставить звезду на GitHub", "sidebar.starred": "Звезда на GitHub поставлена", @@ -1931,4 +1932,43 @@ export const ru: Record = { "sub.delegation.modelHint": "Модель, к которой Codex обращается первой, когда передаёт работу. Список выше — кого он вообще может вызвать, а здесь выбирается первый в очереди.", "dash.syncModelsHint": "Перезаписывает каталог моделей Codex по подключённым провайдерам.", "dash.syncRun": "Синхронизировать", + "lab.title": "Compatibility Lab", + "lab.subtitle": "Read-only compatibility verdict matrix from lab projection evidence.", + "lab.loadFailed": "Could not load compatibility lab data", + "lab.projectionUnavailable": "Lab projection is not available. Run conformance or live probes first.", + "lab.projectionIncompatible": "Lab projection schema is incompatible. Rebuild the projection.", + "lab.statusTitle": "Projection status", + "lab.matrixTitle": "Compatibility matrix", + "lab.verdictsTitle": "Verdict records", + "lab.filter.layer": "Evidence layer", + "lab.filter.verdict": "Verdict", + "lab.filter.subject": "Subject ID", + "lab.filter.all": "All", + "lab.col.subject": "Subject", + "lab.col.layer": "Layer", + "lab.col.suite": "Suite", + "lab.col.verdict": "Verdict", + "lab.col.asOf": "As of", + "lab.col.protocol": "Protocol conformance", + "lab.col.live": "Live route compatibility", + "lab.col.task": "Task effectiveness", + "lab.empty": "No compatibility verdicts in the projection yet.", + "lab.subjectKind": "Kind", + "lab.observationCount": "Observations", + "lab.eventCount": "Events", + "lab.verdictCount": "Verdicts", + "lab.subjectCount": "Subjects", + "lab.builtAt": "Built", + "lab.loading": "Loading compatibility evidence…", + "lab.refresh": "Refresh", + "lab.verdict.UNKNOWN": "Unknown", + "lab.verdict.CLAIMED": "Claimed", + "lab.verdict.PROBED": "Probed", + "lab.verdict.VERIFIED": "Verified", + "lab.verdict.DEGRADED": "Degraded", + "lab.verdict.BLOCKED": "Blocked", + "lab.verdict.UNSUPPORTED": "Unsupported", + "lab.layer.protocol_conformance": "Protocol conformance", + "lab.layer.live_route_compatibility": "Live route compatibility", + "lab.layer.task_effectiveness": "Task effectiveness", }; diff --git a/gui/src/i18n/tr.ts b/gui/src/i18n/tr.ts index 32e97e2e41..e2c83461cf 100644 --- a/gui/src/i18n/tr.ts +++ b/gui/src/i18n/tr.ts @@ -18,6 +18,7 @@ export const tr: Record = { "nav.subagents": "Alt Ajanlar", "nav.logs": "Günlükler & Hata Ayıklama", "nav.usage": "Kullanım", + "nav.lab": "Uyumluluk Laboratuvarı", "common.github": "GitHub", "sidebar.star": "GitHub'da Yıldız Ver", "sidebar.starred": "GitHub'da Yıldız Verildi", @@ -1931,4 +1932,43 @@ export const tr: Record = { "claudeDesktop.health.stats": "{count} istek / {errors} hata", "claudeDesktop.effort.supported": "çaba", "claudeDesktop.effort.displayOnly": "çaba (yalnızca ekran)", + "lab.title": "Compatibility Lab", + "lab.subtitle": "Read-only compatibility verdict matrix from lab projection evidence.", + "lab.loadFailed": "Could not load compatibility lab data", + "lab.projectionUnavailable": "Lab projection is not available. Run conformance or live probes first.", + "lab.projectionIncompatible": "Lab projection schema is incompatible. Rebuild the projection.", + "lab.statusTitle": "Projection status", + "lab.matrixTitle": "Compatibility matrix", + "lab.verdictsTitle": "Verdict records", + "lab.filter.layer": "Evidence layer", + "lab.filter.verdict": "Verdict", + "lab.filter.subject": "Subject ID", + "lab.filter.all": "All", + "lab.col.subject": "Subject", + "lab.col.layer": "Layer", + "lab.col.suite": "Suite", + "lab.col.verdict": "Verdict", + "lab.col.asOf": "As of", + "lab.col.protocol": "Protocol conformance", + "lab.col.live": "Live route compatibility", + "lab.col.task": "Task effectiveness", + "lab.empty": "No compatibility verdicts in the projection yet.", + "lab.subjectKind": "Kind", + "lab.observationCount": "Observations", + "lab.eventCount": "Events", + "lab.verdictCount": "Verdicts", + "lab.subjectCount": "Subjects", + "lab.builtAt": "Built", + "lab.loading": "Loading compatibility evidence…", + "lab.refresh": "Refresh", + "lab.verdict.UNKNOWN": "Unknown", + "lab.verdict.CLAIMED": "Claimed", + "lab.verdict.PROBED": "Probed", + "lab.verdict.VERIFIED": "Verified", + "lab.verdict.DEGRADED": "Degraded", + "lab.verdict.BLOCKED": "Blocked", + "lab.verdict.UNSUPPORTED": "Unsupported", + "lab.layer.protocol_conformance": "Protocol conformance", + "lab.layer.live_route_compatibility": "Live route compatibility", + "lab.layer.task_effectiveness": "Task effectiveness", }; diff --git a/gui/src/i18n/zh.ts b/gui/src/i18n/zh.ts index c62f4477cc..de3ba1fa75 100644 --- a/gui/src/i18n/zh.ts +++ b/gui/src/i18n/zh.ts @@ -64,6 +64,7 @@ export const zh: Record = { "routing.analyticsEmpty": "暂无分析 — 请先发送一些请求。", "nav.logs": "日志与调试", "nav.usage": "用量", + "nav.lab": "兼容性实验室", "common.github": "GitHub", "sidebar.star": "在 GitHub 上加星", "sidebar.starred": "已在 GitHub 加星", @@ -1929,4 +1930,43 @@ export const zh: Record = { "sub.delegation.modelHint": "Codex 分派工作时最先调用的模型。上面的推荐是可调用的名单,这里选的是其中第一顺位。", "dash.syncModelsHint": "按已连接的提供商重写 Codex 的模型目录。", "dash.syncRun": "立即同步", + "lab.title": "Compatibility Lab", + "lab.subtitle": "Read-only compatibility verdict matrix from lab projection evidence.", + "lab.loadFailed": "Could not load compatibility lab data", + "lab.projectionUnavailable": "Lab projection is not available. Run conformance or live probes first.", + "lab.projectionIncompatible": "Lab projection schema is incompatible. Rebuild the projection.", + "lab.statusTitle": "Projection status", + "lab.matrixTitle": "Compatibility matrix", + "lab.verdictsTitle": "Verdict records", + "lab.filter.layer": "Evidence layer", + "lab.filter.verdict": "Verdict", + "lab.filter.subject": "Subject ID", + "lab.filter.all": "All", + "lab.col.subject": "Subject", + "lab.col.layer": "Layer", + "lab.col.suite": "Suite", + "lab.col.verdict": "Verdict", + "lab.col.asOf": "As of", + "lab.col.protocol": "Protocol conformance", + "lab.col.live": "Live route compatibility", + "lab.col.task": "Task effectiveness", + "lab.empty": "No compatibility verdicts in the projection yet.", + "lab.subjectKind": "Kind", + "lab.observationCount": "Observations", + "lab.eventCount": "Events", + "lab.verdictCount": "Verdicts", + "lab.subjectCount": "Subjects", + "lab.builtAt": "Built", + "lab.loading": "Loading compatibility evidence…", + "lab.refresh": "Refresh", + "lab.verdict.UNKNOWN": "Unknown", + "lab.verdict.CLAIMED": "Claimed", + "lab.verdict.PROBED": "Probed", + "lab.verdict.VERIFIED": "Verified", + "lab.verdict.DEGRADED": "Degraded", + "lab.verdict.BLOCKED": "Blocked", + "lab.verdict.UNSUPPORTED": "Unsupported", + "lab.layer.protocol_conformance": "Protocol conformance", + "lab.layer.live_route_compatibility": "Live route compatibility", + "lab.layer.task_effectiveness": "Task effectiveness", }; diff --git a/gui/src/icons.tsx b/gui/src/icons.tsx index bed8492599..d19e8fac0c 100644 --- a/gui/src/icons.tsx +++ b/gui/src/icons.tsx @@ -15,6 +15,7 @@ export const IconList = (p: P) => (); export const IconTerminal = (p: P) => (); export const IconActivity = (p: P) => (); +export const IconLab = (p: P) => (); export const IconHardDrive = (p: P) => (); export const IconCheck = (p: P) => (); diff --git a/gui/src/pages/CompatibilityMatrix.tsx b/gui/src/pages/CompatibilityMatrix.tsx new file mode 100644 index 0000000000..d525828a22 --- /dev/null +++ b/gui/src/pages/CompatibilityMatrix.tsx @@ -0,0 +1,344 @@ +import { useCallback, useMemo, useState } from "react"; +import { IconRefresh } from "../icons"; +import { useI18n, type TKey } from "../i18n/shared"; +import { EmptyState, Notice, Select } from "../ui"; +import { useDataSurface } from "../data-surface"; +import { DataSurfaceSkeleton, DataSurfaceStatus } from "../components/data-surface"; +import { fetchLabPageData, type LabPageData } from "./compatibility-matrix-api"; +import { + COMPATIBILITY_VERDICTS, + EVIDENCE_LAYERS, + buildMatrixRows, + filterVerdicts, + formatAsOf, + shortSubjectId, + type CompatibilityVerdict, + type EvidenceLayer, + type VerdictDto, + type VerdictFilters, +} from "./compatibility-matrix-shared"; + +const LAYER_LABEL: Record = { + protocol_conformance: "lab.layer.protocol_conformance", + live_route_compatibility: "lab.layer.live_route_compatibility", + task_effectiveness: "lab.layer.task_effectiveness", +}; + +const LAYER_COLUMN: Record = { + protocol_conformance: "lab.col.protocol", + live_route_compatibility: "lab.col.live", + task_effectiveness: "lab.col.task", +}; + +const VERDICT_LABEL: Record = { + UNKNOWN: "lab.verdict.UNKNOWN", + CLAIMED: "lab.verdict.CLAIMED", + PROBED: "lab.verdict.PROBED", + VERIFIED: "lab.verdict.VERIFIED", + DEGRADED: "lab.verdict.DEGRADED", + BLOCKED: "lab.verdict.BLOCKED", + UNSUPPORTED: "lab.verdict.UNSUPPORTED", +}; + +function localizedFetchError(e: unknown, fallback: string): string { + if (!(e instanceof Error)) return fallback; + const msg = e.message; + if ( + msg === "Failed to fetch" + || msg.includes("NetworkError") + || msg.includes("network error") + ) { + return fallback; + } + return msg || fallback; +} + +function VerdictBadge({ + verdict, + suiteId, + label, +}: { + verdict: CompatibilityVerdict; + suiteId: string; + label: string; +}) { + return ( + + {label} + {suiteId} + + ); +} + +function VerdictCell({ + rows, + t, +}: { + rows: VerdictDto[]; + t: (key: TKey) => string; +}) { + if (rows.length === 0) return ; + return ( +
+ {rows.map(row => ( + + ))} +
+ ); +} + +function StatusCards({ + data, + t, + locale, +}: { + data: LabPageData; + t: (key: TKey, vars?: Record) => string; + locale: string; +}) { + const { status } = data; + const cards: Array<{ label: string; value: string }> = [ + { label: t("lab.subjectCount"), value: String(status.subjectCount ?? 0) }, + { label: t("lab.verdictCount"), value: String(status.verdictCount ?? 0) }, + { label: t("lab.observationCount"), value: String(status.observationCount ?? 0) }, + { label: t("lab.eventCount"), value: String(status.eventCount ?? 0) }, + ]; + if (status.builtAtMs) { + cards.push({ + label: t("lab.builtAt"), + value: formatAsOf(status.builtAtMs, locale), + }); + } + return ( +
+ {cards.map(card => ( +
+ {card.label} + {card.value} +
+ ))} +
+ ); +} + +export default function CompatibilityMatrix({ apiBase }: { apiBase: string }) { + const { t, locale } = useI18n(); + const [filters, setFilters] = useState({ + layer: "", + verdict: "", + subjectQuery: "", + }); + + const resourceKey = `lab-matrix:${apiBase}`; + const fetchPage = useCallback( + (signal: AbortSignal) => fetchLabPageData(apiBase, signal), + [apiBase], + ); + + const surface = useDataSurface(resourceKey, [apiBase], fetchPage, { + isEmpty: (data: LabPageData) => data.verdicts.length === 0, + pollMs: 60_000, + }); + + const filteredVerdicts = useMemo(() => { + if (!surface.data) return []; + return filterVerdicts(surface.data.verdicts, filters); + }, [surface.data, filters]); + + const matrixRows = useMemo(() => { + if (!surface.data) return []; + return buildMatrixRows(filteredVerdicts, surface.data.subjects); + }, [filteredVerdicts, surface.data]); + + const layerOptions = [ + { value: "", label: t("lab.filter.all") }, + ...EVIDENCE_LAYERS.map(layer => ({ value: layer, label: t(LAYER_LABEL[layer]) })), + ]; + const verdictOptions = [ + { value: "", label: t("lab.filter.all") }, + ...COMPATIBILITY_VERDICTS.map(verdict => ({ value: verdict, label: t(VERDICT_LABEL[verdict]) })), + ]; + + if (surface.state.showSkeleton) { + return ( +
+

{t("lab.title")}

+

{t("lab.subtitle")}

+ +
+ ); + } + + const loadError = surface.state.showError + ? localizedFetchError(surface.error, t("lab.loadFailed")) + : null; + + const status = surface.data?.status; + const projectionUnavailable = status && !status.projectionAvailable; + const projectionIncompatible = status?.projectionIncompatible === true; + + return ( +
+
+
+

{t("lab.title")}

+

{t("lab.subtitle")}

+
+ +
+ + {surface.refreshing && !surface.state.showSkeleton && ( + + {t("common.loading")} + + )} + + {loadError && {loadError}} + + {projectionIncompatible && ( + {t("lab.projectionIncompatible")} + )} + + {projectionUnavailable && !projectionIncompatible && ( + + )} + + {surface.data && status?.projectionAvailable && ( + <> + + +
+
+ + setFilters(current => ({ + ...current, + verdict: value as CompatibilityVerdict | "", + }))} + label={t("lab.filter.verdict")} + portal={false} + /> +
+
+ + setFilters(current => ({ + ...current, + subjectQuery: event.target.value, + }))} + placeholder={t("lab.filter.subject")} + /> +
+
+ + {matrixRows.length === 0 ? ( + + ) : ( + <> +
+

{t("lab.matrixTitle")}

+
+ + + + + + {EVIDENCE_LAYERS.map(layer => ( + + ))} + + + + {matrixRows.map(row => ( + + + + {EVIDENCE_LAYERS.map(layer => ( + + ))} + + ))} + +
{t("lab.col.subject")}{t("lab.subjectKind")}{t(LAYER_COLUMN[layer])}
+ {shortSubjectId(row.subjectId)} + {row.subjectKind} + +
+
+
+ +
+

{t("lab.verdictsTitle")}

+
+ + + + + + + + + + + + {filteredVerdicts.map(verdict => ( + + + + + + + + ))} + +
{t("lab.col.subject")}{t("lab.col.layer")}{t("lab.col.suite")}{t("lab.col.verdict")}{t("lab.col.asOf")}
+ {shortSubjectId(verdict.subjectId)} + {t(LAYER_LABEL[verdict.evidenceLayer])}{verdict.suiteId} + + {formatAsOf(verdict.asOf, locale)}
+
+
+ + )} + + )} +
+ ); +} diff --git a/gui/src/pages/compatibility-matrix-api.ts b/gui/src/pages/compatibility-matrix-api.ts new file mode 100644 index 0000000000..79f5944c5a --- /dev/null +++ b/gui/src/pages/compatibility-matrix-api.ts @@ -0,0 +1,82 @@ +import { readJsonOrThrow } from "../fetch-json"; +import { + parseLabStatus, + parseSubjectPage, + parseVerdictPage, + type LabStatusDto, + type PaginatedSubjects, + type VerdictDto, +} from "./compatibility-matrix-shared"; +const PAGE_LIMIT = 100; + +async function fetchLabJson( + apiBase: string, + path: string, + signal: AbortSignal, +): Promise { + const res = await fetch(`${apiBase}${path}`, { signal }); + return readJsonOrThrow(res); +} + +export async function fetchLabStatus( + apiBase: string, + signal: AbortSignal, +): Promise { + const raw = await fetchLabJson(apiBase, "/api/lab/status", signal); + return parseLabStatus(raw) ?? { projectionAvailable: false }; +} + +export async function fetchAllVerdicts( + apiBase: string, + signal: AbortSignal, +): Promise { + const rows: VerdictDto[] = []; + let cursor: string | undefined; + do { + const query = new URLSearchParams({ limit: String(PAGE_LIMIT) }); + if (cursor) query.set("cursor", cursor); + const raw = await fetchLabJson(apiBase, `/api/lab/verdicts?${query}`, signal); + const page = parseVerdictPage(raw); + rows.push(...page.verdicts); + cursor = page.hasMore ? page.nextCursor : undefined; + } while (cursor); + return rows; +} + +export async function fetchAllSubjects( + apiBase: string, + signal: AbortSignal, +): Promise { + const rows: PaginatedSubjects["subjects"] = []; + let cursor: string | undefined; + do { + const query = new URLSearchParams({ limit: String(PAGE_LIMIT) }); + if (cursor) query.set("cursor", cursor); + const raw = await fetchLabJson(apiBase, `/api/lab/subjects?${query}`, signal); + const page = parseSubjectPage(raw); + rows.push(...page.subjects); + cursor = page.hasMore ? page.nextCursor : undefined; + } while (cursor); + return rows; +} + +export type LabPageData = { + status: LabStatusDto; + verdicts: VerdictDto[]; + subjects: PaginatedSubjects["subjects"]; +}; + +export async function fetchLabPageData( + apiBase: string, + signal: AbortSignal, +): Promise { + const status = await fetchLabStatus(apiBase, signal); + if (!status.projectionAvailable) { + return { status, verdicts: [], subjects: [] }; + } + const [verdicts, subjects] = await Promise.all([ + fetchAllVerdicts(apiBase, signal), + fetchAllSubjects(apiBase, signal), + ]); + return { status, verdicts, subjects }; +} diff --git a/gui/src/pages/compatibility-matrix-shared.ts b/gui/src/pages/compatibility-matrix-shared.ts new file mode 100644 index 0000000000..d441f171ae --- /dev/null +++ b/gui/src/pages/compatibility-matrix-shared.ts @@ -0,0 +1,186 @@ +/** + * CL-05 Compatibility Matrix — shared types and matrix helpers. + * Read-only DTO shapes mirror GET /api/lab/* responses. + */ + +export const EVIDENCE_LAYERS = [ + "protocol_conformance", + "live_route_compatibility", + "task_effectiveness", +] as const; + +export type EvidenceLayer = (typeof EVIDENCE_LAYERS)[number]; + +export const COMPATIBILITY_VERDICTS = [ + "UNKNOWN", + "CLAIMED", + "PROBED", + "VERIFIED", + "DEGRADED", + "BLOCKED", + "UNSUPPORTED", +] as const; + +export type CompatibilityVerdict = (typeof COMPATIBILITY_VERDICTS)[number]; + +export type LabStatusDto = { + projectionAvailable: boolean; + projectionIncompatible?: boolean; + sqliteSchemaVersion?: number; + projectionSpecVersion?: string; + builtAtMs?: number; + eventCount?: number; + subjectCount?: number; + observationCount?: number; + claimCount?: number; + verdictCount?: number; + artifactCount?: number; + corruptionCount?: number; +}; + +export type VerdictDto = { + projectionKey: string; + subjectId: string; + evidenceLayer: EvidenceLayer; + suiteId: string; + suiteVersion: string; + suiteManifestDigest: string; + projectionSpecVersion: string; + verdict: CompatibilityVerdict; + asOf: number; + scenarioManifestDigests: string[]; + claimSourceDigest: string | null; + contributingEventIds: string[]; + contradictingEventIds: string[]; + notes: string[]; +}; + +export type SubjectListItemDto = { + subjectId: string; + subjectKind: string; +}; + +export type PaginatedVerdicts = { + verdicts: VerdictDto[]; + hasMore: boolean; + nextCursor?: string; +}; + +export type PaginatedSubjects = { + subjects: SubjectListItemDto[]; + hasMore: boolean; + nextCursor?: string; +}; + +export type MatrixRow = { + subjectId: string; + subjectKind: string; + byLayer: Record; +}; + +export type VerdictFilters = { + layer: EvidenceLayer | ""; + verdict: CompatibilityVerdict | ""; + subjectQuery: string; +}; + +export function isPlainObject(value: unknown): value is Record { + return !!value && typeof value === "object" && !Array.isArray(value); +} + +export function parseLabStatus(raw: unknown): LabStatusDto | null { + if (!isPlainObject(raw)) return null; + if (typeof raw.projectionAvailable !== "boolean") return null; + return raw as LabStatusDto; +} + +export function parseVerdictDto(raw: unknown): VerdictDto | null { + if (!isPlainObject(raw)) return null; + if (typeof raw.subjectId !== "string") return null; + if (typeof raw.evidenceLayer !== "string") return null; + if (!EVIDENCE_LAYERS.includes(raw.evidenceLayer as EvidenceLayer)) return null; + if (typeof raw.suiteId !== "string") return null; + if (typeof raw.verdict !== "string") return null; + if (!COMPATIBILITY_VERDICTS.includes(raw.verdict as CompatibilityVerdict)) return null; + return raw as VerdictDto; +} + +export function parseVerdictPage(raw: unknown): PaginatedVerdicts { + if (!isPlainObject(raw) || !Array.isArray(raw.verdicts)) { + return { verdicts: [], hasMore: false }; + } + const verdicts = raw.verdicts + .map(parseVerdictDto) + .filter((row): row is VerdictDto => row !== null); + return { + verdicts, + hasMore: raw.hasMore === true, + nextCursor: typeof raw.nextCursor === "string" ? raw.nextCursor : undefined, + }; +} + +export function parseSubjectPage(raw: unknown): PaginatedSubjects { + if (!isPlainObject(raw) || !Array.isArray(raw.subjects)) { + return { subjects: [], hasMore: false }; + } + const subjects = raw.subjects.filter((row): row is SubjectListItemDto => { + if (!isPlainObject(row)) return false; + return typeof row.subjectId === "string" && typeof row.subjectKind === "string"; + }); + return { + subjects, + hasMore: raw.hasMore === true, + nextCursor: typeof raw.nextCursor === "string" ? raw.nextCursor : undefined, + }; +} + +export function emptyLayerMap(): Record { + return { + protocol_conformance: [], + live_route_compatibility: [], + task_effectiveness: [], + }; +} + +export function buildMatrixRows( + verdicts: VerdictDto[], + subjects: SubjectListItemDto[], +): MatrixRow[] { + const kindById = new Map(subjects.map(row => [row.subjectId, row.subjectKind])); + const bySubject = new Map(); + + for (const verdict of verdicts) { + let row = bySubject.get(verdict.subjectId); + if (!row) { + row = { + subjectId: verdict.subjectId, + subjectKind: kindById.get(verdict.subjectId) ?? "unknown", + byLayer: emptyLayerMap(), + }; + bySubject.set(verdict.subjectId, row); + } + row.byLayer[verdict.evidenceLayer].push(verdict); + } + + return [...bySubject.values()].sort((a, b) => a.subjectId.localeCompare(b.subjectId)); +} + +export function filterVerdicts(verdicts: VerdictDto[], filters: VerdictFilters): VerdictDto[] { + const query = filters.subjectQuery.trim().toLowerCase(); + return verdicts.filter(verdict => { + if (filters.layer && verdict.evidenceLayer !== filters.layer) return false; + if (filters.verdict && verdict.verdict !== filters.verdict) return false; + if (query && !verdict.subjectId.toLowerCase().includes(query)) return false; + return true; + }); +} + +export function shortSubjectId(subjectId: string): string { + if (subjectId.length <= 16) return subjectId; + return `${subjectId.slice(0, 8)}…${subjectId.slice(-6)}`; +} + +export function formatAsOf(ms: number, locale: string): string { + if (!Number.isFinite(ms) || ms <= 0) return "–"; + return new Date(ms).toLocaleString(locale); +} diff --git a/gui/src/styles-compatibility-matrix.css b/gui/src/styles-compatibility-matrix.css new file mode 100644 index 0000000000..79a900b9ae --- /dev/null +++ b/gui/src/styles-compatibility-matrix.css @@ -0,0 +1,229 @@ +/* ============================================================================ + compatibility-matrix — CL-05 read-only lab verdict matrix + Namespace: lab-matrix- + ============================================================================ */ + +.main-inner:has(.lab-page) { + max-width: 1200px; + box-sizing: border-box; +} + +.lab-page { + display: flex; + flex-direction: column; + gap: var(--space-3); + min-width: 0; +} + +.lab-page .page-head { + margin-bottom: 2px; +} + +.lab-page .page-sub { + margin: 0 0 0.5rem; +} + +.lab-status-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr)); + gap: var(--space-2); +} + +.lab-status-card { + border: 1px solid var(--border); + border-radius: var(--radius-md); + background: var(--surface); + padding: 0.65rem 0.75rem; + min-width: 0; +} + +.lab-status-card .label { + display: block; + font-size: var(--text-xs); + color: var(--muted); + margin-bottom: 0.2rem; +} + +.lab-status-card .value { + font-variant-numeric: tabular-nums; + font-weight: var(--weight-semibold); +} + +.lab-filters { + display: flex; + flex-wrap: wrap; + gap: var(--space-2); + align-items: flex-end; +} + +.lab-filter-field { + display: flex; + flex-direction: column; + gap: 0.25rem; + min-width: 10rem; +} + +.lab-filter-field label { + font-size: var(--text-xs); + color: var(--muted); +} + +.lab-filter-field input, +.lab-filter-field select { + min-height: 2rem; + border: 1px solid var(--border); + border-radius: var(--radius-sm); + background: var(--surface); + color: var(--text); + padding: 0.25rem 0.5rem; + font: inherit; +} + +.lab-matrix-block { + border: 1px solid var(--border); + border-radius: var(--radius-md); + background: var(--surface); + padding: 0.75rem; +} + +.lab-matrix-title { + margin: 0 0 0.65rem; + font-size: var(--text-sm); + font-weight: var(--weight-semibold); +} + +.lab-matrix-scroll { + overflow: auto; + max-width: 100%; +} + +.lab-matrix { + width: 100%; + border-collapse: collapse; + font-size: var(--text-sm); +} + +.lab-matrix th, +.lab-matrix td { + border: 1px solid var(--border-soft); + padding: 0.45rem 0.55rem; + text-align: left; + vertical-align: top; +} + +.lab-matrix th { + background: var(--raised); + font-weight: var(--weight-semibold); + white-space: nowrap; +} + +.lab-matrix td.subject { + font-family: var(--font-mono); + font-size: var(--text-xs); + max-width: 14rem; + overflow-wrap: anywhere; +} + +.lab-matrix td.kind { + color: var(--muted); + font-size: var(--text-xs); + white-space: nowrap; +} + +.lab-verdict-stack { + display: flex; + flex-direction: column; + gap: 0.25rem; +} + +.lab-verdict-badge { + display: inline-flex; + align-items: center; + gap: 0.35rem; + border-radius: 999px; + padding: 0.1rem 0.45rem; + font-size: var(--text-xs); + font-weight: var(--weight-semibold); + border: 1px solid transparent; + white-space: nowrap; +} + +.lab-verdict-badge .suite { + font-weight: var(--weight-regular); + color: var(--muted); + font-family: var(--font-mono); +} + +.lab-verdict-badge[data-verdict="VERIFIED"], +.lab-verdict-badge[data-verdict="PROBED"] { + background: color-mix(in srgb, var(--green) 14%, transparent); + border-color: color-mix(in srgb, var(--green) 35%, transparent); +} + +.lab-verdict-badge[data-verdict="CLAIMED"], +.lab-verdict-badge[data-verdict="UNKNOWN"] { + background: color-mix(in srgb, var(--muted) 12%, transparent); + border-color: color-mix(in srgb, var(--muted) 30%, transparent); +} + +.lab-verdict-badge[data-verdict="DEGRADED"] { + background: color-mix(in srgb, #c47a00 14%, transparent); + border-color: color-mix(in srgb, #c47a00 35%, transparent); +} + +.lab-verdict-badge[data-verdict="BLOCKED"], +.lab-verdict-badge[data-verdict="UNSUPPORTED"] { + background: color-mix(in srgb, var(--red) 12%, transparent); + border-color: color-mix(in srgb, var(--red) 35%, transparent); +} + +.lab-detail-table { + width: 100%; + border-collapse: collapse; + font-size: var(--text-sm); +} + +.lab-detail-table th, +.lab-detail-table td { + border-bottom: 1px solid var(--border-soft); + padding: 0.45rem 0.55rem; + text-align: left; + vertical-align: top; +} + +.lab-detail-table th { + color: var(--muted); + font-weight: var(--weight-semibold); + font-size: var(--text-xs); +} + +.lab-detail-table td.mono { + font-family: var(--font-mono); + font-size: var(--text-xs); + overflow-wrap: anywhere; +} + +.lab-toolbar { + display: flex; + flex-wrap: wrap; + gap: var(--space-2); + align-items: center; + justify-content: space-between; +} + +.lab-toolbar .btn-ghost { + display: inline-flex; + align-items: center; + gap: 0.35rem; +} + +@media (max-width: 720px) { + .lab-filters { + flex-direction: column; + align-items: stretch; + } + + .lab-filter-field { + width: 100%; + } +} diff --git a/gui/src/styles.css b/gui/src/styles.css index 0710f7c1e1..d07d2fdac3 100644 --- a/gui/src/styles.css +++ b/gui/src/styles.css @@ -22,6 +22,7 @@ @import "./styles-usage-workspace.css"; @import "./styles-claudecode-workspace.css"; @import "./styles-apikeys-workspace.css"; +@import "./styles-compatibility-matrix.css"; :root { /* default: follow the OS; [data-theme] below pins color-scheme so light-dark() obeys it */ diff --git a/gui/tests/compatibility-matrix-layout.test.ts b/gui/tests/compatibility-matrix-layout.test.ts new file mode 100644 index 0000000000..97c5f4e42d --- /dev/null +++ b/gui/tests/compatibility-matrix-layout.test.ts @@ -0,0 +1,27 @@ +import { expect, test } from "bun:test"; + +async function readSources(): Promise { + const app = await Bun.file(new URL("../src/App.tsx", import.meta.url)).text(); + const routing = await Bun.file(new URL("../src/app-routing.ts", import.meta.url)).text(); + const page = await Bun.file(new URL("../src/pages/CompatibilityMatrix.tsx", import.meta.url)).text(); + const css = await Bun.file(new URL("../src/styles.css", import.meta.url)).text(); + const styles = await Bun.file(new URL("../src/styles-compatibility-matrix.css", import.meta.url)).text(); + return `${app}\n${routing}\n${page}\n${css}\n${styles}`; +} + +test("Compatibility Lab page is mounted from App sidebar routing", async () => { + const src = await readSources(); + expect(src).toContain('"lab"'); + expect(src).toContain(""); + expect(src).toContain("nav.lab"); + expect(src).toContain('@import "./styles-compatibility-matrix.css"'); + expect(src).toContain("lab-matrix"); + expect(src).toContain("lab-verdict-badge"); +}); + +test("Compatibility matrix uses scrollable table layout", async () => { + const styles = await Bun.file(new URL("../src/styles-compatibility-matrix.css", import.meta.url)).text(); + expect(styles).toContain(".lab-matrix-scroll"); + expect(styles).toContain(".lab-matrix"); + expect(styles).toContain(".lab-detail-table"); +}); diff --git a/gui/tests/compatibility-matrix.test.tsx b/gui/tests/compatibility-matrix.test.tsx new file mode 100644 index 0000000000..8cc882f45f --- /dev/null +++ b/gui/tests/compatibility-matrix.test.tsx @@ -0,0 +1,196 @@ +/** @jsxImportSource react */ +import { afterEach, beforeEach, expect, test } from "bun:test"; +import { Window } from "happy-dom"; +import { act } from "react"; +import type { Root } from "react-dom/client"; +import { LanguageProvider } from "../src/i18n/provider"; +import CompatibilityMatrix from "../src/pages/CompatibilityMatrix"; +import { + buildMatrixRows, + filterVerdicts, + parseVerdictPage, + shortSubjectId, +} from "../src/pages/compatibility-matrix-shared"; + +const originalFetch = globalThis.fetch; +let restoreGlobals: (() => void) | undefined; +let previousLanguageDescriptor: PropertyDescriptor | undefined; +let testWindow: Window; + +const STATUS_AVAILABLE = { + projectionAvailable: true, + subjectCount: 1, + verdictCount: 2, + observationCount: 4, + eventCount: 5, + builtAtMs: 1_700_000_000_000, +}; + +const VERDICTS = { + verdicts: [ + { + projectionKey: "k1", + subjectId: "subject-alpha", + evidenceLayer: "protocol_conformance", + suiteId: "responses-core", + suiteVersion: "1", + suiteManifestDigest: "digest-a", + projectionSpecVersion: "cl-02.v1", + verdict: "VERIFIED", + asOf: 1_700_000_000_100, + scenarioManifestDigests: [], + claimSourceDigest: null, + contributingEventIds: ["e1"], + contradictingEventIds: [], + notes: [], + }, + { + projectionKey: "k2", + subjectId: "subject-alpha", + evidenceLayer: "live_route_compatibility", + suiteId: "live-core", + suiteVersion: "1", + suiteManifestDigest: "digest-b", + projectionSpecVersion: "cl-02.v1", + verdict: "PROBED", + asOf: 1_700_000_000_200, + scenarioManifestDigests: [], + claimSourceDigest: null, + contributingEventIds: ["e2"], + contradictingEventIds: [], + notes: [], + }, + ], + hasMore: false, +}; + +const SUBJECTS = { + subjects: [{ subjectId: "subject-alpha", subjectKind: "protocol" }], + hasMore: false, +}; + +beforeEach(() => { + testWindow = new Window({ url: "http://localhost/" }); + previousLanguageDescriptor = Object.getOwnPropertyDescriptor(globalThis.navigator, "language"); + Object.defineProperty(globalThis.navigator, "language", { configurable: true, value: "en-US" }); + const keys = ["document", "window", "localStorage", "IS_REACT_ACT_ENVIRONMENT"] as const; + const previous = Object.fromEntries( + keys.map(key => [key, Object.getOwnPropertyDescriptor(globalThis, key)]), + ) as Record<(typeof keys)[number], PropertyDescriptor | undefined>; + Object.defineProperties(globalThis, { + document: { configurable: true, value: testWindow.document }, + window: { configurable: true, value: testWindow }, + localStorage: { configurable: true, value: testWindow.localStorage }, + IS_REACT_ACT_ENVIRONMENT: { configurable: true, value: true }, + }); + restoreGlobals = () => { + for (const key of keys) { + const descriptor = previous[key]; + if (descriptor) Object.defineProperty(globalThis, key, descriptor); + else delete (globalThis as Record)[key]; + } + if (previousLanguageDescriptor) { + Object.defineProperty(globalThis.navigator, "language", previousLanguageDescriptor); + } + }; +}); + +afterEach(() => { + restoreGlobals?.(); + globalThis.fetch = originalFetch; + testWindow.close(); +}); + +async function waitFor(predicate: () => boolean, timeoutMs = 2000): Promise { + const start = Date.now(); + while (!predicate()) { + if (Date.now() - start > timeoutMs) throw new Error("waitFor timed out"); + await act(async () => { + await new Promise(resolve => testWindow.setTimeout(resolve, 10)); + }); + } +} + +async function renderPage(): Promise<{ root: Root; container: HTMLDivElement }> { + const React = await import("react"); + const { createRoot } = await import("react-dom/client"); + const container = testWindow.document.createElement("div"); + testWindow.document.body.appendChild(container); + const root = createRoot(container); + await act(async () => { + root.render( + + + , + ); + }); + return { root, container }; +} + +test("parseVerdictPage rejects malformed payloads", () => { + expect(parseVerdictPage(null).verdicts).toEqual([]); + expect(parseVerdictPage({ verdicts: [{ subjectId: "x" }] }).verdicts).toEqual([]); +}); + +test("buildMatrixRows groups verdicts by subject and layer", () => { + const page = parseVerdictPage(VERDICTS); + const rows = buildMatrixRows(page.verdicts, SUBJECTS.subjects); + expect(rows).toHaveLength(1); + expect(rows[0]!.byLayer.protocol_conformance).toHaveLength(1); + expect(rows[0]!.byLayer.live_route_compatibility).toHaveLength(1); + expect(rows[0]!.byLayer.task_effectiveness).toHaveLength(0); +}); + +test("filterVerdicts applies layer and subject filters", () => { + const page = parseVerdictPage(VERDICTS); + const filtered = filterVerdicts(page.verdicts, { + layer: "protocol_conformance", + verdict: "", + subjectQuery: "alpha", + }); + expect(filtered).toHaveLength(1); + expect(filtered[0]!.verdict).toBe("VERIFIED"); +}); + +test("shortSubjectId keeps short ids intact", () => { + expect(shortSubjectId("abc")).toBe("abc"); + expect(shortSubjectId("012345678901234567890")).toContain("…"); +}); + +test("CompatibilityMatrix renders matrix rows from lab APIs", async () => { + globalThis.fetch = (async (input: RequestInfo | URL) => { + const url = String(input); + if (url.endsWith("/api/lab/status")) { + return new Response(JSON.stringify(STATUS_AVAILABLE), { status: 200 }); + } + if (url.includes("/api/lab/verdicts")) { + return new Response(JSON.stringify(VERDICTS), { status: 200 }); + } + if (url.includes("/api/lab/subjects")) { + return new Response(JSON.stringify(SUBJECTS), { status: 200 }); + } + return new Response("{}", { status: 404 }); + }) as typeof fetch; + + const { root, container } = await renderPage(); + await waitFor(() => container.textContent?.includes("Compatibility matrix") ?? false); + expect(container.textContent).toContain("Verified"); + expect(container.textContent).toContain("Probed"); + expect(container.querySelector(".lab-matrix tbody tr")).not.toBeNull(); + await act(async () => root.unmount()); +}); + +test("CompatibilityMatrix shows unavailable state when projection is missing", async () => { + globalThis.fetch = (async (input: RequestInfo | URL) => { + const url = String(input); + if (url.endsWith("/api/lab/status")) { + return new Response(JSON.stringify({ projectionAvailable: false }), { status: 200 }); + } + return new Response("{}", { status: 404 }); + }) as typeof fetch; + + const { root, container } = await renderPage(); + await waitFor(() => container.textContent?.includes("not available") ?? false); + expect(container.querySelector(".lab-matrix")).toBeNull(); + await act(async () => root.unmount()); +}); diff --git a/structure/09_compatibility-lab.md b/structure/09_compatibility-lab.md index 5535f830aa..c5ba3e1d93 100644 --- a/structure/09_compatibility-lab.md +++ b/structure/09_compatibility-lab.md @@ -19,3 +19,7 @@ The two machine-readable Live V1 authority copies are required to be byte-identi ## Scope guard CL-03 does not expose a management CLI/API or UI. Those surfaces remain CL-04+ work. Production request routing must not synchronously trigger Compatibility Lab probing or rebuild Lab evidence. + +## CL-05 GUI read surface + +CL-05 adds a read-only dashboard route (`#lab`) that visualizes the compatibility verdict matrix from existing `GET /api/lab/*` management APIs. The GUI never triggers probe execution, projection rebuilds, or evidence mutation. Verdicts remain per `(subject, evidence layer, suite)`; layers are not collapsed into a universal score. From 38ce4408840ff1e76f2df8797c8a57ec4323275f Mon Sep 17 00:00:00 2001 From: Wibias <37517432+Wibias@users.noreply.github.com> Date: Mon, 10 Aug 2026 01:50:44 +0200 Subject: [PATCH 02/16] fix(gui): move CL-05 compatibility matrix into Models tab MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Relocate the read-only compatibility matrix from standalone #lab sidebar route to Models → Compatibility (#models/compatibility) with legacy #lab redirect, server-side verdict filters, pagination, and detail pane. --- .../005_cl05_compatibility_matrix_ui.md | 31 +- gui/src/App.tsx | 6 +- gui/src/app-routing.ts | 13 +- gui/src/i18n/de.ts | 11 +- gui/src/i18n/en.ts | 11 +- gui/src/i18n/ja.ts | 11 +- gui/src/i18n/ko.ts | 11 +- gui/src/i18n/ru.ts | 11 +- gui/src/i18n/tr.ts | 11 +- gui/src/i18n/zh.ts | 11 +- gui/src/icons.tsx | 1 - gui/src/pages/CompatibilityMatrix.tsx | 482 ++++++++++++----- gui/src/pages/Models.tsx | 26 +- gui/src/pages/compatibility-matrix-api.ts | 196 ++++++- gui/src/pages/compatibility-matrix-shared.ts | 171 +++++- gui/src/pages/models-tab-strip.tsx | 1 + gui/src/pages/models-tab.ts | 5 +- gui/src/styles-compatibility-matrix.css | 72 +++ gui/tests/compatibility-lab.test.tsx | 510 ++++++++++++++++++ gui/tests/compatibility-matrix.test.tsx | 196 ------- gui/tests/models-workspace-panels.test.tsx | 19 +- structure/09_compatibility-lab.md | 2 +- tests/models-workspace-tabs.test.ts | 11 +- 23 files changed, 1418 insertions(+), 401 deletions(-) create mode 100644 gui/tests/compatibility-lab.test.tsx delete mode 100644 gui/tests/compatibility-matrix.test.tsx diff --git a/devlog/_plan/260807_compatibility_lab/005_cl05_compatibility_matrix_ui.md b/devlog/_plan/260807_compatibility_lab/005_cl05_compatibility_matrix_ui.md index efa090d69f..a2b0ba4bba 100644 --- a/devlog/_plan/260807_compatibility_lab/005_cl05_compatibility_matrix_ui.md +++ b/devlog/_plan/260807_compatibility_lab/005_cl05_compatibility_matrix_ui.md @@ -1,41 +1,42 @@ -# CL-05 implementation record — Compatibility Matrix UI +# CL-05 implementation record - Compatibility Matrix UI ## Programme position - **Phase:** CL-05 (read-only GUI) - **Starting `upstream/dev` SHA:** `d517161aeaa3a974ad3c0360ff0c97b03b4c4520` (merge #1378 / CL-04) - **Branch:** `feat/cl-05-compatibility-matrix-ui` -- **PR:** DRAFT PENDING → `lidge-jun/opencodex:dev` +- **PR:** DRAFT → `lidge-jun/opencodex:dev` ([#1384](https://github.com/lidge-jun/opencodex/pull/1384)) - **CL-06:** not started ## Scope delivered ### GUI (`gui/src/pages/`) -- New sidebar route `#lab` — **Compatibility Lab** -- `CompatibilityMatrix.tsx` — read-only verdict matrix over CL-04 management APIs -- `compatibility-matrix-api.ts` — paginated fetch helpers for `/api/lab/status`, `/api/lab/verdicts`, `/api/lab/subjects` -- `compatibility-matrix-shared.ts` — DTO parsing, matrix grouping, filters -- `styles-compatibility-matrix.css` — scrollable matrix + detail tables (api-auth-matrix pattern) +- **Models → Compatibility tab** at `#models/compatibility` (not a standalone sidebar page) +- Legacy `#lab` hash redirects to `#models/compatibility` +- `CompatibilityMatrix.tsx` - read-only verdict matrix over CL-04 management APIs +- `compatibility-matrix-api.ts` - paginated fetch helpers for `/api/lab/status`, `/api/lab/verdicts`, `/api/lab/subjects`, detail reads +- `compatibility-matrix-shared.ts` - DTO parsing, matrix grouping, filters +- `styles-compatibility-matrix.css` - scrollable matrix + detail pane - i18n keys in all seven locales (`en`, `de`, `ko`, `zh`, `ru`, `ja`, `tr`) -- Component/layout tests under `gui/tests/compatibility-matrix*.test.*` +- Component/layout tests under `gui/tests/compatibility-lab.test.tsx` ### Behaviour - Projection status cards (subjects, verdicts, observations, events, built-at) - Subject × evidence-layer matrix with per-suite verdict badges -- Filterable verdict detail table (layer, verdict, subject id) +- Server-side verdict filters (layer, verdict, subjectId, suiteId) with paginated "Load more" +- Verdict detail pane (subject, observations, contributing events, artifact metadata only) - Empty/unavailable/incompatible projection states via existing data-surface contract +- Lazy mount with `active` / `pauseWhenHidden` gating inside Models workspace - No probe execution, projection rebuild, or evidence mutation ## Validation (local) -- `bun x tsc --noEmit` — pending -- `bun test tests/lab-read-surfaces.test.ts` — pending -- `cd gui && bun test tests/compatibility-matrix.test.tsx tests/compatibility-matrix-layout.test.ts` — pending -- `cd gui && bun run lint` — pending -- `cd gui && bun run build` — pending -- `bun run privacy:scan` — pending +- `bun x tsc --noEmit` - pending +- `bun test tests/lab-read-surfaces.test.ts tests/models-workspace-tabs.test.ts` - pending +- `cd gui && bun test tests/compatibility-lab.test.tsx tests/models-workspace-panels.test.tsx` - pending +- `bun run lint:gui && bun run doctor:gui && bun run build:gui && bun run privacy:scan` - pending ## Acceptance blockers diff --git a/gui/src/App.tsx b/gui/src/App.tsx index fa8ae94b04..e2afbb4f84 100644 --- a/gui/src/App.tsx +++ b/gui/src/App.tsx @@ -9,11 +9,10 @@ import Usage from "./pages/Usage"; import Storage from "./pages/Storage"; import CodexAuth from "./pages/CodexAuth"; import Integrations from "./pages/Integrations"; -import CompatibilityMatrix from "./pages/CompatibilityMatrix"; import Startup from "./pages/Startup"; import ErrorBoundary from "./components/ErrorBoundary"; import { SidebarGithubRow } from "./components/sidebar-github-row"; -import { IconGrid, IconServer, IconBoxes, IconBot, IconList, IconActivity, IconLab, IconHardDrive, IconKey, IconMenu, IconSun, IconMoon, IconMonitor, IconGlobe, IconPower, IconX } from "./icons"; +import { IconGrid, IconServer, IconBoxes, IconBot, IconList, IconActivity, IconHardDrive, IconKey, IconMenu, IconSun, IconMoon, IconMonitor, IconGlobe, IconPower, IconX } from "./icons"; import { useI18n, useT, LOCALES, localeDisplayName, type Locale, type TKey } from "./i18n/shared"; import { Select } from "./ui"; import { installApiAuthFetch } from "./api"; @@ -34,7 +33,6 @@ const PAGE_TKEY: Record = { subagents: "nav.subagents", logs: "nav.logs", usage: "nav.usage", - lab: "nav.lab", storage: "nav.storage", "codex-auth": "nav.codexAuth", integrations: "nav.integrations", @@ -65,7 +63,6 @@ const NAV: NavEntry[] = [ { id: "subagents", tkey: "nav.subagents", Icon: IconBot }, { id: "logs", tkey: "nav.logs", Icon: IconList }, { id: "usage", tkey: "nav.usage", Icon: IconActivity }, - { id: "lab", tkey: "nav.lab", Icon: IconLab }, { id: "storage", tkey: "nav.storage", Icon: IconHardDrive }, { id: "integrations", tkey: "nav.integrations", Icon: IconGlobe }, ]; @@ -308,7 +305,6 @@ export default function App() { {page === "subagents" && } {page === "logs" && } {page === "usage" && } - {page === "lab" && } {page === "storage" && } {page === "codex-auth" && } {page === "integrations" && } diff --git a/gui/src/app-routing.ts b/gui/src/app-routing.ts index 20dcba2698..24339c9f40 100644 --- a/gui/src/app-routing.ts +++ b/gui/src/app-routing.ts @@ -10,7 +10,6 @@ export type Page = | "subagents" | "logs" | "usage" - | "lab" | "storage" | "codex-auth" | "integrations"; @@ -23,7 +22,6 @@ export const VALID_PAGES = new Set([ "subagents", "logs", "usage", - "lab", "storage", "codex-auth", "integrations", @@ -56,11 +54,11 @@ export function readPageFromHash(hash?: string): Page { export const DASHBOARD_TAB_HASHES = ["dashboard/providers", "dashboard/models"] as const; /** - * Models owns three tabs: the catalog, Combos, and Routing. The catalog is the bare - * `#models`, so it has no suffix entry here — same convention Dashboard uses for - * Overview and Logs uses for the log list. + * Models owns four tabs: the catalog, Combos, Routing, and Compatibility. The catalog + * is the bare `#models`, so it has no suffix entry here - same convention Dashboard + * uses for Overview and Logs uses for the log list. */ -export const MODELS_TAB_HASHES = ["models/combos", "models/routing"] as const; +export const MODELS_TAB_HASHES = ["models/combos", "models/routing", "models/compatibility"] as const; /** * `#dashboard/update` is an action deep link, not a tab: the sidebar update button uses @@ -134,6 +132,9 @@ export function resolveAppHashChange(rawHash: string): AppHashChangeAction { if (rawHash === "routing" || rawHash.startsWith("routing/")) { return { page: "models", replaceTo: "models/routing" }; } + if (rawHash === "lab" || rawHash.startsWith("lab/")) { + return { page: "models", replaceTo: "models/compatibility" }; + } /* * Legacy top-level integration pages. diff --git a/gui/src/i18n/de.ts b/gui/src/i18n/de.ts index 034c4a0831..a53882bef9 100644 --- a/gui/src/i18n/de.ts +++ b/gui/src/i18n/de.ts @@ -64,7 +64,6 @@ export const de: Record = { "routing.analyticsEmpty": "Noch keine Analysen – senden Sie zuerst einige Anfragen.", "nav.logs": "Protokolle & Diagnose", "nav.usage": "Nutzung", - "nav.lab": "Kompatibilitäts-Labor", "common.github": "GitHub", "sidebar.star": "Auf GitHub mit Stern markieren", "sidebar.starred": "Auf GitHub markiert", @@ -435,9 +434,11 @@ export const de: Record = { "prov.openaiApiSetup": "API-Schlüssel einrichten", "models.tab.catalog": "Modelle", "models.tab.combos": "Combos", + "models.tab.compatibility": "Kompatibilität", "models.tab.routing": "Routing (beta)", "models.tabsLabel": "Modell-Oberflächen", "models.subtitle.combos": "Geordnete Modellgruppen, die unter einer id antworten. Failover probiert Ziele der Reihe nach, Round-Robin verteilt die Last.", + "models.subtitle.compatibility": "Schreibgeschützte Kompatibilitätsmatrix aus der Lab-Projektion.", "models.subtitle.routing": "Policy-Profile, Dry-Run-Auswertung und quellenbasierte Routing-Analysen.", "models.subtitle": "Steuere, welche Modelle Codex sieht — natives GPT-Passthrough und geroutete Anbieter, nach Anbieter gruppiert (Kopfzeile zum Einklappen anklicken). Ausgeblendete Modelle fehlen in Katalog und Auswahl, bleiben aber per genauer ID aufrufbar. Änderungen gelten bei der nächsten Codex-Runde — opencodex invalidiert Codex 5-Minuten-Modell-Cache, kein Neustart nötig.", "models.nativeGroupLabel": "OpenAI nativ", @@ -1937,6 +1938,14 @@ export const de: Record = { "lab.subjectCount": "Subjects", "lab.builtAt": "Erstellt", "lab.loading": "Kompatibilitätsevidenz wird geladen…", + "lab.loadMore": "Load more", + "lab.detailTitle": "Verdict detail", + "lab.detailClose": "Close", + "lab.detailSubject": "Subject", + "lab.detailObservations": "Observations", + "lab.detailEvents": "Contributing events", + "lab.detailArtifacts": "Artifact metadata", + "lab.detailLoadFailed": "Could not load verdict detail", "lab.refresh": "Aktualisieren", "lab.verdict.UNKNOWN": "Unbekannt", "lab.verdict.CLAIMED": "Behauptet", diff --git a/gui/src/i18n/en.ts b/gui/src/i18n/en.ts index 3cef5e1487..6d4347316f 100644 --- a/gui/src/i18n/en.ts +++ b/gui/src/i18n/en.ts @@ -19,7 +19,6 @@ export const en = { "nav.subagents": "Subagents", "nav.logs": "Logs & Debug", "nav.usage": "Usage", - "nav.lab": "Compatibility Lab", "common.github": "GitHub", "sidebar.star": "Star on GitHub", "sidebar.starred": "Starred on GitHub", @@ -454,9 +453,11 @@ export const en = { // models "models.tab.catalog": "Models", "models.tab.combos": "Combos", + "models.tab.compatibility": "Compatibility", "models.tab.routing": "Routing (beta)", "models.tabsLabel": "Model surfaces", "models.subtitle.combos": "Ordered groups of models that answer as one id. Failover tries targets in order; round-robin spreads the load.", + "models.subtitle.compatibility": "Read-only compatibility verdict matrix from lab projection evidence.", "models.subtitle.routing": "Policy profiles, dry-run evaluation, and source-backed routing analytics.", "models.subtitle": "Toggle which models Codex sees — native GPT passthrough and routed providers, grouped by provider (click a header to collapse). Hidden models stay off the catalog + model picker but remain directly callable by exact id. Changes apply on the next Codex turn — opencodex invalidates Codex's 5-min model cache so no restart is needed.", "models.nativeGroupLabel": "OpenAI native", @@ -1966,6 +1967,14 @@ export const en = { "lab.subjectCount": "Subjects", "lab.builtAt": "Built", "lab.loading": "Loading compatibility evidence…", + "lab.loadMore": "Load more", + "lab.detailTitle": "Verdict detail", + "lab.detailClose": "Close", + "lab.detailSubject": "Subject", + "lab.detailObservations": "Observations", + "lab.detailEvents": "Contributing events", + "lab.detailArtifacts": "Artifact metadata", + "lab.detailLoadFailed": "Could not load verdict detail", "lab.refresh": "Refresh", "lab.verdict.UNKNOWN": "Unknown", "lab.verdict.CLAIMED": "Claimed", diff --git a/gui/src/i18n/ja.ts b/gui/src/i18n/ja.ts index f58d21e95a..3770c07224 100644 --- a/gui/src/i18n/ja.ts +++ b/gui/src/i18n/ja.ts @@ -64,7 +64,6 @@ export const ja: Record = { "routing.analyticsEmpty": "分析はまだありません。まずリクエストを送信してください。", "nav.logs": "ログ & デバッグ", "nav.usage": "使用量", - "nav.lab": "互換性ラボ", "common.github": "GitHub", "sidebar.star": "GitHub でスターを付ける", "sidebar.starred": "GitHub でスター済み", @@ -443,9 +442,11 @@ export const ja: Record = { // models "models.tab.catalog": "モデル", "models.tab.combos": "コンボ", + "models.tab.compatibility": "互換性", "models.tab.routing": "ルーティング (beta)", "models.tabsLabel": "モデルサーフェス", "models.subtitle.combos": "複数のモデルを 1 つの id にまとめ、順に応答させます。failover は順番に試し、round-robin は負荷を分散します。", + "models.subtitle.compatibility": "ラボ投影証拠の読み取り専用互換性判定マトリクス。", "models.subtitle.routing": "ポリシープロファイル、dry-run 評価、そして根拠の残るルーティング分析です。", "models.subtitle": "Codex に表示するモデルを切り替えます — ネイティブ GPT パススルーとルーティングプロバイダー、プロバイダー別(ヘッダーをクリックで折りたたみ)。非表示モデルはカタログとピッカーから外れますが、正確な id での直接呼び出しは可能です。変更は次回の Codex ターンで適用 — opencodex は Codex の 5 分間モデルキャッシュを無効化するので再起動は不要です。", "models.nativeGroupLabel": "OpenAI ネイティブ", @@ -1958,6 +1959,14 @@ export const ja: Record = { "lab.subjectCount": "Subjects", "lab.builtAt": "Built", "lab.loading": "Loading compatibility evidence…", + "lab.loadMore": "Load more", + "lab.detailTitle": "Verdict detail", + "lab.detailClose": "Close", + "lab.detailSubject": "Subject", + "lab.detailObservations": "Observations", + "lab.detailEvents": "Contributing events", + "lab.detailArtifacts": "Artifact metadata", + "lab.detailLoadFailed": "Could not load verdict detail", "lab.refresh": "Refresh", "lab.verdict.UNKNOWN": "Unknown", "lab.verdict.CLAIMED": "Claimed", diff --git a/gui/src/i18n/ko.ts b/gui/src/i18n/ko.ts index f49d8c0560..1021288915 100644 --- a/gui/src/i18n/ko.ts +++ b/gui/src/i18n/ko.ts @@ -64,7 +64,6 @@ export const ko: Record = { "routing.analyticsEmpty": "분석이 아직 없습니다. 먼저 요청을 보내세요.", "nav.logs": "로그&디버그", "nav.usage": "사용량", - "nav.lab": "호환성 랩", "common.github": "GitHub", "sidebar.star": "GitHub에서 스타 누르기", "sidebar.starred": "GitHub 스타 완료", @@ -446,9 +445,11 @@ export const ko: Record = { // models "models.tab.catalog": "모델", "models.tab.combos": "콤보", + "models.tab.compatibility": "호환성", "models.tab.routing": "라우팅 (beta)", "models.tabsLabel": "모델 표면", "models.subtitle.combos": "여러 모델을 하나의 id로 묶어 순서대로 응답하게 합니다. failover는 순서대로 시도하고, round-robin은 부하를 나눕니다.", + "models.subtitle.compatibility": "랩 프로젝션 증거의 읽기 전용 호환성 판정 행렬.", "models.subtitle.routing": "정책 프로필, dry-run 평가, 그리고 근거가 남는 라우팅 분석입니다.", "models.subtitle": "Codex가 보는 모델을 켜고 끕니다 — 네이티브 GPT passthrough와 라우팅된 모델을 프로바이더별로 묶어 보여줍니다(헤더를 클릭하면 접힘). 숨긴 모델은 카탈로그와 선택기에서 빠지지만 정확한 id로 직접 호출할 수 있습니다. 변경 사항은 다음 Codex 턴에 적용됩니다 — opencodex가 Codex의 5분 모델 캐시를 무효화하므로 재시작이 필요 없습니다.", "models.nativeGroupLabel": "OpenAI 네이티브", @@ -1958,6 +1959,14 @@ export const ko: Record = { "lab.subjectCount": "Subjects", "lab.builtAt": "Built", "lab.loading": "Loading compatibility evidence…", + "lab.loadMore": "Load more", + "lab.detailTitle": "Verdict detail", + "lab.detailClose": "Close", + "lab.detailSubject": "Subject", + "lab.detailObservations": "Observations", + "lab.detailEvents": "Contributing events", + "lab.detailArtifacts": "Artifact metadata", + "lab.detailLoadFailed": "Could not load verdict detail", "lab.refresh": "Refresh", "lab.verdict.UNKNOWN": "Unknown", "lab.verdict.CLAIMED": "Claimed", diff --git a/gui/src/i18n/ru.ts b/gui/src/i18n/ru.ts index 886d0691d1..2f9fc958d1 100644 --- a/gui/src/i18n/ru.ts +++ b/gui/src/i18n/ru.ts @@ -64,7 +64,6 @@ export const ru: Record = { "routing.analyticsEmpty": "Аналитики пока нет — сначала отправьте несколько запросов.", "nav.logs": "Логи и отладка", "nav.usage": "Использование", - "nav.lab": "Лаборатория совместимости", "common.github": "GitHub", "sidebar.star": "Поставить звезду на GitHub", "sidebar.starred": "Звезда на GitHub поставлена", @@ -448,9 +447,11 @@ export const ru: Record = { // models "models.tab.catalog": "Модели", "models.tab.combos": "Комбо", + "models.tab.compatibility": "Совместимость", "models.tab.routing": "Маршрутизация (beta)", "models.tabsLabel": "Поверхности моделей", "models.subtitle.combos": "Упорядоченные группы моделей, отвечающие под одним id. Failover пробует цели по порядку, round-robin распределяет нагрузку.", + "models.subtitle.compatibility": "Матрица совместимости только для чтения из проекции лаборатории.", "models.subtitle.routing": "Профили политик, оценка в режиме dry-run и аналитика маршрутизации с подтверждением источников.", "models.subtitle": "Управляйте тем, какие модели видит Codex — нативные GPT (сквозной проброс) и модели маршрутизируемых провайдеров, сгруппированные по провайдеру (нажмите на заголовок, чтобы свернуть группу). Скрытые модели исчезают из каталога и селектора, но остаются вызываемыми по точному id. Изменения применяются на следующем ходе Codex — opencodex сбрасывает 5-минутный кэш моделей Codex, поэтому перезапуск не требуется.", "models.nativeGroupLabel": "Нативные OpenAI", @@ -1960,6 +1961,14 @@ export const ru: Record = { "lab.subjectCount": "Subjects", "lab.builtAt": "Built", "lab.loading": "Loading compatibility evidence…", + "lab.loadMore": "Load more", + "lab.detailTitle": "Verdict detail", + "lab.detailClose": "Close", + "lab.detailSubject": "Subject", + "lab.detailObservations": "Observations", + "lab.detailEvents": "Contributing events", + "lab.detailArtifacts": "Artifact metadata", + "lab.detailLoadFailed": "Could not load verdict detail", "lab.refresh": "Refresh", "lab.verdict.UNKNOWN": "Unknown", "lab.verdict.CLAIMED": "Claimed", diff --git a/gui/src/i18n/tr.ts b/gui/src/i18n/tr.ts index e2c83461cf..6fd435e533 100644 --- a/gui/src/i18n/tr.ts +++ b/gui/src/i18n/tr.ts @@ -18,7 +18,6 @@ export const tr: Record = { "nav.subagents": "Alt Ajanlar", "nav.logs": "Günlükler & Hata Ayıklama", "nav.usage": "Kullanım", - "nav.lab": "Uyumluluk Laboratuvarı", "common.github": "GitHub", "sidebar.star": "GitHub'da Yıldız Ver", "sidebar.starred": "GitHub'da Yıldız Verildi", @@ -451,9 +450,11 @@ export const tr: Record = { // models "models.tab.catalog": "Modeller", "models.tab.combos": "Kombolar", + "models.tab.compatibility": "Uyumluluk", "models.tab.routing": "Yönlendirme (beta)", "models.tabsLabel": "Model yüzeyleri", "models.subtitle.combos": "Tek bir kimlik olarak yanıt veren sıralı model grupları.", + "models.subtitle.compatibility": "Lab projeksiyon kanıtından salt okunur uyumluluk matrisi.", "models.subtitle.routing": "Politika profilleri ve simülasyon değerlendirmesi.", "models.subtitle": "Codex'in göreceği modelleri açıp kapatın.", "models.nativeGroupLabel": "Yerel OpenAI", @@ -1960,6 +1961,14 @@ export const tr: Record = { "lab.subjectCount": "Subjects", "lab.builtAt": "Built", "lab.loading": "Loading compatibility evidence…", + "lab.loadMore": "Load more", + "lab.detailTitle": "Verdict detail", + "lab.detailClose": "Close", + "lab.detailSubject": "Subject", + "lab.detailObservations": "Observations", + "lab.detailEvents": "Contributing events", + "lab.detailArtifacts": "Artifact metadata", + "lab.detailLoadFailed": "Could not load verdict detail", "lab.refresh": "Refresh", "lab.verdict.UNKNOWN": "Unknown", "lab.verdict.CLAIMED": "Claimed", diff --git a/gui/src/i18n/zh.ts b/gui/src/i18n/zh.ts index de3ba1fa75..2ae8b6ac2c 100644 --- a/gui/src/i18n/zh.ts +++ b/gui/src/i18n/zh.ts @@ -64,7 +64,6 @@ export const zh: Record = { "routing.analyticsEmpty": "暂无分析 — 请先发送一些请求。", "nav.logs": "日志与调试", "nav.usage": "用量", - "nav.lab": "兼容性实验室", "common.github": "GitHub", "sidebar.star": "在 GitHub 上加星", "sidebar.starred": "已在 GitHub 加星", @@ -443,9 +442,11 @@ export const zh: Record = { // models "models.tab.catalog": "模型", "models.tab.combos": "组合", + "models.tab.compatibility": "兼容性", "models.tab.routing": "路由 (beta)", "models.tabsLabel": "模型界面", "models.subtitle.combos": "把多个模型合成一个 id 依次应答。failover 按顺序尝试,round-robin 分摊负载。", + "models.subtitle.compatibility": "来自实验室投影证据的只读兼容性判定矩阵。", "models.subtitle.routing": "策略配置、dry-run 评估,以及有据可查的路由分析。", "models.subtitle": "开关 Codex 可见的模型 — 原生 GPT passthrough 与已路由模型按提供方分组(点击标题可折叠)。隐藏的模型不会出现在目录和模型选择器中,但仍可按精确 id 直接调用。更改在下一个 Codex 回合生效 — opencodex 会使 Codex 的 5 分钟模型缓存失效,因此无需重启。", "models.nativeGroupLabel": "OpenAI 原生", @@ -1958,6 +1959,14 @@ export const zh: Record = { "lab.subjectCount": "Subjects", "lab.builtAt": "Built", "lab.loading": "Loading compatibility evidence…", + "lab.loadMore": "Load more", + "lab.detailTitle": "Verdict detail", + "lab.detailClose": "Close", + "lab.detailSubject": "Subject", + "lab.detailObservations": "Observations", + "lab.detailEvents": "Contributing events", + "lab.detailArtifacts": "Artifact metadata", + "lab.detailLoadFailed": "Could not load verdict detail", "lab.refresh": "Refresh", "lab.verdict.UNKNOWN": "Unknown", "lab.verdict.CLAIMED": "Claimed", diff --git a/gui/src/icons.tsx b/gui/src/icons.tsx index d19e8fac0c..bed8492599 100644 --- a/gui/src/icons.tsx +++ b/gui/src/icons.tsx @@ -15,7 +15,6 @@ export const IconList = (p: P) => (); export const IconTerminal = (p: P) => (); export const IconActivity = (p: P) => (); -export const IconLab = (p: P) => (); export const IconHardDrive = (p: P) => (); export const IconCheck = (p: P) => (); diff --git a/gui/src/pages/CompatibilityMatrix.tsx b/gui/src/pages/CompatibilityMatrix.tsx index d525828a22..071c3810dc 100644 --- a/gui/src/pages/CompatibilityMatrix.tsx +++ b/gui/src/pages/CompatibilityMatrix.tsx @@ -1,17 +1,23 @@ -import { useCallback, useMemo, useState } from "react"; +import { useCallback, useEffect, useMemo, useState } from "react"; import { IconRefresh } from "../icons"; import { useI18n, type TKey } from "../i18n/shared"; import { EmptyState, Notice, Select } from "../ui"; import { useDataSurface } from "../data-surface"; import { DataSurfaceSkeleton, DataSurfaceStatus } from "../components/data-surface"; -import { fetchLabPageData, type LabPageData } from "./compatibility-matrix-api"; +import { + fetchLabPageData, + fetchMoreVerdicts, + fetchVerdictDetail, + type LabPageData, + type VerdictDetailData, +} from "./compatibility-matrix-api"; import { COMPATIBILITY_VERDICTS, EVIDENCE_LAYERS, buildMatrixRows, - filterVerdicts, formatAsOf, shortSubjectId, + verdictQueryFromFilters, type CompatibilityVerdict, type EvidenceLayer, type VerdictDto, @@ -57,13 +63,26 @@ function VerdictBadge({ verdict, suiteId, label, + selected, + onSelect, }: { verdict: CompatibilityVerdict; suiteId: string; label: string; + selected?: boolean; + onSelect?: () => void; }) { + const className = `lab-verdict-badge${selected ? " lab-verdict-badge--selected" : ""}`; + if (onSelect) { + return ( + + ); + } return ( - + {label} {suiteId} @@ -73,11 +92,15 @@ function VerdictBadge({ function VerdictCell({ rows, t, + selectedKey, + onSelect, }: { rows: VerdictDto[]; t: (key: TKey) => string; + selectedKey: string | null; + onSelect: (verdict: VerdictDto) => void; }) { - if (rows.length === 0) return ; + if (rows.length === 0) return -; return (
{rows.map(row => ( @@ -86,6 +109,8 @@ function VerdictCell({ verdict={row.verdict} suiteId={row.suiteId} label={t(VERDICT_LABEL[row.verdict])} + selected={selectedKey === row.projectionKey} + onSelect={() => onSelect(row)} /> ))}
@@ -126,34 +151,201 @@ function StatusCards({ ); } -export default function CompatibilityMatrix({ apiBase }: { apiBase: string }) { +function DetailPane({ + verdict, + detail, + loading, + error, + t, + locale, + onClose, +}: { + verdict: VerdictDto; + detail: VerdictDetailData | null; + loading: boolean; + error: string | null; + t: (key: TKey, vars?: Record) => string; + locale: string; + onClose: () => void; +}) { + return ( + + ); +} + +export default function CompatibilityMatrix({ + apiBase, + active = true, + onCountChange, +}: { + apiBase: string; + active?: boolean; + onCountChange?: (count: number | null) => void; +}) { const { t, locale } = useI18n(); const [filters, setFilters] = useState({ layer: "", verdict: "", subjectQuery: "", + suiteId: "", }); + const [extraVerdicts, setExtraVerdicts] = useState([]); + const [nextCursor, setNextCursor] = useState(); + const [hasMore, setHasMore] = useState(false); + const [loadingMore, setLoadingMore] = useState(false); + const [selectedVerdict, setSelectedVerdict] = useState(null); + const [detail, setDetail] = useState(null); + const [detailLoading, setDetailLoading] = useState(false); + const [detailError, setDetailError] = useState(null); + + const queryFilters = useMemo(() => verdictQueryFromFilters(filters), [filters]); + const queryKey = JSON.stringify(queryFilters); - const resourceKey = `lab-matrix:${apiBase}`; const fetchPage = useCallback( - (signal: AbortSignal) => fetchLabPageData(apiBase, signal), - [apiBase], + (signal: AbortSignal) => fetchLabPageData(apiBase, queryFilters, signal), + [apiBase, queryFilters], ); - const surface = useDataSurface(resourceKey, [apiBase], fetchPage, { + const resourceKey = `lab-matrix:${apiBase}:${queryKey}`; + const surface = useDataSurface(resourceKey, [apiBase, queryKey], fetchPage, { isEmpty: (data: LabPageData) => data.verdicts.length === 0, pollMs: 60_000, + enabled: active, + pauseWhenHidden: !active, }); - const filteredVerdicts = useMemo(() => { + const updateFilters = useCallback((updater: (current: VerdictFilters) => VerdictFilters) => { + setFilters(updater); + setExtraVerdicts([]); + setNextCursor(undefined); + setHasMore(false); + }, []); + + const reportedCount = useMemo(() => { + if (!active) return null; + if (!surface.data?.status.projectionAvailable) return null; + const total = surface.data.status.verdictCount; + return typeof total === "number" ? total : surface.data.verdicts.length + extraVerdicts.length; + }, [active, extraVerdicts.length, surface.data]); + + useEffect(() => { + onCountChange?.(reportedCount); + }, [onCountChange, reportedCount]); + + const allVerdicts = useMemo(() => { if (!surface.data) return []; - return filterVerdicts(surface.data.verdicts, filters); - }, [surface.data, filters]); + return [...surface.data.verdicts, ...extraVerdicts]; + }, [extraVerdicts, surface.data]); const matrixRows = useMemo(() => { if (!surface.data) return []; - return buildMatrixRows(filteredVerdicts, surface.data.subjects); - }, [filteredVerdicts, surface.data]); + return buildMatrixRows(allVerdicts, surface.data.subjects); + }, [allVerdicts, surface.data]); + + const loadMore = async () => { + const cursor = nextCursor ?? surface.data?.nextCursor; + if (!cursor || loadingMore) return; + setLoadingMore(true); + try { + const controller = new AbortController(); + const page = await fetchMoreVerdicts(apiBase, queryFilters, cursor, controller.signal); + setExtraVerdicts(current => [...current, ...page.verdicts]); + setNextCursor(page.nextCursor); + setHasMore(page.hasMore); + } catch { + // keep current page; user can refresh + } finally { + setLoadingMore(false); + } + }; + + const visibleSelection = active ? selectedVerdict : null; + + const selectVerdict = useCallback(async (verdict: VerdictDto) => { + if (!active) return; + setSelectedVerdict(verdict); + setDetail(null); + setDetailError(null); + setDetailLoading(true); + setFilters(current => ({ ...current, suiteId: verdict.suiteId })); + try { + const controller = new AbortController(); + const loaded = await fetchVerdictDetail(apiBase, verdict, controller.signal); + setDetail(loaded); + } catch (e) { + setDetailError(localizedFetchError(e, t("lab.detailLoadFailed"))); + } finally { + setDetailLoading(false); + } + }, [active, apiBase, t]); + + const pageHasMore = extraVerdicts.length > 0 ? hasMore : (surface.data?.hasMore ?? false); const layerOptions = [ { value: "", label: t("lab.filter.all") }, @@ -165,13 +357,7 @@ export default function CompatibilityMatrix({ apiBase }: { apiBase: string }) { ]; if (surface.state.showSkeleton) { - return ( -
-

{t("lab.title")}

-

{t("lab.subtitle")}

- -
- ); + return ; } const loadError = surface.state.showError @@ -185,10 +371,6 @@ export default function CompatibilityMatrix({ apiBase }: { apiBase: string }) { return (
-
-

{t("lab.title")}

-

{t("lab.subtitle")}

-
- {matrixRows.length === 0 ? ( - - ) : ( - <> -
-

{t("lab.matrixTitle")}

-
- - - - - - {EVIDENCE_LAYERS.map(layer => ( - - ))} - - - - {matrixRows.map(row => ( - - - + {matrixRows.length === 0 ? ( + + ) : ( + <> +
+

{t("lab.matrixTitle")}

+
+
{t("lab.col.subject")}{t("lab.subjectKind")}{t(LAYER_COLUMN[layer])}
- {shortSubjectId(row.subjectId)} - {row.subjectKind}
+ + + + {EVIDENCE_LAYERS.map(layer => ( - + ))} - ))} - -
{t("lab.col.subject")}{t("lab.subjectKind")} - - {t(LAYER_COLUMN[layer])}
+ + + {matrixRows.map(row => ( + + + {shortSubjectId(row.subjectId)} + + {row.subjectKind} + {EVIDENCE_LAYERS.map(layer => ( + + + + ))} + + ))} + + +
-
-
-

{t("lab.verdictsTitle")}

-
- - - - - - - - - - - - {filteredVerdicts.map(verdict => ( - - - - - - +
+

{t("lab.verdictsTitle")}

+
+
{t("lab.col.subject")}{t("lab.col.layer")}{t("lab.col.suite")}{t("lab.col.verdict")}{t("lab.col.asOf")}
- {shortSubjectId(verdict.subjectId)} - {t(LAYER_LABEL[verdict.evidenceLayer])}{verdict.suiteId} - - {formatAsOf(verdict.asOf, locale)}
+ + + + + + + - ))} - -
{t("lab.col.subject")}{t("lab.col.layer")}{t("lab.col.suite")}{t("lab.col.verdict")}{t("lab.col.asOf")}
+ + + {allVerdicts.map(verdict => ( + { void selectVerdict(verdict); }} + onKeyDown={event => { + if (event.key === "Enter" || event.key === " ") { + event.preventDefault(); + void selectVerdict(verdict); + } + }} + > + + {shortSubjectId(verdict.subjectId)} + + {t(LAYER_LABEL[verdict.evidenceLayer])} + {verdict.suiteId} + + + + {formatAsOf(verdict.asOf, locale)} + + ))} + + +
- - + + {pageHasMore && ( +
+ +
+ )} + + )} + + + {visibleSelection && ( + { + setSelectedVerdict(null); + setDetail(null); + setDetailError(null); + }} + /> )} - + )} ); diff --git a/gui/src/pages/Models.tsx b/gui/src/pages/Models.tsx index 8958a76224..51d8294f57 100644 --- a/gui/src/pages/Models.tsx +++ b/gui/src/pages/Models.tsx @@ -13,6 +13,7 @@ import { DataSurfaceSkeleton } from "../components/data-surface"; import ErrorBoundary from "../components/ErrorBoundary"; import Combos from "./Combos"; import RoutingProfiles from "./RoutingProfiles"; +import CompatibilityMatrix from "./CompatibilityMatrix"; import { ModelsTabStrip } from "./models-tab-strip"; import { modelsPanelDomId, @@ -71,6 +72,7 @@ const SUBTITLE_TKEY: Record = { catalog: "models.subtitle", combos: "models.subtitle.combos", routing: "models.subtitle.routing", + compatibility: "models.subtitle.compatibility", }; /** @@ -128,6 +130,7 @@ export default function Models({ apiBase }: { apiBase: string }) { /** Counts reported up by the panels that own the underlying lists. */ const [comboCount, setComboCount] = useState(null); const [routingCount, setRoutingCount] = useState(null); + const [compatibilityCount, setCompatibilityCount] = useState(null); const t: TFn = useT(); const cacheKey = `ocx.models.catalog.v1:${apiBase}`; @@ -532,7 +535,8 @@ export default function Models({ apiBase }: { apiBase: string }) { : undefined, combos: comboCount === null ? undefined : String(comboCount), routing: routingCount === null ? undefined : String(routingCount), - }), [catalogCountReady, comboCount, effectiveVisibleCount, models.length, routingCount, t]); + compatibility: compatibilityCount === null ? undefined : String(compatibilityCount), + }), [catalogCountReady, comboCount, compatibilityCount, effectiveVisibleCount, models.length, routingCount, t]); const applyVisibility = async ( scope: ModelVisibilityScope, @@ -1799,6 +1803,26 @@ export default function Models({ apiBase }: { apiBase: string }) { )} + + ); diff --git a/gui/src/pages/compatibility-matrix-api.ts b/gui/src/pages/compatibility-matrix-api.ts index 79f5944c5a..71ef55fb26 100644 --- a/gui/src/pages/compatibility-matrix-api.ts +++ b/gui/src/pages/compatibility-matrix-api.ts @@ -1,13 +1,27 @@ import { readJsonOrThrow } from "../fetch-json"; import { + artifactDigestsForVerdict, + parseArtifactMetadata, + parseLabEvent, parseLabStatus, + parseObservationsPage, + parseSubjectDetail, parseSubjectPage, parseVerdictPage, + type ArtifactMetadataDto, + type LabEventDto, type LabStatusDto, + type ObservationDto, + type PaginatedObservations, type PaginatedSubjects, + type PaginatedVerdicts, + type SubjectDetailDto, + type SubjectListItemDto, type VerdictDto, + type VerdictQueryFilters, } from "./compatibility-matrix-shared"; -const PAGE_LIMIT = 100; + +const PAGE_LIMIT = 50; async function fetchLabJson( apiBase: string, @@ -18,6 +32,18 @@ async function fetchLabJson( return readJsonOrThrow(res); } +function buildQuery( + params: Record, + cursor?: string, +): string { + const query = new URLSearchParams({ limit: String(PAGE_LIMIT) }); + for (const [key, value] of Object.entries(params)) { + if (value) query.set(key, value); + } + if (cursor) query.set("cursor", cursor); + return query.toString(); +} + export async function fetchLabStatus( apiBase: string, signal: AbortSignal, @@ -26,57 +52,177 @@ export async function fetchLabStatus( return parseLabStatus(raw) ?? { projectionAvailable: false }; } -export async function fetchAllVerdicts( +export async function fetchVerdictPage( apiBase: string, + filters: VerdictQueryFilters, + cursor: string | undefined, signal: AbortSignal, -): Promise { - const rows: VerdictDto[] = []; - let cursor: string | undefined; - do { - const query = new URLSearchParams({ limit: String(PAGE_LIMIT) }); - if (cursor) query.set("cursor", cursor); - const raw = await fetchLabJson(apiBase, `/api/lab/verdicts?${query}`, signal); - const page = parseVerdictPage(raw); - rows.push(...page.verdicts); - cursor = page.hasMore ? page.nextCursor : undefined; - } while (cursor); - return rows; +): Promise { + const raw = await fetchLabJson( + apiBase, + `/api/lab/verdicts?${buildQuery({ + layer: filters.layer, + verdict: filters.verdict, + subjectId: filters.subjectId, + suiteId: filters.suiteId, + }, cursor)}`, + signal, + ); + return parseVerdictPage(raw); +} + +export async function fetchSubjectPage( + apiBase: string, + cursor: string | undefined, + signal: AbortSignal, +): Promise { + const raw = await fetchLabJson( + apiBase, + `/api/lab/subjects?${buildQuery({}, cursor)}`, + signal, + ); + return parseSubjectPage(raw); } export async function fetchAllSubjects( apiBase: string, signal: AbortSignal, -): Promise { - const rows: PaginatedSubjects["subjects"] = []; +): Promise { + const rows: SubjectListItemDto[] = []; let cursor: string | undefined; do { - const query = new URLSearchParams({ limit: String(PAGE_LIMIT) }); - if (cursor) query.set("cursor", cursor); - const raw = await fetchLabJson(apiBase, `/api/lab/subjects?${query}`, signal); - const page = parseSubjectPage(raw); + const page = await fetchSubjectPage(apiBase, cursor, signal); rows.push(...page.subjects); cursor = page.hasMore ? page.nextCursor : undefined; } while (cursor); return rows; } +export async function fetchSubjectDetail( + apiBase: string, + subjectId: string, + signal: AbortSignal, +): Promise { + const raw = await fetchLabJson( + apiBase, + `/api/lab/subjects/${encodeURIComponent(subjectId)}`, + signal, + ); + return parseSubjectDetail(raw); +} + +export async function fetchObservationsPage( + apiBase: string, + filters: { subjectId: string; layer?: string; suiteId?: string }, + cursor: string | undefined, + signal: AbortSignal, +): Promise { + const raw = await fetchLabJson( + apiBase, + `/api/lab/observations?${buildQuery({ + subjectId: filters.subjectId, + layer: filters.layer, + suiteId: filters.suiteId, + }, cursor)}`, + signal, + ); + return parseObservationsPage(raw); +} + +export async function fetchEventById( + apiBase: string, + eventId: string, + signal: AbortSignal, +): Promise { + const raw = await fetchLabJson( + apiBase, + `/api/lab/events/${encodeURIComponent(eventId)}`, + signal, + ); + return parseLabEvent(raw); +} + +export async function fetchArtifactByDigest( + apiBase: string, + digest: string, + signal: AbortSignal, +): Promise { + const raw = await fetchLabJson( + apiBase, + `/api/lab/artifacts/${encodeURIComponent(digest)}`, + signal, + ); + return parseArtifactMetadata(raw); +} + export type LabPageData = { status: LabStatusDto; verdicts: VerdictDto[]; - subjects: PaginatedSubjects["subjects"]; + subjects: SubjectListItemDto[]; + hasMore: boolean; + nextCursor?: string; }; export async function fetchLabPageData( apiBase: string, + filters: VerdictQueryFilters, signal: AbortSignal, ): Promise { const status = await fetchLabStatus(apiBase, signal); if (!status.projectionAvailable) { - return { status, verdicts: [], subjects: [] }; + return { status, verdicts: [], subjects: [], hasMore: false }; } - const [verdicts, subjects] = await Promise.all([ - fetchAllVerdicts(apiBase, signal), + const [verdictPage, subjects] = await Promise.all([ + fetchVerdictPage(apiBase, filters, undefined, signal), fetchAllSubjects(apiBase, signal), ]); - return { status, verdicts, subjects }; + return { + status, + verdicts: verdictPage.verdicts, + subjects, + hasMore: verdictPage.hasMore, + nextCursor: verdictPage.nextCursor, + }; +} + +export async function fetchMoreVerdicts( + apiBase: string, + filters: VerdictQueryFilters, + cursor: string, + signal: AbortSignal, +): Promise { + return fetchVerdictPage(apiBase, filters, cursor, signal); +} + +export type VerdictDetailData = { + subject: SubjectDetailDto | null; + observations: ObservationDto[]; + events: LabEventDto[]; + artifacts: ArtifactMetadataDto[]; +}; + +export async function fetchVerdictDetail( + apiBase: string, + verdict: VerdictDto, + signal: AbortSignal, +): Promise { + const eventIds = [...verdict.contributingEventIds, ...verdict.contradictingEventIds]; + const [subject, observationsPage, ...rest] = await Promise.all([ + fetchSubjectDetail(apiBase, verdict.subjectId, signal), + fetchObservationsPage(apiBase, { + subjectId: verdict.subjectId, + layer: verdict.evidenceLayer, + suiteId: verdict.suiteId, + }, undefined, signal), + ...eventIds.map(id => fetchEventById(apiBase, id, signal)), + ...artifactDigestsForVerdict(verdict).map(digest => fetchArtifactByDigest(apiBase, digest, signal)), + ]); + const events = rest.slice(0, eventIds.length).filter((row): row is LabEventDto => row !== null); + const artifacts = rest.slice(eventIds.length).filter((row): row is ArtifactMetadataDto => row !== null); + return { + subject, + observations: observationsPage.observations, + events, + artifacts, + }; } diff --git a/gui/src/pages/compatibility-matrix-shared.ts b/gui/src/pages/compatibility-matrix-shared.ts index d441f171ae..1f00e9ef03 100644 --- a/gui/src/pages/compatibility-matrix-shared.ts +++ b/gui/src/pages/compatibility-matrix-shared.ts @@ -1,5 +1,5 @@ /** - * CL-05 Compatibility Matrix — shared types and matrix helpers. + * CL-05 Compatibility Matrix - shared types and matrix helpers. * Read-only DTO shapes mirror GET /api/lab/* responses. */ @@ -60,6 +60,61 @@ export type SubjectListItemDto = { subjectKind: string; }; +export type SubjectDetailDto = { + subjectKind: string; + subjectSchemaVersion?: number; + [key: string]: unknown; +}; + +export type ObservationDto = { + eventId: string; + subjectId: string; + evidenceLayer: EvidenceLayer; + suiteId: string; + suiteVersion: string; + suiteManifestDigest: string; + scenarioId: string; + scenarioVersion: string; + scenarioManifestDigest: string; + outcome: string; + completedAt: number; + executionMode: string; + excluded: boolean; + exclusionReason: string | null; +}; + +export type EventListItemDto = { + eventId: string; + eventKind: string; + recordedAt: number; + excluded: boolean; + exclusionReason: string | null; +}; + +export type LabEventDto = { + eventKind: string; + eventId: string; + recordedAt: number; + producer: string; + producerVersion: string; + subjectId?: string; + evidenceLayer?: EvidenceLayer; + suiteId?: string; + outcome?: string; + excluded: boolean; + exclusionReason: string | null; + [key: string]: unknown; +}; + +export type ArtifactMetadataDto = { + digest: string; + artifactClass: string | null; + mediaType: string | null; + byteCount: number | null; + status: "present" | "corrupt" | "purged_unavailable"; + lastError: string | null; +}; + export type PaginatedVerdicts = { verdicts: VerdictDto[]; hasMore: boolean; @@ -72,16 +127,37 @@ export type PaginatedSubjects = { nextCursor?: string; }; +export type PaginatedObservations = { + observations: ObservationDto[]; + hasMore: boolean; + nextCursor?: string; +}; + +export type PaginatedEvents = { + events: EventListItemDto[]; + hasMore: boolean; + nextCursor?: string; +}; + export type MatrixRow = { subjectId: string; subjectKind: string; byLayer: Record; }; +/** UI filter state; subjectQuery maps to the API subjectId param when refetching. */ export type VerdictFilters = { layer: EvidenceLayer | ""; verdict: CompatibilityVerdict | ""; subjectQuery: string; + suiteId: string; +}; + +export type VerdictQueryFilters = { + layer?: EvidenceLayer; + verdict?: CompatibilityVerdict; + subjectId?: string; + suiteId?: string; }; export function isPlainObject(value: unknown): value is Record { @@ -134,6 +210,86 @@ export function parseSubjectPage(raw: unknown): PaginatedSubjects { }; } +export function parseSubjectDetail(raw: unknown): SubjectDetailDto | null { + if (!isPlainObject(raw) || !isPlainObject(raw.subject)) return null; + const subject = raw.subject; + if (typeof subject.subjectKind !== "string") return null; + return subject as SubjectDetailDto; +} + +export function parseObservationDto(raw: unknown): ObservationDto | null { + if (!isPlainObject(raw)) return null; + if (typeof raw.eventId !== "string") return null; + if (typeof raw.subjectId !== "string") return null; + if (typeof raw.evidenceLayer !== "string") return null; + if (!EVIDENCE_LAYERS.includes(raw.evidenceLayer as EvidenceLayer)) return null; + if (typeof raw.suiteId !== "string") return null; + if (typeof raw.outcome !== "string") return null; + return raw as ObservationDto; +} + +export function parseObservationsPage(raw: unknown): PaginatedObservations { + if (!isPlainObject(raw) || !Array.isArray(raw.observations)) { + return { observations: [], hasMore: false }; + } + const observations = raw.observations + .map(parseObservationDto) + .filter((row): row is ObservationDto => row !== null); + return { + observations, + hasMore: raw.hasMore === true, + nextCursor: typeof raw.nextCursor === "string" ? raw.nextCursor : undefined, + }; +} + +export function parseEventListItem(raw: unknown): EventListItemDto | null { + if (!isPlainObject(raw)) return null; + if (typeof raw.eventId !== "string") return null; + if (typeof raw.eventKind !== "string") return null; + return raw as EventListItemDto; +} + +export function parseEventsPage(raw: unknown): PaginatedEvents { + if (!isPlainObject(raw) || !Array.isArray(raw.events)) { + return { events: [], hasMore: false }; + } + const events = raw.events + .map(parseEventListItem) + .filter((row): row is EventListItemDto => row !== null); + return { + events, + hasMore: raw.hasMore === true, + nextCursor: typeof raw.nextCursor === "string" ? raw.nextCursor : undefined, + }; +} + +export function parseLabEvent(raw: unknown): LabEventDto | null { + if (!isPlainObject(raw) || !isPlainObject(raw.event)) return null; + const event = { ...raw.event }; + delete event.payload_json; + if (typeof event.eventKind !== "string") return null; + if (typeof event.eventId !== "string") return null; + return event as LabEventDto; +} + +export function parseArtifactMetadata(raw: unknown): ArtifactMetadataDto | null { + if (!isPlainObject(raw) || !isPlainObject(raw.artifact)) return null; + const artifact = raw.artifact; + if (typeof artifact.digest !== "string") return null; + if (typeof artifact.status !== "string") return null; + return artifact as ArtifactMetadataDto; +} + +export function verdictQueryFromFilters(filters: VerdictFilters): VerdictQueryFilters { + const query: VerdictQueryFilters = {}; + const subjectId = filters.subjectQuery.trim(); + if (filters.layer) query.layer = filters.layer; + if (filters.verdict) query.verdict = filters.verdict; + if (subjectId) query.subjectId = subjectId; + if (filters.suiteId.trim()) query.suiteId = filters.suiteId.trim(); + return query; +} + export function emptyLayerMap(): Record { return { protocol_conformance: [], @@ -170,6 +326,7 @@ export function filterVerdicts(verdicts: VerdictDto[], filters: VerdictFilters): return verdicts.filter(verdict => { if (filters.layer && verdict.evidenceLayer !== filters.layer) return false; if (filters.verdict && verdict.verdict !== filters.verdict) return false; + if (filters.suiteId && verdict.suiteId !== filters.suiteId) return false; if (query && !verdict.subjectId.toLowerCase().includes(query)) return false; return true; }); @@ -177,10 +334,18 @@ export function filterVerdicts(verdicts: VerdictDto[], filters: VerdictFilters): export function shortSubjectId(subjectId: string): string { if (subjectId.length <= 16) return subjectId; - return `${subjectId.slice(0, 8)}…${subjectId.slice(-6)}`; + return `${subjectId.slice(0, 8)}.${subjectId.slice(-6)}`; } export function formatAsOf(ms: number, locale: string): string { - if (!Number.isFinite(ms) || ms <= 0) return "–"; + if (!Number.isFinite(ms) || ms <= 0) return "-"; return new Date(ms).toLocaleString(locale); } + +export function artifactDigestsForVerdict(verdict: VerdictDto): string[] { + const digests = new Set(); + digests.add(verdict.suiteManifestDigest); + for (const digest of verdict.scenarioManifestDigests) digests.add(digest); + if (verdict.claimSourceDigest) digests.add(verdict.claimSourceDigest); + return [...digests]; +} diff --git a/gui/src/pages/models-tab-strip.tsx b/gui/src/pages/models-tab-strip.tsx index c60f1958b2..934a00ad9d 100644 --- a/gui/src/pages/models-tab-strip.tsx +++ b/gui/src/pages/models-tab-strip.tsx @@ -20,6 +20,7 @@ const TAB_LABEL: Record = { catalog: "models.tab.catalog", combos: "models.tab.combos", routing: "models.tab.routing", + compatibility: "models.tab.compatibility", }; export function ModelsTabStrip({ diff --git a/gui/src/pages/models-tab.ts b/gui/src/pages/models-tab.ts index 28bc30f46c..952d37f5c3 100644 --- a/gui/src/pages/models-tab.ts +++ b/gui/src/pages/models-tab.ts @@ -13,9 +13,9 @@ import { navigateHash, normalizeHashPath } from "../hash-routing"; * tab shows the plain model list, so a distinct id keeps "the page" and "the tab" from * ever having to be disambiguated in code. The visible label is still "Models". */ -export type ModelsTab = "catalog" | "combos" | "routing"; +export type ModelsTab = "catalog" | "combos" | "routing" | "compatibility"; -export const MODELS_TABS: readonly ModelsTab[] = ["catalog", "combos", "routing"]; +export const MODELS_TABS: readonly ModelsTab[] = ["catalog", "combos", "routing", "compatibility"]; export function modelsTabHash(tab: ModelsTab): string { return tab === "catalog" ? "models" : `models/${tab}`; @@ -34,6 +34,7 @@ export function readModelsTab(hash = window.location.hash): ModelsTab { const raw = normalizeHashPath(hash); if (raw === "models/combos" || raw === "combos" || raw.startsWith("combos/")) return "combos"; if (raw === "models/routing" || raw === "routing" || raw.startsWith("routing/")) return "routing"; + if (raw === "models/compatibility" || raw === "lab" || raw.startsWith("lab/")) return "compatibility"; return "catalog"; } diff --git a/gui/src/styles-compatibility-matrix.css b/gui/src/styles-compatibility-matrix.css index 79a900b9ae..9bfc9ce8e1 100644 --- a/gui/src/styles-compatibility-matrix.css +++ b/gui/src/styles-compatibility-matrix.css @@ -227,3 +227,75 @@ width: 100%; } } +.lab-layout { + display: grid; + grid-template-columns: minmax(0, 1fr) minmax(220px, 320px); + gap: var(--space-3); + align-items: start; +} + +.lab-main { + min-width: 0; +} + +.lab-detail-pane { + border: 1px solid var(--border); + border-radius: var(--radius-md); + padding: var(--space-3); + background: var(--surface-1); +} + +.lab-detail-head { + display: flex; + align-items: center; + justify-content: space-between; + gap: var(--space-2); + margin-bottom: var(--space-2); +} + +.lab-detail-meta { + display: grid; + gap: var(--space-1); + margin: 0 0 var(--space-3); +} + +.lab-detail-meta dt { + font-size: var(--text-xs); + color: var(--text-muted); +} + +.lab-detail-section h4 { + margin: 0 0 var(--space-1); +} + +.lab-detail-list { + list-style: none; + margin: 0; + padding: 0; + display: grid; + gap: var(--space-1); +} + +.lab-load-more { + display: flex; + justify-content: center; + margin-top: var(--space-2); +} + +.lab-verdict-badge--selected { + outline: 2px solid var(--accent); +} + +.lab-detail-table tbody tr { + cursor: pointer; +} + +.lab-detail-table tbody tr.selected { + background: var(--surface-2); +} + +@media (max-width: 960px) { + .lab-layout { + grid-template-columns: 1fr; + } +} diff --git a/gui/tests/compatibility-lab.test.tsx b/gui/tests/compatibility-lab.test.tsx new file mode 100644 index 0000000000..563b8c37ce --- /dev/null +++ b/gui/tests/compatibility-lab.test.tsx @@ -0,0 +1,510 @@ +/** @jsxImportSource react */ +import { afterEach, beforeEach, expect, jest, test } from "bun:test"; +import { Window } from "happy-dom"; +import { act } from "react"; +import type { Root } from "react-dom/client"; +import { LanguageProvider } from "../src/i18n/provider"; +import Models from "../src/pages/Models"; +import CompatibilityMatrix from "../src/pages/CompatibilityMatrix"; +import { clearClientResourceStoresForTests } from "../src/client-resource"; +import { + buildMatrixRows, + filterVerdicts, + parseArtifactMetadata, + parseEventsPage, + parseLabEvent, + parseObservationDto, + parseSubjectDetail, + parseVerdictPage, + shortSubjectId, + verdictQueryFromFilters, +} from "../src/pages/compatibility-matrix-shared"; +import { + modelsTabHash, + readModelsTab, +} from "../src/pages/models-tab"; +import { resolveAppHashChange } from "../src/app-routing"; + +const originalFetch = globalThis.fetch; +let restoreGlobals: (() => void) | undefined; +let previousLanguageDescriptor: PropertyDescriptor | undefined; +let testWindow: Window; + +const API_BASE = "http://127.0.0.1:4096"; + +const STATUS_AVAILABLE = { + projectionAvailable: true, + subjectCount: 1, + verdictCount: 2, + observationCount: 4, + eventCount: 5, + builtAtMs: 1_700_000_000_000, +}; + +const VERDICTS_PAGE_1 = { + verdicts: [ + { + projectionKey: "k1", + subjectId: "subject-alpha", + evidenceLayer: "protocol_conformance", + suiteId: "responses-core", + suiteVersion: "1", + suiteManifestDigest: "digest-a", + projectionSpecVersion: "cl-02.v1", + verdict: "VERIFIED", + asOf: 1_700_000_000_100, + scenarioManifestDigests: ["scenario-digest"], + claimSourceDigest: null, + contributingEventIds: ["e1"], + contradictingEventIds: [], + notes: [], + }, + { + projectionKey: "k2", + subjectId: "subject-alpha", + evidenceLayer: "live_route_compatibility", + suiteId: "live-core", + suiteVersion: "1", + suiteManifestDigest: "digest-b", + projectionSpecVersion: "cl-02.v1", + verdict: "PROBED", + asOf: 1_700_000_000_200, + scenarioManifestDigests: [], + claimSourceDigest: null, + contributingEventIds: ["e2"], + contradictingEventIds: [], + notes: [], + }, + ], + hasMore: true, + nextCursor: "cursor-2", +}; + +const VERDICTS_PAGE_2 = { + verdicts: [ + { + projectionKey: "k3", + subjectId: "subject-beta", + evidenceLayer: "task_effectiveness", + suiteId: "task-core", + suiteVersion: "1", + suiteManifestDigest: "digest-c", + projectionSpecVersion: "cl-02.v1", + verdict: "BLOCKED", + asOf: 1_700_000_000_300, + scenarioManifestDigests: [], + claimSourceDigest: null, + contributingEventIds: [], + contradictingEventIds: [], + notes: [], + }, + ], + hasMore: false, +}; + +const SUBJECTS = { + subjects: [ + { subjectId: "subject-alpha", subjectKind: "protocol" }, + { subjectId: "subject-beta", subjectKind: "route" }, + ], + hasMore: false, +}; + +const SUBJECT_DETAIL = { + subject: { + subjectKind: "protocol", + subjectSchemaVersion: 1, + inboundProtocol: "openai-chat", + }, +}; + +const OBSERVATIONS = { + observations: [ + { + eventId: "obs-1", + subjectId: "subject-alpha", + evidenceLayer: "protocol_conformance", + suiteId: "responses-core", + suiteVersion: "1", + suiteManifestDigest: "digest-a", + scenarioId: "scenario-1", + scenarioVersion: "1", + scenarioManifestDigest: "scenario-digest", + outcome: "pass", + completedAt: 1_700_000_000_050, + executionMode: "fixture", + excluded: false, + exclusionReason: null, + }, + ], + hasMore: false, +}; + +const EVENT_DETAIL = { + event: { + eventKind: "observation", + eventId: "e1", + recordedAt: 1_700_000_000_040, + producer: "lab", + producerVersion: "1", + subjectId: "subject-alpha", + evidenceLayer: "protocol_conformance", + suiteId: "responses-core", + outcome: "pass", + excluded: false, + exclusionReason: null, + }, +}; + +const ARTIFACT_DETAIL = { + artifact: { + digest: "digest-a", + artifactClass: "suite_manifest", + mediaType: "application/json", + byteCount: 120, + status: "present", + lastError: null, + }, +}; + +type FetchOptions = { + unavailable?: boolean; + incompatible?: boolean; + empty?: boolean; + malformedVerdicts?: boolean; + trackRequests?: string[]; + inactive?: boolean; +}; + +function installLabFetch(opts: FetchOptions = {}) { + const requests: string[] = []; + globalThis.fetch = (async (input: RequestInfo | URL, init?: RequestInit) => { + const url = String(input); + const method = init?.method ?? "GET"; + if (method !== "GET") { + return new Response("method not allowed", { status: 405 }); + } + requests.push(url); + if (opts.trackRequests) opts.trackRequests.push(url); + + if (url.endsWith("/api/lab/status")) { + if (opts.incompatible) { + return new Response(JSON.stringify({ projectionAvailable: true, projectionIncompatible: true }), { status: 200 }); + } + if (opts.unavailable) { + return new Response(JSON.stringify({ projectionAvailable: false }), { status: 200 }); + } + return new Response(JSON.stringify(STATUS_AVAILABLE), { status: 200 }); + } + if (url.includes("/api/lab/verdicts")) { + if (opts.malformedVerdicts) { + return new Response(JSON.stringify({ verdicts: [{ subjectId: "x" }] }), { status: 200 }); + } + if (opts.empty) { + return new Response(JSON.stringify({ verdicts: [], hasMore: false }), { status: 200 }); + } + if (url.includes("cursor=cursor-2")) { + return new Response(JSON.stringify(VERDICTS_PAGE_2), { status: 200 }); + } + return new Response(JSON.stringify(VERDICTS_PAGE_1), { status: 200 }); + } + if (url.includes("/api/lab/subjects/subject-alpha")) { + return new Response(JSON.stringify(SUBJECT_DETAIL), { status: 200 }); + } + if (url.includes("/api/lab/subjects")) { + return new Response(JSON.stringify(SUBJECTS), { status: 200 }); + } + if (url.includes("/api/lab/observations")) { + return new Response(JSON.stringify(OBSERVATIONS), { status: 200 }); + } + if (url.includes("/api/lab/events/e1")) { + return new Response(JSON.stringify(EVENT_DETAIL), { status: 200 }); + } + if (url.includes("/api/lab/events/e2")) { + return new Response(JSON.stringify({ event: { ...EVENT_DETAIL.event, eventId: "e2" } }), { status: 200 }); + } + if (url.includes("/api/lab/artifacts/digest-a")) { + return new Response(JSON.stringify(ARTIFACT_DETAIL), { status: 200 }); + } + if (url.includes("/api/lab/artifacts/scenario-digest")) { + return new Response(JSON.stringify({ + artifact: { ...ARTIFACT_DETAIL.artifact, digest: "scenario-digest", artifactClass: "scenario_manifest" }, + }), { status: 200 }); + } + if (url.includes("/api/models")) return Response.json([]); + if (url.includes("/api/provider-context-caps")) return Response.json({ providers: {} }); + if (url.includes("/api/providers")) return Response.json([]); + if (url.includes("/api/selected-models")) return Response.json({}); + if (url.includes("/api/combos")) return Response.json([]); + if (url.includes("/api/config")) return Response.json(null); + if (url.includes("/api/routing-profiles")) return Response.json([]); + if (url.includes("/api/routing-analytics")) return Response.json(null); + if (url.includes("/api/shadow-call-settings")) return Response.json({ enabled: false }); + if (url.includes("/api/v2")) return new Response(null, { status: 404 }); + return new Response("{}", { status: 404 }); + }) as typeof fetch; + return { requests }; +} + +beforeEach(() => { + clearClientResourceStoresForTests(); + testWindow = new Window({ url: "http://localhost/#models" }); + previousLanguageDescriptor = Object.getOwnPropertyDescriptor(globalThis.navigator, "language"); + Object.defineProperty(globalThis.navigator, "language", { configurable: true, value: "en-US" }); + const keys = ["document", "window", "localStorage", "IS_REACT_ACT_ENVIRONMENT"] as const; + const previous = Object.fromEntries( + keys.map(key => [key, Object.getOwnPropertyDescriptor(globalThis, key)]), + ) as Record<(typeof keys)[number], PropertyDescriptor | undefined>; + Object.defineProperties(globalThis, { + document: { configurable: true, value: testWindow.document }, + window: { configurable: true, value: testWindow }, + localStorage: { configurable: true, value: testWindow.localStorage }, + IS_REACT_ACT_ENVIRONMENT: { configurable: true, value: true }, + }); + restoreGlobals = () => { + for (const key of keys) { + const descriptor = previous[key]; + if (descriptor) Object.defineProperty(globalThis, key, descriptor); + else delete (globalThis as Record)[key]; + } + if (previousLanguageDescriptor) { + Object.defineProperty(globalThis.navigator, "language", previousLanguageDescriptor); + } + }; +}); + +afterEach(() => { + restoreGlobals?.(); + globalThis.fetch = originalFetch; + clearClientResourceStoresForTests(); + testWindow.close(); +}); + +async function waitFor(predicate: () => boolean, timeoutMs = 3000): Promise { + const start = Date.now(); + while (!predicate()) { + if (Date.now() - start > timeoutMs) throw new Error("waitFor timed out"); + await act(async () => { + await new Promise(resolve => testWindow.setTimeout(resolve, 10)); + }); + } +} + +async function renderMatrix(active = true): Promise<{ root: Root; container: HTMLDivElement }> { + const React = await import("react"); + const { createRoot } = await import("react-dom/client"); + const container = testWindow.document.createElement("div"); + testWindow.document.body.appendChild(container); + const root = createRoot(container); + await act(async () => { + root.render( + + + , + ); + }); + return { root, container }; +} + +async function mountModels(hash = "#models"): Promise<{ root: Root; container: HTMLDivElement }> { + testWindow.location.hash = hash; + const { createRoot } = await import("react-dom/client"); + const container = testWindow.document.createElement("div"); + testWindow.document.body.appendChild(container); + let root!: Root; + await act(async () => { + root = createRoot(container); + root.render( + + + , + ); + }); + await act(async () => { await Promise.resolve(); }); + return { root, container }; +} + +test("1. Models tab includes Compatibility", async () => { + installLabFetch(); + const { root, container } = await mountModels(); + try { + expect(container.querySelector("#models-tab-compatibility")).toBeTruthy(); + } finally { + await act(async () => root.unmount()); + } +}); + +test("2. #models/compatibility resolves", () => { + expect(readModelsTab("#models/compatibility")).toBe("compatibility"); + expect(modelsTabHash("compatibility")).toBe("models/compatibility"); + expect(resolveAppHashChange("models/compatibility").replaceTo).toBeNull(); +}); + +test("3. refresh/bookmark behavior via models-tab roundtrip", () => { + expect(resolveAppHashChange("lab").replaceTo).toBe("models/compatibility"); + expect(readModelsTab("#lab")).toBe("compatibility"); +}); + +test("4. keyboard traversal covers four tabs in strip", async () => { + installLabFetch(); + const { root, container } = await mountModels(); + try { + const tabs = [...container.querySelectorAll('[role="tab"]')] as HTMLButtonElement[]; + expect(tabs).toHaveLength(4); + const routing = container.querySelector("#models-tab-routing") as HTMLButtonElement; + await act(async () => { routing.click(); }); + routing.focus(); + await act(async () => { + routing.dispatchEvent(new testWindow.KeyboardEvent("keydown", { key: "ArrowRight", bubbles: true })); + }); + expect(document.activeElement?.id).toBe("models-tab-compatibility"); + } finally { + await act(async () => root.unmount()); + } +}); + +test("5. available projection renders data", async () => { + installLabFetch(); + const { root, container } = await renderMatrix(); + await waitFor(() => container.textContent?.includes("Verified") ?? false); + expect(container.querySelector(".lab-matrix tbody tr")).not.toBeNull(); + await act(async () => root.unmount()); +}); + +test("6. unavailable projection is not shown as empty matrix", async () => { + installLabFetch({ unavailable: true }); + const { root, container } = await renderMatrix(); + await waitFor(() => container.textContent?.includes("not available") ?? false); + expect(container.querySelector(".lab-matrix")).toBeNull(); + await act(async () => root.unmount()); +}); + +test("7. incompatible projection shows distinct state", async () => { + installLabFetch({ incompatible: true }); + const { root, container } = await renderMatrix(); + await waitFor(() => container.textContent?.includes("incompatible") ?? false); + expect(container.querySelector(".lab-matrix")).toBeNull(); + await act(async () => root.unmount()); +}); + +test("8. empty projection shows empty state", async () => { + installLabFetch({ empty: true }); + const { root, container } = await renderMatrix(); + await waitFor(() => container.textContent?.includes("No compatibility verdicts") ?? false); + await act(async () => root.unmount()); +}); + +test("9. verdict text rendering", async () => { + installLabFetch(); + const { root, container } = await renderMatrix(); + await waitFor(() => container.textContent?.includes("Probed") ?? false); + expect(container.textContent).toContain("Verified"); + await act(async () => root.unmount()); +}); + +test("10. evidence layers render as separate columns", async () => { + const page = parseVerdictPage(VERDICTS_PAGE_1); + const rows = buildMatrixRows(page.verdicts, SUBJECTS.subjects); + expect(rows[0]!.byLayer.protocol_conformance).toHaveLength(1); + expect(rows[0]!.byLayer.live_route_compatibility).toHaveLength(1); + expect(rows[0]!.byLayer.task_effectiveness).toHaveLength(0); +}); + +test("11. filters affect API query strings", () => { + const query = verdictQueryFromFilters({ + layer: "protocol_conformance", + verdict: "VERIFIED", + subjectQuery: "subject-alpha", + suiteId: "responses-core", + }); + expect(query).toEqual({ + layer: "protocol_conformance", + verdict: "VERIFIED", + subjectId: "subject-alpha", + suiteId: "responses-core", + }); +}); + +test("12. load more pagination appends rows", async () => { + installLabFetch(); + const { root, container } = await renderMatrix(); + await waitFor(() => container.querySelector(".lab-load-more button") !== null); + const loadMore = container.querySelector(".lab-load-more button") as HTMLButtonElement; + await act(async () => { loadMore.click(); }); + await waitFor(() => container.textContent?.includes("Blocked") ?? false); + await act(async () => root.unmount()); +}); + +test("13. detail flow on selection", async () => { + installLabFetch(); + const { root, container } = await renderMatrix(); + await waitFor(() => container.querySelector(".lab-detail-table tbody tr") !== null); + const row = container.querySelector(".lab-detail-table tbody tr") as HTMLTableRowElement; + await act(async () => { row.click(); }); + await waitFor(() => container.querySelector(".lab-detail-pane") !== null); + expect(container.textContent).toContain("Contributing events"); + await act(async () => root.unmount()); +}); + +test("14. sanitized display has no payload_json fields", () => { + expect(parseVerdictPage({ verdicts: [{ subjectId: "x", payload_json: "{}" }] }).verdicts).toEqual([]); + const event = parseLabEvent({ event: { ...EVENT_DETAIL.event, payload_json: "{}" } }); + expect(event).not.toHaveProperty("payload_json"); +}); + +test("15. artifact metadata only in detail pane", async () => { + installLabFetch(); + const { root, container } = await renderMatrix(); + await waitFor(() => container.querySelector(".lab-detail-table tbody tr") !== null); + const row = container.querySelector(".lab-detail-table tbody tr") as HTMLTableRowElement; + await act(async () => { row.click(); }); + await waitFor(() => container.textContent?.includes("Artifact metadata") ?? false); + expect(container.textContent).toContain("suite_manifest"); + await act(async () => root.unmount()); +}); + +test("16. inactive panel suppresses loads", async () => { + const tracked: string[] = []; + installLabFetch({ trackRequests: tracked }); + const { root } = await renderMatrix(false); + await act(async () => { await Promise.resolve(); }); + expect(tracked.filter(url => url.includes("/api/lab/")).length).toBe(0); + await act(async () => root.unmount()); +}); + +test("17. malformed payloads fail safely", () => { + expect(parseVerdictPage(null).verdicts).toEqual([]); + expect(parseSubjectDetail(null)).toBeNull(); + expect(parseObservationDto({ eventId: "x" })).toBeNull(); + expect(parseArtifactMetadata({ artifact: { digest: "x" } })).toBeNull(); + expect(shortSubjectId("abc")).toBe("abc"); +}); + +test("18. no mutation requests are issued", async () => { + const methods: string[] = []; + installLabFetch(); + const original = globalThis.fetch; + globalThis.fetch = (async (input, init) => { + methods.push(init?.method ?? "GET"); + return original(input, init); + }) as typeof fetch; + const { root, container } = await renderMatrix(); + await waitFor(() => container.querySelector(".lab-detail-table tbody tr") !== null); + expect(methods.every(method => method === "GET")).toBe(true); + await act(async () => root.unmount()); +}); + +test("parseEventsPage rejects malformed payloads", () => { + expect(parseEventsPage(null).events).toEqual([]); +}); + +test("filterVerdicts applies client filters for suite id", () => { + const page = parseVerdictPage(VERDICTS_PAGE_1); + const filtered = filterVerdicts(page.verdicts, { + layer: "", + verdict: "", + subjectQuery: "", + suiteId: "responses-core", + }); + expect(filtered).toHaveLength(1); +}); diff --git a/gui/tests/compatibility-matrix.test.tsx b/gui/tests/compatibility-matrix.test.tsx deleted file mode 100644 index 8cc882f45f..0000000000 --- a/gui/tests/compatibility-matrix.test.tsx +++ /dev/null @@ -1,196 +0,0 @@ -/** @jsxImportSource react */ -import { afterEach, beforeEach, expect, test } from "bun:test"; -import { Window } from "happy-dom"; -import { act } from "react"; -import type { Root } from "react-dom/client"; -import { LanguageProvider } from "../src/i18n/provider"; -import CompatibilityMatrix from "../src/pages/CompatibilityMatrix"; -import { - buildMatrixRows, - filterVerdicts, - parseVerdictPage, - shortSubjectId, -} from "../src/pages/compatibility-matrix-shared"; - -const originalFetch = globalThis.fetch; -let restoreGlobals: (() => void) | undefined; -let previousLanguageDescriptor: PropertyDescriptor | undefined; -let testWindow: Window; - -const STATUS_AVAILABLE = { - projectionAvailable: true, - subjectCount: 1, - verdictCount: 2, - observationCount: 4, - eventCount: 5, - builtAtMs: 1_700_000_000_000, -}; - -const VERDICTS = { - verdicts: [ - { - projectionKey: "k1", - subjectId: "subject-alpha", - evidenceLayer: "protocol_conformance", - suiteId: "responses-core", - suiteVersion: "1", - suiteManifestDigest: "digest-a", - projectionSpecVersion: "cl-02.v1", - verdict: "VERIFIED", - asOf: 1_700_000_000_100, - scenarioManifestDigests: [], - claimSourceDigest: null, - contributingEventIds: ["e1"], - contradictingEventIds: [], - notes: [], - }, - { - projectionKey: "k2", - subjectId: "subject-alpha", - evidenceLayer: "live_route_compatibility", - suiteId: "live-core", - suiteVersion: "1", - suiteManifestDigest: "digest-b", - projectionSpecVersion: "cl-02.v1", - verdict: "PROBED", - asOf: 1_700_000_000_200, - scenarioManifestDigests: [], - claimSourceDigest: null, - contributingEventIds: ["e2"], - contradictingEventIds: [], - notes: [], - }, - ], - hasMore: false, -}; - -const SUBJECTS = { - subjects: [{ subjectId: "subject-alpha", subjectKind: "protocol" }], - hasMore: false, -}; - -beforeEach(() => { - testWindow = new Window({ url: "http://localhost/" }); - previousLanguageDescriptor = Object.getOwnPropertyDescriptor(globalThis.navigator, "language"); - Object.defineProperty(globalThis.navigator, "language", { configurable: true, value: "en-US" }); - const keys = ["document", "window", "localStorage", "IS_REACT_ACT_ENVIRONMENT"] as const; - const previous = Object.fromEntries( - keys.map(key => [key, Object.getOwnPropertyDescriptor(globalThis, key)]), - ) as Record<(typeof keys)[number], PropertyDescriptor | undefined>; - Object.defineProperties(globalThis, { - document: { configurable: true, value: testWindow.document }, - window: { configurable: true, value: testWindow }, - localStorage: { configurable: true, value: testWindow.localStorage }, - IS_REACT_ACT_ENVIRONMENT: { configurable: true, value: true }, - }); - restoreGlobals = () => { - for (const key of keys) { - const descriptor = previous[key]; - if (descriptor) Object.defineProperty(globalThis, key, descriptor); - else delete (globalThis as Record)[key]; - } - if (previousLanguageDescriptor) { - Object.defineProperty(globalThis.navigator, "language", previousLanguageDescriptor); - } - }; -}); - -afterEach(() => { - restoreGlobals?.(); - globalThis.fetch = originalFetch; - testWindow.close(); -}); - -async function waitFor(predicate: () => boolean, timeoutMs = 2000): Promise { - const start = Date.now(); - while (!predicate()) { - if (Date.now() - start > timeoutMs) throw new Error("waitFor timed out"); - await act(async () => { - await new Promise(resolve => testWindow.setTimeout(resolve, 10)); - }); - } -} - -async function renderPage(): Promise<{ root: Root; container: HTMLDivElement }> { - const React = await import("react"); - const { createRoot } = await import("react-dom/client"); - const container = testWindow.document.createElement("div"); - testWindow.document.body.appendChild(container); - const root = createRoot(container); - await act(async () => { - root.render( - - - , - ); - }); - return { root, container }; -} - -test("parseVerdictPage rejects malformed payloads", () => { - expect(parseVerdictPage(null).verdicts).toEqual([]); - expect(parseVerdictPage({ verdicts: [{ subjectId: "x" }] }).verdicts).toEqual([]); -}); - -test("buildMatrixRows groups verdicts by subject and layer", () => { - const page = parseVerdictPage(VERDICTS); - const rows = buildMatrixRows(page.verdicts, SUBJECTS.subjects); - expect(rows).toHaveLength(1); - expect(rows[0]!.byLayer.protocol_conformance).toHaveLength(1); - expect(rows[0]!.byLayer.live_route_compatibility).toHaveLength(1); - expect(rows[0]!.byLayer.task_effectiveness).toHaveLength(0); -}); - -test("filterVerdicts applies layer and subject filters", () => { - const page = parseVerdictPage(VERDICTS); - const filtered = filterVerdicts(page.verdicts, { - layer: "protocol_conformance", - verdict: "", - subjectQuery: "alpha", - }); - expect(filtered).toHaveLength(1); - expect(filtered[0]!.verdict).toBe("VERIFIED"); -}); - -test("shortSubjectId keeps short ids intact", () => { - expect(shortSubjectId("abc")).toBe("abc"); - expect(shortSubjectId("012345678901234567890")).toContain("…"); -}); - -test("CompatibilityMatrix renders matrix rows from lab APIs", async () => { - globalThis.fetch = (async (input: RequestInfo | URL) => { - const url = String(input); - if (url.endsWith("/api/lab/status")) { - return new Response(JSON.stringify(STATUS_AVAILABLE), { status: 200 }); - } - if (url.includes("/api/lab/verdicts")) { - return new Response(JSON.stringify(VERDICTS), { status: 200 }); - } - if (url.includes("/api/lab/subjects")) { - return new Response(JSON.stringify(SUBJECTS), { status: 200 }); - } - return new Response("{}", { status: 404 }); - }) as typeof fetch; - - const { root, container } = await renderPage(); - await waitFor(() => container.textContent?.includes("Compatibility matrix") ?? false); - expect(container.textContent).toContain("Verified"); - expect(container.textContent).toContain("Probed"); - expect(container.querySelector(".lab-matrix tbody tr")).not.toBeNull(); - await act(async () => root.unmount()); -}); - -test("CompatibilityMatrix shows unavailable state when projection is missing", async () => { - globalThis.fetch = (async (input: RequestInfo | URL) => { - const url = String(input); - if (url.endsWith("/api/lab/status")) { - return new Response(JSON.stringify({ projectionAvailable: false }), { status: 200 }); - } - return new Response("{}", { status: 404 }); - }) as typeof fetch; - - const { root, container } = await renderPage(); - await waitFor(() => container.textContent?.includes("not available") ?? false); - expect(container.querySelector(".lab-matrix")).toBeNull(); - await act(async () => root.unmount()); -}); diff --git a/gui/tests/models-workspace-panels.test.tsx b/gui/tests/models-workspace-panels.test.tsx index 93ec55893f..252edd46e8 100644 --- a/gui/tests/models-workspace-panels.test.tsx +++ b/gui/tests/models-workspace-panels.test.tsx @@ -45,6 +45,7 @@ function installFetch(): { hits: Map } { if (url.includes("/api/routing-analytics")) return Response.json(null); if (url.includes("/api/shadow-call-settings")) return Response.json({ enabled: false }); if (url.includes("/api/v2")) return new Response(null, { status: 404 }); + if (url.includes("/api/lab/status")) return Response.json({ projectionAvailable: false }); return new Response(null, { status: 404 }); }) as typeof fetch; return { hits }; @@ -93,12 +94,12 @@ async function mountModels(): Promise<{ container: HTMLElement; root: Root }> { const tabs = (container: HTMLElement) => [...container.querySelectorAll('[role="tab"]')] as HTMLButtonElement[]; const panel = (container: HTMLElement, id: string) => container.querySelector(`#models-panel-${id}`); -test("the strip renders all three tabs with the catalog selected on the bare hash", async () => { +test("the strip renders all four tabs with the catalog selected on the bare hash", async () => { installFetch(); const { container, root } = await mountModels(); try { expect(tabs(container).map(t => t.id)).toEqual([ - "models-tab-catalog", "models-tab-combos", "models-tab-routing", + "models-tab-catalog", "models-tab-combos", "models-tab-routing", "models-tab-compatibility", ]); const selected = tabs(container).filter(t => t.getAttribute("aria-selected") === "true"); expect(selected).toHaveLength(1); @@ -130,11 +131,11 @@ test("a cold catalog never removes the tab strip", async () => { const { container, root } = await mountModels(); try { // Still cold here: the catalog fetch is parked on the gate. - expect(tabs(container)).toHaveLength(3); + expect(tabs(container)).toHaveLength(4); expect(panel(container, "catalog")).toBeTruthy(); releaseCatalog(); await act(async () => { await Promise.resolve(); }); - expect(tabs(container)).toHaveLength(3); + expect(tabs(container)).toHaveLength(4); } finally { await act(async () => root.unmount()); } @@ -156,7 +157,7 @@ test("a cold catalog failure still lets the user reach another tab", async () => const { container, root } = await mountModels(); try { await act(async () => { await Promise.resolve(); }); - expect(tabs(container)).toHaveLength(3); + expect(tabs(container)).toHaveLength(4); // "Reachable" has to mean the click works and the panel actually appears — asserting // the button merely exists would pass with a dead tab. @@ -225,13 +226,13 @@ test("every rendered panel is wired to its tab", async () => { installFetch(); const { container, root } = await mountModels(); try { - for (const id of ["combos", "routing"]) { + for (const id of ["combos", "routing", "compatibility"]) { await act(async () => { (container.querySelector(`#models-tab-${id}`) as HTMLButtonElement).click(); }); await act(async () => { await Promise.resolve(); }); } - for (const id of ["catalog", "combos", "routing"]) { + for (const id of ["catalog", "combos", "routing", "compatibility"]) { const p = panel(container, id)!; expect(p.getAttribute("role")).toBe("tabpanel"); expect(p.getAttribute("aria-labelledby")).toBe(`models-tab-${id}`); @@ -246,7 +247,7 @@ test("every rendered panel is wired to its tab", async () => { /* * The ARIA test above pins wiring, not isolation — it would pass with every boundary * deleted. This one makes a panel actually throw. App's boundary is keyed by page, and - * all three tabs are now one page, so without per-panel boundaries one broken tab would + * all four tabs are now one page, so without per-panel boundaries one broken tab would * take the whole workspace down and stay broken across a switch. */ test("a panel load failure does not take its siblings with it", async () => { @@ -275,7 +276,7 @@ test("a panel load failure does not take its siblings with it", async () => { // failed LOAD, not a render throw — the boundary mechanism itself is covered by // error-boundary.test.tsx; what matters here is that one panel's failure is // contained. - expect(tabs(container)).toHaveLength(3); + expect(tabs(container)).toHaveLength(4); await act(async () => { (container.querySelector("#models-tab-routing") as HTMLButtonElement).click(); }); diff --git a/structure/09_compatibility-lab.md b/structure/09_compatibility-lab.md index c5ba3e1d93..2704a92aea 100644 --- a/structure/09_compatibility-lab.md +++ b/structure/09_compatibility-lab.md @@ -22,4 +22,4 @@ CL-03 does not expose a management CLI/API or UI. Those surfaces remain CL-04+ w ## CL-05 GUI read surface -CL-05 adds a read-only dashboard route (`#lab`) that visualizes the compatibility verdict matrix from existing `GET /api/lab/*` management APIs. The GUI never triggers probe execution, projection rebuilds, or evidence mutation. Verdicts remain per `(subject, evidence layer, suite)`; layers are not collapsed into a universal score. +CL-05 adds a read-only Models tab (`#models/compatibility`) that visualizes the compatibility verdict matrix from existing `GET /api/lab/*` management APIs. The legacy `#lab` hash redirects to `#models/compatibility`. The GUI never triggers probe execution, projection rebuilds, or evidence mutation. Verdicts remain per `(subject, evidence layer, suite)`; layers are not collapsed into a universal score. diff --git a/tests/models-workspace-tabs.test.ts b/tests/models-workspace-tabs.test.ts index a30b175261..e15414a6fe 100644 --- a/tests/models-workspace-tabs.test.ts +++ b/tests/models-workspace-tabs.test.ts @@ -23,7 +23,7 @@ import { describe("nested Models hashes", () => { test("both tab hashes are registered and belong to the models page", () => { - expect([...MODELS_TAB_HASHES]).toEqual(["models/combos", "models/routing"]); + expect([...MODELS_TAB_HASHES]).toEqual(["models/combos", "models/routing", "models/compatibility"]); for (const hash of MODELS_TAB_HASHES) { expect(hashBelongsToPage(hash, "models")).toBe(true); // The first segment already answers the page; the suffix only picks the tab. @@ -53,6 +53,7 @@ describe("readModelsTab", () => { expect(readModelsTab("#models")).toBe("catalog"); expect(readModelsTab("#models/combos")).toBe("combos"); expect(readModelsTab("#models/routing")).toBe("routing"); + expect(readModelsTab("#models/compatibility")).toBe("compatibility"); }); test("accepts the bare and slash-prefixed hash forms", () => { @@ -135,3 +136,11 @@ test("an unregistered deep hash normalises to the bare page, matching readModels expect(readModelsTab(`#${stray}`)).toBe("catalog"); } }); + + +describe("legacy lab hash", () => { + test("#lab redirects to models/compatibility", () => { + expect(resolveAppHashChange("lab")).toEqual({ page: "models", replaceTo: "models/compatibility" }); + expect(readModelsTab("#lab")).toBe("compatibility"); + }); +}); From 2a159b8b765d7eb7ddbe013df440f351be3e84d5 Mon Sep 17 00:00:00 2001 From: Wibias <37517432+Wibias@users.noreply.github.com> Date: Mon, 10 Aug 2026 01:51:10 +0200 Subject: [PATCH 03/16] docs(devlog): record CL-05 validation after Models tab move --- .../005_cl05_compatibility_matrix_ui.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/devlog/_plan/260807_compatibility_lab/005_cl05_compatibility_matrix_ui.md b/devlog/_plan/260807_compatibility_lab/005_cl05_compatibility_matrix_ui.md index a2b0ba4bba..6155cf7c8c 100644 --- a/devlog/_plan/260807_compatibility_lab/005_cl05_compatibility_matrix_ui.md +++ b/devlog/_plan/260807_compatibility_lab/005_cl05_compatibility_matrix_ui.md @@ -33,10 +33,10 @@ ## Validation (local) -- `bun x tsc --noEmit` - pending -- `bun test tests/lab-read-surfaces.test.ts tests/models-workspace-tabs.test.ts` - pending -- `cd gui && bun test tests/compatibility-lab.test.tsx tests/models-workspace-panels.test.tsx` - pending -- `bun run lint:gui && bun run doctor:gui && bun run build:gui && bun run privacy:scan` - pending +- `bun x tsc --noEmit` - passed +- `bun test tests/lab-read-surfaces.test.ts tests/models-workspace-tabs.test.ts` - 33/33 passed +- `cd gui && bun test tests/compatibility-lab.test.tsx tests/models-workspace-panels.test.tsx` - 29/29 passed +- `bun run lint:gui && bun run doctor:gui && bun run build:gui && bun run privacy:scan` - passed ## Acceptance blockers From ddcc710fea0074ee09c69225f7b406c1edd6dc91 Mon Sep 17 00:00:00 2001 From: Wibias <37517432+Wibias@users.noreply.github.com> Date: Mon, 10 Aug 2026 01:51:20 +0200 Subject: [PATCH 04/16] docs(devlog): record CL-05 implementation head on stack status --- devlog/_plan/260807_compatibility_lab/001_pr_stack_status.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/devlog/_plan/260807_compatibility_lab/001_pr_stack_status.md b/devlog/_plan/260807_compatibility_lab/001_pr_stack_status.md index 60d03393aa..cdd56426b7 100644 --- a/devlog/_plan/260807_compatibility_lab/001_pr_stack_status.md +++ b/devlog/_plan/260807_compatibility_lab/001_pr_stack_status.md @@ -24,7 +24,7 @@ independent review, blockers, and whether a later phase is authorized. | CL-02 | `feat/cl-02-evidence-ledger` | `4bb249b756abd468c675d2d92fffe4da95ad3e2a` | NOT RECORDED | [#1333](https://github.com/lidge-jun/opencodex/pull/1333) | MERGED TO `dev` at `025c37916225dd685d9217e5b40190600f06d278`; POST-MERGE HARDENING [#1343](https://github.com/lidge-jun/opencodex/pull/1343) MERGED at `eee2dab4d1bbacefce56057adad51d734f346702`; FINAL CLOSURE GATE [#1348](https://github.com/lidge-jun/opencodex/pull/1348) | | CL-03 | `feat/cl-03-live-route-probes` | `4f746d13799888ea0a8c7a111aa2ad61c2126ea0` | `003f7402f49bfe8dd710a7beba52f717051bfadf` | [#1352](https://github.com/lidge-jun/opencodex/pull/1352) | MERGED TO `dev` at `68c71a4e9cdf882d812f09fd94783a28749db629`; ACCEPTED/CLOSED | | CL-04 | `feat/cl-04-lab-read-surfaces` | `68c71a4e9cdf882d812f09fd94783a28749db629` | NOT RECORDED | [#1378](https://github.com/lidge-jun/opencodex/pull/1378) | MERGED TO `dev` at `d517161aeaa3a974ad3c0360ff0c97b03b4c4520` | -| CL-05 | `feat/cl-05-compatibility-matrix-ui` | `d517161aeaa3a974ad3c0360ff0c97b03b4c4520` | NOT RECORDED | DRAFT PENDING | IMPLEMENTATION IN PROGRESS (not accepted) | +| CL-05 | `feat/cl-05-compatibility-matrix-ui` | `d517161aeaa3a974ad3c0360ff0c97b03b4c4520` | `2a159b8b7` (Models tab placement) | [#1384](https://github.com/lidge-jun/opencodex/pull/1384) | IMPLEMENTATION IN PROGRESS (not accepted) | The CL-01 starting SHA is the exact CL-00 tip recorded when CL-01 began. Its moving base-ref name is not a substitute for that historical SHA. From 4805477414dc63eddd1e81f990a0e9abad400d04 Mon Sep 17 00:00:00 2001 From: Wibias <37517432+Wibias@users.noreply.github.com> Date: Mon, 10 Aug 2026 02:09:31 +0200 Subject: [PATCH 05/16] docs(devlog): add CL-05 compatibility matrix GUI screenshots MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Capture real Models → Compatibility UI states for PR #1384 review and the GUI screenshot gate. --- .../cl-05/01-matrix-populated-dark.png | Bin 0 -> 104466 bytes .../cl-05/02-projection-unavailable-dark.png | Bin 0 -> 77428 bytes .../cl-05/03-projection-empty-dark.png | Bin 0 -> 82246 bytes .../cl-05/04-verdict-detail-dark.png | Bin 0 -> 150240 bytes .../cl-05/05-matrix-narrow-dark.png | Bin 0 -> 55283 bytes 5 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 devlog/_plan/260807_compatibility_lab/screenshots/cl-05/01-matrix-populated-dark.png create mode 100644 devlog/_plan/260807_compatibility_lab/screenshots/cl-05/02-projection-unavailable-dark.png create mode 100644 devlog/_plan/260807_compatibility_lab/screenshots/cl-05/03-projection-empty-dark.png create mode 100644 devlog/_plan/260807_compatibility_lab/screenshots/cl-05/04-verdict-detail-dark.png create mode 100644 devlog/_plan/260807_compatibility_lab/screenshots/cl-05/05-matrix-narrow-dark.png diff --git a/devlog/_plan/260807_compatibility_lab/screenshots/cl-05/01-matrix-populated-dark.png b/devlog/_plan/260807_compatibility_lab/screenshots/cl-05/01-matrix-populated-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..20e8b7c6e6bae5dc53aed000722692f6dd53c231 GIT binary patch literal 104466 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 B9&1F|0@B#@>}GiP(ReR?0S5 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 O2a%IfmaGsr3H(3Iuzwl= literal 0 HcmV?d00001 diff --git a/devlog/_plan/260807_compatibility_lab/screenshots/cl-05/02-projection-unavailable-dark.png b/devlog/_plan/260807_compatibility_lab/screenshots/cl-05/02-projection-unavailable-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..91deca33e574cf9b1b0f3773dc7065c03b04fcbd GIT binary patch literal 77428 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 UbGmUL_zj=sH5=2KtGDj|AMTLf1^@s6 literal 0 HcmV?d00001 diff --git a/devlog/_plan/260807_compatibility_lab/screenshots/cl-05/03-projection-empty-dark.png b/devlog/_plan/260807_compatibility_lab/screenshots/cl-05/03-projection-empty-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..55053aa4ddd1783abe99574edc3c89e6679a1019 GIT binary patch literal 82246 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�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 Date: Mon, 10 Aug 2026 03:00:48 +0200 Subject: [PATCH 06/16] fix(lab): address CL-05 review findings --- .../005_cl05_compatibility_matrix_ui.md | 40 +- gui/src/app-routing.ts | 47 +- gui/src/i18n/catalogs.ts | 22 +- gui/src/i18n/lab-translations.ts | 436 ++++++++++++++++++ gui/src/pages/CompatibilityMatrix.tsx | 334 +++++++------- gui/src/pages/compatibility-matrix-api.ts | 223 +++++---- gui/src/pages/compatibility-matrix-shared.ts | 142 +++--- gui/src/styles-compatibility-matrix.css | 96 ++-- gui/tests/compatibility-lab-i18n.test.ts | 23 + gui/tests/compatibility-lab.test.tsx | 262 ++++++----- gui/tests/compatibility-matrix-layout.test.ts | 16 +- tests/models-workspace-tabs.test.ts | 47 +- 12 files changed, 1154 insertions(+), 534 deletions(-) create mode 100644 gui/src/i18n/lab-translations.ts create mode 100644 gui/tests/compatibility-lab-i18n.test.ts diff --git a/devlog/_plan/260807_compatibility_lab/005_cl05_compatibility_matrix_ui.md b/devlog/_plan/260807_compatibility_lab/005_cl05_compatibility_matrix_ui.md index 6155cf7c8c..7d2a311988 100644 --- a/devlog/_plan/260807_compatibility_lab/005_cl05_compatibility_matrix_ui.md +++ b/devlog/_plan/260807_compatibility_lab/005_cl05_compatibility_matrix_ui.md @@ -15,33 +15,51 @@ - **Models → Compatibility tab** at `#models/compatibility` (not a standalone sidebar page) - Legacy `#lab` hash redirects to `#models/compatibility` - `CompatibilityMatrix.tsx` - read-only verdict matrix over CL-04 management APIs -- `compatibility-matrix-api.ts` - paginated fetch helpers for `/api/lab/status`, `/api/lab/verdicts`, `/api/lab/subjects`, detail reads -- `compatibility-matrix-shared.ts` - DTO parsing, matrix grouping, filters +- `compatibility-matrix-api.ts` - bounded paginated fetch helpers for `/api/lab/status`, `/api/lab/verdicts`, `/api/lab/subjects`, and detail reads +- `compatibility-matrix-shared.ts` - fail-closed DTO parsing, matrix grouping, and filters - `styles-compatibility-matrix.css` - scrollable matrix + detail pane -- i18n keys in all seven locales (`en`, `de`, `ko`, `zh`, `ru`, `ja`, `tr`) -- Component/layout tests under `gui/tests/compatibility-lab.test.tsx` +- Compatibility Lab copy localized for all seven locales (`en`, `de`, `ko`, `zh`, `ru`, `ja`, `tr`) +- Component/layout tests in `gui/tests/compatibility-lab.test.tsx` and `gui/tests/compatibility-matrix-layout.test.ts` ### Behaviour - Projection status cards (subjects, verdicts, observations, events, built-at) - Subject × evidence-layer matrix with per-suite verdict badges -- Server-side verdict filters (layer, verdict, subjectId, suiteId) with paginated "Load more" -- Verdict detail pane (subject, observations, contributing events, artifact metadata only) -- Empty/unavailable/incompatible projection states via existing data-surface contract -- Lazy mount with `active` / `pauseWhenHidden` gating inside Models workspace +- Server-side verdict filters for evidence layer, verdict, and an exact Subject-ID picker, with paginated "Load more" +- Verdict detail pane (subject, all paginated observations, bounded evidence events, artifact metadata only) +- Verdict selection is presentation state only; it never changes matrix filters or pagination identity +- Empty/unavailable/incompatible projection states via existing data-surface contract; malformed successful API payloads fail closed as load errors +- Lazy mount with `active` / hidden-panel gating inside Models workspace - No probe execution, projection rebuild, or evidence mutation -## Validation (local) +## Review remediation + +The follow-up review pass addresses all validated CodeRabbit findings plus the independent lifecycle findings found while reviewing #1384: + +- legacy `#lab` cold-load page alignment and delimiter-aware regression coverage +- repeated-cursor/page-count guards for subject and observation pagination +- strict verdict/detail DTO validation and malformed-200 handling +- bounded, partial-failure-tolerant event/artifact enrichment +- detail-selection and load-more stale-response protection +- first-page refresh/poll invalidation of appended cursor pages +- exact Subject-ID picker semantics instead of misleading free-text search +- localized closed-value labels and neutral evidence-event wording +- real button semantics for verdict-detail selection +- inactive-panel, selection/filter, pagination, localization, and routing regression coverage +- Models-tab layout test updated from the removed standalone App/sidebar architecture + +## Validation recorded before review remediation - `bun x tsc --noEmit` - passed - `bun test tests/lab-read-surfaces.test.ts tests/models-workspace-tabs.test.ts` - 33/33 passed - `cd gui && bun test tests/compatibility-lab.test.tsx tests/models-workspace-panels.test.tsx` - 29/29 passed - `bun run lint:gui && bun run doctor:gui && bun run build:gui && bun run privacy:scan` - passed +The remediation commit requires a fresh CI pass before acceptance; these earlier results are retained only as the pre-review baseline. + ## Acceptance blockers -- Draft PR requires cross-platform CI green -- GUI screenshot in PR body (or `gui-screenshot-waived` label) +- Fresh cross-platform CI on the remediation head must be green - Independent acceptance review not performed ## Out of scope (confirmed) diff --git a/gui/src/app-routing.ts b/gui/src/app-routing.ts index 24339c9f40..306a7c79f0 100644 --- a/gui/src/app-routing.ts +++ b/gui/src/app-routing.ts @@ -35,8 +35,11 @@ export function readPageFromHash(hash?: string): Page { const pageId = raw.split("/")[0] as Page; // Legacy: Debug used to be a standalone page; it now lives as a tab on Logs. if (pageId === ("debug" as Page)) return "logs"; - // Legacy: Combos and Routing used to be standalone pages; both are Models tabs now. - if (pageId === ("combos" as Page) || pageId === ("routing" as Page)) return "models"; + // Legacy: Combos, Routing, and Lab are Models tabs now. Resolve the destination page + // immediately so a cold legacy hash never flashes Dashboard before replacement. + if (pageId === ("combos" as Page) + || pageId === ("routing" as Page) + || pageId === ("lab" as Page)) return "models"; // Legacy integration pages now live below one Integrations route. Returning // the destination page here keeps the initial hook state aligned until the // resolver replaces the hash with the exact nested destination. @@ -98,7 +101,6 @@ export function hashBelongsToPage(rawHash: string, page: Page): boolean { && (INTEGRATION_TAB_HASHES as readonly string[]).includes(rawHash)); } - /** Result of resolving an incoming hash. */ export type AppHashChangeAction = { page: Page; @@ -119,13 +121,7 @@ export function resolveAppHashChange(rawHash: string): AppHashChangeAction { return { page: "logs", replaceTo: "logs/debug" }; } - /* - * Legacy: Combos and Routing used to be standalone pages, now Models tabs. - * - * The `startsWith` arm is not decoration. Without it the generic normalization below - * would rewrite `#routing/anything` to the bare page and drop the destination — the - * same bug the `#api` comment below documents. - */ + /* Legacy Models pages. Delimiter-aware prefix arms preserve nested legacy bookmarks. */ if (rawHash === "combos" || rawHash.startsWith("combos/")) { return { page: "models", replaceTo: "models/combos" }; } @@ -136,34 +132,15 @@ export function resolveAppHashChange(rawHash: string): AppHashChangeAction { return { page: "models", replaceTo: "models/compatibility" }; } - /* - * Legacy top-level integration pages. - * - * `readPageFromHash("api")` already answers `integrations`, so without these - * branches the generic normalization below would rewrite the hash to the - * bare page and silently drop the nested destination — an old `#api` - * bookmark would land on Overview instead of API Keys. `replaceTo` is - * applied with replaceState, so the correction adds no history entry. - */ - if (rawHash === "api") { - return { page: "integrations", replaceTo: "integrations/keys" }; - } - if (rawHash === "claude") { - return { page: "integrations", replaceTo: "integrations/claude" }; - } - if (rawHash === "grok") { - return { page: "integrations", replaceTo: "integrations/grok" }; - } + /* Legacy top-level integration pages. */ + if (rawHash === "api") return { page: "integrations", replaceTo: "integrations/keys" }; + if (rawHash === "claude") return { page: "integrations", replaceTo: "integrations/claude" }; + if (rawHash === "grok") return { page: "integrations", replaceTo: "integrations/grok" }; // Legacy deep link from the removed dual-layout era. - if (rawHash === "providers/workspace") { - return { page: "providers", replaceTo: "providers" }; - } + if (rawHash === "providers/workspace") return { page: "providers", replaceTo: "providers" }; // An unrecognised sub-hash is normalised away rather than left in the URL. - if (!hashBelongsToPage(rawHash, nextPage)) { - return { page: nextPage, replaceTo: nextPage }; - } - + if (!hashBelongsToPage(rawHash, nextPage)) return { page: nextPage, replaceTo: nextPage }; return { page: nextPage, replaceTo: null }; } diff --git a/gui/src/i18n/catalogs.ts b/gui/src/i18n/catalogs.ts index 6d756ef8d0..262593ab96 100644 --- a/gui/src/i18n/catalogs.ts +++ b/gui/src/i18n/catalogs.ts @@ -5,11 +5,29 @@ import { zh } from "./zh"; import { ru } from "./ru"; import { ja } from "./ja"; import { tr } from "./tr"; +import { LAB_CATALOG_OVERRIDES, type LabLocale } from "./lab-translations"; /** React-free locale catalog registry for formatters and other shared helpers. */ -export type Locale = "en" | "de" | "ko" | "zh" | "ru" | "ja" | "tr"; +export type Locale = LabLocale; -export const DICTS: Record> = { en, de, ko, zh, ru, ja, tr }; +function withLabTranslations(locale: Locale, catalog: Record): Record { + return { ...catalog, ...LAB_CATALOG_OVERRIDES[locale] }; +} + +/** + * CL-05 translations are overlaid centrally so the compatibility surface cannot regress to + * copied English values in a locale catalog. The locale parity test still validates the base + * catalogs; this overlay is deliberately limited to the closed `lab.*` namespace. + */ +export const DICTS: Record> = { + en: withLabTranslations("en", en), + de: withLabTranslations("de", de), + ko: withLabTranslations("ko", ko), + zh: withLabTranslations("zh", zh), + ru: withLabTranslations("ru", ru), + ja: withLabTranslations("ja", ja), + tr: withLabTranslations("tr", tr), +}; /** Native language names shown by the language picker, kept inside i18n rather than UI metadata. */ export function localeDisplayName(locale: Locale): string { diff --git a/gui/src/i18n/lab-translations.ts b/gui/src/i18n/lab-translations.ts new file mode 100644 index 0000000000..f75959d05b --- /dev/null +++ b/gui/src/i18n/lab-translations.ts @@ -0,0 +1,436 @@ +import type { TKey } from "./en"; + +export type LabLocale = "en" | "de" | "ko" | "zh" | "ru" | "ja" | "tr"; +export type LabCatalogKey = Extract; +export type LabSupplementKey = + | "subjectKindUnknown" + | "artifact.present" + | "artifact.corrupt" + | "artifact.purged_unavailable" + | "selectVerdict"; + +const en: Record = { + "lab.title": "Compatibility Lab", + "lab.subtitle": "Read-only compatibility verdict matrix from lab projection evidence.", + "lab.loadFailed": "Could not load compatibility lab data", + "lab.projectionUnavailable": "Lab projection is not available. Run conformance or live probes first.", + "lab.projectionIncompatible": "Lab projection schema is incompatible. Rebuild the projection.", + "lab.statusTitle": "Projection status", + "lab.matrixTitle": "Compatibility matrix", + "lab.verdictsTitle": "Verdict records", + "lab.filter.layer": "Evidence layer", + "lab.filter.verdict": "Verdict", + "lab.filter.subject": "Subject ID", + "lab.filter.all": "All", + "lab.col.subject": "Subject", + "lab.col.layer": "Layer", + "lab.col.suite": "Suite", + "lab.col.verdict": "Verdict", + "lab.col.asOf": "As of", + "lab.col.protocol": "Protocol conformance", + "lab.col.live": "Live route compatibility", + "lab.col.task": "Task effectiveness", + "lab.empty": "No compatibility verdicts in the projection yet.", + "lab.subjectKind": "Kind", + "lab.observationCount": "Observations", + "lab.eventCount": "Events", + "lab.verdictCount": "Verdicts", + "lab.subjectCount": "Subjects", + "lab.builtAt": "Built", + "lab.loading": "Loading compatibility evidence…", + "lab.loadMore": "Load more", + "lab.detailTitle": "Verdict detail", + "lab.detailClose": "Close", + "lab.detailSubject": "Subject", + "lab.detailObservations": "Observations", + "lab.detailEvents": "Evidence events", + "lab.detailArtifacts": "Artifact metadata", + "lab.detailLoadFailed": "Could not load verdict detail", + "lab.refresh": "Refresh", + "lab.verdict.UNKNOWN": "Unknown", + "lab.verdict.CLAIMED": "Claimed", + "lab.verdict.PROBED": "Probed", + "lab.verdict.VERIFIED": "Verified", + "lab.verdict.DEGRADED": "Degraded", + "lab.verdict.BLOCKED": "Blocked", + "lab.verdict.UNSUPPORTED": "Unsupported", + "lab.layer.protocol_conformance": "Protocol conformance", + "lab.layer.live_route_compatibility": "Live route compatibility", + "lab.layer.task_effectiveness": "Task effectiveness", +}; + +const de: Record = { + "lab.title": "Kompatibilitäts-Labor", + "lab.subtitle": "Schreibgeschützte Kompatibilitätsmatrix aus den Evidenzen der Lab-Projektion.", + "lab.loadFailed": "Kompatibilitätsdaten konnten nicht geladen werden", + "lab.projectionUnavailable": "Die Lab-Projektion ist nicht verfügbar. Führe zuerst Konformitäts- oder Live-Probes aus.", + "lab.projectionIncompatible": "Das Schema der Lab-Projektion ist inkompatibel. Baue die Projektion neu auf.", + "lab.statusTitle": "Projektionsstatus", + "lab.matrixTitle": "Kompatibilitätsmatrix", + "lab.verdictsTitle": "Urteilsdatensätze", + "lab.filter.layer": "Evidenzschicht", + "lab.filter.verdict": "Urteil", + "lab.filter.subject": "Subjekt-ID", + "lab.filter.all": "Alle", + "lab.col.subject": "Subjekt", + "lab.col.layer": "Schicht", + "lab.col.suite": "Suite", + "lab.col.verdict": "Urteil", + "lab.col.asOf": "Stand", + "lab.col.protocol": "Protokollkonformität", + "lab.col.live": "Live-Route-Kompatibilität", + "lab.col.task": "Aufgabenwirksamkeit", + "lab.empty": "In der Projektion gibt es noch keine Kompatibilitätsurteile.", + "lab.subjectKind": "Art", + "lab.observationCount": "Beobachtungen", + "lab.eventCount": "Ereignisse", + "lab.verdictCount": "Urteile", + "lab.subjectCount": "Subjekte", + "lab.builtAt": "Erstellt", + "lab.loading": "Kompatibilitätsevidenz wird geladen…", + "lab.loadMore": "Mehr laden", + "lab.detailTitle": "Urteilsdetails", + "lab.detailClose": "Schließen", + "lab.detailSubject": "Subjekt", + "lab.detailObservations": "Beobachtungen", + "lab.detailEvents": "Evidenzereignisse", + "lab.detailArtifacts": "Artefakt-Metadaten", + "lab.detailLoadFailed": "Urteilsdetails konnten nicht geladen werden", + "lab.refresh": "Aktualisieren", + "lab.verdict.UNKNOWN": "Unbekannt", + "lab.verdict.CLAIMED": "Behauptet", + "lab.verdict.PROBED": "Geprüft", + "lab.verdict.VERIFIED": "Verifiziert", + "lab.verdict.DEGRADED": "Eingeschränkt", + "lab.verdict.BLOCKED": "Blockiert", + "lab.verdict.UNSUPPORTED": "Nicht unterstützt", + "lab.layer.protocol_conformance": "Protokollkonformität", + "lab.layer.live_route_compatibility": "Live-Route-Kompatibilität", + "lab.layer.task_effectiveness": "Aufgabenwirksamkeit", +}; + +const ja: Record = { + "lab.title": "互換性ラボ", + "lab.subtitle": "ラボ投影の証拠に基づく読み取り専用の互換性判定マトリクスです。", + "lab.loadFailed": "互換性ラボのデータを読み込めませんでした", + "lab.projectionUnavailable": "ラボ投影を利用できません。先に適合性プローブまたはライブプローブを実行してください。", + "lab.projectionIncompatible": "ラボ投影のスキーマに互換性がありません。投影を再構築してください。", + "lab.statusTitle": "投影ステータス", + "lab.matrixTitle": "互換性マトリクス", + "lab.verdictsTitle": "判定レコード", + "lab.filter.layer": "証拠レイヤー", + "lab.filter.verdict": "判定", + "lab.filter.subject": "サブジェクト ID", + "lab.filter.all": "すべて", + "lab.col.subject": "サブジェクト", + "lab.col.layer": "レイヤー", + "lab.col.suite": "スイート", + "lab.col.verdict": "判定", + "lab.col.asOf": "時点", + "lab.col.protocol": "プロトコル適合性", + "lab.col.live": "ライブ経路互換性", + "lab.col.task": "タスク有効性", + "lab.empty": "投影にはまだ互換性判定がありません。", + "lab.subjectKind": "種類", + "lab.observationCount": "観測", + "lab.eventCount": "イベント", + "lab.verdictCount": "判定", + "lab.subjectCount": "サブジェクト", + "lab.builtAt": "構築日時", + "lab.loading": "互換性の証拠を読み込み中…", + "lab.loadMore": "さらに読み込む", + "lab.detailTitle": "判定の詳細", + "lab.detailClose": "閉じる", + "lab.detailSubject": "サブジェクト", + "lab.detailObservations": "観測", + "lab.detailEvents": "証拠イベント", + "lab.detailArtifacts": "アーティファクトのメタデータ", + "lab.detailLoadFailed": "判定の詳細を読み込めませんでした", + "lab.refresh": "更新", + "lab.verdict.UNKNOWN": "不明", + "lab.verdict.CLAIMED": "申告済み", + "lab.verdict.PROBED": "プローブ済み", + "lab.verdict.VERIFIED": "検証済み", + "lab.verdict.DEGRADED": "低下", + "lab.verdict.BLOCKED": "ブロック", + "lab.verdict.UNSUPPORTED": "未対応", + "lab.layer.protocol_conformance": "プロトコル適合性", + "lab.layer.live_route_compatibility": "ライブ経路互換性", + "lab.layer.task_effectiveness": "タスク有効性", +}; + +const ko: Record = { + "lab.title": "호환성 랩", + "lab.subtitle": "랩 프로젝션 증거를 기반으로 한 읽기 전용 호환성 판정 매트릭스입니다.", + "lab.loadFailed": "호환성 랩 데이터를 불러오지 못했습니다", + "lab.projectionUnavailable": "랩 프로젝션을 사용할 수 없습니다. 먼저 적합성 또는 라이브 프로브를 실행하세요.", + "lab.projectionIncompatible": "랩 프로젝션 스키마가 호환되지 않습니다. 프로젝션을 다시 빌드하세요.", + "lab.statusTitle": "프로젝션 상태", + "lab.matrixTitle": "호환성 매트릭스", + "lab.verdictsTitle": "판정 레코드", + "lab.filter.layer": "증거 레이어", + "lab.filter.verdict": "판정", + "lab.filter.subject": "대상 ID", + "lab.filter.all": "전체", + "lab.col.subject": "대상", + "lab.col.layer": "레이어", + "lab.col.suite": "스위트", + "lab.col.verdict": "판정", + "lab.col.asOf": "기준 시각", + "lab.col.protocol": "프로토콜 적합성", + "lab.col.live": "라이브 경로 호환성", + "lab.col.task": "작업 효과성", + "lab.empty": "프로젝션에 아직 호환성 판정이 없습니다.", + "lab.subjectKind": "종류", + "lab.observationCount": "관측", + "lab.eventCount": "이벤트", + "lab.verdictCount": "판정", + "lab.subjectCount": "대상", + "lab.builtAt": "빌드 시각", + "lab.loading": "호환성 증거를 불러오는 중…", + "lab.loadMore": "더 불러오기", + "lab.detailTitle": "판정 상세", + "lab.detailClose": "닫기", + "lab.detailSubject": "대상", + "lab.detailObservations": "관측", + "lab.detailEvents": "증거 이벤트", + "lab.detailArtifacts": "아티팩트 메타데이터", + "lab.detailLoadFailed": "판정 상세를 불러오지 못했습니다", + "lab.refresh": "새로고침", + "lab.verdict.UNKNOWN": "알 수 없음", + "lab.verdict.CLAIMED": "주장됨", + "lab.verdict.PROBED": "프로브됨", + "lab.verdict.VERIFIED": "검증됨", + "lab.verdict.DEGRADED": "저하됨", + "lab.verdict.BLOCKED": "차단됨", + "lab.verdict.UNSUPPORTED": "지원되지 않음", + "lab.layer.protocol_conformance": "프로토콜 적합성", + "lab.layer.live_route_compatibility": "라이브 경로 호환성", + "lab.layer.task_effectiveness": "작업 효과성", +}; + +const ru: Record = { + "lab.title": "Лаборатория совместимости", + "lab.subtitle": "Матрица вердиктов совместимости только для чтения на основе данных проекции лаборатории.", + "lab.loadFailed": "Не удалось загрузить данные лаборатории совместимости", + "lab.projectionUnavailable": "Проекция лаборатории недоступна. Сначала выполните проверки соответствия или live-проверки.", + "lab.projectionIncompatible": "Схема проекции лаборатории несовместима. Перестройте проекцию.", + "lab.statusTitle": "Состояние проекции", + "lab.matrixTitle": "Матрица совместимости", + "lab.verdictsTitle": "Записи вердиктов", + "lab.filter.layer": "Слой доказательств", + "lab.filter.verdict": "Вердикт", + "lab.filter.subject": "ID субъекта", + "lab.filter.all": "Все", + "lab.col.subject": "Субъект", + "lab.col.layer": "Слой", + "lab.col.suite": "Набор", + "lab.col.verdict": "Вердикт", + "lab.col.asOf": "По состоянию на", + "lab.col.protocol": "Соответствие протоколу", + "lab.col.live": "Совместимость live-маршрута", + "lab.col.task": "Эффективность задач", + "lab.empty": "В проекции пока нет вердиктов совместимости.", + "lab.subjectKind": "Тип", + "lab.observationCount": "Наблюдения", + "lab.eventCount": "События", + "lab.verdictCount": "Вердикты", + "lab.subjectCount": "Субъекты", + "lab.builtAt": "Собрано", + "lab.loading": "Загрузка доказательств совместимости…", + "lab.loadMore": "Загрузить ещё", + "lab.detailTitle": "Детали вердикта", + "lab.detailClose": "Закрыть", + "lab.detailSubject": "Субъект", + "lab.detailObservations": "Наблюдения", + "lab.detailEvents": "События доказательств", + "lab.detailArtifacts": "Метаданные артефактов", + "lab.detailLoadFailed": "Не удалось загрузить детали вердикта", + "lab.refresh": "Обновить", + "lab.verdict.UNKNOWN": "Неизвестно", + "lab.verdict.CLAIMED": "Заявлено", + "lab.verdict.PROBED": "Проверено пробой", + "lab.verdict.VERIFIED": "Подтверждено", + "lab.verdict.DEGRADED": "Ограничено", + "lab.verdict.BLOCKED": "Заблокировано", + "lab.verdict.UNSUPPORTED": "Не поддерживается", + "lab.layer.protocol_conformance": "Соответствие протоколу", + "lab.layer.live_route_compatibility": "Совместимость live-маршрута", + "lab.layer.task_effectiveness": "Эффективность задач", +}; + +const tr: Record = { + "lab.title": "Uyumluluk Laboratuvarı", + "lab.subtitle": "Laboratuvar projeksiyonu kanıtlarından oluşturulan salt okunur uyumluluk karar matrisi.", + "lab.loadFailed": "Uyumluluk laboratuvarı verileri yüklenemedi", + "lab.projectionUnavailable": "Laboratuvar projeksiyonu kullanılamıyor. Önce uygunluk veya canlı probları çalıştırın.", + "lab.projectionIncompatible": "Laboratuvar projeksiyonu şeması uyumsuz. Projeksiyonu yeniden oluşturun.", + "lab.statusTitle": "Projeksiyon durumu", + "lab.matrixTitle": "Uyumluluk matrisi", + "lab.verdictsTitle": "Karar kayıtları", + "lab.filter.layer": "Kanıt katmanı", + "lab.filter.verdict": "Karar", + "lab.filter.subject": "Özne kimliği", + "lab.filter.all": "Tümü", + "lab.col.subject": "Özne", + "lab.col.layer": "Katman", + "lab.col.suite": "Paket", + "lab.col.verdict": "Karar", + "lab.col.asOf": "Tarih", + "lab.col.protocol": "Protokol uygunluğu", + "lab.col.live": "Canlı rota uyumluluğu", + "lab.col.task": "Görev etkinliği", + "lab.empty": "Projeksiyonda henüz uyumluluk kararı yok.", + "lab.subjectKind": "Tür", + "lab.observationCount": "Gözlemler", + "lab.eventCount": "Olaylar", + "lab.verdictCount": "Kararlar", + "lab.subjectCount": "Özneler", + "lab.builtAt": "Oluşturulma", + "lab.loading": "Uyumluluk kanıtları yükleniyor…", + "lab.loadMore": "Daha fazla yükle", + "lab.detailTitle": "Karar ayrıntısı", + "lab.detailClose": "Kapat", + "lab.detailSubject": "Özne", + "lab.detailObservations": "Gözlemler", + "lab.detailEvents": "Kanıt olayları", + "lab.detailArtifacts": "Artefakt meta verileri", + "lab.detailLoadFailed": "Karar ayrıntısı yüklenemedi", + "lab.refresh": "Yenile", + "lab.verdict.UNKNOWN": "Bilinmiyor", + "lab.verdict.CLAIMED": "İddia edildi", + "lab.verdict.PROBED": "Problandı", + "lab.verdict.VERIFIED": "Doğrulandı", + "lab.verdict.DEGRADED": "Kısıtlı", + "lab.verdict.BLOCKED": "Engellendi", + "lab.verdict.UNSUPPORTED": "Desteklenmiyor", + "lab.layer.protocol_conformance": "Protokol uygunluğu", + "lab.layer.live_route_compatibility": "Canlı rota uyumluluğu", + "lab.layer.task_effectiveness": "Görev etkinliği", +}; + +const zh: Record = { + "lab.title": "兼容性实验室", + "lab.subtitle": "基于实验室投影证据的只读兼容性判定矩阵。", + "lab.loadFailed": "无法加载兼容性实验室数据", + "lab.projectionUnavailable": "实验室投影不可用。请先运行一致性探测或实时探测。", + "lab.projectionIncompatible": "实验室投影架构不兼容。请重新构建投影。", + "lab.statusTitle": "投影状态", + "lab.matrixTitle": "兼容性矩阵", + "lab.verdictsTitle": "判定记录", + "lab.filter.layer": "证据层", + "lab.filter.verdict": "判定", + "lab.filter.subject": "主体 ID", + "lab.filter.all": "全部", + "lab.col.subject": "主体", + "lab.col.layer": "层", + "lab.col.suite": "测试套件", + "lab.col.verdict": "判定", + "lab.col.asOf": "截至", + "lab.col.protocol": "协议一致性", + "lab.col.live": "实时路由兼容性", + "lab.col.task": "任务有效性", + "lab.empty": "投影中还没有兼容性判定。", + "lab.subjectKind": "类型", + "lab.observationCount": "观测", + "lab.eventCount": "事件", + "lab.verdictCount": "判定", + "lab.subjectCount": "主体", + "lab.builtAt": "构建时间", + "lab.loading": "正在加载兼容性证据…", + "lab.loadMore": "加载更多", + "lab.detailTitle": "判定详情", + "lab.detailClose": "关闭", + "lab.detailSubject": "主体", + "lab.detailObservations": "观测", + "lab.detailEvents": "证据事件", + "lab.detailArtifacts": "制品元数据", + "lab.detailLoadFailed": "无法加载判定详情", + "lab.refresh": "刷新", + "lab.verdict.UNKNOWN": "未知", + "lab.verdict.CLAIMED": "已声明", + "lab.verdict.PROBED": "已探测", + "lab.verdict.VERIFIED": "已验证", + "lab.verdict.DEGRADED": "降级", + "lab.verdict.BLOCKED": "已阻止", + "lab.verdict.UNSUPPORTED": "不支持", + "lab.layer.protocol_conformance": "协议一致性", + "lab.layer.live_route_compatibility": "实时路由兼容性", + "lab.layer.task_effectiveness": "任务有效性", +}; + +export const LAB_CATALOG_OVERRIDES: Record> = { + en, + de, + ko, + zh, + ru, + ja, + tr, +}; + +const supplements: Record> = { + en: { + subjectKindUnknown: "Unknown", + "artifact.present": "Present", + "artifact.corrupt": "Corrupt", + "artifact.purged_unavailable": "Purged / unavailable", + selectVerdict: "View verdict for {subject}", + }, + de: { + subjectKindUnknown: "Unbekannt", + "artifact.present": "Vorhanden", + "artifact.corrupt": "Beschädigt", + "artifact.purged_unavailable": "Gelöscht / nicht verfügbar", + selectVerdict: "Urteil für {subject} anzeigen", + }, + ko: { + subjectKindUnknown: "알 수 없음", + "artifact.present": "있음", + "artifact.corrupt": "손상됨", + "artifact.purged_unavailable": "삭제됨 / 사용할 수 없음", + selectVerdict: "{subject}의 판정 보기", + }, + zh: { + subjectKindUnknown: "未知", + "artifact.present": "存在", + "artifact.corrupt": "已损坏", + "artifact.purged_unavailable": "已清除 / 不可用", + selectVerdict: "查看 {subject} 的判定", + }, + ru: { + subjectKindUnknown: "Неизвестно", + "artifact.present": "Доступен", + "artifact.corrupt": "Повреждён", + "artifact.purged_unavailable": "Удалён / недоступен", + selectVerdict: "Открыть вердикт для {subject}", + }, + ja: { + subjectKindUnknown: "不明", + "artifact.present": "存在", + "artifact.corrupt": "破損", + "artifact.purged_unavailable": "削除済み / 利用不可", + selectVerdict: "{subject} の判定を表示", + }, + tr: { + subjectKindUnknown: "Bilinmiyor", + "artifact.present": "Mevcut", + "artifact.corrupt": "Bozuk", + "artifact.purged_unavailable": "Temizlenmiş / kullanılamıyor", + selectVerdict: "{subject} için kararı görüntüle", + }, +}; + +export function labSupplement( + locale: LabLocale, + key: LabSupplementKey, + vars?: Record, +): string { + let value = supplements[locale][key]; + if (vars) { + for (const [name, replacement] of Object.entries(vars)) { + value = value.split(`{${name}}`).join(String(replacement)); + } + } + return value; +} diff --git a/gui/src/pages/CompatibilityMatrix.tsx b/gui/src/pages/CompatibilityMatrix.tsx index 071c3810dc..370abeeb04 100644 --- a/gui/src/pages/CompatibilityMatrix.tsx +++ b/gui/src/pages/CompatibilityMatrix.tsx @@ -1,6 +1,7 @@ -import { useCallback, useEffect, useMemo, useState } from "react"; +import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import { IconRefresh } from "../icons"; import { useI18n, type TKey } from "../i18n/shared"; +import { labSupplement, type LabSupplementKey } from "../i18n/lab-translations"; import { EmptyState, Notice, Select } from "../ui"; import { useDataSurface } from "../data-surface"; import { DataSurfaceSkeleton, DataSurfaceStatus } from "../components/data-surface"; @@ -18,6 +19,7 @@ import { formatAsOf, shortSubjectId, verdictQueryFromFilters, + type ArtifactStatus, type CompatibilityVerdict, type EvidenceLayer, type VerdictDto, @@ -46,14 +48,16 @@ const VERDICT_LABEL: Record = { UNSUPPORTED: "lab.verdict.UNSUPPORTED", }; +const ARTIFACT_STATUS_LABEL: Record = { + present: "artifact.present", + corrupt: "artifact.corrupt", + purged_unavailable: "artifact.purged_unavailable", +}; + function localizedFetchError(e: unknown, fallback: string): string { if (!(e instanceof Error)) return fallback; const msg = e.message; - if ( - msg === "Failed to fetch" - || msg.includes("NetworkError") - || msg.includes("network error") - ) { + if (msg === "Failed to fetch" || msg.includes("NetworkError") || msg.includes("network error")) { return fallback; } return msg || fallback; @@ -61,13 +65,13 @@ function localizedFetchError(e: unknown, fallback: string): string { function VerdictBadge({ verdict, - suiteId, + caption, label, selected, onSelect, }: { verdict: CompatibilityVerdict; - suiteId: string; + caption: string; label: string; selected?: boolean; onSelect?: () => void; @@ -75,16 +79,16 @@ function VerdictBadge({ const className = `lab-verdict-badge${selected ? " lab-verdict-badge--selected" : ""}`; if (onSelect) { return ( - ); } return ( - + {label} - {suiteId} + {caption} ); } @@ -107,7 +111,7 @@ function VerdictCell({ onSelect(row)} @@ -117,11 +121,7 @@ function VerdictCell({ ); } -function StatusCards({ - data, - t, - locale, -}: { +function StatusCards({ data, t, locale }: { data: LabPageData; t: (key: TKey, vars?: Record) => string; locale: string; @@ -133,12 +133,7 @@ function StatusCards({ { label: t("lab.observationCount"), value: String(status.observationCount ?? 0) }, { label: t("lab.eventCount"), value: String(status.eventCount ?? 0) }, ]; - if (status.builtAtMs) { - cards.push({ - label: t("lab.builtAt"), - value: formatAsOf(status.builtAtMs, locale), - }); - } + if (status.builtAtMs) cards.push({ label: t("lab.builtAt"), value: formatAsOf(status.builtAtMs, locale) }); return (

{cards.map(card => ( @@ -165,16 +160,14 @@ function DetailPane({ loading: boolean; error: string | null; t: (key: TKey, vars?: Record) => string; - locale: string; + locale: Parameters[0]; onClose: () => void; }) { return (
@@ -554,11 +582,7 @@ export default function CompatibilityMatrix({ error={detailError} t={t} locale={locale} - onClose={() => { - setSelectedVerdict(null); - setDetail(null); - setDetailError(null); - }} + onClose={clearDetail} /> )} diff --git a/gui/src/pages/compatibility-matrix-api.ts b/gui/src/pages/compatibility-matrix-api.ts index 71ef55fb26..12a6ac3718 100644 --- a/gui/src/pages/compatibility-matrix-api.ts +++ b/gui/src/pages/compatibility-matrix-api.ts @@ -1,6 +1,7 @@ import { readJsonOrThrow } from "../fetch-json"; import { artifactDigestsForVerdict, + isPlainObject, parseArtifactMetadata, parseLabEvent, parseLabStatus, @@ -22,34 +23,61 @@ import { } from "./compatibility-matrix-shared"; const PAGE_LIMIT = 50; +const MAX_PAGES = 200; +const DETAIL_CONCURRENCY = 6; +const MAX_DETAIL_REFERENCES = 200; -async function fetchLabJson( - apiBase: string, - path: string, - signal: AbortSignal, -): Promise { +async function fetchLabJson(apiBase: string, path: string, signal: AbortSignal): Promise { const res = await fetch(`${apiBase}${path}`, { signal }); return readJsonOrThrow(res); } -function buildQuery( - params: Record, - cursor?: string, -): string { +function buildQuery(params: Record, cursor?: string): string { const query = new URLSearchParams({ limit: String(PAGE_LIMIT) }); - for (const [key, value] of Object.entries(params)) { - if (value) query.set(key, value); - } + for (const [key, value] of Object.entries(params)) if (value) query.set(key, value); if (cursor) query.set("cursor", cursor); return query.toString(); } -export async function fetchLabStatus( - apiBase: string, - signal: AbortSignal, -): Promise { +function invalidResponse(surface: string): Error { + return new Error(`Invalid Compatibility Lab ${surface} response`); +} + +function assertPaginationContract(raw: Record, hasMore: boolean, nextCursor: string | undefined, surface: string) { + if (raw.hasMore !== undefined && typeof raw.hasMore !== "boolean") throw invalidResponse(surface); + if (raw.nextCursor !== undefined && typeof raw.nextCursor !== "string") throw invalidResponse(surface); + if (hasMore && !nextCursor) throw invalidResponse(surface); +} + +function parseStrictVerdictPage(raw: unknown): PaginatedVerdicts { + if (!isPlainObject(raw) || !Array.isArray(raw.verdicts)) throw invalidResponse("verdicts"); + const page = parseVerdictPage(raw); + if (page.verdicts.length !== raw.verdicts.length) throw invalidResponse("verdicts"); + assertPaginationContract(raw, page.hasMore, page.nextCursor, "verdicts"); + return page; +} + +function parseStrictSubjectPage(raw: unknown): PaginatedSubjects { + if (!isPlainObject(raw) || !Array.isArray(raw.subjects)) throw invalidResponse("subjects"); + const page = parseSubjectPage(raw); + if (page.subjects.length !== raw.subjects.length) throw invalidResponse("subjects"); + assertPaginationContract(raw, page.hasMore, page.nextCursor, "subjects"); + return page; +} + +function parseStrictObservationPage(raw: unknown): PaginatedObservations { + if (!isPlainObject(raw) || !Array.isArray(raw.observations)) throw invalidResponse("observations"); + const page = parseObservationsPage(raw); + if (page.observations.length !== raw.observations.length) throw invalidResponse("observations"); + assertPaginationContract(raw, page.hasMore, page.nextCursor, "observations"); + return page; +} + +export async function fetchLabStatus(apiBase: string, signal: AbortSignal): Promise { const raw = await fetchLabJson(apiBase, "/api/lab/status", signal); - return parseLabStatus(raw) ?? { projectionAvailable: false }; + const status = parseLabStatus(raw); + if (!status) throw invalidResponse("status"); + return status; } export async function fetchVerdictPage( @@ -68,7 +96,7 @@ export async function fetchVerdictPage( }, cursor)}`, signal, ); - return parseVerdictPage(raw); + return parseStrictVerdictPage(raw); } export async function fetchSubjectPage( @@ -76,39 +104,50 @@ export async function fetchSubjectPage( cursor: string | undefined, signal: AbortSignal, ): Promise { - const raw = await fetchLabJson( - apiBase, - `/api/lab/subjects?${buildQuery({}, cursor)}`, - signal, - ); - return parseSubjectPage(raw); + const raw = await fetchLabJson(apiBase, `/api/lab/subjects?${buildQuery({}, cursor)}`, signal); + return parseStrictSubjectPage(raw); } -export async function fetchAllSubjects( - apiBase: string, - signal: AbortSignal, -): Promise { - const rows: SubjectListItemDto[] = []; +async function collectPages( + loadPage: (cursor: string | undefined) => Promise<{ rows: T[]; hasMore: boolean; nextCursor?: string }>, + surface: string, +): Promise { + const rows: T[] = []; + const seen = new Set(); let cursor: string | undefined; - do { - const page = await fetchSubjectPage(apiBase, cursor, signal); - rows.push(...page.subjects); - cursor = page.hasMore ? page.nextCursor : undefined; - } while (cursor); - return rows; + for (let pageNumber = 0; pageNumber < MAX_PAGES; pageNumber++) { + const page = await loadPage(cursor); + rows.push(...page.rows); + if (!page.hasMore) return rows; + const next = page.nextCursor; + if (!next || seen.has(next) || next === cursor) { + throw new Error(`Compatibility Lab ${surface} pagination did not advance`); + } + seen.add(next); + cursor = next; + } + throw new Error(`Compatibility Lab ${surface} pagination exceeded ${MAX_PAGES} pages`); +} + +export async function fetchAllSubjects(apiBase: string, signal: AbortSignal): Promise { + return collectPages( + async cursor => { + const page = await fetchSubjectPage(apiBase, cursor, signal); + return { rows: page.subjects, hasMore: page.hasMore, nextCursor: page.nextCursor }; + }, + "subjects", + ); } export async function fetchSubjectDetail( apiBase: string, subjectId: string, signal: AbortSignal, -): Promise { - const raw = await fetchLabJson( - apiBase, - `/api/lab/subjects/${encodeURIComponent(subjectId)}`, - signal, - ); - return parseSubjectDetail(raw); +): Promise { + const raw = await fetchLabJson(apiBase, `/api/lab/subjects/${encodeURIComponent(subjectId)}`, signal); + const subject = parseSubjectDetail(raw); + if (!subject) throw invalidResponse("subject detail"); + return subject; } export async function fetchObservationsPage( @@ -126,33 +165,39 @@ export async function fetchObservationsPage( }, cursor)}`, signal, ); - return parseObservationsPage(raw); + return parseStrictObservationPage(raw); } -export async function fetchEventById( +async function fetchAllObservations( apiBase: string, - eventId: string, + filters: { subjectId: string; layer?: string; suiteId?: string }, signal: AbortSignal, -): Promise { - const raw = await fetchLabJson( - apiBase, - `/api/lab/events/${encodeURIComponent(eventId)}`, - signal, +): Promise { + return collectPages( + async cursor => { + const page = await fetchObservationsPage(apiBase, filters, cursor, signal); + return { rows: page.observations, hasMore: page.hasMore, nextCursor: page.nextCursor }; + }, + "observations", ); - return parseLabEvent(raw); +} + +export async function fetchEventById(apiBase: string, eventId: string, signal: AbortSignal): Promise { + const raw = await fetchLabJson(apiBase, `/api/lab/events/${encodeURIComponent(eventId)}`, signal); + const event = parseLabEvent(raw); + if (!event) throw invalidResponse("event detail"); + return event; } export async function fetchArtifactByDigest( apiBase: string, digest: string, signal: AbortSignal, -): Promise { - const raw = await fetchLabJson( - apiBase, - `/api/lab/artifacts/${encodeURIComponent(digest)}`, - signal, - ); - return parseArtifactMetadata(raw); +): Promise { + const raw = await fetchLabJson(apiBase, `/api/lab/artifacts/${encodeURIComponent(digest)}`, signal); + const artifact = parseArtifactMetadata(raw); + if (!artifact) throw invalidResponse("artifact detail"); + return artifact; } export type LabPageData = { @@ -169,9 +214,7 @@ export async function fetchLabPageData( signal: AbortSignal, ): Promise { const status = await fetchLabStatus(apiBase, signal); - if (!status.projectionAvailable) { - return { status, verdicts: [], subjects: [], hasMore: false }; - } + if (!status.projectionAvailable) return { status, verdicts: [], subjects: [], hasMore: false }; const [verdictPage, subjects] = await Promise.all([ fetchVerdictPage(apiBase, filters, undefined, signal), fetchAllSubjects(apiBase, signal), @@ -195,34 +238,56 @@ export async function fetchMoreVerdicts( } export type VerdictDetailData = { - subject: SubjectDetailDto | null; + subject: SubjectDetailDto; observations: ObservationDto[]; events: LabEventDto[]; artifacts: ArtifactMetadataDto[]; }; +async function mapSettledBounded( + items: readonly TItem[], + concurrency: number, + signal: AbortSignal, + mapper: (item: TItem) => Promise, +): Promise { + const limited = items.slice(0, MAX_DETAIL_REFERENCES); + const results: TResult[] = []; + let index = 0; + const worker = async () => { + while (true) { + if (signal.aborted) throw new DOMException("Aborted", "AbortError"); + const current = index++; + if (current >= limited.length) return; + try { + results.push(await mapper(limited[current]!)); + } catch (error) { + if (signal.aborted) throw error; + // Referenced events/artifacts are optional detail enrichment. Keep successful peers. + } + } + }; + const workerCount = Math.min(concurrency, limited.length); + await Promise.all(Array.from({ length: workerCount }, () => worker())); + return results; +} + export async function fetchVerdictDetail( apiBase: string, verdict: VerdictDto, signal: AbortSignal, ): Promise { - const eventIds = [...verdict.contributingEventIds, ...verdict.contradictingEventIds]; - const [subject, observationsPage, ...rest] = await Promise.all([ + const eventIds = [...new Set([...verdict.contributingEventIds, ...verdict.contradictingEventIds])]; + const digests = artifactDigestsForVerdict(verdict); + const observationFilters = { + subjectId: verdict.subjectId, + layer: verdict.evidenceLayer, + suiteId: verdict.suiteId, + }; + const [subject, observations, events, artifacts] = await Promise.all([ fetchSubjectDetail(apiBase, verdict.subjectId, signal), - fetchObservationsPage(apiBase, { - subjectId: verdict.subjectId, - layer: verdict.evidenceLayer, - suiteId: verdict.suiteId, - }, undefined, signal), - ...eventIds.map(id => fetchEventById(apiBase, id, signal)), - ...artifactDigestsForVerdict(verdict).map(digest => fetchArtifactByDigest(apiBase, digest, signal)), + fetchAllObservations(apiBase, observationFilters, signal), + mapSettledBounded(eventIds, DETAIL_CONCURRENCY, signal, id => fetchEventById(apiBase, id, signal)), + mapSettledBounded(digests, DETAIL_CONCURRENCY, signal, digest => fetchArtifactByDigest(apiBase, digest, signal)), ]); - const events = rest.slice(0, eventIds.length).filter((row): row is LabEventDto => row !== null); - const artifacts = rest.slice(eventIds.length).filter((row): row is ArtifactMetadataDto => row !== null); - return { - subject, - observations: observationsPage.observations, - events, - artifacts, - }; + return { subject, observations, events, artifacts }; } diff --git a/gui/src/pages/compatibility-matrix-shared.ts b/gui/src/pages/compatibility-matrix-shared.ts index 1f00e9ef03..02f2e2ac03 100644 --- a/gui/src/pages/compatibility-matrix-shared.ts +++ b/gui/src/pages/compatibility-matrix-shared.ts @@ -23,6 +23,9 @@ export const COMPATIBILITY_VERDICTS = [ export type CompatibilityVerdict = (typeof COMPATIBILITY_VERDICTS)[number]; +export const ARTIFACT_STATUSES = ["present", "corrupt", "purged_unavailable"] as const; +export type ArtifactStatus = (typeof ARTIFACT_STATUSES)[number]; + export type LabStatusDto = { projectionAvailable: boolean; projectionIncompatible?: boolean; @@ -111,7 +114,7 @@ export type ArtifactMetadataDto = { artifactClass: string | null; mediaType: string | null; byteCount: number | null; - status: "present" | "corrupt" | "purged_unavailable"; + status: ArtifactStatus; lastError: string | null; }; @@ -141,11 +144,12 @@ export type PaginatedEvents = { export type MatrixRow = { subjectId: string; + /** Empty means the subject page did not contain a matching row. */ subjectKind: string; byLayer: Record; }; -/** UI filter state; subjectQuery maps to the API subjectId param when refetching. */ +/** UI filter state. subjectQuery is an exact subject id selected from the subject picker. */ export type VerdictFilters = { layer: EvidenceLayer | ""; verdict: CompatibilityVerdict | ""; @@ -164,30 +168,60 @@ export function isPlainObject(value: unknown): value is Record return !!value && typeof value === "object" && !Array.isArray(value); } +function isStringArray(value: unknown): value is string[] { + return Array.isArray(value) && value.every(item => typeof item === "string"); +} + +function isNullableString(value: unknown): value is string | null { + return value === null || typeof value === "string"; +} + +function isOptionalFiniteNumber(value: unknown): boolean { + return value === undefined || (typeof value === "number" && Number.isFinite(value)); +} + export function parseLabStatus(raw: unknown): LabStatusDto | null { - if (!isPlainObject(raw)) return null; - if (typeof raw.projectionAvailable !== "boolean") return null; + if (!isPlainObject(raw) || typeof raw.projectionAvailable !== "boolean") return null; + if (raw.projectionIncompatible !== undefined && typeof raw.projectionIncompatible !== "boolean") return null; + for (const key of [ + "sqliteSchemaVersion", + "builtAtMs", + "eventCount", + "subjectCount", + "observationCount", + "claimCount", + "verdictCount", + "artifactCount", + "corruptionCount", + ] as const) { + if (!isOptionalFiniteNumber(raw[key])) return null; + } + if (raw.projectionSpecVersion !== undefined && typeof raw.projectionSpecVersion !== "string") return null; return raw as LabStatusDto; } export function parseVerdictDto(raw: unknown): VerdictDto | null { if (!isPlainObject(raw)) return null; - if (typeof raw.subjectId !== "string") return null; - if (typeof raw.evidenceLayer !== "string") return null; - if (!EVIDENCE_LAYERS.includes(raw.evidenceLayer as EvidenceLayer)) return null; - if (typeof raw.suiteId !== "string") return null; - if (typeof raw.verdict !== "string") return null; - if (!COMPATIBILITY_VERDICTS.includes(raw.verdict as CompatibilityVerdict)) return null; + if (typeof raw.projectionKey !== "string" || raw.projectionKey.length === 0) return null; + if (typeof raw.subjectId !== "string" || raw.subjectId.length === 0) return null; + if (typeof raw.evidenceLayer !== "string" || !EVIDENCE_LAYERS.includes(raw.evidenceLayer as EvidenceLayer)) return null; + if (typeof raw.suiteId !== "string" || raw.suiteId.length === 0) return null; + if (typeof raw.suiteVersion !== "string") return null; + if (typeof raw.suiteManifestDigest !== "string") return null; + if (typeof raw.projectionSpecVersion !== "string") return null; + if (typeof raw.verdict !== "string" || !COMPATIBILITY_VERDICTS.includes(raw.verdict as CompatibilityVerdict)) return null; + if (typeof raw.asOf !== "number" || !Number.isFinite(raw.asOf)) return null; + if (!isStringArray(raw.scenarioManifestDigests)) return null; + if (!isNullableString(raw.claimSourceDigest)) return null; + if (!isStringArray(raw.contributingEventIds)) return null; + if (!isStringArray(raw.contradictingEventIds)) return null; + if (!isStringArray(raw.notes)) return null; return raw as VerdictDto; } export function parseVerdictPage(raw: unknown): PaginatedVerdicts { - if (!isPlainObject(raw) || !Array.isArray(raw.verdicts)) { - return { verdicts: [], hasMore: false }; - } - const verdicts = raw.verdicts - .map(parseVerdictDto) - .filter((row): row is VerdictDto => row !== null); + if (!isPlainObject(raw) || !Array.isArray(raw.verdicts)) return { verdicts: [], hasMore: false }; + const verdicts = raw.verdicts.map(parseVerdictDto).filter((row): row is VerdictDto => row !== null); return { verdicts, hasMore: raw.hasMore === true, @@ -196,13 +230,9 @@ export function parseVerdictPage(raw: unknown): PaginatedVerdicts { } export function parseSubjectPage(raw: unknown): PaginatedSubjects { - if (!isPlainObject(raw) || !Array.isArray(raw.subjects)) { - return { subjects: [], hasMore: false }; - } - const subjects = raw.subjects.filter((row): row is SubjectListItemDto => { - if (!isPlainObject(row)) return false; - return typeof row.subjectId === "string" && typeof row.subjectKind === "string"; - }); + if (!isPlainObject(raw) || !Array.isArray(raw.subjects)) return { subjects: [], hasMore: false }; + const subjects = raw.subjects.filter((row): row is SubjectListItemDto => + isPlainObject(row) && typeof row.subjectId === "string" && typeof row.subjectKind === "string"); return { subjects, hasMore: raw.hasMore === true, @@ -212,29 +242,27 @@ export function parseSubjectPage(raw: unknown): PaginatedSubjects { export function parseSubjectDetail(raw: unknown): SubjectDetailDto | null { if (!isPlainObject(raw) || !isPlainObject(raw.subject)) return null; - const subject = raw.subject; - if (typeof subject.subjectKind !== "string") return null; - return subject as SubjectDetailDto; + if (typeof raw.subject.subjectKind !== "string") return null; + return raw.subject as SubjectDetailDto; } export function parseObservationDto(raw: unknown): ObservationDto | null { if (!isPlainObject(raw)) return null; - if (typeof raw.eventId !== "string") return null; - if (typeof raw.subjectId !== "string") return null; - if (typeof raw.evidenceLayer !== "string") return null; - if (!EVIDENCE_LAYERS.includes(raw.evidenceLayer as EvidenceLayer)) return null; - if (typeof raw.suiteId !== "string") return null; - if (typeof raw.outcome !== "string") return null; + if (typeof raw.eventId !== "string" || typeof raw.subjectId !== "string") return null; + if (typeof raw.evidenceLayer !== "string" || !EVIDENCE_LAYERS.includes(raw.evidenceLayer as EvidenceLayer)) return null; + if (typeof raw.suiteId !== "string" || typeof raw.suiteVersion !== "string") return null; + if (typeof raw.suiteManifestDigest !== "string") return null; + if (typeof raw.scenarioId !== "string" || typeof raw.scenarioVersion !== "string") return null; + if (typeof raw.scenarioManifestDigest !== "string" || typeof raw.outcome !== "string") return null; + if (typeof raw.completedAt !== "number" || !Number.isFinite(raw.completedAt)) return null; + if (typeof raw.executionMode !== "string" || typeof raw.excluded !== "boolean") return null; + if (!isNullableString(raw.exclusionReason)) return null; return raw as ObservationDto; } export function parseObservationsPage(raw: unknown): PaginatedObservations { - if (!isPlainObject(raw) || !Array.isArray(raw.observations)) { - return { observations: [], hasMore: false }; - } - const observations = raw.observations - .map(parseObservationDto) - .filter((row): row is ObservationDto => row !== null); + if (!isPlainObject(raw) || !Array.isArray(raw.observations)) return { observations: [], hasMore: false }; + const observations = raw.observations.map(parseObservationDto).filter((row): row is ObservationDto => row !== null); return { observations, hasMore: raw.hasMore === true, @@ -244,18 +272,15 @@ export function parseObservationsPage(raw: unknown): PaginatedObservations { export function parseEventListItem(raw: unknown): EventListItemDto | null { if (!isPlainObject(raw)) return null; - if (typeof raw.eventId !== "string") return null; - if (typeof raw.eventKind !== "string") return null; + if (typeof raw.eventId !== "string" || typeof raw.eventKind !== "string") return null; + if (typeof raw.recordedAt !== "number" || !Number.isFinite(raw.recordedAt)) return null; + if (typeof raw.excluded !== "boolean" || !isNullableString(raw.exclusionReason)) return null; return raw as EventListItemDto; } export function parseEventsPage(raw: unknown): PaginatedEvents { - if (!isPlainObject(raw) || !Array.isArray(raw.events)) { - return { events: [], hasMore: false }; - } - const events = raw.events - .map(parseEventListItem) - .filter((row): row is EventListItemDto => row !== null); + if (!isPlainObject(raw) || !Array.isArray(raw.events)) return { events: [], hasMore: false }; + const events = raw.events.map(parseEventListItem).filter((row): row is EventListItemDto => row !== null); return { events, hasMore: raw.hasMore === true, @@ -267,8 +292,10 @@ export function parseLabEvent(raw: unknown): LabEventDto | null { if (!isPlainObject(raw) || !isPlainObject(raw.event)) return null; const event = { ...raw.event }; delete event.payload_json; - if (typeof event.eventKind !== "string") return null; - if (typeof event.eventId !== "string") return null; + if (typeof event.eventKind !== "string" || typeof event.eventId !== "string") return null; + if (typeof event.recordedAt !== "number" || !Number.isFinite(event.recordedAt)) return null; + if (typeof event.producer !== "string" || typeof event.producerVersion !== "string") return null; + if (typeof event.excluded !== "boolean" || !isNullableString(event.exclusionReason)) return null; return event as LabEventDto; } @@ -276,7 +303,10 @@ export function parseArtifactMetadata(raw: unknown): ArtifactMetadataDto | null if (!isPlainObject(raw) || !isPlainObject(raw.artifact)) return null; const artifact = raw.artifact; if (typeof artifact.digest !== "string") return null; - if (typeof artifact.status !== "string") return null; + if (typeof artifact.status !== "string" || !ARTIFACT_STATUSES.includes(artifact.status as ArtifactStatus)) return null; + if (!isNullableString(artifact.artifactClass) || !isNullableString(artifact.mediaType)) return null; + if (artifact.byteCount !== null && (typeof artifact.byteCount !== "number" || !Number.isFinite(artifact.byteCount))) return null; + if (!isNullableString(artifact.lastError)) return null; return artifact as ArtifactMetadataDto; } @@ -298,29 +328,25 @@ export function emptyLayerMap(): Record { }; } -export function buildMatrixRows( - verdicts: VerdictDto[], - subjects: SubjectListItemDto[], -): MatrixRow[] { +export function buildMatrixRows(verdicts: VerdictDto[], subjects: SubjectListItemDto[]): MatrixRow[] { const kindById = new Map(subjects.map(row => [row.subjectId, row.subjectKind])); const bySubject = new Map(); - for (const verdict of verdicts) { let row = bySubject.get(verdict.subjectId); if (!row) { row = { subjectId: verdict.subjectId, - subjectKind: kindById.get(verdict.subjectId) ?? "unknown", + subjectKind: kindById.get(verdict.subjectId) ?? "", byLayer: emptyLayerMap(), }; bySubject.set(verdict.subjectId, row); } row.byLayer[verdict.evidenceLayer].push(verdict); } - return [...bySubject.values()].sort((a, b) => a.subjectId.localeCompare(b.subjectId)); } +/** Client-side helper retained for tests and future local-only filters. */ export function filterVerdicts(verdicts: VerdictDto[], filters: VerdictFilters): VerdictDto[] { const query = filters.subjectQuery.trim().toLowerCase(); return verdicts.filter(verdict => { @@ -344,8 +370,8 @@ export function formatAsOf(ms: number, locale: string): string { export function artifactDigestsForVerdict(verdict: VerdictDto): string[] { const digests = new Set(); - digests.add(verdict.suiteManifestDigest); - for (const digest of verdict.scenarioManifestDigests) digests.add(digest); + if (verdict.suiteManifestDigest) digests.add(verdict.suiteManifestDigest); + for (const digest of verdict.scenarioManifestDigests) if (digest) digests.add(digest); if (verdict.claimSourceDigest) digests.add(verdict.claimSourceDigest); return [...digests]; } diff --git a/gui/src/styles-compatibility-matrix.css b/gui/src/styles-compatibility-matrix.css index 9bfc9ce8e1..db86e4a89d 100644 --- a/gui/src/styles-compatibility-matrix.css +++ b/gui/src/styles-compatibility-matrix.css @@ -15,13 +15,8 @@ min-width: 0; } -.lab-page .page-head { - margin-bottom: 2px; -} - -.lab-page .page-sub { - margin: 0 0 0.5rem; -} +.lab-page .page-head { margin-bottom: 2px; } +.lab-page .page-sub { margin: 0 0 0.5rem; } .lab-status-grid { display: grid; @@ -31,7 +26,7 @@ .lab-status-card { border: 1px solid var(--border); - border-radius: var(--radius-md); + border-radius: var(--radius); background: var(--surface); padding: 0.65rem 0.75rem; min-width: 0; @@ -39,7 +34,7 @@ .lab-status-card .label { display: block; - font-size: var(--text-xs); + font-size: var(--text-label); color: var(--muted); margin-bottom: 0.2rem; } @@ -64,7 +59,7 @@ } .lab-filter-field label { - font-size: var(--text-xs); + font-size: var(--text-label); color: var(--muted); } @@ -81,14 +76,14 @@ .lab-matrix-block { border: 1px solid var(--border); - border-radius: var(--radius-md); + border-radius: var(--radius); background: var(--surface); padding: 0.75rem; } .lab-matrix-title { margin: 0 0 0.65rem; - font-size: var(--text-sm); + font-size: var(--text-control); font-weight: var(--weight-semibold); } @@ -100,7 +95,7 @@ .lab-matrix { width: 100%; border-collapse: collapse; - font-size: var(--text-sm); + font-size: var(--text-control); } .lab-matrix th, @@ -118,15 +113,15 @@ } .lab-matrix td.subject { - font-family: var(--font-mono); - font-size: var(--text-xs); + font-family: var(--font-code); + font-size: var(--text-label); max-width: 14rem; overflow-wrap: anywhere; } .lab-matrix td.kind { color: var(--muted); - font-size: var(--text-xs); + font-size: var(--text-label); white-space: nowrap; } @@ -140,18 +135,25 @@ display: inline-flex; align-items: center; gap: 0.35rem; - border-radius: 999px; + border-radius: var(--radius-pill); padding: 0.1rem 0.45rem; - font-size: var(--text-xs); + font: inherit; + font-size: var(--text-label); font-weight: var(--weight-semibold); + color: inherit; border: 1px solid transparent; white-space: nowrap; } +button.lab-verdict-badge { + appearance: none; + cursor: pointer; +} + .lab-verdict-badge .suite { font-weight: var(--weight-regular); color: var(--muted); - font-family: var(--font-mono); + font-family: var(--font-code); } .lab-verdict-badge[data-verdict="VERIFIED"], @@ -180,7 +182,7 @@ .lab-detail-table { width: 100%; border-collapse: collapse; - font-size: var(--text-sm); + font-size: var(--text-control); } .lab-detail-table th, @@ -194,12 +196,12 @@ .lab-detail-table th { color: var(--muted); font-weight: var(--weight-semibold); - font-size: var(--text-xs); + font-size: var(--text-label); } .lab-detail-table td.mono { - font-family: var(--font-mono); - font-size: var(--text-xs); + font-family: var(--font-code); + font-size: var(--text-label); overflow-wrap: anywhere; } @@ -217,16 +219,6 @@ gap: 0.35rem; } -@media (max-width: 720px) { - .lab-filters { - flex-direction: column; - align-items: stretch; - } - - .lab-filter-field { - width: 100%; - } -} .lab-layout { display: grid; grid-template-columns: minmax(0, 1fr) minmax(220px, 320px); @@ -234,15 +226,13 @@ align-items: start; } -.lab-main { - min-width: 0; -} +.lab-main { min-width: 0; } .lab-detail-pane { border: 1px solid var(--border); - border-radius: var(--radius-md); + border-radius: var(--radius); padding: var(--space-3); - background: var(--surface-1); + background: var(--surface); } .lab-detail-head { @@ -260,13 +250,11 @@ } .lab-detail-meta dt { - font-size: var(--text-xs); - color: var(--text-muted); + font-size: var(--text-label); + color: var(--muted); } -.lab-detail-section h4 { - margin: 0 0 var(--space-1); -} +.lab-detail-section h4 { margin: 0 0 var(--space-1); } .lab-detail-list { list-style: none; @@ -282,20 +270,18 @@ margin-top: var(--space-2); } -.lab-verdict-badge--selected { - outline: 2px solid var(--accent); -} - -.lab-detail-table tbody tr { - cursor: pointer; -} +.lab-verdict-badge--selected { outline: 2px solid var(--accent); } +.lab-detail-table tbody tr.selected { background: var(--raised); } -.lab-detail-table tbody tr.selected { - background: var(--surface-2); +@media (max-width: 960px) { + .lab-layout { grid-template-columns: 1fr; } } -@media (max-width: 960px) { - .lab-layout { - grid-template-columns: 1fr; +@media (max-width: 720px) { + .lab-filters { + flex-direction: column; + align-items: stretch; } + + .lab-filter-field { width: 100%; } } diff --git a/gui/tests/compatibility-lab-i18n.test.ts b/gui/tests/compatibility-lab-i18n.test.ts new file mode 100644 index 0000000000..252271dd56 --- /dev/null +++ b/gui/tests/compatibility-lab-i18n.test.ts @@ -0,0 +1,23 @@ +import { expect, test } from "bun:test"; +import { DICTS, type Locale } from "../src/i18n/catalogs"; +import { LAB_CATALOG_OVERRIDES, labSupplement } from "../src/i18n/lab-translations"; + +const NON_ENGLISH: Locale[] = ["de", "ja", "ko", "ru", "tr", "zh"]; + +test("Compatibility Lab catalog overrides cover the complete English lab namespace", () => { + const englishKeys = Object.keys(DICTS.en).filter(key => key.startsWith("lab.")).sort(); + for (const locale of Object.keys(LAB_CATALOG_OVERRIDES) as Locale[]) { + expect(Object.keys(LAB_CATALOG_OVERRIDES[locale]).sort()).toEqual(englishKeys); + } +}); + +test("Compatibility Lab ships localized core copy for every non-English locale", () => { + for (const locale of NON_ENGLISH) { + expect(DICTS[locale]["lab.title"]).not.toBe(DICTS.en["lab.title"]); + expect(DICTS[locale]["lab.loadMore"]).not.toBe(DICTS.en["lab.loadMore"]); + expect(DICTS[locale]["lab.detailClose"]).not.toBe(DICTS.en["lab.detailClose"]); + expect(DICTS[locale]["lab.detailEvents"]).not.toBe("Contributing events"); + expect(labSupplement(locale, "artifact.present")).toBeTruthy(); + expect(labSupplement(locale, "selectVerdict", { subject: "subject-a" })).toContain("subject-a"); + } +}); diff --git a/gui/tests/compatibility-lab.test.tsx b/gui/tests/compatibility-lab.test.tsx index 563b8c37ce..9629d8943d 100644 --- a/gui/tests/compatibility-lab.test.tsx +++ b/gui/tests/compatibility-lab.test.tsx @@ -1,5 +1,5 @@ /** @jsxImportSource react */ -import { afterEach, beforeEach, expect, jest, test } from "bun:test"; +import { afterEach, beforeEach, expect, test } from "bun:test"; import { Window } from "happy-dom"; import { act } from "react"; import type { Root } from "react-dom/client"; @@ -20,9 +20,11 @@ import { verdictQueryFromFilters, } from "../src/pages/compatibility-matrix-shared"; import { - modelsTabHash, - readModelsTab, -} from "../src/pages/models-tab"; + fetchAllSubjects, + fetchLabStatus, + fetchVerdictDetail, +} from "../src/pages/compatibility-matrix-api"; +import { modelsTabHash, readModelsTab } from "../src/pages/models-tab"; import { resolveAppHashChange } from "../src/app-routing"; const originalFetch = globalThis.fetch; @@ -34,8 +36,8 @@ const API_BASE = "http://127.0.0.1:4096"; const STATUS_AVAILABLE = { projectionAvailable: true, - subjectCount: 1, - verdictCount: 2, + subjectCount: 2, + verdictCount: 3, observationCount: 4, eventCount: 5, builtAtMs: 1_700_000_000_000, @@ -173,7 +175,6 @@ type FetchOptions = { empty?: boolean; malformedVerdicts?: boolean; trackRequests?: string[]; - inactive?: boolean; }; function installLabFetch(opts: FetchOptions = {}) { @@ -181,55 +182,29 @@ function installLabFetch(opts: FetchOptions = {}) { globalThis.fetch = (async (input: RequestInfo | URL, init?: RequestInit) => { const url = String(input); const method = init?.method ?? "GET"; - if (method !== "GET") { - return new Response("method not allowed", { status: 405 }); - } + if (method !== "GET") return new Response("method not allowed", { status: 405 }); requests.push(url); - if (opts.trackRequests) opts.trackRequests.push(url); + opts.trackRequests?.push(url); if (url.endsWith("/api/lab/status")) { - if (opts.incompatible) { - return new Response(JSON.stringify({ projectionAvailable: true, projectionIncompatible: true }), { status: 200 }); - } - if (opts.unavailable) { - return new Response(JSON.stringify({ projectionAvailable: false }), { status: 200 }); - } - return new Response(JSON.stringify(STATUS_AVAILABLE), { status: 200 }); + if (opts.incompatible) return Response.json({ projectionAvailable: true, projectionIncompatible: true }); + if (opts.unavailable) return Response.json({ projectionAvailable: false }); + return Response.json(STATUS_AVAILABLE); } if (url.includes("/api/lab/verdicts")) { - if (opts.malformedVerdicts) { - return new Response(JSON.stringify({ verdicts: [{ subjectId: "x" }] }), { status: 200 }); - } - if (opts.empty) { - return new Response(JSON.stringify({ verdicts: [], hasMore: false }), { status: 200 }); - } - if (url.includes("cursor=cursor-2")) { - return new Response(JSON.stringify(VERDICTS_PAGE_2), { status: 200 }); - } - return new Response(JSON.stringify(VERDICTS_PAGE_1), { status: 200 }); - } - if (url.includes("/api/lab/subjects/subject-alpha")) { - return new Response(JSON.stringify(SUBJECT_DETAIL), { status: 200 }); - } - if (url.includes("/api/lab/subjects")) { - return new Response(JSON.stringify(SUBJECTS), { status: 200 }); - } - if (url.includes("/api/lab/observations")) { - return new Response(JSON.stringify(OBSERVATIONS), { status: 200 }); - } - if (url.includes("/api/lab/events/e1")) { - return new Response(JSON.stringify(EVENT_DETAIL), { status: 200 }); - } - if (url.includes("/api/lab/events/e2")) { - return new Response(JSON.stringify({ event: { ...EVENT_DETAIL.event, eventId: "e2" } }), { status: 200 }); - } - if (url.includes("/api/lab/artifacts/digest-a")) { - return new Response(JSON.stringify(ARTIFACT_DETAIL), { status: 200 }); + if (opts.malformedVerdicts) return Response.json({ verdicts: [{ subjectId: "x" }] }); + if (opts.empty) return Response.json({ verdicts: [], hasMore: false }); + if (url.includes("cursor=cursor-2")) return Response.json(VERDICTS_PAGE_2); + return Response.json(VERDICTS_PAGE_1); } + if (url.includes("/api/lab/subjects/subject-alpha")) return Response.json(SUBJECT_DETAIL); + if (url.includes("/api/lab/subjects")) return Response.json(SUBJECTS); + if (url.includes("/api/lab/observations")) return Response.json(OBSERVATIONS); + if (url.includes("/api/lab/events/e1")) return Response.json(EVENT_DETAIL); + if (url.includes("/api/lab/events/e2")) return Response.json({ event: { ...EVENT_DETAIL.event, eventId: "e2" } }); + if (url.includes("/api/lab/artifacts/digest-a")) return Response.json(ARTIFACT_DETAIL); if (url.includes("/api/lab/artifacts/scenario-digest")) { - return new Response(JSON.stringify({ - artifact: { ...ARTIFACT_DETAIL.artifact, digest: "scenario-digest", artifactClass: "scenario_manifest" }, - }), { status: 200 }); + return Response.json({ artifact: { ...ARTIFACT_DETAIL.artifact, digest: "scenario-digest", artifactClass: "scenario_manifest" } }); } if (url.includes("/api/models")) return Response.json([]); if (url.includes("/api/provider-context-caps")) return Response.json({ providers: {} }); @@ -252,9 +227,7 @@ beforeEach(() => { previousLanguageDescriptor = Object.getOwnPropertyDescriptor(globalThis.navigator, "language"); Object.defineProperty(globalThis.navigator, "language", { configurable: true, value: "en-US" }); const keys = ["document", "window", "localStorage", "IS_REACT_ACT_ENVIRONMENT"] as const; - const previous = Object.fromEntries( - keys.map(key => [key, Object.getOwnPropertyDescriptor(globalThis, key)]), - ) as Record<(typeof keys)[number], PropertyDescriptor | undefined>; + const previous = Object.fromEntries(keys.map(key => [key, Object.getOwnPropertyDescriptor(globalThis, key)])) as Record<(typeof keys)[number], PropertyDescriptor | undefined>; Object.defineProperties(globalThis, { document: { configurable: true, value: testWindow.document }, window: { configurable: true, value: testWindow }, @@ -267,9 +240,7 @@ beforeEach(() => { if (descriptor) Object.defineProperty(globalThis, key, descriptor); else delete (globalThis as Record)[key]; } - if (previousLanguageDescriptor) { - Object.defineProperty(globalThis.navigator, "language", previousLanguageDescriptor); - } + if (previousLanguageDescriptor) Object.defineProperty(globalThis.navigator, "language", previousLanguageDescriptor); }; }); @@ -284,24 +255,17 @@ async function waitFor(predicate: () => boolean, timeoutMs = 3000): Promise timeoutMs) throw new Error("waitFor timed out"); - await act(async () => { - await new Promise(resolve => testWindow.setTimeout(resolve, 10)); - }); + await act(async () => { await new Promise(resolve => testWindow.setTimeout(resolve, 10)); }); } } async function renderMatrix(active = true): Promise<{ root: Root; container: HTMLDivElement }> { - const React = await import("react"); const { createRoot } = await import("react-dom/client"); const container = testWindow.document.createElement("div"); testWindow.document.body.appendChild(container); const root = createRoot(container); await act(async () => { - root.render( - - - , - ); + root.render(); }); return { root, container }; } @@ -311,27 +275,21 @@ async function mountModels(hash = "#models"): Promise<{ root: Root; container: H const { createRoot } = await import("react-dom/client"); const container = testWindow.document.createElement("div"); testWindow.document.body.appendChild(container); - let root!: Root; - await act(async () => { - root = createRoot(container); - root.render( - - - , - ); - }); + const root = createRoot(container); + await act(async () => { root.render(); }); await act(async () => { await Promise.resolve(); }); return { root, container }; } +function detailButton(container: HTMLDivElement, key = "k1"): HTMLButtonElement { + return container.querySelector(`button[data-verdict-detail="${key}"]`) as HTMLButtonElement; +} + test("1. Models tab includes Compatibility", async () => { installLabFetch(); const { root, container } = await mountModels(); - try { - expect(container.querySelector("#models-tab-compatibility")).toBeTruthy(); - } finally { - await act(async () => root.unmount()); - } + try { expect(container.querySelector("#models-tab-compatibility")).toBeTruthy(); } + finally { await act(async () => root.unmount()); } }); test("2. #models/compatibility resolves", () => { @@ -354,13 +312,9 @@ test("4. keyboard traversal covers four tabs in strip", async () => { const routing = container.querySelector("#models-tab-routing") as HTMLButtonElement; await act(async () => { routing.click(); }); routing.focus(); - await act(async () => { - routing.dispatchEvent(new testWindow.KeyboardEvent("keydown", { key: "ArrowRight", bubbles: true })); - }); + await act(async () => { routing.dispatchEvent(new testWindow.KeyboardEvent("keydown", { key: "ArrowRight", bubbles: true })); }); expect(document.activeElement?.id).toBe("models-tab-compatibility"); - } finally { - await act(async () => root.unmount()); - } + } finally { await act(async () => root.unmount()); } }); test("5. available projection renders data", async () => { @@ -402,7 +356,7 @@ test("9. verdict text rendering", async () => { await act(async () => root.unmount()); }); -test("10. evidence layers render as separate columns", async () => { +test("10. evidence layers render as separate columns", () => { const page = parseVerdictPage(VERDICTS_PAGE_1); const rows = buildMatrixRows(page.verdicts, SUBJECTS.subjects); expect(rows[0]!.byLayer.protocol_conformance).toHaveLength(1); @@ -410,7 +364,7 @@ test("10. evidence layers render as separate columns", async () => { expect(rows[0]!.byLayer.task_effectiveness).toHaveLength(0); }); -test("11. filters affect API query strings", () => { +test("11. exact subject picker filters through the API contract", () => { const query = verdictQueryFromFilters({ layer: "protocol_conformance", verdict: "VERIFIED", @@ -429,20 +383,18 @@ test("12. load more pagination appends rows", async () => { installLabFetch(); const { root, container } = await renderMatrix(); await waitFor(() => container.querySelector(".lab-load-more button") !== null); - const loadMore = container.querySelector(".lab-load-more button") as HTMLButtonElement; - await act(async () => { loadMore.click(); }); + await act(async () => { (container.querySelector(".lab-load-more button") as HTMLButtonElement).click(); }); await waitFor(() => container.textContent?.includes("Blocked") ?? false); await act(async () => root.unmount()); }); -test("13. detail flow on selection", async () => { +test("13. detail flow on selection uses a neutral evidence heading", async () => { installLabFetch(); const { root, container } = await renderMatrix(); - await waitFor(() => container.querySelector(".lab-detail-table tbody tr") !== null); - const row = container.querySelector(".lab-detail-table tbody tr") as HTMLTableRowElement; - await act(async () => { row.click(); }); - await waitFor(() => container.querySelector(".lab-detail-pane") !== null); - expect(container.textContent).toContain("Contributing events"); + await waitFor(() => detailButton(container) !== null); + await act(async () => { detailButton(container).click(); }); + await waitFor(() => container.querySelector(".lab-detail-pane") !== null && !container.textContent?.includes("Loading…")); + expect(container.textContent).toContain("Evidence events"); await act(async () => root.unmount()); }); @@ -455,24 +407,26 @@ test("14. sanitized display has no payload_json fields", () => { test("15. artifact metadata only in detail pane", async () => { installLabFetch(); const { root, container } = await renderMatrix(); - await waitFor(() => container.querySelector(".lab-detail-table tbody tr") !== null); - const row = container.querySelector(".lab-detail-table tbody tr") as HTMLTableRowElement; - await act(async () => { row.click(); }); + await waitFor(() => detailButton(container) !== null); + await act(async () => { detailButton(container).click(); }); await waitFor(() => container.textContent?.includes("Artifact metadata") ?? false); expect(container.textContent).toContain("suite_manifest"); + expect(container.textContent).toContain("Present"); await act(async () => root.unmount()); }); -test("16. inactive panel suppresses loads", async () => { +test("16. inactive panel suppresses deferred and scheduled loads", async () => { const tracked: string[] = []; installLabFetch({ trackRequests: tracked }); const { root } = await renderMatrix(false); - await act(async () => { await Promise.resolve(); }); + for (let i = 0; i < 5; i++) { + await act(async () => { await new Promise(resolve => testWindow.setTimeout(resolve, 20)); }); + } expect(tracked.filter(url => url.includes("/api/lab/")).length).toBe(0); await act(async () => root.unmount()); }); -test("17. malformed payloads fail safely", () => { +test("17. malformed parser payloads fail safely", () => { expect(parseVerdictPage(null).verdicts).toEqual([]); expect(parseSubjectDetail(null)).toBeNull(); expect(parseObservationDto({ eventId: "x" })).toBeNull(); @@ -489,22 +443,116 @@ test("18. no mutation requests are issued", async () => { return original(input, init); }) as typeof fetch; const { root, container } = await renderMatrix(); - await waitFor(() => container.querySelector(".lab-detail-table tbody tr") !== null); + await waitFor(() => detailButton(container) !== null); expect(methods.every(method => method === "GET")).toBe(true); await act(async () => root.unmount()); }); +test("19. selecting a verdict does not silently narrow the matrix to one suite", async () => { + const { requests } = installLabFetch(); + const { root, container } = await renderMatrix(); + await waitFor(() => detailButton(container) !== null); + const before = container.querySelectorAll(".lab-matrix tbody tr").length; + const beforeRequests = requests.length; + await act(async () => { detailButton(container).click(); }); + await waitFor(() => container.querySelector(".lab-detail-pane") !== null); + const selectionRequests = requests.slice(beforeRequests); + expect(selectionRequests.some(url => url.includes("/api/lab/verdicts") && url.includes("suiteId="))).toBe(false); + expect(container.querySelectorAll(".lab-matrix tbody tr").length).toBe(before); + await act(async () => root.unmount()); +}); + +test("20. malformed successful API payloads reject instead of impersonating unavailable data", async () => { + globalThis.fetch = (async () => Response.json({ nope: true })) as typeof fetch; + const controller = new AbortController(); + await expect(fetchLabStatus(API_BASE, controller.signal)).rejects.toThrow("Invalid Compatibility Lab status response"); +}); + +test("21. subject pagination fails closed when the cursor does not advance", async () => { + globalThis.fetch = (async () => Response.json({ + subjects: [{ subjectId: "subject-alpha", subjectKind: "protocol" }], + hasMore: true, + nextCursor: "same", + })) as typeof fetch; + const controller = new AbortController(); + await expect(fetchAllSubjects(API_BASE, controller.signal)).rejects.toThrow("pagination did not advance"); +}); + +test("22. verdict detail follows observation pagination and tolerates missing optional evidence", async () => { + const requests: string[] = []; + globalThis.fetch = (async (input: RequestInfo | URL) => { + const url = String(input); + requests.push(url); + if (url.includes("/subjects/subject-alpha")) return Response.json(SUBJECT_DETAIL); + if (url.includes("/observations") && url.includes("cursor=obs-2")) { + return Response.json({ observations: [{ ...OBSERVATIONS.observations[0], eventId: "obs-2", scenarioId: "scenario-2" }], hasMore: false }); + } + if (url.includes("/observations")) return Response.json({ ...OBSERVATIONS, hasMore: true, nextCursor: "obs-2" }); + if (url.includes("/events/e1")) return new Response("gone", { status: 404 }); + if (url.includes("/artifacts/")) return new Response("gone", { status: 404 }); + return new Response("{}", { status: 404 }); + }) as typeof fetch; + const verdict = parseVerdictPage(VERDICTS_PAGE_1).verdicts[0]!; + const detail = await fetchVerdictDetail(API_BASE, verdict, new AbortController().signal); + expect(detail.observations.map(row => row.scenarioId)).toEqual(["scenario-1", "scenario-2"]); + expect(detail.events).toEqual([]); + expect(detail.artifacts).toEqual([]); + expect(requests.some(url => url.includes("cursor=obs-2"))).toBe(true); +}); + test("parseEventsPage rejects malformed payloads", () => { expect(parseEventsPage(null).events).toEqual([]); }); test("filterVerdicts applies client filters for suite id", () => { const page = parseVerdictPage(VERDICTS_PAGE_1); - const filtered = filterVerdicts(page.verdicts, { - layer: "", - verdict: "", - subjectQuery: "", - suiteId: "responses-core", - }); + const filtered = filterVerdicts(page.verdicts, { layer: "", verdict: "", subjectQuery: "", suiteId: "responses-core" }); expect(filtered).toHaveLength(1); }); + +test("23. a slower previous detail request cannot overwrite the latest selection", async () => { + installLabFetch(); + const baseFetch = globalThis.fetch; + let e1Requested = false; + let releaseE1: (() => void) | undefined; + globalThis.fetch = (async (input: RequestInfo | URL, init?: RequestInit) => { + const url = String(input); + if (url.includes("/api/lab/events/e1")) { + e1Requested = true; + return new Promise(resolve => { + releaseE1 = () => resolve(Response.json(EVENT_DETAIL)); + }); + } + return baseFetch(input, init); + }) as typeof fetch; + + const { root, container } = await renderMatrix(); + await waitFor(() => container.querySelectorAll("button[data-verdict-detail]").length >= 2); + const buttons = [...container.querySelectorAll("button[data-verdict-detail]")] as HTMLButtonElement[]; + await act(async () => { buttons[0]!.click(); }); + await waitFor(() => e1Requested); + await act(async () => { buttons[1]!.click(); }); + await waitFor(() => container.querySelector(".lab-detail-pane")?.textContent?.includes("e2") ?? false); + releaseE1?.(); + await act(async () => { + await new Promise(resolve => testWindow.setTimeout(resolve, 30)); + }); + const paneText = container.querySelector(".lab-detail-pane")?.textContent ?? ""; + expect(paneText).toContain("e2"); + expect(paneText).not.toContain("e1"); + await act(async () => root.unmount()); +}); + +test("24. refreshing the first page discards appended cursor pages", async () => { + installLabFetch(); + const { root, container } = await renderMatrix(); + await waitFor(() => container.querySelector(".lab-load-more button") !== null); + await act(async () => { (container.querySelector(".lab-load-more button") as HTMLButtonElement).click(); }); + await waitFor(() => container.querySelectorAll(".lab-detail-table tbody tr").length === 3); + const refresh = [...container.querySelectorAll("button")].find(button => button.textContent?.includes("Refresh")); + expect(refresh).toBeTruthy(); + await act(async () => { refresh!.click(); }); + await waitFor(() => container.querySelectorAll(".lab-detail-table tbody tr").length === 2); + expect(container.textContent).not.toContain("Blocked"); + await act(async () => root.unmount()); +}); diff --git a/gui/tests/compatibility-matrix-layout.test.ts b/gui/tests/compatibility-matrix-layout.test.ts index 97c5f4e42d..8ebd39fee0 100644 --- a/gui/tests/compatibility-matrix-layout.test.ts +++ b/gui/tests/compatibility-matrix-layout.test.ts @@ -1,19 +1,20 @@ import { expect, test } from "bun:test"; async function readSources(): Promise { - const app = await Bun.file(new URL("../src/App.tsx", import.meta.url)).text(); + const models = await Bun.file(new URL("../src/pages/Models.tsx", import.meta.url)).text(); const routing = await Bun.file(new URL("../src/app-routing.ts", import.meta.url)).text(); + const tabs = await Bun.file(new URL("../src/pages/models-tab.ts", import.meta.url)).text(); const page = await Bun.file(new URL("../src/pages/CompatibilityMatrix.tsx", import.meta.url)).text(); const css = await Bun.file(new URL("../src/styles.css", import.meta.url)).text(); const styles = await Bun.file(new URL("../src/styles-compatibility-matrix.css", import.meta.url)).text(); - return `${app}\n${routing}\n${page}\n${css}\n${styles}`; + return `${models}\n${routing}\n${tabs}\n${page}\n${css}\n${styles}`; } -test("Compatibility Lab page is mounted from App sidebar routing", async () => { +test("Compatibility Lab is mounted as the Models Compatibility tab", async () => { const src = await readSources(); - expect(src).toContain('"lab"'); - expect(src).toContain(""); - expect(src).toContain("nav.lab"); + expect(src).toContain('"models/compatibility"'); + expect(src).toContain('modelsPanelDomId("compatibility")'); + expect(src).toContain(''); expect(src).toContain('@import "./styles-compatibility-matrix.css"'); expect(src).toContain("lab-matrix"); expect(src).toContain("lab-verdict-badge"); @@ -24,4 +25,7 @@ test("Compatibility matrix uses scrollable table layout", async () => { expect(styles).toContain(".lab-matrix-scroll"); expect(styles).toContain(".lab-matrix"); expect(styles).toContain(".lab-detail-table"); + for (const removedToken of ["--radius-md", "--text-xs", "--text-sm", "--font-mono", "--surface-1", "--surface-2", "--text-muted"]) { + expect(styles).not.toContain(`var(${removedToken})`); + } }); diff --git a/tests/models-workspace-tabs.test.ts b/tests/models-workspace-tabs.test.ts index e15414a6fe..53109c7f2b 100644 --- a/tests/models-workspace-tabs.test.ts +++ b/tests/models-workspace-tabs.test.ts @@ -1,9 +1,9 @@ /** * Models workspace tabs — routing contract. * - * `#combos` and `#routing` are no longer pages. Both resolve to the Models page and - * redirect to their nested tab hashes, and `readModelsTab` recognises the pre-redirect - * form so a cold load lands on the right tab. + * Legacy standalone Combos, Routing, and Lab hashes resolve to Models and redirect to + * their nested tab hashes. `readModelsTab` also recognizes the pre-redirect form so a + * cold load lands on the intended tab without a transient page mismatch. */ import { expect, test, describe } from "bun:test"; import { @@ -22,11 +22,10 @@ import { } from "../gui/src/pages/models-tab"; describe("nested Models hashes", () => { - test("both tab hashes are registered and belong to the models page", () => { + test("all tab hashes are registered and belong to the models page", () => { expect([...MODELS_TAB_HASHES]).toEqual(["models/combos", "models/routing", "models/compatibility"]); for (const hash of MODELS_TAB_HASHES) { expect(hashBelongsToPage(hash, "models")).toBe(true); - // The first segment already answers the page; the suffix only picks the tab. expect(readPageFromHash(hash)).toBe("models"); } }); @@ -61,11 +60,6 @@ describe("readModelsTab", () => { expect(readModelsTab("#/models/routing")).toBe("routing"); }); - /* - * The redirect that rewrites `#combos` uses replaceState and emits no `hashchange`, - * so tab state is read from the ORIGINAL hash. Recognising only the nested form - * would land a cold load on the catalog with the URL claiming Combos. - */ test("resolves legacy top-level hashes so a cold load lands on the right tab", () => { expect(readModelsTab("#combos")).toBe("combos"); expect(readModelsTab("#routing")).toBe("routing"); @@ -79,11 +73,6 @@ describe("readModelsTab", () => { expect(readModelsTab("")).toBe("catalog"); }); - /* - * The legacy arms match on a `/` delimiter, not a bare prefix. Without these a - * later "simplification" to `startsWith("routing")` would hijack any future page - * whose id merely begins with one of these words. - */ test("legacy matching is delimiter-aware, not prefix-aware", () => { expect(readModelsTab("#combosomething")).toBe("catalog"); expect(readModelsTab("#routings")).toBe("catalog"); @@ -91,10 +80,6 @@ describe("readModelsTab", () => { expect(readModelsTab("#combos-legacy")).toBe("catalog"); }); - /* - * `models/combos/extra` is not a registered hash: the resolver normalises it away, - * so the tab reader must agree rather than treating it as the Combos tab. - */ test("a deeper nested hash is not mistaken for a tab", () => { expect(readModelsTab("#models/combos/extra")).toBe("catalog"); expect(readModelsTab("#models/routing/extra")).toBe("catalog"); @@ -103,15 +88,14 @@ describe("readModelsTab", () => { describe("modelsTabHash", () => { test("round-trips every tab", () => { - for (const tab of MODELS_TABS) { - expect(readModelsTab(`#${modelsTabHash(tab)}`)).toBe(tab); - } + for (const tab of MODELS_TABS) expect(readModelsTab(`#${modelsTabHash(tab)}`)).toBe(tab); }); test("the catalog owns the bare page hash", () => { expect(modelsTabHash("catalog")).toBe("models"); expect(modelsTabHash("combos")).toBe("models/combos"); expect(modelsTabHash("routing")).toBe("models/routing"); + expect(modelsTabHash("compatibility")).toBe("models/compatibility"); }); test("every non-catalog hash is registered for normalization", () => { @@ -123,8 +107,6 @@ describe("modelsTabHash", () => { test("tab and panel dom ids are distinct per tab, so aria-controls cannot collide", () => { const ids = MODELS_TABS.flatMap(tab => [modelsTabDomId(tab), modelsPanelDomId(tab)]); expect(new Set(ids).size).toBe(ids.length); - // Pin the exact shape: the rendered aria-controls/aria-labelledby pair is asserted - // against these ids once the strip exists, so a silent rename would desync them. expect(modelsTabDomId("combos")).toBe("models-tab-combos"); expect(modelsPanelDomId("combos")).toBe("models-panel-combos"); }); @@ -137,10 +119,23 @@ test("an unregistered deep hash normalises to the bare page, matching readModels } }); - describe("legacy lab hash", () => { - test("#lab redirects to models/compatibility", () => { + test("#lab redirects to models/compatibility and resolves Models immediately", () => { expect(resolveAppHashChange("lab")).toEqual({ page: "models", replaceTo: "models/compatibility" }); expect(readModelsTab("#lab")).toBe("compatibility"); + expect(readPageFromHash("#lab")).toBe("models"); + }); + + test("the nested legacy form keeps its destination", () => { + expect(resolveAppHashChange("lab/anything")).toEqual({ page: "models", replaceTo: "models/compatibility" }); + expect(readModelsTab("#lab/anything")).toBe("compatibility"); + expect(readPageFromHash("#lab/anything")).toBe("models"); + }); + + test("legacy lab matching is delimiter-aware, not prefix-aware", () => { + expect(readModelsTab("#labs")).toBe("catalog"); + expect(readModelsTab("#label")).toBe("catalog"); + expect(readModelsTab("#lab-legacy")).toBe("catalog"); + expect(resolveAppHashChange("labs")).toEqual({ page: "dashboard", replaceTo: "dashboard" }); }); }); From adf28fca6ab5243287bf7f325177719e0c0f35b9 Mon Sep 17 00:00:00 2001 From: Wibias <37517432+Wibias@users.noreply.github.com> Date: Mon, 10 Aug 2026 03:06:34 +0200 Subject: [PATCH 07/16] fix(lab): use typed contract failures in CL-05 GUI --- gui/src/pages/compatibility-matrix-api.ts | 47 +++++++++++------------ 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/gui/src/pages/compatibility-matrix-api.ts b/gui/src/pages/compatibility-matrix-api.ts index 12a6ac3718..f18e38f049 100644 --- a/gui/src/pages/compatibility-matrix-api.ts +++ b/gui/src/pages/compatibility-matrix-api.ts @@ -39,44 +39,46 @@ function buildQuery(params: Record, cursor?: string) return query.toString(); } -function invalidResponse(surface: string): Error { - return new Error(`Invalid Compatibility Lab ${surface} response`); +export class LabDataContractError extends Error {} + +function invalidResponse(): LabDataContractError { + return new LabDataContractError(); } -function assertPaginationContract(raw: Record, hasMore: boolean, nextCursor: string | undefined, surface: string) { - if (raw.hasMore !== undefined && typeof raw.hasMore !== "boolean") throw invalidResponse(surface); - if (raw.nextCursor !== undefined && typeof raw.nextCursor !== "string") throw invalidResponse(surface); - if (hasMore && !nextCursor) throw invalidResponse(surface); +function assertPaginationContract(raw: Record, hasMore: boolean, nextCursor: string | undefined) { + if (raw.hasMore !== undefined && typeof raw.hasMore !== "boolean") throw invalidResponse(); + if (raw.nextCursor !== undefined && typeof raw.nextCursor !== "string") throw invalidResponse(); + if (hasMore && !nextCursor) throw invalidResponse(); } function parseStrictVerdictPage(raw: unknown): PaginatedVerdicts { - if (!isPlainObject(raw) || !Array.isArray(raw.verdicts)) throw invalidResponse("verdicts"); + if (!isPlainObject(raw) || !Array.isArray(raw.verdicts)) throw invalidResponse(); const page = parseVerdictPage(raw); - if (page.verdicts.length !== raw.verdicts.length) throw invalidResponse("verdicts"); - assertPaginationContract(raw, page.hasMore, page.nextCursor, "verdicts"); + if (page.verdicts.length !== raw.verdicts.length) throw invalidResponse(); + assertPaginationContract(raw, page.hasMore, page.nextCursor); return page; } function parseStrictSubjectPage(raw: unknown): PaginatedSubjects { - if (!isPlainObject(raw) || !Array.isArray(raw.subjects)) throw invalidResponse("subjects"); + if (!isPlainObject(raw) || !Array.isArray(raw.subjects)) throw invalidResponse(); const page = parseSubjectPage(raw); - if (page.subjects.length !== raw.subjects.length) throw invalidResponse("subjects"); - assertPaginationContract(raw, page.hasMore, page.nextCursor, "subjects"); + if (page.subjects.length !== raw.subjects.length) throw invalidResponse(); + assertPaginationContract(raw, page.hasMore, page.nextCursor); return page; } function parseStrictObservationPage(raw: unknown): PaginatedObservations { - if (!isPlainObject(raw) || !Array.isArray(raw.observations)) throw invalidResponse("observations"); + if (!isPlainObject(raw) || !Array.isArray(raw.observations)) throw invalidResponse(); const page = parseObservationsPage(raw); - if (page.observations.length !== raw.observations.length) throw invalidResponse("observations"); - assertPaginationContract(raw, page.hasMore, page.nextCursor, "observations"); + if (page.observations.length !== raw.observations.length) throw invalidResponse(); + assertPaginationContract(raw, page.hasMore, page.nextCursor); return page; } export async function fetchLabStatus(apiBase: string, signal: AbortSignal): Promise { const raw = await fetchLabJson(apiBase, "/api/lab/status", signal); const status = parseLabStatus(raw); - if (!status) throw invalidResponse("status"); + if (!status) throw invalidResponse(); return status; } @@ -110,7 +112,6 @@ export async function fetchSubjectPage( async function collectPages( loadPage: (cursor: string | undefined) => Promise<{ rows: T[]; hasMore: boolean; nextCursor?: string }>, - surface: string, ): Promise { const rows: T[] = []; const seen = new Set(); @@ -121,12 +122,12 @@ async function collectPages( if (!page.hasMore) return rows; const next = page.nextCursor; if (!next || seen.has(next) || next === cursor) { - throw new Error(`Compatibility Lab ${surface} pagination did not advance`); + throw new LabDataContractError(); } seen.add(next); cursor = next; } - throw new Error(`Compatibility Lab ${surface} pagination exceeded ${MAX_PAGES} pages`); + throw new LabDataContractError(); } export async function fetchAllSubjects(apiBase: string, signal: AbortSignal): Promise { @@ -135,7 +136,6 @@ export async function fetchAllSubjects(apiBase: string, signal: AbortSignal): Pr const page = await fetchSubjectPage(apiBase, cursor, signal); return { rows: page.subjects, hasMore: page.hasMore, nextCursor: page.nextCursor }; }, - "subjects", ); } @@ -146,7 +146,7 @@ export async function fetchSubjectDetail( ): Promise { const raw = await fetchLabJson(apiBase, `/api/lab/subjects/${encodeURIComponent(subjectId)}`, signal); const subject = parseSubjectDetail(raw); - if (!subject) throw invalidResponse("subject detail"); + if (!subject) throw invalidResponse(); return subject; } @@ -178,14 +178,13 @@ async function fetchAllObservations( const page = await fetchObservationsPage(apiBase, filters, cursor, signal); return { rows: page.observations, hasMore: page.hasMore, nextCursor: page.nextCursor }; }, - "observations", ); } export async function fetchEventById(apiBase: string, eventId: string, signal: AbortSignal): Promise { const raw = await fetchLabJson(apiBase, `/api/lab/events/${encodeURIComponent(eventId)}`, signal); const event = parseLabEvent(raw); - if (!event) throw invalidResponse("event detail"); + if (!event) throw invalidResponse(); return event; } @@ -196,7 +195,7 @@ export async function fetchArtifactByDigest( ): Promise { const raw = await fetchLabJson(apiBase, `/api/lab/artifacts/${encodeURIComponent(digest)}`, signal); const artifact = parseArtifactMetadata(raw); - if (!artifact) throw invalidResponse("artifact detail"); + if (!artifact) throw invalidResponse(); return artifact; } From 2dead294da0bdb7765a1eb3b2fc1101f32137b9e Mon Sep 17 00:00:00 2001 From: Wibias <37517432+Wibias@users.noreply.github.com> Date: Mon, 10 Aug 2026 03:07:57 +0200 Subject: [PATCH 08/16] fix(lab): keep CL-05 pagination state effect-safe --- gui/src/pages/CompatibilityMatrix.tsx | 83 ++++++++++++++------------- 1 file changed, 43 insertions(+), 40 deletions(-) diff --git a/gui/src/pages/CompatibilityMatrix.tsx b/gui/src/pages/CompatibilityMatrix.tsx index 370abeeb04..22ebc97045 100644 --- a/gui/src/pages/CompatibilityMatrix.tsx +++ b/gui/src/pages/CompatibilityMatrix.tsx @@ -54,6 +54,14 @@ const ARTIFACT_STATUS_LABEL: Record = { purged_unavailable: "artifact.purged_unavailable", }; +type ExtraVerdictPage = { + baseData: LabPageData; + queryKey: string; + verdicts: VerdictDto[]; + nextCursor?: string; + hasMore: boolean; +}; + function localizedFetchError(e: unknown, fallback: string): string { if (!(e instanceof Error)) return fallback; const msg = e.message; @@ -241,9 +249,7 @@ export default function CompatibilityMatrix({ }) { const { t, locale } = useI18n(); const [filters, setFilters] = useState({ layer: "", verdict: "", subjectQuery: "", suiteId: "" }); - const [extraVerdicts, setExtraVerdicts] = useState([]); - const [nextCursor, setNextCursor] = useState(); - const [hasMore, setHasMore] = useState(false); + const [extraPage, setExtraPage] = useState(null); const [loadingMore, setLoadingMore] = useState(false); const [selectedVerdict, setSelectedVerdict] = useState(null); const [detail, setDetail] = useState(null); @@ -253,8 +259,6 @@ export default function CompatibilityMatrix({ const loadMoreRef = useRef(null); const detailRequestRef = useRef(null); const selectedKeyRef = useRef(null); - const queryKeyRef = useRef(""); - const surfaceDataRef = useRef(undefined); const queryFilters = useMemo(() => verdictQueryFromFilters(filters), [filters]); const queryKey = JSON.stringify(queryFilters); @@ -274,9 +278,7 @@ export default function CompatibilityMatrix({ const resetPagination = useCallback(() => { loadMoreRef.current?.abort(); loadMoreRef.current = null; - setExtraVerdicts([]); - setNextCursor(undefined); - setHasMore(false); + setExtraPage(null); setLoadingMore(false); }, []); @@ -291,23 +293,11 @@ export default function CompatibilityMatrix({ }, []); useEffect(() => { - queryKeyRef.current = queryKey; - // A query identity change makes an in-flight cursor page stale immediately. + // A refreshed first page makes any in-flight cursor request stale. The associated + // appended-page state is identity-bound below, so it becomes invisible immediately + // without synchronously cascading state from this effect. loadMoreRef.current?.abort(); - }, [queryKey]); - - useEffect(() => { - surfaceDataRef.current = surface.data; - // A new first-page snapshot (filter change, manual refresh, or poll) invalidates every - // appended cursor page. Keeping them would merge different projection snapshots. - resetPagination(); - }, [surface.data, resetPagination]); - - useEffect(() => { - if (active) return; - clearDetail(); - resetPagination(); - }, [active, clearDetail, resetPagination]); + }, [surface.data]); useEffect(() => () => { loadMoreRef.current?.abort(); @@ -320,17 +310,23 @@ export default function CompatibilityMatrix({ setFilters(updater); }, [clearDetail, resetPagination]); + const validExtraPage = extraPage?.baseData === surface.data && extraPage.queryKey === queryKey + ? extraPage + : null; + const reportedCount = useMemo(() => { if (!active || !surface.data?.status.projectionAvailable) return null; const total = surface.data.status.verdictCount; - return typeof total === "number" ? total : surface.data.verdicts.length + extraVerdicts.length; - }, [active, extraVerdicts.length, surface.data]); + return typeof total === "number" + ? total + : surface.data.verdicts.length + (validExtraPage?.verdicts.length ?? 0); + }, [active, surface.data, validExtraPage]); useEffect(() => { onCountChange?.(reportedCount); }, [onCountChange, reportedCount]); const allVerdicts = useMemo( - () => surface.data ? [...surface.data.verdicts, ...extraVerdicts] : [], - [extraVerdicts, surface.data], + () => surface.data ? [...surface.data.verdicts, ...(validExtraPage?.verdicts ?? [])] : [], + [surface.data, validExtraPage], ); const matrixRows = useMemo( () => surface.data ? buildMatrixRows(allVerdicts, surface.data.subjects) : [], @@ -338,7 +334,7 @@ export default function CompatibilityMatrix({ ); const loadMore = useCallback(async () => { - const cursor = nextCursor ?? surface.data?.nextCursor; + const cursor = validExtraPage?.nextCursor ?? surface.data?.nextCursor; const baseData = surface.data; if (!cursor || !baseData || loadingMore) return; loadMoreRef.current?.abort(); @@ -348,21 +344,28 @@ export default function CompatibilityMatrix({ setLoadingMore(true); try { const page = await fetchMoreVerdicts(apiBase, queryFilters, cursor, controller.signal); - if (controller.signal.aborted || queryKeyRef.current !== startedKey || surfaceDataRef.current !== baseData) return; - setExtraVerdicts(current => [...current, ...page.verdicts]); - setNextCursor(page.nextCursor); - setHasMore(page.hasMore); - } catch (error) { - if (!controller.signal.aborted) { - // Keep the current rows. The normal refresh action retries from a consistent first page. - } + if (controller.signal.aborted) return; + setExtraPage(current => { + const existing = current?.baseData === baseData && current.queryKey === startedKey + ? current.verdicts + : []; + return { + baseData, + queryKey: startedKey, + verdicts: [...existing, ...page.verdicts], + nextCursor: page.nextCursor, + hasMore: page.hasMore, + }; + }); + } catch { + // Keep the current rows. The normal refresh action retries from a consistent first page. } finally { if (loadMoreRef.current === controller) { loadMoreRef.current = null; - if (!controller.signal.aborted) setLoadingMore(false); + setLoadingMore(false); } } - }, [apiBase, loadingMore, nextCursor, queryFilters, queryKey, surface.data]); + }, [apiBase, loadingMore, queryFilters, queryKey, surface.data, validExtraPage]); const selectVerdict = useCallback(async (verdict: VerdictDto) => { if (!active) return; @@ -397,7 +400,7 @@ export default function CompatibilityMatrix({ }, [clearDetail, refreshSurface, resetPagination]); const visibleSelection = active ? selectedVerdict : null; - const pageHasMore = extraVerdicts.length > 0 ? hasMore : (surface.data?.hasMore ?? false); + const pageHasMore = validExtraPage ? validExtraPage.hasMore : (surface.data?.hasMore ?? false); const layerOptions = [ { value: "", label: t("lab.filter.all") }, ...EVIDENCE_LAYERS.map(layer => ({ value: layer, label: t(LAYER_LABEL[layer]) })), From a381a9dc341097aad3380e589640e1c7d1d6a0ad Mon Sep 17 00:00:00 2001 From: Wibias <37517432+Wibias@users.noreply.github.com> Date: Mon, 10 Aug 2026 03:09:15 +0200 Subject: [PATCH 09/16] test(lab): assert typed CL-05 contract failures --- gui/tests/compatibility-lab.test.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/gui/tests/compatibility-lab.test.tsx b/gui/tests/compatibility-lab.test.tsx index 9629d8943d..5bdd7d9592 100644 --- a/gui/tests/compatibility-lab.test.tsx +++ b/gui/tests/compatibility-lab.test.tsx @@ -23,6 +23,7 @@ import { fetchAllSubjects, fetchLabStatus, fetchVerdictDetail, + LabDataContractError, } from "../src/pages/compatibility-matrix-api"; import { modelsTabHash, readModelsTab } from "../src/pages/models-tab"; import { resolveAppHashChange } from "../src/app-routing"; @@ -465,7 +466,7 @@ test("19. selecting a verdict does not silently narrow the matrix to one suite", test("20. malformed successful API payloads reject instead of impersonating unavailable data", async () => { globalThis.fetch = (async () => Response.json({ nope: true })) as typeof fetch; const controller = new AbortController(); - await expect(fetchLabStatus(API_BASE, controller.signal)).rejects.toThrow("Invalid Compatibility Lab status response"); + await expect(fetchLabStatus(API_BASE, controller.signal)).rejects.toBeInstanceOf(LabDataContractError); }); test("21. subject pagination fails closed when the cursor does not advance", async () => { @@ -475,7 +476,7 @@ test("21. subject pagination fails closed when the cursor does not advance", asy nextCursor: "same", })) as typeof fetch; const controller = new AbortController(); - await expect(fetchAllSubjects(API_BASE, controller.signal)).rejects.toThrow("pagination did not advance"); + await expect(fetchAllSubjects(API_BASE, controller.signal)).rejects.toBeInstanceOf(LabDataContractError); }); test("22. verdict detail follows observation pagination and tolerates missing optional evidence", async () => { From 716118ea94fee216549529703b8ed8b813204eca Mon Sep 17 00:00:00 2001 From: Wibias <37517432+Wibias@users.noreply.github.com> Date: Mon, 10 Aug 2026 03:11:17 +0200 Subject: [PATCH 10/16] fix(lab): make appended-page narrowing explicit --- gui/src/pages/CompatibilityMatrix.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/gui/src/pages/CompatibilityMatrix.tsx b/gui/src/pages/CompatibilityMatrix.tsx index 22ebc97045..f5efe6ea70 100644 --- a/gui/src/pages/CompatibilityMatrix.tsx +++ b/gui/src/pages/CompatibilityMatrix.tsx @@ -310,7 +310,9 @@ export default function CompatibilityMatrix({ setFilters(updater); }, [clearDetail, resetPagination]); - const validExtraPage = extraPage?.baseData === surface.data && extraPage.queryKey === queryKey + const validExtraPage = extraPage !== null + && extraPage.baseData === surface.data + && extraPage.queryKey === queryKey ? extraPage : null; From 8a6331cd7121f85294a4fd71d3f5b521bb9ab875 Mon Sep 17 00:00:00 2001 From: Wibias <37517432+Wibias@users.noreply.github.com> Date: Mon, 10 Aug 2026 03:26:12 +0200 Subject: [PATCH 11/16] test(lab): cover bounded pagination truncation --- .../compatibility-pagination-cap.test.ts | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 gui/tests/compatibility-pagination-cap.test.ts diff --git a/gui/tests/compatibility-pagination-cap.test.ts b/gui/tests/compatibility-pagination-cap.test.ts new file mode 100644 index 0000000000..477d4568e5 --- /dev/null +++ b/gui/tests/compatibility-pagination-cap.test.ts @@ -0,0 +1,28 @@ +import { expect, test } from "bun:test"; +import { fetchAllSubjects } from "../src/pages/compatibility-matrix-api"; + +const API_BASE = "http://127.0.0.1:4096"; + +test("advancing pagination at the safety cap is truncated, not a contract error", async () => { + const originalFetch = globalThis.fetch; + let requests = 0; + globalThis.fetch = (async (input: RequestInfo | URL) => { + requests += 1; + const url = new URL(String(input)); + const cursor = Number(url.searchParams.get("cursor") ?? "0"); + return Response.json({ + subjects: [{ subjectId: `subject-${cursor}`, subjectKind: "protocol" }], + hasMore: true, + nextCursor: String(cursor + 1), + }); + }) as typeof fetch; + + try { + const result = await fetchAllSubjects(API_BASE, new AbortController().signal); + expect(result.rows).toHaveLength(200); + expect(result.truncated).toBe(true); + expect(requests).toBe(200); + } finally { + globalThis.fetch = originalFetch; + } +}); From b460adfdd258e18749b80947f6599fe199998bdd Mon Sep 17 00:00:00 2001 From: Wibias <37517432+Wibias@users.noreply.github.com> Date: Mon, 10 Aug 2026 03:26:45 +0200 Subject: [PATCH 12/16] fix(lab): distinguish pagination truncation from contract failure --- gui/src/pages/compatibility-matrix-api.ts | 35 +++++++++++++++++------ 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/gui/src/pages/compatibility-matrix-api.ts b/gui/src/pages/compatibility-matrix-api.ts index f18e38f049..2d7c01aec1 100644 --- a/gui/src/pages/compatibility-matrix-api.ts +++ b/gui/src/pages/compatibility-matrix-api.ts @@ -110,16 +110,21 @@ export async function fetchSubjectPage( return parseStrictSubjectPage(raw); } +type CollectedPages = { + rows: T[]; + truncated: boolean; +}; + async function collectPages( loadPage: (cursor: string | undefined) => Promise<{ rows: T[]; hasMore: boolean; nextCursor?: string }>, -): Promise { +): Promise> { const rows: T[] = []; const seen = new Set(); let cursor: string | undefined; for (let pageNumber = 0; pageNumber < MAX_PAGES; pageNumber++) { const page = await loadPage(cursor); rows.push(...page.rows); - if (!page.hasMore) return rows; + if (!page.hasMore) return { rows, truncated: false }; const next = page.nextCursor; if (!next || seen.has(next) || next === cursor) { throw new LabDataContractError(); @@ -127,10 +132,13 @@ async function collectPages( seen.add(next); cursor = next; } - throw new LabDataContractError(); + // The server kept advancing correctly but exceeded the browser-side safety bound. + // Preserve the coherent prefix and report truncation separately instead of + // misclassifying a legitimate large dataset as a broken pagination contract. + return { rows, truncated: true }; } -export async function fetchAllSubjects(apiBase: string, signal: AbortSignal): Promise { +export async function fetchAllSubjects(apiBase: string, signal: AbortSignal): Promise> { return collectPages( async cursor => { const page = await fetchSubjectPage(apiBase, cursor, signal); @@ -172,7 +180,7 @@ async function fetchAllObservations( apiBase: string, filters: { subjectId: string; layer?: string; suiteId?: string }, signal: AbortSignal, -): Promise { +): Promise> { return collectPages( async cursor => { const page = await fetchObservationsPage(apiBase, filters, cursor, signal); @@ -203,6 +211,7 @@ export type LabPageData = { status: LabStatusDto; verdicts: VerdictDto[]; subjects: SubjectListItemDto[]; + subjectsTruncated: boolean; hasMore: boolean; nextCursor?: string; }; @@ -213,7 +222,9 @@ export async function fetchLabPageData( signal: AbortSignal, ): Promise { const status = await fetchLabStatus(apiBase, signal); - if (!status.projectionAvailable) return { status, verdicts: [], subjects: [], hasMore: false }; + if (!status.projectionAvailable) { + return { status, verdicts: [], subjects: [], subjectsTruncated: false, hasMore: false }; + } const [verdictPage, subjects] = await Promise.all([ fetchVerdictPage(apiBase, filters, undefined, signal), fetchAllSubjects(apiBase, signal), @@ -221,7 +232,8 @@ export async function fetchLabPageData( return { status, verdicts: verdictPage.verdicts, - subjects, + subjects: subjects.rows, + subjectsTruncated: subjects.truncated, hasMore: verdictPage.hasMore, nextCursor: verdictPage.nextCursor, }; @@ -239,6 +251,7 @@ export async function fetchMoreVerdicts( export type VerdictDetailData = { subject: SubjectDetailDto; observations: ObservationDto[]; + observationsTruncated: boolean; events: LabEventDto[]; artifacts: ArtifactMetadataDto[]; }; @@ -288,5 +301,11 @@ export async function fetchVerdictDetail( mapSettledBounded(eventIds, DETAIL_CONCURRENCY, signal, id => fetchEventById(apiBase, id, signal)), mapSettledBounded(digests, DETAIL_CONCURRENCY, signal, digest => fetchArtifactByDigest(apiBase, digest, signal)), ]); - return { subject, observations, events, artifacts }; + return { + subject, + observations: observations.rows, + observationsTruncated: observations.truncated, + events, + artifacts, + }; } From cdf576570fbb6528982628935f3269eff0f8ea12 Mon Sep 17 00:00:00 2001 From: Wibias <37517432+Wibias@users.noreply.github.com> Date: Mon, 10 Aug 2026 03:27:06 +0200 Subject: [PATCH 13/16] docs(lab): align CL-05 validation record with review --- .../005_cl05_compatibility_matrix_ui.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/devlog/_plan/260807_compatibility_lab/005_cl05_compatibility_matrix_ui.md b/devlog/_plan/260807_compatibility_lab/005_cl05_compatibility_matrix_ui.md index 7d2a311988..128b1c700d 100644 --- a/devlog/_plan/260807_compatibility_lab/005_cl05_compatibility_matrix_ui.md +++ b/devlog/_plan/260807_compatibility_lab/005_cl05_compatibility_matrix_ui.md @@ -37,7 +37,7 @@ The follow-up review pass addresses all validated CodeRabbit findings plus the independent lifecycle findings found while reviewing #1384: - legacy `#lab` cold-load page alignment and delimiter-aware regression coverage -- repeated-cursor/page-count guards for subject and observation pagination +- repeated-cursor contract guards plus explicit truncation when advancing pagination reaches the browser-side safety cap - strict verdict/detail DTO validation and malformed-200 handling - bounded, partial-failure-tolerant event/artifact enrichment - detail-selection and load-more stale-response protection @@ -46,6 +46,7 @@ The follow-up review pass addresses all validated CodeRabbit findings plus the i - localized closed-value labels and neutral evidence-event wording - real button semantics for verdict-detail selection - inactive-panel, selection/filter, pagination, localization, and routing regression coverage +- focused `compatibility-pagination-cap.test.ts` coverage proving a large advancing dataset is truncated rather than mislabeled as a broken contract - Models-tab layout test updated from the removed standalone App/sidebar architecture ## Validation recorded before review remediation @@ -53,9 +54,10 @@ The follow-up review pass addresses all validated CodeRabbit findings plus the i - `bun x tsc --noEmit` - passed - `bun test tests/lab-read-surfaces.test.ts tests/models-workspace-tabs.test.ts` - 33/33 passed - `cd gui && bun test tests/compatibility-lab.test.tsx tests/models-workspace-panels.test.tsx` - 29/29 passed +- `cd gui && bun test tests/compatibility-matrix-layout.test.ts` - 2/2 passed in the full GUI gate - `bun run lint:gui && bun run doctor:gui && bun run build:gui && bun run privacy:scan` - passed -The remediation commit requires a fresh CI pass before acceptance; these earlier results are retained only as the pre-review baseline. +The latest pagination-cap remediation adds `gui/tests/compatibility-pagination-cap.test.ts` and requires a fresh CI pass before acceptance; the earlier results above are retained only as baseline evidence. ## Acceptance blockers From 68edcd4bc25eac1da8179f2c96ccd4b6ad4659ed Mon Sep 17 00:00:00 2001 From: Wibias <37517432+Wibias@users.noreply.github.com> Date: Mon, 10 Aug 2026 03:42:14 +0200 Subject: [PATCH 14/16] test(cli): document Compatibility Lab parity --- tests/cli-headless-parity.test.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/cli-headless-parity.test.ts b/tests/cli-headless-parity.test.ts index 38258abf7a..084626cb64 100644 --- a/tests/cli-headless-parity.test.ts +++ b/tests/cli-headless-parity.test.ts @@ -87,6 +87,7 @@ describe("headless GUI parity CLI", () => { ["/api/injection", "ocx agent"], ["/api/keys", "ocx access"], ["/api/logs", "ocx observe"], + ["/api/lab", "ocx lab"], ["/api/config", "ocx config"], ["/api/settings", "ocx system"], // Routing Intelligence (RI-04..RI-10): profiles + dry-run are mirrored by @@ -229,9 +230,9 @@ describe("headless GUI parity CLI", () => { expect(runtime.requests[0]).toEqual({ path: "/api/provider-context-caps", method: "PUT", body: { provider: "openai", enabled: true, value: 128_000 } }); const offRuntime = fakeRuntime(); - const offCode = await handleModelsRuntimeCommand("context", ["provider", "openai", "off", "--json"], offRuntime.deps); + const offCode = await handleModelsRuntimeCommand("context", ["provider", "openai", "off", "--json"], runtime.deps); expect(offCode).toBe(0); - expect(offRuntime.requests[0]).toEqual({ path: "/api/provider-context-caps", method: "PUT", body: { provider: "openai", enabled: false } }); + expect(runtime.requests[0]).toEqual({ path: "/api/provider-context-caps", method: "PUT", body: { provider: "openai", enabled: false } }); // --value is only valid with `on`; the rejected form must not send any request. const rejectedRuntime = fakeRuntime(); From 594492c0b68b831ad33c009e5ac24e6d69072777 Mon Sep 17 00:00:00 2001 From: Wibias <37517432+Wibias@users.noreply.github.com> Date: Mon, 10 Aug 2026 03:43:48 +0200 Subject: [PATCH 15/16] test(cli): restore provider context assertion --- tests/cli-headless-parity.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/cli-headless-parity.test.ts b/tests/cli-headless-parity.test.ts index 084626cb64..dbb8479f0a 100644 --- a/tests/cli-headless-parity.test.ts +++ b/tests/cli-headless-parity.test.ts @@ -230,9 +230,9 @@ describe("headless GUI parity CLI", () => { expect(runtime.requests[0]).toEqual({ path: "/api/provider-context-caps", method: "PUT", body: { provider: "openai", enabled: true, value: 128_000 } }); const offRuntime = fakeRuntime(); - const offCode = await handleModelsRuntimeCommand("context", ["provider", "openai", "off", "--json"], runtime.deps); + const offCode = await handleModelsRuntimeCommand("context", ["provider", "openai", "off", "--json"], offRuntime.deps); expect(offCode).toBe(0); - expect(runtime.requests[0]).toEqual({ path: "/api/provider-context-caps", method: "PUT", body: { provider: "openai", enabled: false } }); + expect(offRuntime.requests[0]).toEqual({ path: "/api/provider-context-caps", method: "PUT", body: { provider: "openai", enabled: false } }); // --value is only valid with `on`; the rejected form must not send any request. const rejectedRuntime = fakeRuntime(); From d717984cafd8d66608286f46a1d22ed477aaa399 Mon Sep 17 00:00:00 2001 From: Wibias <37517432+Wibias@users.noreply.github.com> Date: Mon, 10 Aug 2026 04:01:09 +0200 Subject: [PATCH 16/16] test(lab): assert pagination cursor progression --- gui/tests/compatibility-pagination-cap.test.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/gui/tests/compatibility-pagination-cap.test.ts b/gui/tests/compatibility-pagination-cap.test.ts index 477d4568e5..f1253fe02f 100644 --- a/gui/tests/compatibility-pagination-cap.test.ts +++ b/gui/tests/compatibility-pagination-cap.test.ts @@ -20,9 +20,12 @@ test("advancing pagination at the safety cap is truncated, not a contract error" try { const result = await fetchAllSubjects(API_BASE, new AbortController().signal); expect(result.rows).toHaveLength(200); + expect(result.rows.map(row => row.subjectId)).toEqual( + Array.from({ length: 200 }, (_, cursor) => `subject-${cursor}`), + ); expect(result.truncated).toBe(true); expect(requests).toBe(200); } finally { globalThis.fetch = originalFetch; } -}); +}); \ No newline at end of file