Skip to content

v4.27 — Hallmark Design-Debt Remediation

Every WCAG AA floor Desi's 70-gate audit found broken is fixed, or the rule that would have prevented it is written down where the next author will actually find it.

Summary

Desi's objectuve-hallmark design-debt autopilot scored all 59 ionic_frontend/src/views/** surfaces against 70 gates (source issue OBJ-1964) and surfaced three defect families worth a milestone rather than a one-off fix: hard WCAG AA contrast and tap-target failures on high-traffic surfaces (sign-in, onboarding), a query-state-fabrication bug recurring for the third time (OBJ-1711's "an unresolved query renders as a confident, specific, wrong answer" shape), and unconverged design-system drift (arbitrary pixel type sizes, hand-rolled card recipes, raw text-white/slate-* instead of tokens).

The milestone's real payoff isn't the diffs — it's that three of those four defect families were breakable because the rule that would have caught them was never written down anywhere an author would look. Phase 5 (this page, plus docs/reference/desi-design-context.md and this project's CHANGELOG.md) exists specifically to close that gap: document the contrast rule, the type-ramp rule, the card recipe, and the query-state honesty rule, each with a concrete in-repo wrong-shape and right-shape example, so a fifth recurrence of any of them has no excuse.

teams/** was pulled out of scope entirely on 2026-08-01 (Josh's call, recorded on OBJ-1966) once the branch it needed to build on turned out to be a hard CI blocker (pr-scope-guard) rather than just a scheduling risk — it now ships as a fast-follow gated on the gsd/v4.19-teams-v1-wiringmaster promotion, tracked as OBJ-1969 (which has since shipped its own PR, #1970).

Goal

Close the design debt Desi's 70-gate audit found across 59 view surfaces, and — more importantly — leave behind the guards that stop each defect family from recurring. Concretely: clear every WCAG AA floor that a real user hits; kill the third recurrence of the OBJ-1711 "fabricated state rendered as fact" query bug and land a lint rule so there is no fourth; converge the teams/** type ramp and the app-wide token drift back onto the design system; and write the three broken rules down where the next author will actually find them.

Scope — What Shipped

  • Phase 1: Community.vue tap targets and CTA label grown to spec.
  • Phase 2: Coach.vue and EnneagramTypeDetail.vue converted to honest loading/error/empty/ready state gating via a new QueryStateCard component, plus a mechanical ESLint guard (no-fabricated-query-state) against a fourth recurrence.
  • Phase 3 (pulled from this milestone, 2026-08-01): teams/** type ramp + semantic corrections — moved to a fast-follow (OBJ-1969), shipped separately (PR #1970, on master).
  • Phase 4: three independent design-system convergence sweeps — a shared .selectable-card recipe replacing three hand-rolled copies (and fixing a genuine light-mode invisible-border bug), a real blanket prefers-reduced-motion rule, and a text-white/slate-* token-drift sweep that also gated the internal /design-system token gallery behind auth.
  • Phase 5: the prevention docs — four rules written down with in-repo evidence, CHANGELOG.md entries for every user-visible fix, and this narrative.
  • Not part of this milestone, but its evidence sits on master: the OBJ-1965 contrast sweep (SignIn.vue and nine other anchors) was dispatched to Codi ahead of milestone kickoff — highest-severity finding, smallest diff, no design decisions — and shipped directly to master via PRs #1932 and #1934 rather than through this milestone's integration branch.

Promoted to master 2026-08-02 via PR #1987 (merge commit df03a252543a31bdcd4d19208d93850c3f5cd627), per the stranded-branch lesson CLAUDE.md's Common Gotchas documents from v4.15/v4.19/v4.13/v4.14/v4.3 — a milestone is not shipped when its phases merge, only when master contains its code. Master containment verified by content presence (scripts/check-branch-promotion.mjs) and, since the promotion itself was a real merge commit rather than a squash, by true ancestry (git merge-base --is-ancestor) as well. The promotion's full Vitest run caught a fresh alpha-modifier regression this milestone's own Phase 4b had introduced (SlideWizardLayout.vue), fixed before shipping. The Phase 2 hard gate — Coach.vue/EnneagramTypeDetail.vue's live loading/error/empty states, never visually verified through two review rounds — was cleared before promotion via Storybook + Playwright captures (10 screenshots, 5 states × light/dark).

Phases

PhaseNameStatusPlansHighlights
1Accessibility floor completionShipped1Community.vue tap targets 32px → 44px, sentence-case CTA (OBJ-1967, PR #1937)
2Query-state honesty + the guard that stops recurrence #4Shipped3Coach.vue/EnneagramTypeDetail.vue honest state gating, QueryStateCard, no-fabricated-query-state ESLint rule (OBJ-1968, PR #1946)
3teams/** type ramp + semantic correctionsPulled from milestone (2026-08-01)Rescoped to a fast-follow gated on the gsd/v4.19-teams-v1-wiringmaster promotion; shipped separately as OBJ-1969, PR #1970
4Token & system convergenceShipped3.selectable-card recipe + light-mode border fix (OBJ-2002, PR #1957); blanket reduced-motion rule (PR #1973); text-white/slate-* sweep + /design-system auth gate (PR #1964)
5Prevention & docsShipped1This page, docs/reference/desi-design-context.md rule documentation, CHANGELOG.md
6Master promotionShipped1PR #1987, merge df03a252 — 56-commit rebase, alpha-modifier regression caught and fixed, Phase 2 visual-evidence hard gate cleared

Key Decisions

  • teams/** (Phase 3) pulled from the milestone, 2026-08-01 — the intended baseline branch, gsd/v4.19-teams-v1-wiring, turned out to be blocked outright by the pr-scope-guard CI check rather than merely at scheduling risk. Escalated to Josh rather than guessed at; decision recorded on OBJ-1966. teams/** slices were struck from Phase 4's MOTION-1 and TOKEN-1 tasks too, so v4.27 ships everything non-teams/** with zero special-casing.
  • The OBJ-1965 contrast sweep shipped ahead of and outside this milestone, directly to master (PRs #1932, #1934), because it was the audit's highest-severity finding with the smallest diff and zero design decisions — making it wait on milestone numbering would have been the wrong trade. Consequence: the integration branch and master diverged, so Phase 5's docs had to verify each of the four rules against the correct ref per rule (contrast and type-ramp against master; card recipe and query-state honesty against the integration branch) rather than one uniform baseline.
  • Coverage bar revised after Phase 1: "≥80% on the lines this milestone changes, with no file-wide regression" replaces the original "≥80% on every changed file" wording, after Community.vue (52% file-wide before and after, all of it pre-existing untouched surface) showed the literal reading would mean back-filling unrelated coverage into a design-debt PR — scope creep wearing a quality costume.
  • CARD-1 used --shadow-card/--shadow-card-hover instead of the originally-specced --shadow-md/--shadow-lg — verified against design_system/css/tokens.css that only the -card shadow tokens carry a dark-mode override; following the literal task spec would have fixed an invisible-border bug in light mode by introducing an invisible-shadow bug in dark mode.
  • Every phase after Phase 1 branches from the tip of the integration branch, never master — Phase 1's branch was accidentally cut from a pre-milestone master commit and had to be rebuilt after Riley caught it at PR time.

Requirements Coverage

This milestone is driven by Desi's 70-gate objectuve-hallmark audit (OBJ-1964), not a formal PRD or REQUIREMENTS.md — there is no requirements file to quote coverage from. Progress is tracked per audit finding in the ROADMAP's phase checklist instead.

Outcomes

  • Every input placeholder and secondary-text anchor the audit flagged for stacked-opacity contrast failure now clears the 4.5:1 WCAG AA floor in both themes (on master, via OBJ-1965).
  • Community.vue's icon buttons and error-recovery CTA meet the 44px tap-target floor, with test coverage that asserts computed pixels rather than class-name presence.
  • Coach.vue and EnneagramTypeDetail.vue can no longer render an unresolved query as a confirmed, specific, wrong answer — and a mechanical ESLint guard exists so a fourth occurrence of this bug family gets caught before review.
  • The three onboarding/Coach-setup option-card surfaces share one token-only recipe with a real, visible border in light mode.
  • prefers-reduced-motion: reduce is a real blanket rule across the app, not two hand-picked animations.
  • The internal /design-system token gallery is no longer reachable unauthenticated in production.
  • The four rules this milestone exists to prevent recurrence of are now documented with in-repo wrong-shape/right-shape evidence in docs/reference/desi-design-context.md (§5 type-ramp, §7 card recipes, §13 contrast, §14 query-state honesty), plus a query-state honesty checklist entry in CONTRIBUTING.md.

Tech Debt

  • (Phase 2) The computed-dimensions tap-target rule has no mechanical enforcement. It was broken twice in this milestone alone — caught by review both times, not by CI. ionic_frontend/tests/unit/helpers/tapTarget.ts exists to make the correct assertion easy, but nothing requires a new component's tests to use it. Open need: a lint rule or CI assertion, not a reviewer's memory. Recorded in docs/reference/desi-design-context.md §15.
  • (Phase 2, resolved before promotion) Live loading/error/empty states for Coach.vue/EnneagramTypeDetail.vue had never been visually verified against Desi's mockups through two review rounds — CI's "Capture UI Evidence" job only screenshots the default/ready state on six unrelated routes. Cleared by Vicki before master promotion via Storybook + Playwright captures (10 screenshots, 5 states × light/dark). Recorded in docs/reference/desi-design-context.md §15.
  • (Milestone-level, OBJ-2039) branch-promotion-guard's declared-branch parser flagged this milestone's own promotion against the wrong branch. The parser takes the first backtick-quoted gsd/... token in the ROADMAP file, which happened to be gsd/v4.19-teams-v1-wiring (quoted in the decision-log explaining the Phase 3 rescope) rather than this milestone's own branch, named un-backticked on the Delivery model: line. Vicki verified the flag was a false positive (v4.19 is independently on master via PR #1956) and overrode it correctly. Filed as OBJ-2039 (backlog, not urgent); durable fix is to derive the branch from the ROADMAP filename rather than scanning prose.
  • (Milestone-level) Integration branch not yet deleted. gsd/v4.27-hallmark-design-debt-remediation is confirmed promoted (content-presence verified, master...branch ahead:0) but remains on origin. Per this repo's planning canon, deleting it removes a live pr-scope-guard cross-branch-overlap risk for other branches — flagged as a follow-up, not a docs task.
  • 917baba0a — fix(a11y): grow Community.vue tap targets to 44px, sentence-case CTA (OBJ-1967, PR #1937)
  • dd476f245 — fix(coach): delete the || 'spark' persona fallback the UI-SPEC named for removal (OBJ-1968, PR #1946)
  • 03e9418fd — feat(coach,enneagram): add QueryStateCard for honest loading/error/empty states (OBJ-1968, PR #1946)
  • 6d7818f57 — fix(welcome,coach): converge selectable-card recipe, fix light-mode border bug (OBJ-2002, PR #1957)
  • 2729c8201 — fix(theme): replace narrow reduced-motion guard with a real blanket rule (OBJ-1970, PR #1973)
  • 6177398f5 — fix(tokens): sweep raw text-white/slate-* drift, gate /design-system behind auth (OBJ-1970, PR #1964)
  • fc021535a — fix(a11y): remove alpha modifiers from muted-foreground/foreground text tokens (OBJ-1965, PR #1932, on master)
  • c34312bf1 — fix(a11y): drop alpha modifier on text-foreground contrast anchors (OBJ-1976, PR #1934, on master)
  • 002e2fdbe — docs: extend OBJ-1711 gotcha for Coach.vue/EnneagramTypeDetail.vue recurrence + no-fabricated-query-state guard (OBJ-1999, PR #1950)
  • 6cae23f55 — fix(tokens): drop alpha-modified foreground token on SlideWizardLayout back button (OBJ-2025)
  • df03a252 — Merge pull request #1987 from gsd/v4.27-hallmark-design-debt-remediation (OBJ-2025, milestone promotion to master)

Last updated: 2026-08-02

Loading…