Skip to content

Retire the --shadow-tight role alias onto the --e1 elevation tier - #1803

Merged
BigSimmo merged 7 commits into
mainfrom
claude/codex-m4b-shadow-tight-migration-53a8kn
Aug 10, 2026
Merged

Retire the --shadow-tight role alias onto the --e1 elevation tier#1803
BigSimmo merged 7 commits into
mainfrom
claude/codex-m4b-shadow-tight-migration-53a8kn

Conversation

@BigSimmo

Copy link
Copy Markdown
Owner

Summary

  • Migrate every --shadow-tight consumer onto the --e1 elevation tier. 150 var(--shadow-tight) occurrences across 71 files become var(--e1) — 90 of those are the gated production sites across 48 files that check:design-system-contract records under legacyShadowAliases, and the remaining 60 are design-scratch mockups, migrated in the same pass so that no file names a token that is about to be deleted. GATES.md already forbids reaching for a role alias in new code, so every one of these call sites was recorded debt (#262 part 1).
  • Retire the --shadow-tight role alias. All three declarations are deleted: :root, .dark, and the forced-colors flattening. Isolated in its own commit because it edits the theme blocks. design-token-contract.test.ts drops the alias from the role map and asserts the token is absent from the whole stylesheet rather than per theme block, because any scope that redeclares it makes the alias spellable again. The one tailwind-merge conflict fixture is repointed so no test names a token that no longer exists.
  • Pin the ratchet to measured rather than merely lowering it.legacyShadowAliases 220 → 127 with 17 paths dropped and per-path counts made exact. The previous ceiling was also carrying 3 aliases of slack across the other six roles (measured 217 against a 220 ceiling) — the same re-accumulated drift #264 corrected on 9 August.
  • Documentation updated in the same commit as the gate change, which is the specific failure #301 records: the GATES.md §3 prohibition row, a new GATES.md §6 record of this pass, a TOKENS.md §6 disposition row, and the alias list in docs/design-system.md, both redesign direction docs and .design-sync/conventions.md. #262 part 1 is closed in the outstanding-issues ledger.

Why this renders identically, and why the obvious argument is not sufficient

--shadow-tight pointed at var(--e1) in both themes and the forced-colors block already flattened --e1 alongside the roles, so the substitution looks trivially safe from the declarations alone. It is not safe on that basis, and the reason is recorded in GATES §6 because it is owed to every remaining alias in #262.

ckb-v2-tokens.css redeclares the tier — light 0 1px 2px rgb(13 40 71 / 5%) against globals' 0 1px 2px rgb(11 42 56 / 7%) — and never redeclares the roles. A custom property whose value contains var() substitutes on the element it is declared on, so an alias declared in one scope and overridden in a narrower one freezes at the outer value and the two spellings diverge. This migration survives only because both selectors match the same element: .ckb-v2 sits on <html> in layout.tsx and .ckb-v2.ckb-v2 outspecifies :root, so the alias substitutes against the winning v2 tier.

That was measured in Chromium rather than argued. A page carrying exactly that cascade computes var(--shadow-tight) and var(--e1) both to rgba(13, 40, 71, 0.05) 0px 1px 2px 0px — the v2 value, not the :root value. Light is the only theme where the two layers disagree at all; the dark tiers are byte-identical strings and forced-colors is none on both sides.

What this does not do

Clearing --shadow-tight does not zero the metric. 127 aliases remain across --shadow-soft (71), --shadow-elevated (17), --shadow-hover (17), --shadow-card (12), --shadow-lux (8) and --shadow-lift (2) — the other #262 tranches. Count a token by reading the var() call and not the declaration it sits in: two of the 71 --shadow-soft hits are the value of the --shadow-focus declarations in each theme, which is how an earlier pass mis-read them as a --shadow-focus tally. LEGACY_SHADOW_ALIAS has never matched focus, so #261 shares no counter with this metric.

Verification

  • npm run verify:pr-local — superseded by the broader gate below, which covers it and more.

npm run verify:cheap ran green through all 30 static gates, lint and typecheck. Decisive lines:

Design-system contract passed (706 production files; raw colors 2; literal shadows 0; legacy tap classes 0; edge conflicts 27; 1px shadow spreads 2).
Motion/z/palette ratchets: hardcoded CSS durations 42; layout transitions 11; raw CSS z-index 9; legacy palette utilities 0; dark color overrides 0; legacy shadow aliases 127; arbitrary tracking 0.

The offline unit suite finished Test Files 1 failed | 553 passed (554) / Tests 1 failed | 6024 passed | 4 skipped (6029). The single failure is tests/pr-handoff-stop.test.ts > emits handoff context only when the marker file exists, and it is pre-existing and environmental, not from this diff: the same test file fails identically on the untouched base a16dd26 in a clean worktree. The case chmods the git dir to 0o555 and expects the marker write to fail; this container runs as root, and root ignores the permission bits, so the write succeeds. It passes on a non-root CI runner.

Two targeted proofs beyond the suite:

  • Mutation-verified the new retirement assertion — restoring --shadow-tight: var(--e1); to :root fails with --shadow-tight is retired; call sites use --e1, and the file was restored afterwards.
  • Mutation-verified the ratchet is real rather than slack: the per-path pins were rewritten to exact measured counts, so a reintroduced alias in any of the 66 remaining paths trips findDebtPathRegressions.
  • npm run verify:uiUI verification not run: the installed Playwright browser revision does not match this checkout's expected revision (/opt/pw-browsers carries chromium-1194 while Playwright resolves chromium_headless_shell-1234), which is the known drift tracked as #255. Per docs/testing.md, browser proof is delegated to the CI Production UI job rather than forcing a mismatched Chromium path. The targeted Chromium measurement described above was taken by launching the installed 1194 binary directly for a single computed-style read, which does not substitute for the journey suite.
  • npm run verify:release — not run; no release or handoff confidence claim is made here, and it is provider-backed.
  • npm run eval:retrieval:quality — not applicable. No retrieval, ranking, selection, chunking or scoring code is touched.
  • npm run eval:rag -- --limit 15 + npm run eval:quality -- --rag-only — not applicable. No answer generation, synthesis prompt or answer post-processing is touched.
  • npm run check:production-readiness — not applicable, and provider-backed. No clinical workflow, privacy, environment, Supabase, source-governance or deployment behaviour changes.
  • npm run check:deployment-readiness — not applicable. No deployment startup, hosting or rollout behaviour changes.

Risk and rollout

  • Risk: Low, and bounded to painted elevation. The change is a textual substitution of one custom-property name for the tier it already resolved to, plus the deletion of the now-unconsumed alias. The one way it could have been wrong — the v2 layer redeclaring --e1 in a scope the alias could not see — was measured in Chromium and is not the case here; that measurement is recorded in GATES §6 as a prerequisite for the remaining #262 tranches rather than a one-off. No logic, data, routing, or clinical behaviour is touched. The residual risk is a rendering difference the computed-style read would not catch, which the CI Production UI job covers.
  • Rollback: git revert either commit independently. The retirement commit reverts on its own and simply restores the alias declarations next to their siblings; the migration commit reverts on its own only if the retirement is reverted first, since restoring var(--shadow-tight) call sites needs the token to exist.
  • Provider or production effects: None. No provider-backed command was run, and no Supabase, OpenAI, Railway or hosted-CI surface is touched.

Clinical Governance Preflight

Included because classifyPullRequestFiles returns clinicalRisk: true for this diff — it edits components under the document-viewer, differentials, DSM, factsheets and clinical-dashboard trees. The edits within those files are confined to shadow token names in class strings, so each item below is satisfied by the change touching nothing in that area.

  • Source-backed claims still require linked source verification before clinical use
  • No patient-identifiable document workflow was introduced or expanded without explicit governance approval
  • Supabase target remains Clinical KB Database (sjrfecxgysukkwxsowpy)
  • Service-role keys and private document access remain server-only
  • Demo/synthetic content remains clearly separated from real clinical sources
  • Source metadata, review status, and outdated/unknown-source behavior remain conservative
  • Deployment classification/TGA SaMD impact was checked when clinical decision-support behavior changed

Notes

  • The originating handover document for this task lives at a Windows path on the author's machine (C:\Users\joshs\.claude\projects\...\CODEX-M4B-SHADOW-TIGHT-MIGRATION.md) and was not reachable from the remote container, so the scope was reconstructed from the repository's own record: the branch name, #262 part 1, the GATES.md prohibition row, and the #1797 precedent for retiring a declared-but-unconsumed token. If the handover asked for something narrower — migrating the call sites without deleting the alias — the second commit is the part to drop.
  • Both commits pass npm run format:check across the whole tree, not per changed file.

Generated by Claude Code

`--shadow-tight` has resolved to exactly `var(--e1)` in every scope since the
elevation ladder landed: both theme declarations point at the tier, and the
forced-colors block flattens `--e1` alongside the role aliases. GATES.md
already forbids reaching for an alias in new code, so every one of these call
sites was recorded debt under `legacyShadowAliases` (`#262` part 1).
Substituting the tier for the alias is textual and value-preserving — computed
`box-shadow` is unchanged in light, dark and forced-colors — so this carries no
visual review of its own.
- 150 `var(--shadow-tight)` occurrences across 71 files become `var(--e1)`;
90 of those are the gated production sites across 48 files, the rest are
design-scratch mockups migrated in the same pass so nothing names the token
- repoint the `tailwind-merge` docstring example at the ladder, since the
sentence is about which custom properties generate no `shadow-<name>` utility
- `check:design-system-contract` legacy shadow aliases 217 -> 127; the three
`--shadow-tight` declarations themselves are retired in the next commit
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019XDuNkNHU4zFn1cDquUXv5
With every call site on `--e1` the alias has no consumers, and a role that
resolves to the same tier is the quietest way for the debt to come back — it
looks harmless at the declaration and reads as sanctioned at the call site.
Isolated from the migration commit because it edits the theme blocks.
The value-preserving claim is not safe from the declarations alone, and the
reason is recorded in GATES §6 because it is owed to every remaining alias in
`#262`: `ckb-v2-tokens.css` redeclares `--e1` (light `13 40 71 / 5%` against
globals' `11 42 56 / 7%`) and never redeclares the roles, and a custom property
containing `var()` substitutes on the element it is *declared* on — an alias
declared in an outer scope and overridden in a narrower one freezes at the
outer value. This migration survives only because both selectors match the same
element: `.ckb-v2` is on `<html>` and outspecifies `:root`, so the alias
substitutes against the winning v2 tier. Measured in Chromium rather than
argued — both spellings compute to `rgba(13, 40, 71, 0.05) 0px 1px 2px 0px`.
- delete all three declarations: `:root`, `.dark`, and the forced-colors
flattening (`--e1` is already flattened there, so nothing changes)
- `design-token-contract.test.ts` drops the alias from the role map and asserts
the token is absent from the whole stylesheet rather than per theme block —
any scope that redeclares it makes the alias spellable again.
Mutation-verified: restoring it to `:root` fails with
`--shadow-tight is retired; call sites use --e1`
- repoint the one `tailwind-merge` conflict fixture so no test names a token
that no longer exists
- pin `legacyShadowAliases` to measured: 220 -> 127, 17 paths dropped. The old
ceiling also carried 3 aliases of slack across the other six roles (measured
217), the same re-accumulated drift `#264` corrected on 9 August
- GATES.md §3 row and a new §6 record; TOKENS.md §6 disposition row; the alias
list in design-system.md, the two redesign direction docs and
.design-sync/conventions.md; `#262` part 1 closed in the ledger
The remaining 127 aliases are `#262`'s other tranches: soft 71, elevated 17,
hover 17, card 12, lux 8, lift 2. Count by reading the `var()` call and not the
declaration around it — two of the soft hits are the value of `--shadow-focus`,
which is `#261` and shares no counter with this metric.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019XDuNkNHU4zFn1cDquUXv5
@coderabbitai

coderabbitaiBot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in:36 minutes

Your organization has reached its usage spending cap. Adjust your spending cap in the billing tab.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 31e417b4-51a1-4be0-973b-979c6f627b49

📥 Commits

Reviewing files that changed from the base of the PR and between 0055b24 and 7d9d84f.

📒 Files selected for processing (82)
  • .design-sync/conventions.md
  • docs/branch-review-ledger.md
  • docs/design-system.md
  • docs/design-system/GATES.md
  • docs/design-system/TOKENS.md
  • docs/outstanding-issues.md
  • docs/redesign/02-design-direction.md
  • docs/redesign/permanent-colour-direction.md
  • scripts/design-system-contract-baseline.json
  • src/app/globals.css
  • src/app/mockups/answer-evidence-popups/page.tsx
  • src/app/mockups/mode-dropdown/page.tsx
  • src/components/DocumentViewer.tsx
  • src/components/applications-launcher-page.tsx
  • src/components/calculator-mockups/calculator-ui.tsx
  • src/components/calculator-mockups/directory-grid-mockup.tsx
  • src/components/calculator-mockups/guided-flow-mockup.tsx
  • src/components/calculator-mockups/search-page-mockup.tsx
  • src/components/calculators/calculator-ui.tsx
  • src/components/calculators/directory-grid.tsx
  • src/components/calculators/guided-flow.tsx
  • src/components/calculators/search-page.tsx
  • src/components/clinical-dashboard/ClinicalSidebar.tsx
  • src/components/clinical-dashboard/account-setup-dialog.tsx
  • src/components/clinical-dashboard/cross-mode-links.tsx
  • src/components/clinical-dashboard/dashboard-nav.tsx
  • src/components/clinical-dashboard/differentials-home.tsx
  • src/components/clinical-dashboard/document-search-results.tsx
  • src/components/clinical-dashboard/evidence-panels.tsx
  • src/components/clinical-dashboard/favourites-command-library-page.tsx
  • src/components/clinical-dashboard/favourites-hub.tsx
  • src/components/clinical-dashboard/favourites-library-nav.tsx
  • src/components/clinical-dashboard/master-search-header.tsx
  • src/components/clinical-dashboard/settings-dialog.tsx
  • src/components/clinical-dashboard/signed-image.tsx
  • src/components/differentials/diagnosis-map-panel.tsx
  • src/components/differentials/differential-detail-page.tsx
  • src/components/document-phone-fused-directions-mockups.tsx
  • src/components/document-phone-title-mockups.tsx
  • src/components/document-phone-title-refined-mockups.tsx
  • src/components/document-search-mockups.tsx
  • src/components/document-top-navigation-mockups.tsx
  • src/components/document-viewer/document-clinical-summary.tsx
  • src/components/document-viewer/non-pdf-source-preview.tsx
  • src/components/document-viewer/pdf-canvas-viewer.tsx
  • src/components/document-viewer/section-nav.tsx
  • src/components/dsm/dsm-comparison-page.tsx
  • src/components/dsm/dsm-differential-considerations-page.tsx
  • src/components/dsm/dsm-search-page.tsx
  • src/components/factsheets/factsheets-search-page.tsx
  • src/components/favourites-page-mockups/favourites-page-mockup-page.tsx
  • src/components/forms/forms-search-results-page.tsx
  • src/components/formulation/formulation-builder-page.tsx
  • src/components/master-document-flow-mockups.tsx
  • src/components/patient-safety-plan.tsx
  • src/components/phone-mode-sheet-yes-mockups.tsx
  • src/components/privacy-live-signal-perfected-mockups.tsx
  • src/components/pwa-lifecycle.tsx
  • src/components/registry-record-loader.tsx
  • src/components/services/service-detail-page.tsx
  • src/components/services/services-navigator-page.tsx
  • src/components/settings-search-mockups/settings-search-mockup-page.tsx
  • src/components/source-overlay-redesign-mockups.tsx
  • src/components/therapy-compass/bindings.tsx
  • src/components/therapy-compass/controls.ts
  • src/components/therapy-compass/screens/compare-screen.tsx
  • src/components/therapy-compass/screens/detail-screen.tsx
  • src/components/therapy-compass/screens/other-screen.tsx
  • src/components/therapy-compass/screens/recommend-screen.tsx
  • src/components/therapy-compass/screens/sheets-screen.tsx
  • src/components/tools-page-mockups/rectangle-direction-mockups.tsx
  • src/components/tools-page-mockups/split-pane-refined-mockups.tsx
  • src/components/tools-page-mockups/task-directory-mockup.tsx
  • src/components/tools-page-mockups/tools-page-mockup-page.tsx
  • src/components/ui-primitives.tsx
  • src/components/ui/button.tsx
  • src/components/ui/document-frame.tsx
  • src/components/ui/segmented-control.tsx
  • src/components/universal-search-redesign-mockups.tsx
  • src/lib/tailwind-merge.ts
  • tests/design-token-contract.test.ts
  • tests/tailwind-merge-config.test.ts

Comment @coderabbitai help to get the list of available commands.

@supabase

supabaseBot commented Aug 10, 2026

Copy link
Copy Markdown

This pull request has been ignored for the connected project sjrfecxgysukkwxsowpy because there are no changes detected in supabase directory. You can change this behaviour in Project Integrations Settings ↗︎.


Preview Branches by Supabase.
Learn more about Supabase Branching ↗︎.

@BigSimmo
BigSimmo enabled auto-merge (squash) August 10, 2026 13:52
@BigSimmo

Copy link
Copy Markdown
OwnerAuthor

Unblock snapshot (2026-08-10): PR head is now d3f4079. I synced origin/main into this PR (commit d3f4079) to resolve an earlier real merge conflict. Current checks at snapshot: merge-tree clean, mergeable=true, mergeStateStatus=BEHIND, required workflows passing (Gitleaks + PR policy). No required-merge blockers or unresolved blocker threads remain. Required checks are green; pending is only normal behind state vs main while the tip is ahead by one commit from sync. Merge left to you.

@BigSimmo
BigSimmo merged commit 9d8370a into mainAug 10, 2026
26 checks passed
@BigSimmo
BigSimmo deleted the claude/codex-m4b-shadow-tight-migration-53a8kn branch August 10, 2026 14:27
BigSimmo pushed a commit that referenced this pull request Aug 13, 2026
Four merge-safe intake requests, no canonical ledger edit:
- P1 rec: no gate detects a merged PR whose content is silently
reverted by a later merge resolution. Blob sweep over origin/main
found seven such PRs since 2026-08-06, six first wiped at one
commit in the PR #1815 unblock chain. The reverts took each PR's
tests in the same stroke, which is why nothing went red.
- P2 task: re-land PR #1800 (fuzzy catalogue search) with the #310
one-edit cap applied in the same commit.
- P2 task: re-land PR #1803 (--shadow-tight retirement); 67 files on
main still reference the retired alias.
- update #310: re-scoped. The defect is not reachable on main because
the matcher is absent, not because it was fixed, so the row must not
be closed and the fix belongs in the #1800 re-land.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DuYJz8hauCsCdx8r4fXiZU
BigSimmo added a commit that referenced this pull request Aug 14, 2026
…bt rows (#1942)
* refactor(tokens): re-land the --shadow-tight retirement onto --e1
PR #1803 retired the --shadow-tight role alias in favour of the --e1
elevation tier across 49 files and squash-merged as 9d8370a on
2026-08-10. The acf78bf merge on 2026-08-11 silently reverted it, along
with six other PRs. This re-applies the retirement against current main:
130 call sites across 67 files, plus both declarations.
The alias was a pure pass-through -- `--shadow-tight: var(--e1)` in the
light and dark role blocks -- so the substitution is value-preserving.
Confirmed for forced-colors too rather than assumed: the
`@media (forced-colors: active)` block scopes `:root, .dark`, the same
`html` element the alias is declared on, so `--shadow-tight` already
resolved through the flattened `--e1: none` there. The .ckb-v2
redeclaration hazard does not bite for the same reason -- .ckb-v2 sits on
<html> and .ckb-v2.ckb-v2 outspecifies :root, so both spellings
substitute against the winning v2 tier.
Two comments survived acf78bf while the code they describe did not: the
globals.css note that "the resting-hairline role is gone", and the token
test's "unlike the --shadow-tight assertion above". Both are accurate
again.
The token contract test now sweeps the tracked src tree for both
spellings (declaration and var() consumer) instead of only asserting the
declaration. A declaration-only check would have caught this particular
revert, but only because the declarations happened to come back with the
call sites; sweeping both makes the gate independent of which half of a
bad merge lands. Mutation-verified in both directions.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XsBPUoxpsvTwvFMJzrNoyz
* chore(design-system): re-pin the contract ratchets to their measured values
`scripts/design-system-contract-baseline.json` is a ceiling, so paying
debt down leaves silent headroom behind. Ledger #302 records that
pattern: legacyShadowAliases was pinned at 220 against a measured 193,
27 units of unguarded slack, up from 3 units on 2026-08-10.
With the previous commit's --shadow-tight retirement applied the gap is
wider still -- 220 pinned against 119 measured -- because the reland pays
down the debt the acf78bf revert had re-hidden. Four other ratchets had
accumulated slack from unrelated work in the same window.
legacyShadowAliases 220 -> 119
edgeOwnershipConflicts 27 -> 25
rawPaddingLiterals 67 -> 63
rawGapLiterals 34 -> 32
layoutTransitionExceptions 12 -> 11
Regenerated with --print-debt-baseline rather than hand-edited, so the
per-path debtByPath counts move with the totals -- those are what
findDebtPathRegressions compares, and the retirement moved them
wholesale. Every metric in the diff decreases; nothing is absorbed
upward.
This is not the baseline refresh #262 warns against. That stop rule
forbids refreshing to hide the movement; this pins the movement in so it
cannot silently drift back a second time.
Mutation-verified: reintroducing one alias in button.tsx now fails at
both the total (119 -> 120) and the per-path level. Under the old 220
ceiling the same addition passed.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XsBPUoxpsvTwvFMJzrNoyz
* refactor(tokens): hold the search-band count bubble in a spacing token
The active-filter badge sized itself with a raw `h-[1.0625rem]
min-w-[1.0625rem]` pair. Ledger #275 tracks that value as leaked debt:
it had reached five files, so the fix has always been to tokenise once
rather than edit a call site.
Re-measured on merged main, the badge role is down to a single call
site. #170's convergence landed in the meantime -- document-search-
results.tsx now renders the shared control and therapy-compass/
filter-sheet.tsx was deleted outright -- so the leak this row was
written about has already been reabsorbed by the extraction. Holding
the value in @theme is what stops it leaving again.
Two arbitrary values in the same component are deliberately left raw:
pr-[0.6875rem] and min-[414px]:max-[429px] -- the repo defines no
--breakpoint-* tokens at all, and eight peer sites use the same raw
min-[]/max-[] form (359px, 389px, 414px). Naming one window while the
peers stay raw is the same drift #275 warns about on another axis, and
Tailwind named breakpoints would add variants across the whole utility
surface. That belongs in a repo-wide decision, filed separately.
The three remaining 1.0625rem hits in mode-nav.tsx and nav-slot-ink.tsx
are NOT this token. They size <Icon> glyphs -- a 17px icon against a
12/14/16/20/24 --spacing-icon-* scale -- so folding them under a badge
token would merge two roles that only happen to share a number.
check:icon-scale deliberately does not flag arbitrary h-[Nrem], so they
are a real but separate finding, filed rather than guessed at.
The token is also registered in CLINICAL_TWMERGE_THEME.spacing, which
tests/tailwind-merge-config.test.ts asserts against the @theme block --
without it `cn()` cannot resolve a conflict on the new utility. Safe by
that file's own `tap` reasoning: the single call site is a static string
carrying no competing h-*/min-w-* class and never passes through `cn()`,
so there is no same-variant pair for declaration to hand to the later
class. The entry is protective for future use, not load-bearing today.
Value-preserving, and proven rather than inferred: compiling globals.css
through @tailwindcss/postcss emits
.h-search-band-badge { height: var(--spacing-search-band-badge) }
.min-w-search-band-badge { min-width: var(--spacing-search-band-badge) }
No ratchet moved, so the ceilings pinned in the previous commit still sit
at zero slack.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XsBPUoxpsvTwvFMJzrNoyz
* docs(design-system): close out DS Track A3 and refresh the stale gate rows
Track A3 is `#262`. Its three parts are now all settled, each checked
against code rather than against the row that describes it.
Part 1 is the --shadow-tight retirement re-landed earlier in this PR.
Part 3 shipped in PR #1780 per `#301`: rawPaddingLiterals,
rawRadiusLiterals and rawLineHeightLiterals are live baseline keys
enforced over both the class and CSS-declaration spellings, plus
rawGapLiterals beyond the original ask.
Part 2 needs no work, and that had already been adjudicated -- GATES.md
section 3 records it, which is why nothing here builds it. The decidable
half of step selection shipped on 9 Aug inside check:design-system-
contract: a declared @theme step no production surface selects fails the
build. The remaining half -- which existing step a component picks -- is
documented there as something "nothing mechanical can" gate, being a
judgement about the rendered design rather than a property of the source,
with a standing instruction not to duplicate the arbitrary-value check
check:type-scale already ships. Reading `#262` alone would have sent a
session to build it; that is the `#301` failure mode, so the closure
record says so explicitly.
Section 3's live status rows carried numbers this PR moved. `#301`'s
lesson is that a row understating shipped work is a duplicate-work
generator, so they are corrected in the same change:
legacyShadowAliases 224 -> 119, and the alias is now retired
outright rather than "224 left to retire"
edgeOwnershipConflicts 27 -> 25
rawPaddingLiterals 67 -> 63
rawGapLiterals 34 -> 32
layoutTransitionExceptions 12 -> 11
Section 5 is left alone deliberately: it is a dated record measured
against 8db1e53, not a live status surface, and rewriting its figures
would destroy the provenance it exists to hold.
Ledger records are queued as immutable inbox requests: `#262`, `#302` and
`#275` closed; two carve-outs split out of `#275` filed as their own rows
(the repo-wide breakpoint-token decision, and three 17px mode-nav icon
glyphs that sit off the --spacing-icon-* scale with no gate covering
them). The queued re-land request 210e3db5 is cancelled rather than
reconciled -- its headline "67 files on main still use the retired alias"
is false as of this branch, so it would open a row wrong on arrival. The
request file and the cancellation both survive as provenance for the
acf78bf merge loss.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XsBPUoxpsvTwvFMJzrNoyz
* chore(ledger): record the design-token relands review
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XsBPUoxpsvTwvFMJzrNoyz
* fix(issues): retarget the reland record after main reconciled it mid-flight
CI failed `docs:check-links` on this branch with
Error: cancel request 2e791c01... targets missing pending request
210e3db5...
`check-docs-links.mjs` replays the inbox batch to resolve link targets, so
an unresolvable request fails it. The cause was a race, not a bad record:
PR #1936 reconciled 75 queued requests -- 210e3db5 among them -- while
this branch was already in flight. Reconciling moves the request file
into `docs/outstanding-issues-inbox/applied/` and allocates it a canonical
row, so by the time this branch merged main there was no pending request
left for the cancellation to name.
Cancelling was the right call against a pending request and is the wrong
one against a reconciled row. The cancel is dropped and replaced with a
`done` against `#319`, the row 210e3db5 became. That is also the better
record: the work is finished rather than withdrawn, so the ledger should
carry its outcome and its guard, which a cancellation would have thrown
away.
Also merges origin/main (this branch was 3 behind) and files two findings
the PR preflight surfaced, both deliberately not fixed here:
- `check:medication-lexicon-report` has been failing on main for every
local `verify:pr-local`, and no CI job runs it -- a grep over
.github/workflows finds nothing. It is the last step of the local
chain, so it fails preflights while CI stays green. The stale file is
a clinical-facing generated document; regenerating it inside a
CSS-token PR would bundle a clinical-risk artefact with unrelated
chores.
- Claude Code web containers can ship Node 22 with no node_modules,
which fails `npm ci` on engine-strict before any repo script can run.
Re-verified after the merge: the tracked tree still holds zero
`--shadow-tight` references, and every pinned ratchet still measures
exactly its baseline, so the merge moved no metric and the pins stay
honest.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XsBPUoxpsvTwvFMJzrNoyz
* docs(design): retire shadow-tight guidance
* docs(design): retire shadow-tight guidance
* docs(design): retire shadow-tight guidance
* docs(design): retire shadow-tight guidance
---------
Co-authored-by: Claude <noreply@anthropic.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@BigSimmo@claude