Phase 5 UI Redesign — Cycles-First Navigation¶
Status: Shipped 2026-07-04 Scope: React frontend + two new API endpoints. Engine/CLI behavior unchanged.
Why¶
Post-Phase-3 feedback: the React UI read as an unpolished AI-generated beta — generic slate styling, no design tokens or shared components, the brand logo unused, two overlapping execution pages, and no way to discover cycles (users had to type cycle names from memory into a free-text field). The CLI delivered the product promise (straightforward, time-saving); the UI didn't.
Decisions¶
1. Cycle discovery becomes an API + UI feature¶
GET /api/v1/cycles— list summaries (name, description, stage_count, equipment) viadiscover_and_load(); parity withtesto cycles list.GET /api/v1/cycles/{cycle}— resolved stage detail (equipment, target repo, args, timeout, workers, trigger); parity withtesto cycles show. 404 lists valid names; missing config → 503infra_failure.- Models in
testo_api/models.py(CycleSummary,CycleListResponse,StageSummary,CycleDetailResponse); routes intesto_api/routes/cycles.py; contract tests intests/contract/api/test_cycles_contract.py.
2. Cycles-first information architecture¶
- Nav: Dashboard · Cycles · Runs · Compare, plus health indicator (
GET /api/v1/health/ready, polled 30s) and an Advanced ▾ menu (Legacy Execution, AI Settings). Since UI Restyle - 2026-10-19 these sit in a desktop sidebar. - New pages:
frontend/src/features/cycles/CyclesPage.tsx(card grid, Run buttons),CycleDetailPage.tsx(stage breakdown + run panel). - RunPanel (
frontend/src/features/cycles/RunPanel.tsx) replaces the free-textLiveExecutionConsole(deleted): cycle dropdown fed by the new endpoint, core toggles (stream/persist/fail-fast/force), and a progressive-disclosure Advanced accordion covering everyCycleExecutionRequestfield (workers, reporters, report DB, config path, artifacts root). SSE consumption unchanged (locked NDJSON event contract). - Dashboard shows a 3-step first-run guide when no runs exist instead of "n/a" KPI walls.
- Route renames with redirects:
/history→/runs,/runner→/cycles,/execution→/advanced/execution.
3. Design system¶
- Tailwind tokens in
frontend/tailwind.config.ts:inkneutral scale (near-black until 2026-10-19, now navy; see UI Restyle - 2026-10-19), singlebrandblue accent (from the logo), semanticsuccess/danger/warn. - Shared components in
frontend/src/components/ui/: Button, Card, Badge, StatusPill, PageHeader, EmptyState, Spinner, KeyValue. - Pixel arm-muscle mascot in
frontend/src/components/mascot/(crisp-edge SVG grids): logo mark in nav,MuscleFlexon run success,MuscleDefeatedon failure,MuscleShrugfor empty states. Animations viamuscle-flex/muscle-droopkeyframes.
4. Doc drift fixed¶
docs/CLI Commands/Command Reference.md documented testo run --tag/--fail-fast/--dry-run/--reporter and testo doctor/clean/watch/init which are not implemented in testo_core/cli/. Marked as roadmap callouts; the API layer already accepts fail_fast/reporter_override so the UI surfaces them.
Verification (performed at ship time)¶
- 17 API contract tests + 352 backend unit/contract tests pass.
- 14 Vitest tests pass, incl. RunPanel submit-via-click regression (the old "Run cycle" button bug) and advanced-options→payload mapping.
- Real-browser walkthrough: cycles list renders all 5 sample cycles;
sample-pytestsrun streamed stage events over SSE and finished green with the flex mascot; mobile (375px) layout verified.
Follow-ups¶
- Implement the roadmap CLI flags (
--fail-fast,--reporter,--tag,--dry-run) to close the CLI↔API gap in the other direction. - Historical runs stuck in
RUNNINGstatus render as "Running" pills on Runs/Dashboard — data hygiene, not a UI defect. - Consider surfacing
GET /api/v1/cycles?config_path=in the UI for multi-config workflows.