Files
Lumotia/docs/superpowers/audits/2026-04-25-phase10a-static-slice.md
Jake cc77befda8
Some checks failed
check / cargo check (macos-latest) (push) Has been cancelled
check / cargo check (ubuntu-22.04) (push) Has been cancelled
check / cargo check (windows-latest) (push) Has been cancelled
check / svelte build + lint (push) Has been cancelled
docs(phase10a): static slice audit findings
Captures the agent-runnable portion of Phase 10a ahead of Jake's
manual walkthrough and feedback-document pass:

- a11y baseline confirmed clean (svelte-check 0/0; consistent
  aria-label + aria-hidden patterns across icon buttons; global
  :focus-visible ring set in design tokens; prefers-reduced-motion
  guards present where motion warrants them)
- WCAG 2.1 AA contrast tables for both themes computed from the
  token list at design-system/colors_and_type.css. Nine pairs miss
  AA-normal; light-theme warning misses AA-large too. Severity
  ranked, suggested token shifts noted as starting points
- CI matrix state: check.yml runs on every push, build.yml has
  never been end-to-end exercised - recommend manual workflow_
  dispatch before tagging v0.1.0
- Clean-install test plan and the Phase 9d walkthrough checklist
  consolidated for the testing session
2026-04-25 01:02:48 +01:00

12 KiB
Raw Blame History

name, description, type, tags, created, status, author
name description type tags created status author
Phase 10a static slice audit Static a11y + contrast + CI verification produced by Wren on 2026/04/25 as the agent-runnable portion of Phase 10a, ahead of Jake's manual walkthrough and feedback-document pass. audit
phase10a
audit
a11y
contrast
ci
release
2026/04/25 findings Wren (CORBEL's resident agent) on behalf of Jake Sames

Phase 10a — Static Slice Audit

Scope. Everything in Phase 10a that an agent can verify without a running dev server. The dogfood walkthrough, RB-08 macOS power- assertion verification, and runtime keyboard / screen-reader traversal stay with Jake (or Rachmann for the Mac slot).

Baseline. main at 0ca4e0e. 277 cargo tests pass. clippy / fmt / svelte-check / npm build all clean.

Summary of findings

  • A11y static rules: clean. svelte-check reports 0/0 across 3957 files. Spot-checks confirm consistent aria-label on icon-only buttons and aria-hidden="true" on inner SVGs. Global :focus-visible ring is set in design tokens.
  • Contrast: real fails in light theme + small dim text in both themes. Nine token pairs miss WCAG AA-normal (4.5:1). One pair (warning on bg, light) misses AA-large too.
  • CI: cross-platform cargo check matrix exists and runs on every push to main. The full Tauri installer build (build.yml) has never been exercised end-to-end and should be triggered by manual workflow_dispatch before tagging v0.1.0.

A11y baseline

  • npm run check (svelte-check 4): 0 errors / 0 warnings on 3957 files. Svelte's a11y ruleset enforces <img> alt text, form-input labels, click-handler-on-non-interactive, autofocus restrictions, noninteractive-tabindex, and roughly twenty other rules. All pass.
  • Spot-checked icon-only buttons across Sidebar.svelte, ToastViewport.svelte, MicroSteps.svelte, HotkeyRecorder.svelte, HistoryPage.svelte, TasksPage.svelte. Every button carries aria-label. Every inner <svg> carries aria-hidden="true". The pattern is consistent enough to assume it's the convention rather than coincidence.
  • Global focus ring at src/design-system/colors_and_type.css:225: :focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: var(--radius-md); }. Covers every focusable element by default.
  • prefers-reduced-motion guards present in 8 files (ToastViewport, CompletionSparkline, SettingsGroup, DictationPage, TasksPage, app.css, colors_and_type.css, plus the preferences.svelte.ts store that exposes the flag). These cover the four scaled / staggered animations Phase 8 + 9 introduced. Hover-only colour transitions across the rest of the app rely on the global * transition rule and don't pose a vestibular risk; they're under the reduced-motion threshold.

Contrast audit (WCAG 2.1 AA)

