Files
mimic/tasks/todo.md
Knacky 5627d7dcfa docs(sprint 7): plan — terminal-SOC design refresh
9 binding decisions locked with user 2026-06-09 (4-question + 4-question
+ 3-question rounds). Visual direction Bloomberg / terminal SOC. Border
radius 0 except status pills and avatars. Palette kept (primary blue +
slab + canvas/paper/cloud/fog/ink), ADD success/warn semantic tokens.
Scope: 8 pages + 17 components + tokens + DESIGN.md rewrite, all in one
sprint. JetBrains Mono for data only (Inter stays for body/headers).
Light + dark both kept. Zero transitions (brutalist).

Plan validated by spec-reviewer pre-pass: APPROVED with 3 findings
addressed inline (D9 added, R2 reworded, semantic tokens promoted from
optional to locked).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-09 18:34:45 +02:00

12 KiB
Raw Blame History

Sprint 7 — Design Refresh: Terminal-SOC Aesthetic

Branch : sprint/7-design · Worktree : .claude/worktrees/sprint-7-design · Base : main @ e27babe

§0 — Binding decisions (locked with user, 2026-06-09)

  1. Visual direction: Bloomberg / Terminal-SOC — dense, brutalist, semantic colors strong, no ornament.
  2. Border-radius: 0 everywhere except status pills (rounded-pill) and avatars (round). All buttons, cards, modals, inputs, dropdowns, tables, tags → angular.
  3. Palette: KEEP current (#024ad8 primary blue, slab #111827, canvas/paper/cloud/fog/ink light+dark vars). ADD semantic tokens success-green + warn-amber (confirmed scope add — needed for SOC-grade status legibility on dashboards and badges).
  4. Scope: Refonte globale en 1 sprint (all 8 pages + 17 components + tokens + DESIGN.md).
  5. Monospace: data-only — JetBrains Mono for IDs, dates ISO, commands, execution output, MITRE techniques, metrics. Inter stays for body/labels/headers.
  6. Mono font: JetBrains Mono, bundled locally via @fontsource-variable/jetbrains-mono (consistent with existing Inter bundle).
  7. Modes: KEEP light + dark both. Toggle stays.
  8. Animations: Brutalist — zero transition. Remove all transition-* utilities, focus rings sharp, hover instantaneous.
  9. Display scale reduction: locked. display-xxl 72→40, display-xl 56→32, display-lg 44→28, display-md 32→24, display-sm 24→20, display-xs 20→16. Headers stay modest in terminal aesthetic — no editorial flourish at hero scale.

§1 — Pre-work checks (team-lead, before dispatch)

  • Confirm tasks/lessons.md has nothing contradicting this brief
  • Verify uncommitted .claude/agents/frontend-builder.md patch (Skill mandatory) is restored in worktree — sprint hygiene
  • Send plan to spec-reviewer for 2-pass approval (vs SPEC.md, vs §0 binding decisions). MUST be APPROVED before any code touches frontend/.
  • After approval: dispatch frontend-builder with this todo as brief.

§2 — Sprint hygiene (commit #1)

  • chore(agents): frontend-builder must invoke Skill frontend-design before UI work — lands BEFORE design work so the agent itself triggers the Skill on first call this sprint.

§3 — Foundation: DESIGN.md + tokens (commits #2#4)

§3.1 DESIGN.md rewrite (commit #2)

  • Replace current HP-catalog doc (346 lines, off-brand) with terminal-SOC spec covering:
    • Overview: brutalist BAS Purple Team console, angular surfaces, semantic color signals, data-monospace hybrid
    • Colors: keep all existing tokens with role redefinition for terminal-SOC context. Primary = neutral action. Bloom-deep/coral = destructive/alert. ADD success (green) + warn (amber) — locked §0 D3 — with light + dark variants and WCAG AA contrast on slab and canvas surfaces
    • Typography: Inter (body/headers/labels) + JetBrains Mono (data). Concrete tier table with size/weight/line-height
    • Layout: tighter spacing (replace section 80pxsection 48px; halve card padding on dense surfaces)
    • Shapes: ALL radii = 0 except rounded-pill reserved for status badges and avatars
    • Components: re-document btn-*, text-input, card-*, badge-*, nav-*, modal-* with brutalist specs (no shadow, hairline borders, zero transition)
    • Do's/Don'ts: zero rounded on conteneurs; zero transitions; semantic colors only on status surfaces; mono ONLY for data, never headers
    • Iteration guide
  • Doc lives in English (in-repo).

§3.2 Tailwind token refresh (commit #3)

  • frontend/tailwind.config.ts:
    • borderRadius: keep none: 0, keep pill: 9999px. Drop or stop using xs/sm/md/lg/xl for surfaces — keep only if a badge variant needs 2px
    • ADD fontFamily.mono: ['JetBrains Mono Variable', 'JetBrains Mono', 'ui-monospace', 'monospace']
    • ADD semantic colors (locked §0): success: { DEFAULT, soft } (green) + warn: { DEFAULT, soft } (amber). Pull dark-mode variants from CSS vars too. Suggested anchors — success #16a34a (dark #22c55e), warn #d97706 (dark #f59e0b); design-reviewer audits WCAG AA at both modes.
    • Reduce display-* scale (locked §0): display-xxl 72px → 40px, display-xl 56→32, display-lg 44→28, display-md 32→24, display-sm 24→20, display-xs 20→16 — terminal headers are modest
    • Drop tracking[0.7px] and uppercase from button-md (still ALLCAPS via class but no letter-spacing)
    • Drop shadow tokens or keep but ensure no component class applies them
  • frontend/src/styles/index.css:
    • Drop font-size: 16.5px root bump (back to 16px standard)
    • Set body line-height: 1.4, tighten headings to 1.1
    • Rewrite .btn-primary/ink/outline/outline-ink: rounded-none, NO transition-colors, keep uppercase, drop tracking-[0.7px], keep h-11 (touch target)
    • Rewrite .text-input: rounded-none, focus border-primary sharp (no halo), no transition
    • Rewrite .card-product and any .card-*: rounded-none, no shadow, 1px hairline border for separation
    • Rewrite .badge-pill-*: keep rounded-pill ONLY here (status badges); strip uppercase if applied
    • Rewrite .modal-backdrop: same dark backdrop, no rounded for the modal frame itself
    • ADD .mono utility or rely on Tailwind's font-mono (preferred) for data cells

§3.3 JetBrains Mono bundle (commit #4)

  • cd frontend && npm i @fontsource-variable/jetbrains-mono
  • frontend/src/styles/fonts.css: add @import '@fontsource-variable/jetbrains-mono'
  • No CDN. Confirms via npm ls @fontsource-variable/jetbrains-mono.

§4 — Component sweep (commit #5)

Rule: rounded-*rounded-none unless explicitly an avatar or status pill; remove transition-*; data text → font-mono.

  • Layout.tsx: nav-bar/utility-strip already angular — confirm. Remove transition-colors on theme button and hover-underline transitions. Mono font for any data label exposed (e.g. user.role pill).
  • StatusBadge.tsx: KEEP rounded → switch to rounded-pill (it's a status pill, locked exception). Audit semantic mapping (planned/active/closed → semantic tokens once added).
  • SimulationStatusBadge.tsx: same — rounded-pill, semantic colors aligned with new tokens.
  • FormField.tsx: angular inputs (already via .text-input recipe — confirm).
  • EmptyState.tsx: angular wrapper. No rounded illustration container.
  • ErrorState.tsx: angular. Bloom-deep border-left if signalling.
  • LoadingState.tsx: drop any rounded spinner background. Spinner shape ok.
  • ConfirmDialog.tsx: angular modal. Buttons via new .btn-* recipes.
  • Toast.tsx: angular. Semantic color border-left strip.
  • ExportEngagementButton.tsx (sprint 6): angular dropdown menu. Audit rounded-* in the menu/item classes.
  • MitreMatrixModal.tsx: angular modal. Cells already grid — confirm no rounded.
  • MitreTechniquePicker.tsx: angular dropdown.
  • MitreTechniquesField.tsx: angular chips.
  • MitreTechniqueTag.tsx: angular tag (NOT pill — terminal tag, not a status). Decide once and apply consistently across MITRE surfaces.
  • TemplatePickerModal.tsx: angular modal.
  • SimulationList.tsx: angular table. Data cells (commands, executed_at, MITRE techniques) → font-mono.
  • ProtectedRoute.tsx: no visual surface, skip.

§5 — Page sweep (commit #6)

For each page: header/body/footer review, replace rounded card containers with angular hairline-bordered containers, ensure data cells use mono.

  • LoginPage.tsx: angular form card. Drop ornament.
  • EngagementsListPage.tsx: angular table container (currently .card-product with rounded-xl). Data cells (dates) → mono.
  • EngagementDetailPage.tsx: angular header section. Engagement metadata (start/end dates, IDs, created_at) in mono. Simulations table covered via SimulationList.
  • EngagementFormPage.tsx: angular form. Date inputs ok.
  • SimulationFormPage.tsx: angular form. Commands textarea → mono.
  • TemplatesListPage.tsx: angular list.
  • TemplateFormPage.tsx: angular form. Commands field → mono.
  • UsersAdminPage.tsx: angular table. Username column → mono (it's an ID).

§6 — Test refresh (commit #7)

  • cd frontend && npm run test -- --run — identify failing assertions on class names (rounded-xl, card-product, etc.). Update tests to use semantic queries (role, name, data-testid) where possible; if test asserts on visual class, update assertion to the new class.
  • No new vitest tests added (visual sprint, behavior unchanged).
  • Playwright e2e: should be data-testid-driven — run full suite to confirm no regression. If breakage, fix the testid not the test logic.

§7 — Reviews

  • spec-reviewer (pre-dispatch, §1): plan validated vs SPEC.md and §0 binding decisions
  • frontend-builder (§2-§6): implements, runs typecheck/lint/test, delivers screenshots for design-reviewer (every page + key states, light+dark)
  • design-reviewer (post-frontend): reviews screenshots + diff vs new DESIGN.md. Brutalist consistency, mono-discipline (only data), zero-rounded discipline.
  • code-reviewer (post-design): reviews frontend diff for duplication, lost reuse, dead code.
  • test-verifier: skipped this sprint (no new US, no behavior change).
  • backend-builder: idle, no work this sprint.

§8 — Git workflow

  • Branch: sprint/7-design (already created from origin/main)
  • Commits: conventional, one per logical group (§2 to §7)
  • PR via make open-pr (Gitea pattern, per memory)
  • PR body in tasks/pr-body-sprint-7.md
  • CHANGELOG.md sprint 7 section

§9 — Risks & mitigations

  • R1 — Tests break en masse: many vitest specs may assert on class strings (e.g., rounded-xl on cards). Mitigation: update assertions to semantic queries; budget half a phase to test repair.
  • R2 — Dark mode contrast lost: angular + new semantic colors may break WCAG AA contrast on dark slab. Mitigation: design-reviewer audits both modes; adjust the dark variant hex to meet WCAG AA. Rollback the success/warn family only if no accessible green/amber is achievable on the dark slab.
  • R3 — Mono overflow: JetBrains Mono is wider than Inter at same px. Cell widths in tables may overflow. Mitigation: keep table-layout: fixed and word-break: break-word (pattern reused from PDF export CSS sprint 6).
  • R4 — DESIGN.md rewrite churn: replacing 346 lines is a big diff. Mitigation: rewrite atomically in commit #2, keep token names consistent so downstream commits don't drift.
  • R5 — User taste mismatch: "Bloomberg/SOC" may not match user's mental image. Mitigation: design-reviewer screenshots → user check-in BEFORE merge.

§10 — Definition of Done

  • All §0 decisions reflected in DESIGN.md + tokens + components + pages
  • npm run typecheck clean
  • npm run lint clean
  • npm run test -- --run all green
  • Backend untouched — git diff origin/main -- backend/ empty
  • Playwright e2e green (223 baseline preserved)
  • Screenshots delivered (light + dark) for every page + key states
  • DESIGN.md rewritten, no HP/Forma/wordmark/chevron references
  • CHANGELOG.md sprint 7 section
  • PR opened on Gitea
  • User merges PR → sprint closed → team idle ready for sprint 8

§11 — Lessons being applied from prior sprints

  • SPEC/DESIGN commit-first: DESIGN.md rewrite is commit #2 (after sprint hygiene). No design churn mid-sprint.
  • spec-reviewer 2-pass: APPROVED before dispatch, not after.
  • Team idle policy: 6 agents already mounted, no shutdown until PR merged.
  • frontend-builder MUST invoke Skill frontend-design before UI work (the patch commits as #1, takes effect immediately for the same sprint).