- Walked: 2026-05-30–31 during the customer accessibility repair campaign. The dated sweep reduced 402 recorded contrast nodes to a 25-node floor classified as intentional specimens or invalid-parameter skeletons.
- Reconciled: 2026-07-18 against the current Lilith tokens,
readableInkhelper, stylesheet contract tests, system-specimen policy, and canonical desktop/mobile customer accessibility matrices. This was a source reconciliation, not a fresh all-route contrast sweep. - Verdict: partial — the historical record explains a substantial and traceable token repair campaign, and the key fixes remain present in current source. Current automation guards representative customer surfaces and explicitly treats diagnostic specimen pages as render-only. It does not reproduce the dated 181-route inventory or justify carrying “every real customer surface is AA” forward as a current universal claim.
- Current signoff specs:
wcag-aa-signoff-v1-p2-3510.spec.ts,wcag-aa-signoff-v1-p2-3511.spec.ts, andlilith-public-routes.spec.ts.
Result at a glance#
| Evidence lane | Recorded or current result | Authority limit |
|---|---|---|
| 2026-05-30 starting sweep | 402 customer color-contrast nodes |
Historical build, route manifest, runner, and raw JSONL |
| 2026-05-31 recorded floor | 25 nodes: 17 intentional specimen/showcase cases and 8 invalid-parameter skeleton cases | Dated classification, not a current scan |
| Current semantic token repairs | Cream --l-muted, --l-warn, and --l-accent-2-text values remain in the Lilith stylesheet |
Source presence, not rendered coverage |
| Current data-color repair | readableInk darkens six-digit hex text colors toward the cream-surface target and leaves other inputs unchanged |
Helper contract; callers and backgrounds still matter |
| Current customer signoff matrix | Eleven primary/domain surfaces run WCAG 2.1 A/AA at desktop and 390 × 844 | Serious/critical release threshold, representative routes |
| Current specimen policy | Five /system* diagnostic pages render publicly with axe skipped for intentional sub-AA demonstrations |
Exclusion needs continued ownership and clear semantics |
Evidence map#
The useful outcome is not the original count alone. The campaign moved repeated component literals into semantic text tokens and a reusable data-color helper, then retained a smaller portable accessibility matrix.
flowchart LR
A[402 dated contrast nodes] --> B[Trace actual foreground and background]
B --> C[Component literal repairs]
B --> D[readableInk for data colors]
B --> E[Semantic text tokens]
C --> F[25-node dated floor]
D --> F
E --> F
F --> G[17 intentional specimens]
F --> H[8 invalid-param skeletons]
I[Current desktop matrix: 11 surfaces] --> J[Serious and critical gate]
K[Current mobile matrix: same 11] --> J
L[System specimen routes] --> M[Render-only policy]
F -. historical only .-> N[Current posture]
J --> N
M --> N
Proven observations#
Historical remediation trail#
- The repair record documents a descent from 402 customer contrast nodes to 25 through repeated scan, node-level foreground/background tracing, component fixes, shared-token changes, and cross-surface regression checks.
- Data-driven category and domain colors moved through
readableInkwhere a literal six-digit hex was used as text on the cream surface. The helper preserves hue while darkening and intentionally leaves CSS variables, gradients, and rgba inputs unchanged. - Text usages that could not safely reuse brighter fill/icon colors gained
semantic variants, including
--l-accent-2-text. The current cream token is#8f4a1e; the original accent remains distinct at#c97247. - The cream warning token remains at the repaired
#6f5220, and cream muted text remains#574d3f. The stylesheet contract maps the TypeScript token variants back to the CSS custom properties so later theme drift is testable.
Corrections preserved from the dated investigation#
- The apparent
#637b4ftoken transformation was a stale probe, not a runtime color-transform layer. The later trace established that the named tokens resolved to their CSS definitions. - The final plan-review diagnosis also superseded the earlier opacity theory.
Actual axe nodes showed
--l-warnat full opacity on warmer card backgrounds; darkening the cream warning token, rather than removing animation, closed the measured near-misses. - The final historical note therefore classified the remaining 25 nodes as 17 intentional demonstrations and eight invalid-parameter skeletons, with no remaining real-content defect in that dated manifest.
Current durable contract#
- The canonical desktop and mobile signoff specs each cover Home, Library, Search, notifications, Profile, and the Tara, Veritas, Nyx, Arete, Nisaba, and Metis domain entries. They run the WCAG 2.1 A/AA rule set and fail serious or critical findings.
lilith-public-routes.spec.tskeeps the system galleries public and renderable while documenting why their contrast scan is skipped: the pages display palette, ratio, faded-preview, and edge-state specimens, including deliberately sub-AA examples.- This current matrix is portable repository evidence. The original parallel
/tmp/walkrunner and JSONL report are historical provenance only.
Boundaries and gaps#
- The 402-to-25 sequence is historical. It belongs to the 2026-05 route manifest and build. This reconciliation did not rerun that temporary all-customer scanner against today's tree.
- A source token value is not rendered conformance. Backgrounds, opacity, font size/weight, state, animation, blending, nested themes, and user content determine the actual axe result.
readableInkhas a narrow contract. It handles six-digit hex inputs for cream-surface text. CSS variables and non-hex colors pass through unchanged, so callers must choose a semantic text token for those cases.- Specimen exclusions are scoped, not global waivers. The current policy skips contrast on named diagnostic galleries because low contrast is the demonstrated subject. The same token pairing on a task surface remains a defect.
- Invalid-parameter skeletons are not valid dynamic-route evidence. Their faded states explained dated findings but do not certify real ids, empty states, error copy, or every current dynamic route.
- The current release gate is representative. Eleven desktop/mobile surfaces fail serious/critical findings; moderate/minor findings and the rest of the customer route/state inventory need separate coverage.
- Automated contrast is not full accessibility. Forced colors, zoom/reflow, user theme overrides, display calibration, cognition, and assistive- technology task completion remain outside this record.
Re-run evidence#
The current portable browser evidence can be run serially with:
bash
PW_BROWSER_CHANNEL=chrome pnpm exec playwright test \
-c apps/oshun/web/playwright.config.ts \
apps/oshun/web/e2e/wcag-aa-signoff-v1-p2-3510.spec.ts \
apps/oshun/web/e2e/wcag-aa-signoff-v1-p2-3511.spec.ts \
apps/oshun/web/e2e/lilith-public-routes.spec.ts \
--workers=1
That command verifies the maintained representative matrix and specimen render policy. It does not recreate the historical 181-route contrast sweep or its 25-node floor.
Source trail#
- Desktop customer accessibility matrix
- Mobile customer accessibility matrix
- Public and system-specimen policy
- Lilith theme tokens
- Stylesheet/token contract
- Cream-surface data-color helper
- Current key-route accessibility result
Cross-references#
- System contrast specimen view
- System overview
- Customer route coverage matrix
- Studio and Operator accessibility result
- Walkthrough result registry
Open questions#
- What generated route/state inventory should replace the dated 181-route manifest for a safe, repeatable customer contrast sweep?
- Should current CI retain serious/critical as the release threshold while a scheduled job records every axe severity and node-level trend?
- How will diagnostic specimen exclusions be identified semantically so a route-name allowlist cannot hide ordinary product content?
- Which tests should pin contrast for semantic text tokens across cream, cream-high-contrast, dusk, warmer cards, disabled states, and motion frames?
- Where should versioned JSON axe artifacts live so future claims can be compared to this repair history rather than reconstructed from prose?