Computed via Python (sRGB → linear-RGB → relative luminance → Web Content Accessibility Guidelines contrast ratio). Floors: 4.5:1 for normal text, 3:1 for large text (≥18px regular or ≥14px bold) and UI components.

Dark theme

Foreground Background Ratio AA-normal AA-large
text bg 16.38 PASS PASS
text bg-elevated 15.35 PASS PASS
text bg-card 14.77 PASS PASS
text sidebar 15.90 PASS PASS
text nav-active 14.12 PASS PASS
text hover 14.44 PASS PASS
text-secondary bg 6.39 PASS PASS
text-secondary bg-elevated 5.99 PASS PASS
text-secondary bg-card 5.76 PASS PASS
text-secondary sidebar 6.20 PASS PASS
text-secondary hover 5.63 PASS PASS
text-tertiary bg 3.65 FAIL PASS
text-tertiary bg-elevated 3.42 FAIL PASS
text-tertiary bg-card 3.29 FAIL PASS
text-tertiary sidebar 3.54 FAIL PASS
accent bg 9.48 PASS PASS
accent bg-elevated 8.89 PASS PASS
accent bg-card 8.55 PASS PASS
accent sidebar 9.21 PASS PASS
success bg 9.75 PASS PASS
success bg-card 8.80 PASS PASS
danger bg 6.46 PASS PASS
danger bg-card 5.83 PASS PASS
warning bg 11.87 PASS PASS
warning bg-card 10.70 PASS PASS

Light theme

Foreground Background Ratio AA-normal AA-large
text bg 16.70 PASS PASS
text bg-elevated 15.58 PASS PASS
text bg-card 17.70 PASS PASS
text sidebar 15.85 PASS PASS
text nav-active 14.24 PASS PASS
text hover 14.64 PASS PASS
text-secondary bg 6.77 PASS PASS
text-secondary bg-elevated 6.32 PASS PASS
text-secondary bg-card 7.18 PASS PASS
text-secondary sidebar 6.43 PASS PASS
text-secondary hover 5.94 PASS PASS
text-tertiary bg 3.47 FAIL PASS
text-tertiary bg-elevated 3.24 FAIL PASS
text-tertiary bg-card 3.68 FAIL PASS
text-tertiary sidebar 3.30 FAIL PASS
accent bg 3.35 FAIL PASS
accent bg-elevated 3.12 FAIL PASS
accent bg-card 3.55 FAIL PASS
accent sidebar 3.18 FAIL PASS
success bg 3.98 FAIL PASS
success bg-card 4.22 FAIL PASS
danger bg 4.39 FAIL PASS
danger bg-card 4.65 PASS PASS
warning bg 2.56 FAIL FAIL
warning bg-card 2.72 FAIL FAIL

Severity ranking

  1. Light-theme warning on every surface — fails AA-large too (2.562.72:1). Anywhere this colour appears against bg or bg-card is unreadable for low-vision users. Highest priority.
  2. Light-theme accent as link colour — global a { color: var(--accent) } rule at colors_and_type.css:220 puts a 3.35:1 swatch on body text. Link semantics need AA-normal (4.5).
  3. text-tertiary in both themes — used for .k-caption (12px), .k-eyebrow (10px), kbd (11px) and many hint-text contexts (399 class-name hits across the codebase). All small text. All fail AA-normal in both themes.
  4. Light-theme success on bg / bg-card — borderline (3.98 / 4.22). Fine if used only for icons / chips ≥18px, fails for inline body copy.
  5. Light-theme danger on bg — borderline (4.39); 4.65 on bg-card. Fine if used for chips, marginal for inline.

Suggested token shifts (estimates, eyeball before committing)

Numbers below are starting points, not finished colours. Re-run the contrast script against any candidate before merging.

  • --text-tertiary (light): #8a8578 → roughly #6f6a5c. Aim ≥4.5:1 against #faf8f5.
  • --text-tertiary (dark): #716b60 → roughly #888278. Aim ≥4.5:1 against #0f0e0c.
  • --accent (light): #b87a4a → roughly #9a6535. Aim ≥4.5:1 for link role; UI / icon use already passes.
  • --warning (light): #b89a3e → roughly #8a7220.
  • --success (light) and --danger (light): nudge by ~510% if you find them used as inline text during the walkthrough.

