Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
934b348
scaffold vite react typescript console workspace
furyfist Jul 23, 2026
384a4cc
add design tokens and global styles
furyfist Jul 23, 2026
bcbdfdf
add self-hosted fonts and typography scale
furyfist Jul 23, 2026
b2d927a
add spa history fallback to console server
furyfist Jul 23, 2026
557ceb4
add typed api client and endpoint definitions
furyfist Jul 23, 2026
431373b
add query client, keys, and core data hooks
furyfist Jul 23, 2026
1fde0a7
add polling, visibility, online, and motion lifecycle hooks
furyfist Jul 23, 2026
5e54815
add app router, app header, and responsive layout shell
furyfist Jul 23, 2026
a2c2f26
add console package-lock.json
furyfist Jul 23, 2026
56e11ef
add button, icon button, and input primitives
furyfist Jul 23, 2026
49e8c6b
add card, badge, status dot, and state badge
furyfist Jul 23, 2026
f25d4e6
add tooltip, dropdown, toggle chip, and tabs
furyfist Jul 23, 2026
ba4021a
add skeleton, empty state, alert callout, progress bar
furyfist Jul 23, 2026
8cab2c1
add toast, modal, and drawer primitives with focus management
furyfist Jul 23, 2026
f9ab214
add value formatters, number count-up, and display primitives
furyfist Jul 23, 2026
bedee80
add copy button, code block, json viewer, and timeline primitives
furyfist Jul 23, 2026
c6df2f0
fix component type annotations and test suite
furyfist Jul 23, 2026
4abebb1
add hero verdict card with sigma meters, evidence, and state variants
furyfist Jul 23, 2026
8ee27e4
add verdict feed with rows, inline expansion, windowing, and skeletons
furyfist Jul 23, 2026
8265d8d
add feed filters, sort, search, and url state integration
furyfist Jul 23, 2026
eb1e64c
add health strip with live pulse and metric chips
furyfist Jul 23, 2026
dd0246f
add verdict drawer route with detail sections, prev/next, and cache s…
furyfist Jul 23, 2026
8255374
add mobile bottom sheet variant for verdict drawer
furyfist Jul 23, 2026
5e22384
add scopes screen with signal table and progress bars
furyfist Jul 23, 2026
c7ea1c3
add about screen with blind spots and keyboard shortcuts modal
furyfist Jul 23, 2026
aa6ff06
update compiled static assets and screen refinements
furyfist Jul 23, 2026
e8658b8
add hand-authored SVG verdict sparkline with crosshair and legend
furyfist Jul 23, 2026
295a00a
add global keyboard navigation and feed hotkeys
furyfist Jul 23, 2026
e199000
add live announcer provider and route-level error boundary
furyfist Jul 23, 2026
93bfee3
add playwright e2e tests and vitest integration suite
furyfist Jul 23, 2026
cd800a8
add token linter script, bundle budget checks, and ci verification
furyfist Jul 23, 2026
500527f
fix(console): preserve drawer query params and add header skip-to-con…
furyfist Jul 23, 2026
103f239
fix(console): implement mobile bottom-sheet drag-dismiss, sparkline r…
furyfist Jul 23, 2026
11cb564
ci(console): add bundle size budget check and automated axe-core acce…
furyfist Jul 23, 2026
55c576e
test(console): add unit tests for verdict selectors and search filter…
furyfist Jul 23, 2026
767bc24
build(console): update static bundle assets in vitals/console/static
furyfist Jul 23, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,11 @@ dist/
.pytest_cache/
.ruff_cache/
claude.md

# Frontend
console/node_modules/
console/dist/
console/.vite/
console/coverage/
console/playwright-report/
console/test-results/
27 changes: 27 additions & 0 deletions console/biome.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"$schema": "https://biomejs.dev/schemas/1.6.1/schema.json",
"organizeImports": {
"enabled": true
},
"linter": {
"enabled": true,
"rules": {
"recommended": true,
"style": {
"useConst": "error"
}
}
},
"formatter": {
"enabled": true,
"indentStyle": "space",
"indentWidth": 2,
"lineWidth": 100
},
"javascript": {
"formatter": {
"quoteStyle": "double",
"semicolons": "always"
}
}
}
20 changes: 20 additions & 0 deletions console/e2e/a11y.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { expect, test } from "@playwright/test";
import axe from "axe-core";

test.describe("Automated Accessibility Audits (axe-core)", () => {
const routes = ["/", "/scopes", "/about"];

for (const route of routes) {
test(`should have zero axe-core violations on ${route}`, async ({ page }) => {
await page.goto(route);
await page.evaluate(axe.source);
const results = await page.evaluate(async () => {
return await (window as any).axe.run();
});

// Filter out non-critical issues if necessary or assert clean zero violations
const violations = results.violations || [];
expect(violations, `Found ${violations.length} accessibility violations on ${route}`).toEqual([]);
});
}
});
22 changes: 22 additions & 0 deletions console/e2e/console.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { expect, test } from "@playwright/test";

test.describe("Console Screen E2E", () => {
test("loads console, displays hero card, and filters feed", async ({ page }) => {
await page.goto("/");

// Assert main header brand
await expect(page.getByRole("link", { name: /vitals/i })).toBeVisible();

// Assert Hero verdict card or empty state
const heroCard = page.locator('[aria-label^="Latest verdict card"]');
await expect(heroCard).toBeVisible();

// Filter to CHANGED state
const changedChip = page.getByRole("button", { name: /changed/i });
if (await changedChip.isVisible()) {
await changedChip.click();
// Assert URL updated with ?state=changed
await expect(page).toHaveURL(/state=changed/);
}
});
});
35 changes: 35 additions & 0 deletions console/e2e/drawer.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { expect, test } from "@playwright/test";

test.describe("Verdict Drawer E2E & SPA History Fallback", () => {
test("opens drawer on row click, updates URL, closes on Esc", async ({ page }) => {
await page.goto("/");

// Click "View full record →" link in hero card
const viewRecordLink = page.getByRole("link", { name: /view full record/i });
if (await viewRecordLink.isVisible()) {
await viewRecordLink.click();

// Assert URL updated to /v/:id
await expect(page).toHaveURL(/\/v\//);

// Assert drawer dialog is open
const drawer = page.getByRole("dialog", { name: /verdict details/i });
await expect(drawer).toBeVisible();

// Press Escape key
await page.keyboard.press("Escape");

// Assert URL returned to /
await expect(page).toHaveURL(/\/$|^\/[^v]/);
}
});

test("direct deep-link to /v/:verdictId renders drawer (SPA Fallback §0.2)", async ({ page }) => {
// Navigate directly to a deep link
await page.goto("/v/4f2a91b8e301");

// Assert console shell renders underneath and drawer opens
await expect(page.getByRole("link", { name: /vitals/i })).toBeVisible();
await expect(page.getByRole("dialog")).toBeVisible();
});
});
35 changes: 35 additions & 0 deletions console/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vitals Console</title>
<meta name="description" content="Vitals real-time GenAI model monitor and verdict engine console." />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<link
rel="preload"
href="/fonts/InterVariable.woff2"
as="font"
type="font/woff2"
crossorigin
/>
<link
rel="preload"
href="/fonts/JetBrainsMono-Regular.woff2"
as="font"
type="font/woff2"
crossorigin
/>
<link
rel="preload"
href="/fonts/JetBrainsMono-Medium.woff2"
as="font"
type="font/woff2"
crossorigin
/>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
Loading
Loading