Skip to content

fix(design-system): narrow the theme.ts raw-color exemption to APP_THEME_COLORS - #1070

Merged
BigSimmo merged 4 commits into
mainfrom
claude/theme-exemption-narrowing-123366
Jul 22, 2026
Merged

fix(design-system): narrow the theme.ts raw-color exemption to APP_THEME_COLORS#1070
BigSimmo merged 4 commits into
mainfrom
claude/theme-exemption-narrowing-123366

Conversation

@BigSimmo

@BigSimmo BigSimmo commented Jul 22, 2026

Copy link
Copy Markdown
Owner

Summary

Narrows the src/lib/theme.ts raw-colour exemption from whole-file to the APP_THEME_COLORS declaration, closing a hole that shipped in #1059.

An automated reviewer raised this as a P2 on #1059 and it is correct: the exemption I added there blanked the entire file before counting, so any unrelated raw colour added to theme.ts later would have escaped the ratcheting contract — in a file whose baseline had just been ratcheted down to 2. Only the two pre-paint literals are genuinely un-tokenisable (they are read by the inline pre-hydration script and the theme-color meta tag before any CSS, and therefore any token, exists).

This follows the exemption pattern the repo already uses for the two printable-paper scopes: a bounded range plus fail-closed behaviour.

  • scope: "app-theme-colors" masks only the APP_THEME_COLORS block via the existing balancedBlockRange helper.
  • Anchored on export const APP_THEME_COLORS, not the bare identifier, so the later APP_THEME_COLORS.dark / .light references inside THEME_BOOTSTRAP_SCRIPT can never be mistaken for the boundary.
  • Fail-closed: if the declaration is renamed or removed, reportFailure fires (wired to assert(false, …)process.exit(1)) and the source is returned unmasked, so the two literals get counted and the ratcheted baseline goes red loudly rather than the file being silently exempted.

Verification

Proof the hole was real and is now closed — appending export const SNEAKY_ACCENT = "#0f766e"; to the real src/lib/theme.ts:

