From 05421fc886527a0d2fb209f24f37f950fdd91878 Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Sat, 25 Apr 2026 01:06:01 +0000 Subject: [PATCH 1/2] spec(tokens): add D11 (label primary tier = APCA Lc 75 / WCAG 7:1, Apple HIG body text) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Locks the dual-criterion (APCA + WCAG) label tier targets and the Apple-HIG body-text primary level (Lc 75 / WCAG 7.0:1, not Lc 60). Salvaged from PR #27 (PR-M, closed 2026-04-25 because pre-SPEC-v0.2 pipeline made rebase costly). Re-implementation queued as PR-N4 (post-v0.3 RFC-005 Bezold-Brücke pipeline). Co-Authored-By: jaquan_boyer84 --- plan/spec/SPEC.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/plan/spec/SPEC.md b/plan/spec/SPEC.md index 8ac9e3f..3917cfd 100644 --- a/plan/spec/SPEC.md +++ b/plan/spec/SPEC.md @@ -1281,6 +1281,27 @@ Full implementation (2-color stack + `mix-blend-mode: color-dodge` + `backdrop-f **Rationale.** SPEC §2 hard constraints + §7 acceptance + §8 anti-hallucination gates are enforceable only with branch protection. Without it they're convention. +### D11 — Label primary tier: APCA Lc 75 / WCAG 7:1 (Apple HIG body text) + +**Decision.** Label tier targets are dual-criterion `(apca, wcag)` rather than APCA-only. The primary tier targets **APCA Lc 75 normal / Lc 90 ic + WCAG 7:1 / 10.5:1** (Apple HIG `labelColor` body-text envelope), not the APCA Lc 60 "incidentally read" minimum used in the bootstrap config. + +| tier | normal target | ic target | +|------------|------------------------|-------------------------| +| primary | Lc 75 / WCAG 7.0:1 | Lc 90 / WCAG 10.5:1 | +| secondary | Lc 60 / WCAG 4.5:1 | Lc 75 / WCAG 7.0:1 | +| tertiary | Lc 45 / WCAG 3.0:1 | Lc 60 / WCAG 4.5:1 | +| quaternary | Lc 30 / WCAG 2.0:1 | Lc 45 / WCAG 3.0:1 | + +Resolver picks the **stricter** L between APCA-inverse and WCAG-inverse searches per token. Fills and borders remain APCA-only (surface-contrast rules, not text-contrast rules). + +**Why dual-criterion.** APCA Lc is more sensitive than WCAG to short-wavelength blues; tokens like `label-brand-primary` on white can hit APCA 60 while only reaching WCAG ~3:1 — well below AA. The WCAG floor catches that. Conversely, WCAG over-penalizes near-luminance pairs APCA reads correctly; the APCA target catches that. Stricter-of-both is the safe envelope. + +**Why Apple HIG primary.** The original Lc 60 target was APCA's "incidentally read" minimum (footnotes, captions). Apple HIG `labelColor` is ~Lc 90 — body text. Designer's intent is body-text-grade primary, not footnote-grade. + +**Implementation status.** Decision locked. The original implementation (PR #27, closed 2026-04-25) ran on the pre-SPEC-v0.2 pipeline. Re-implementation is queued as **PR-N4**: ports `src/utils/wcag.ts` + dual-criterion resolver onto the post-v0.3 pipeline (after Bezold-Brücke RFC-005 lands), and updates `tokens.config.ts:tier_targets` to the table above. + +**Rationale.** G2 (production-ready, Tier-1 quality), G7 (no magic). Designed-for-body-text labels must read as such on every (sentiment × mode) combination, not just the APCA-easy ones. + --- ### Reset protocol From f81cd430d5a42caf7f35841b4b8a7969175b5d44 Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Sat, 25 Apr 2026 01:12:11 +0000 Subject: [PATCH 2/2] spec(tokens): extend reset-protocol range to D0-D11 (Devin Review fix) Co-Authored-By: jaquan_boyer84 --- plan/spec/SPEC.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plan/spec/SPEC.md b/plan/spec/SPEC.md index 3917cfd..8f0198c 100644 --- a/plan/spec/SPEC.md +++ b/plan/spec/SPEC.md @@ -1306,7 +1306,7 @@ Resolver picks the **stricter** L between APCA-inverse and WCAG-inverse searches ### Reset protocol -A locked decision (D0–D10) can only be reverted via: +A locked decision (D0–D11) can only be reverted via: 1. Explicit designer message reopening the question (e.g. "пересмотри D5 — Fills.Neutral на Gray.500 не работает, попробуй Gray.600"). 2. Or a calibration test failure that surfaces the locked decision as the root cause, in which case Devin proposes alternatives with rationale and blocks until designer resolves.