07 — Quality and Verification
Run the 5-level verification pyramid (static→unit→E2E→AI visual→post-deploy) with WCAG 2.2 AA and 8-gate quality enforcement on every change.
5-level pyramid (bottom to top)
- Static — TS strict + ESLint + oxlint + Prettier + knip (dead code)
- Unit — Vitest 3 (40% faster on 5k+ tests, Rust sharding, browser mode default)
- Playwright E2E — homepage-first, 6 viewports × 3 browsers, hermetic, parallel
- AI visual — vision rubric ≥9/10 per route, 6bp screenshots
- Post-deploy —
wrangler tailclean + console-error-free + axe-clean + Lighthouse green
8-check quality gate (every PR)
npm run typecheckclean (0 errors)npm run lintclean (0 errors, 0 warnings)npm test(Vitest) greennpm run e2e:prodgreen at 6 breakpoints- axe-core 0 violations per
_kernel/standards.md#wcag22 - Lighthouse Perf ≥90, A11y ≥95, BP ≥95, SEO ≥95 (authoritative:
EMDASH_LIGHTHOUSE_MIN_*in~/.claudeenv) - AI vision QA ≥9/10 per route (authoritative:
EMDASH_AI_VISION_MIN) - Console / CSP / network errors = 0
Any fail = blocker. Fix-forward per rules/verification-loop.md.
Playwright Test Agents (v1.59+)
npx playwright init-agents --loop=claudeonce per repo- Planner — Markdown plan; Generator — test code; Healer — auto-fix broken selectors (run before manual rewrite)
browser.bind()for MCP interop;page.screencastfor video receipts on flaky specs
Hermetic spec contract (per rules/e2e-tdd-organization.md)
- Starts at homepage (
/); navigates via clicks/keyboard - Seeds own data via
_fixtures/; cleans own data after-each - Does not write to localStorage / IDB / cookies next spec reads
- Does not depend on
Date.now()/ timezone / random - Does not open network to live third-party APIs (MSW / stub)
Violating any = build fail.
Parallel execution
fullyParallel: trueworkers: process.env.CI ? '50%' : '75%'- Sharded via
--shard=$INDEX/$TOTAL - 6 viewports per
_kernel/standards.md#breakpoints; 3 browsers: Chromium, Firefox, WebKit
AI visual QA
- Random snapshot sampling 30% per step (seeded hash, reproducible)
- New-section AI vision:
e2e/__seen-routes__.jsongates first render of unknown routes - Rubric: layout sane / contrast WCAG AA / brand / no slop / ≥9/10 (Claude Sonnet 4.6 or GPT Image 2 vision)
- Baselines in
e2e/__snapshots__/; pixelmatch tolerance 0.1% / 0.5% area - Per
rules/e2e-visual-inspection.md
Visual regression
- Percy AI Visual Review — 3× faster review, 40% OCR-based noise filter, full-page + flows
- Chromatic — component-level via Storybook
- pixelmatch — local deterministic CI (three-tier: local → PR → deploy)
Multi-agent testing
Spawn parallel in single Agent call:
- functional-tester — happy path + edge cases
- security-reviewer — OWASP Top 10:2025 per
_kernel/standards.md#owasp2025 - accessibility-auditor — axe 6bp + WCAG 2.2 manual review
- performance-profiler — Lighthouse CI + bundle audit + INP via LoAF
- visual-qa — AI vision rubric ≥9/10
Each: 100–300 word brief, ≤200 word summary back. Per rules/agent-selection.md.
INP debugging
PerformanceObservertypelong-animation-frame(LoAF, Chrome 123+)- For SPA per-route CWV: web-vitals v4+ with
softNavs:true - Target ≤100ms cinematic; ≤200ms = fail per
_kernel/standards.md#cwv
Console-error gate
After every deploy: browser console must show 0 CSP violations, 0 JS errors, 0 failed resources. Fixed by rules/verification-loop.md console-error gate.
E2E accumulation
- Tests NEVER deleted, only appended
journey.spec.tsserial + stateful — each feature adds steps- 100% feature coverage matrix in
e2e/FEATURES.md - Removed features: skip + comment, do not delete
Inventory enforcement
e2e/FEATURES.md— row per featuree2e/COVERAGE.yml— feature→spec map; CI fails on any feature without entry/test- Pre-commit lint: new component without matching
e2e/<feature>/warns