Exemption scope Gate result
whole-file (as merged in #1059) passesraw colors 2, the new colour is invisible
app-theme-colors (this PR) failsrawColorLiterals increased from 2 to 3
  • npm run check:design-system-contract on a clean tree — passes with identical counts (raw colors 2; literal shadows 1; legacy tap classes 0), confirming the narrowing masks exactly the two exempted literals and nothing else was being hidden
  • tests/design-system-contract-utils.test.ts5/5 pass, including two new cases: an unrelated #0f766e elsewhere in a theme.ts fixture stays countable while #ffffff/#060708 are masked, and a renamed constant triggers the fail-closed path
  • npm run typecheck, eslint, prettier --check .
  • UI verification not run: build-time guardrail script and its unit test only; no application code, styling, or rendered output is touched.

Risk and rollout

  • Risk: low, and strictly in the safe direction — the change can only make the contract count more, never fewer, raw colours. Worst case is a loud CI failure, never a silent exemption.
  • Rollback: revert this commit; the exemption returns to whole-file and the gate keeps passing.
  • Provider or production effects: none. Verification was fully offline; no provider calls.

Clinical Governance Preflight

(Build-time design-system guardrail only; no runtime, clinical, or data path is touched.)

  • 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 — CI guardrail only, no clinical decision-support behaviour change

RAG impact: no retrieval behaviour change — design-system contract script and its unit test only; no retrieval, ranking, or answer-generation surface is touched.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes

    • Improved design-system color validation by narrowing the pre-paint theme-color exemption scope to app-theme-colors.
    • Color checks now properly exclude only the intended APP_THEME_COLORS declaration, without swallowing unrelated raw colors.
    • Validation now fails clearly when the expected theme-color boundary is missing.
  • Tests

    • Added Vitest coverage for precise masking behavior and “fail closed” handling when boundaries are absent.
  • Documentation

    • Updated the “Tokens only” rule to clarify sanctioned raw-color exceptions and boundary requirements.

…EME_COLORS

The exemption added in #1059 used scope "whole-file", so the entire file was
blanked before counting and any unrelated raw colour added to theme.ts later
would have escaped the contract — in a file whose baseline had just been
ratcheted down to 2. An automated reviewer raised this as a P2 on that PR and
was right; the fix never landed, so #1059 merged with the hole open.

Only the two pre-paint literals are un-tokenisable (read by the inline
pre-hydration script and the theme-color meta tag before any CSS, and
therefore any token, exists). Scope the exemption to the APP_THEME_COLORS
declaration using the bounded-range pattern the printable-paper scopes
already use, anchored on "export const APP_THEME_COLORS" so the later
APP_THEME_COLORS.dark/.light references inside THEME_BOOTSTRAP_SCRIPT can
never be mistaken for the boundary.

Fail-closed: a renamed or removed declaration reports a failure (wired to
assert(false, ...) -> exit 1) and returns the source UNMASKED, so the two
literals are counted and the ratcheted baseline goes red loudly rather than
the file being silently exempted.

Verified by injecting `export const SNEAKY_ACCENT = "#0f766e";` into the real
src/lib/theme.ts: with "whole-file" the gate passes reporting "raw colors 2"
and the colour is invisible; with this change it fails with "rawColorLiterals
increased from 2 to 3". Clean-tree counts are unchanged (2/1/0), confirming
the narrowing masks exactly the two exempted literals.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@supabase

supabase Bot commented Jul 22, 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 ↗︎.

@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 700fae2f-df21-41e1-8077-b5df2cad08c4

📥 Commits

Reviewing files that changed from the base of the PR and between d1a17a4 and 75a838f.

📒 Files selected for processing (2)
  • docs/design-system.md
  • tests/design-system-contract-utils.test.ts

📝 Walkthrough

Walkthrough

The raw-color contract utility now exempts only the APP_THEME_COLORS declaration in src/lib/theme.ts, masks that bounded range, and fails closed when the boundary is missing. Tests and documentation cover selective masking, scoped exceptions, and failure reporting.

Changes

Theme color masking

Layer / File(s) Summary
Scoped masking contract
scripts/design-system-contract-utils.mjs, tests/design-system-contract-utils.test.ts
The pre-paint theme-color exemption uses the app-theme-colors scope; rawColorContractSource masks the bounded declaration, preserves unrelated colors, and reports a specific failure when its boundary is absent.
Exception policy documentation
docs/design-system.md
The documented raw-color exception policy now requires scoped allowlist entries, bounded boundaries where possible, and fail-closed handling for missing boundaries.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

Suggested reviewers: claude

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title concisely describes the main change: narrowing the theme.ts raw-color exemption to APP_THEME_COLORS.
Description check ✅ Passed The description covers Summary, Verification, Risk and rollout, and Clinical Governance Preflight with concrete details.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/theme-exemption-narrowing-123366

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@scripts/design-system-contract-utils.mjs`:
- Around line 185-194: Update the app-theme-colors handling in
balancedBlockRange to locate APP_THEME_COLORS as an exact declaration token,
excluding comments, strings, and suffixed names such as APP_THEME_COLORS_V2, so
renamed declarations trigger reportFailure. Add a regression case covering the
suffixed declaration.
🪄 Autofix (Beta)

✅ Autofix completed


ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 6e742ea2-8c62-4abd-9808-d4e60c578d8b

📥 Commits

Reviewing files that changed from the base of the PR and between ee0c018 and d1a17a4.

📒 Files selected for processing (2)
  • scripts/design-system-contract-utils.mjs
  • tests/design-system-contract-utils.test.ts

Comment thread scripts/design-system-contract-utils.mjs
…ect the docs

Adversarial review of the previous commit found that the anchoring property
its own code comment claims — that the marker is the declaration keyword so a
later *reference* cannot be mistaken for the boundary — was caught by none of
the new assertions. Mutating the marker to a bare "APP_THEME_COLORS" left the
whole file green, and the property is load-bearing: with a bare marker, a doc
comment naming the constant above an unrelated raw colour anchors the mask on
that mention and silently swallows the colour with no failure reported
(masking runs before comments are stripped, so comment-stripping cannot
rescue it). Add that exact fixture as a regression test; it goes red under the
bare-marker mutation and green as shipped.

Also correct docs/design-system.md, which enumerated 6 of the 8 sanctioned
raw-colour categories (omitting the globals.css token definitions and the
pre-paint theme colours) and credited check-design-system-contract.mjs with
owning the path allowlist, which actually lives in RAW_COLOR_EXEMPTIONS in
design-system-contract-utils.mjs. Records the bounded-scope-over-whole-file
preference this change embodies.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 75a838f21a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread scripts/design-system-contract-utils.mjs
@BigSimmo
BigSimmo enabled auto-merge (squash) July 22, 2026 06:35
@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Note

Autofix is a beta feature. Expect some limitations and changes as we gather feedback and continue to improve it.

⚠️ Branch updated during autofix.

The branch was updated while autofix was in progress. Please try again.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8ea91aa7b0

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread scripts/design-system-contract-utils.mjs
@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Note

Autofix is a beta feature. Expect some limitations and changes as we gather feedback and continue to improve it.

Fixes Applied Successfully

Fixed 2 file(s) based on 1 unresolved review comment.

Files modified:

  • scripts/design-system-contract-utils.mjs
  • tests/design-system-contract-utils.test.ts

Commit: 760e60fcbfdc227fac2f34e88c1649baf96ad87d

The changes have been pushed to the claude/theme-exemption-narrowing-123366 branch.

Time taken: 5m 38s

Fixed 2 file(s) based on 1 unresolved review comment.

Co-authored-by: CodeRabbit <noreply@coderabbit.ai>
@BigSimmo
BigSimmo merged commit 4d5c76c into main Jul 22, 2026
41 checks passed
@BigSimmo
BigSimmo deleted the claude/theme-exemption-narrowing-123366 branch July 22, 2026 07:02
Sign up for free to 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.

1 participant