The Python contrast helper used to generate these tables is small enough to keep inline if useful — it's at the bottom of this file.

CI matrix state

Three workflows in .github/workflows/:

  • check.yml. Runs cargo check on ubuntu-22.04, windows-latest, macos-latest on every push to main and every PR. Concurrent-cancels older runs on the same branch. Should be green at 0ca4e0e but cannot be confirmed from this machine (gh CLI not installed). Worth eyeballing in the GitHub Actions UI before declaring 10a done.
  • build.yml. Full Tauri installer build (Linux .AppImage + .deb, Windows .msi + .exe, macOS .dmg + .app). Triggers on tag push v* or manual workflow_dispatch. Has never been exercised end-to-end. First v0.1.0 tag will be its trial run. Strong recommendation: Run workflow against main once before tagging, to catch matrix-specific failures (Vulkan SDK on Windows, libclang location on Linux 22.04, MoltenVK on macOS) without the release artefact pressure.
  • audit.yml. Weekly cargo + npm audit. Independent of v0.1.

Clean-install test plan

Run on a spare user account or a fresh VM, with no prior Corbie / Kon data. Three iterations: one per platform.

  1. Install the artefact from the platform's build.yml output.
  2. Launch from a clean shell (corbie from PATH, or the .app / Start-menu shortcut).
  3. Verify first-run setup flow renders. Walk through the Whisper / LLM model download for the smallest tier.
  4. Confirm app data lands at the expected path:
    • Linux: ~/.local/share/kon/ (will become ~/.local/share/ corbie/ after Phase 10b rename).
    • macOS: ~/Library/Application Support/com.corbel.kon/.
    • Windows: %APPDATA%\com.corbel.kon\.
  5. Record a 10-second brain-dump → cleanup → task extraction. Confirm no log leakage to stderr that references target/ or dev-only paths.
  6. Quit the app. Open the SQLite db (kon.db for now) and verify SELECT version FROM schema_version ORDER BY version DESC LIMIT 1 returns 14.
  7. Re-launch. Confirm settings persist, history shows the test transcript with manual + LLM tags.
  8. Optional but recommended: launch with RUST_LOG=debug once and archive the log. Anything referencing /home/jake/Documents/ CORBEL-Projects/kon/target/ is a dev-leak bug.

For Phase 10c this gets re-run after the rename sweep to confirm the migration shim correctly moves ~/.local/share/kon/~/.local/share/corbie/ and renames kon.dbcorbie.db.

Walkthrough checklist (deferred from Phase 9d)

These need a running dev server, so they belong in Jake's testing session:

  • Keyboard-only traversal across every page. Tab order respects visual order. No keyboard traps.
  • Focus-visible ring shows on every focusable element. Zero invisible focus states.
  • WCAG AA contrast verified visually in both themes after any token shifts from the suggestions above.
  • Dark-mode parity check: every page renders correctly in light + dark. No hard-coded greys that look fine in one theme and broken in the other.
  • Icon-only-button audit: hover reveals the title attribute or the aria-label is announced by VoiceOver / Orca / Narrator.
  • prefers-reduced-motion: reduce enabled in OS — sparkline stagger, badge entrance, settings-group chevron all stop.
  • Screen-reader smoke test: at least announce page titles, primary-button labels, and the sparkline summary line on one platform's SR.

Appendix — contrast helper

Drop into scripts/contrast.py or run inline. Pass two hex strings (with or without #); prints the AA verdict.

def srgb_to_lin(c):
    c = c / 255
    return c / 12.92 if c <= 0.03928 else ((c + 0.055) / 1.055) ** 2.4

def luminance(hex_color):
    h = hex_color.lstrip('#')
    r, g, b = int(h[0:2], 16), int(h[2:4], 16), int(h[4:6], 16)
    return 0.2126 * srgb_to_lin(r) + 0.7152 * srgb_to_lin(g) + 0.0722 * srgb_to_lin(b)

def contrast(c1, c2):
    l1, l2 = luminance(c1), luminance(c2)
    return (max(l1, l2) + 0.05) / (min(l1, l2) + 0.05)

Anchors