feat(design-system): v2 token layer + 26 components — reconciled, cascade-ported, forced-colours owned - #1538
Conversation
Design-system scope only. Nothing is adopted by a product surface: the new components are built and tested but unimported, and the v2 token layer is class-scoped to `.ckb-v2` so importing it cannot repaint any surface that does not opt in. Correctness: - Fix a P1 browser crash. `source-metadata.ts` imported the server logger, whose `activeLevel()` reads `process.env.LOG_LEVEL` — a ReferenceError in a browser, so any off-vocabulary metadata value unmounted the whole React tree instead of falling back. Drops the import, adds a browser-safe diagnostic seam, and guards the env read in `logger.ts` as defence in depth. - Type the three source badges' `metadata` prop. It was `unknown` while the published `.d.ts` promised a shape, so the wrong key compiled cleanly. - Encode the disabled state in `controlBase` instead of `opacity-50`, which dimmed fill and label together and dropped secondary labels below 4.5:1. - Move `fieldLabel` off `--text-soft` (3.07:1) and the uppercase eyebrow treatment. - Delete `ui/card.tsx` and `ui/badge.tsx` — 7 exports, 0 importers, colliding by name with Chip and AnswerCard. Components (built, not adopted): Button, TextField, SearchField, Chip, Toast, Tabs, Tooltip, Pagination, ConfirmDialog, PageHeader, Breadcrumb, AnswerCard, DoseLine, AnswerFooter, Quantity, StatusMark, Citation, the four Link variants, Select, Checkbox, RadioGroup, Disclosure, Progress, StageList. AccessibleTable: per-column numeric alignment, `aria-controls` on the expander, sticky header when expanded, and an explicit unverified-extraction treatment. Verification: tsc pass, lint pass, prettier clean, verify:ui 344 passed, design-system contract pass. Unit 4689 passed / 1 failed / 3 skipped — the failure is `installed-lock-parity`, environmental (brace-expansion 1.1.16 vs lockfile 1.1.18), tracked as issue #149. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…all-through, leading step
C1 reconciliation per docs/design-system/TOKENS.md - the design-side token file
proved unrecoverable (design project 08d6f126 was last updated 2026-07-13; the
31 July copy was never written to it), so the repo file becomes the canonical
reconciled copy:
- Rename the two v2 --shadow-inset overrides to --shadow-well (recessed-well
role). The DS bevel --shadow-inset is inherited from globals.css again,
restoring the bevel highlight to its ~40 consumers.
- Update the token contract test in the same commit: pin --shadow-well as a
true inset and assert --shadow-inset is not redeclared in the v2 layer.
- Author the evidence-spine and status-mark role families repo-side, derived
from existing roles (spine from rule/accent/warning, status-mark from the
gutter dot and StatusMark's previously-inline stroke). Confidence-meter is
deliberately absent: no call site exists yet.
- Add --clinical-chat-document to the v2 dark block so it resolves against the
v2 dark inset; custom properties inherit computed values, so the live .dark
declaration cannot re-resolve inside the subtree.
- answer-card.tsx: use the named leading-prose step instead of the arbitrary
leading-[var(--leading-prose,1.65)], which tripped the design-token contract
('has no arbitrary leading-[...] left in production') and restated a token
value in markup.
Verified: vitest tests/ckb-v2-token-contract.test.ts tests/design-token-contract.test.ts
-> 47 passed (47). No adopted surface exists, so there is no visual change.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…st, AsyncButton type Playbook PR 1+2 and the smallest slices of PR 3+4 (docs/design-system/SPEC.md §13): - Cascade: light is the default on .ckb-v2 itself; dark overrides via .dark .ckb-v2, .ckb-v2.dark. Never :not(.dark) (DS-01) - it matched a subtree inside html.dark and overrode inherited dark values. Contract test's block parser updated in the same commit (collects both .ckb-v2 blocks and the grouped dark selector). - Forced colours: v2 layer ships its own forced-colors block over all three selectors, last in file (C4/DS-02); roles map to system colours, elevation flattens to none. - Button.danger pairs --danger-solid-contrast (DS-03; dark was 2.87:1, the paired token is 6.57:1 and HCM-mapped). - AsyncButton defaults type=button so it can no longer submit a surrounding form (DS-04 adjacent; retirement to Button remains PR 4). Verified: vitest ckb-v2-token-contract + design-token-contract + ui-v2-components.dom + ui-primitives.dom -> 67 passed (67). No adopted surface exists; no visual change ships. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…sign-system-333a69 # Conflicts: # tests/source-metadata.test.ts
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
This pull request has been ignored for the connected project Preview Branches by Supabase. |
🔒 Upgrade RequiredPrivate repository analysis requires Pro or Enterprise. Upgrade: https://ecc.tools/pricing?plan=pro ECC Tools keeps the core app open, and puts private repos, team features, and enterprise controls behind paid tiers. |
|
Warning Review limit reachedYou’ve reached a temporary PR review limit under our Fair Usage Limits Policy. Next review available in: 17 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 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 configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (57)
Comment |
PR Summary by Qodofeat(design-system): v2 opt-in token layer + 26 components, forced-colours support
AI Description
Diagram
High-Level Assessment
Files changed (57)
|
|
@cursoragent Unblock the current open PR. Confirm the PR number and GitHub head first from context. If more than one open PR could apply, stop and say which one you would use and why. Fetch and start from the remote tip that matches that GitHub head. If the named branch ref is missing or stale, use the PR head ref. Preserve unrelated local WIP; do not discard dirty work; do not treat a local-ahead commit as the reviewed tip. Do not merge the PR, force-push, rebase, or arm auto-merge. No provider-backed gates without approval. If you cannot push or resolve threads, diagnose and comment only; if inline replies fail, resolve when possible and put blocker dispositions in the summary comment. If auto-merge is already armed, push only for a real blocker and avoid cancelling in-flight required CI unless the push clears that blocker. If the PR is already merged or closed: confirm outcome, post one summary, and stop. Primary job: clear mergeability and required-CI blockers on this tip. Do a full product review only if needed to explain or fix a blocker. Stay light otherwise—no broad verification suites or Playwright unless needed to prove one concrete unblock fix. Snapshot the GitHub head: tip, behind/ahead, mergeable state, merge-tree versus origin/main (real conflict versus behind-but-clean), required checks on that tip including Production UI when selected, and unresolved threads that block merge or required CI. Missing checks while dirty are not green. Tip moved → re-snapshot. Ledger-lookup against that GitHub head under an unblock/fix scope for this PR. If already handled at this head for unblock work, merge-tree clean, required checks green, and no blocking threads: summarize, comment, stop. Unblock once: real conflict → merge origin/main with the smallest correct resolution (prefer main’s shared queues; keep this PR’s notes); behind-but-clean → one sync, late if required CI is in flight; clean → leave. skip-branch-sync and similar labels do not block a manual sync needed to clear a real blocker. No sync thrash. After any sync or push, re-snapshot tip, merge-tree, and required checks before declaring done. Dedupe the ledger if a merge touched it. Fix only what blocks required checks or mergeability on this tip. Ignore advisory red unless it reveals a real required failure. Prefer the smallest safe fix; if a bot/autofix commit caused the break, prefer revert. Prove with the smallest targeted check only. Format and commit before push. Push only blocker-fix commits. Append ledger for the final GitHub head under the unblock scope. Never push a ledger-only tip. One PR comment: tip, sync/merge-tree, what blocked and what you fixed or dispositioned, required CI status, residual risks; merge left to me. Stop when merge-tree is clean on the current GitHub tip, no blocking threads remain for merge/required CI, and required checks are green or clearly in progress. |
…sign-system-333a69 Bring in docs/design-system perfection pass (#1537). Merge-tree was clean. Co-authored-by: BigSimmo <BigSimmo@users.noreply.github.com>
Static PR checks failed on the type-scale guard: DoseLine used text-[0.8125rem], which is exactly --text-sm-minus. Replace with the named step so the zero-arbitrary gate stays green. Co-authored-by: BigSimmo <BigSimmo@users.noreply.github.com>
🔒 Upgrade RequiredPrivate repository analysis requires Pro or Enterprise. Upgrade: https://ecc.tools/pricing?plan=pro ECC Tools keeps the core app open, and puts private repos, team features, and enterprise controls behind paid tiers. |
Code Review by Qodo
1. design-sync previews have inert buttons
|
|
@cursoragent Unblock the current open PR. Confirm the PR number and GitHub head first from context. If more than one open PR could apply, stop and say which one you would use and why. Fetch and start from the remote tip that matches that GitHub head. If the named branch ref is missing or stale, use the PR head ref. Preserve unrelated local WIP; do not discard dirty work; do not treat a local-ahead commit as the reviewed tip. Do not merge the PR, force-push, rebase, or arm auto-merge. No provider-backed gates without approval. If you cannot push or resolve threads, diagnose and comment only; if inline replies fail, resolve when possible and put blocker dispositions in the summary comment. If auto-merge is already armed, push only for a real blocker and avoid cancelling in-flight required CI unless the push clears that blocker. If the PR is already merged or closed: confirm outcome, post one summary, and stop. Primary job: clear mergeability and required-CI blockers on this tip. Do a full product review only if needed to explain or fix a blocker. Stay light otherwise—no broad verification suites or Playwright unless needed to prove one concrete unblock fix. Snapshot the GitHub head: tip, behind/ahead, mergeable state, merge-tree versus origin/main (real conflict versus behind-but-clean), required checks on that tip including Production UI when selected, and unresolved threads that block merge or required CI. Missing checks while dirty are not green. Tip moved → re-snapshot. Ledger-lookup against that GitHub head under an unblock/fix scope for this PR. If already handled at this head for unblock work, merge-tree clean, required checks green, and no blocking threads: summarize, comment, stop. Unblock once: real conflict → merge origin/main with the smallest correct resolution (prefer main’s shared queues; keep this PR’s notes); behind-but-clean → one sync, late if required CI is in flight; clean → leave. skip-branch-sync and similar labels do not block a manual sync needed to clear a real blocker. No sync thrash. After any sync or push, re-snapshot tip, merge-tree, and required checks before declaring done. Dedupe the ledger if a merge touched it. Fix only what blocks required checks or mergeability on this tip. Ignore advisory red unless it reveals a real required failure. Prefer the smallest safe fix; if a bot/autofix commit caused the break, prefer revert. Prove with the smallest targeted check only. Format and commit before push. Push only blocker-fix commits. Append ledger for the final GitHub head under the unblock scope. Never push a ledger-only tip. One PR comment: tip, sync/merge-tree, what blocked and what you fixed or dispositioned, required CI status, residual risks; merge left to me. Stop when merge-tree is clean on the current GitHub tip, no blocking threads remain for merge/required CI, and required checks are green or clearly in progress. Assess comments and only fix if you agree |
|
PR #1538 at
Comment calls (no code changes):
Merge left to you when Production UI shards finish. |
|
@cursoragent Unblock the current open PR. Confirm the PR number and GitHub head first from context. If more than one open PR could apply, stop and say which one you would use and why. Fetch and start from the remote tip that matches that GitHub head. If the named branch ref is missing or stale, use the PR head ref. Preserve unrelated local WIP; do not discard dirty work; do not treat a local-ahead commit as the reviewed tip. Do not merge the PR, force-push, rebase, or arm auto-merge. No provider-backed gates without approval. If you cannot push or resolve threads, diagnose and comment only; if inline replies fail, resolve when possible and put blocker dispositions in the summary comment. If auto-merge is already armed, push only for a real blocker and avoid cancelling in-flight required CI unless the push clears that blocker. If the PR is already merged or closed: confirm outcome, post one summary, and stop. Primary job: clear mergeability and required-CI blockers on this tip. Do a full product review only if needed to explain or fix a blocker. Stay light otherwise—no broad verification suites or Playwright unless needed to prove one concrete unblock fix. Snapshot the GitHub head: tip, behind/ahead, mergeable state, merge-tree versus origin/main (real conflict versus behind-but-clean), required checks on that tip including Production UI when selected, and unresolved threads that block merge or required CI. Missing checks while dirty are not green. Tip moved → re-snapshot. Ledger-lookup against that GitHub head under an unblock/fix scope for this PR. If already handled at this head for unblock work, merge-tree clean, required checks green, and no blocking threads: summarize, comment, stop. Unblock once: real conflict → merge origin/main with the smallest correct resolution (prefer main’s shared queues; keep this PR’s notes); behind-but-clean → one sync, late if required CI is in flight; clean → leave. skip-branch-sync and similar labels do not block a manual sync needed to clear a real blocker. No sync thrash. After any sync or push, re-snapshot tip, merge-tree, and required checks before declaring done. Dedupe the ledger if a merge touched it. Fix only what blocks required checks or mergeability on this tip. Ignore advisory red unless it reveals a real required failure. Prefer the smallest safe fix; if a bot/autofix commit caused the break, prefer revert. Prove with the smallest targeted check only. Format and commit before push. Push only blocker-fix commits. Append ledger for the final GitHub head under the unblock scope. Never push a ledger-only tip. One PR comment: tip, sync/merge-tree, what blocked and what you fixed or dispositioned, required CI status, residual risks; merge left to me. Stop when merge-tree is clean on the current GitHub tip, no blocking threads remain for merge/required CI, and required checks are green or clearly in progress. |
|
PR #1538 at
No push. Merge left to you. |
- Checkbox Check icon: aria-hidden="true" (decorative; label is the name) - StageList gutter: z-[1] → z-5 (z-index ladder) Co-authored-by: BigSimmo <BigSimmo@users.noreply.github.com>
🔒 Upgrade RequiredPrivate repository analysis requires Pro or Enterprise. Upgrade: https://ecc.tools/pricing?plan=pro ECC Tools keeps the core app open, and puts private repos, team features, and enterprise controls behind paid tiers. |
🔒 Upgrade RequiredPrivate repository analysis requires Pro or Enterprise. Upgrade: https://ecc.tools/pricing?plan=pro ECC Tools keeps the core app open, and puts private repos, team features, and enterprise controls behind paid tiers. |
Unblock summary — PR #1538Tip: What blocked
What I fixed
Threads dispositioned (no code change)
Required CI on this tip
Residual risks
Merge left to you. |
Unblock re-check — PR #1538 (stop)Tip: Required CI on tip
No required-CI or mergeability blocker on this tip. No push (would only cancel in-flight Production UI). Comment assessment (fix only if I agree + would block)
Residual
Merge left to you once Production UI shards finish. |
Unblock status — PR #1538 (no action)Tip: Required CI on this tip
Threads0 unresolved (Sentry Tooltip + 3 Qodo advisories previously dispositioned no-change). Note on stale failure contextThe lint failure reported against No push (would cancel in-flight Production UI with no remaining required blocker). Merge left to you. |
…hygiene PR) (#1541) * fix(design-system): critique fixes — fallback literals, test precision, HCM backdrop, allowlist - Strip literal var() fallback values from the v2 components (20 sites, 5 files) - the last value-restatement channel. The one surviving fallback is role-to-role (var(--e2, var(--shadow-soft))), which restates no value. - Contract test parses the structural and light .ckb-v2 blocks separately, so a token declared in the wrong block now fails instead of passing merged. - Forced-colours --overlay-backdrop is transparent, not opaque Canvas - HCM users rely on borders for layer separation. - Remove the six docs-link allowlist entries whose files landed with #1538, per their own remove-after-merge note. Verified: vitest 5 files -> 70 passed (70); docs:check-links 1517 resolve. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs(design-system): post-merge truth sweep - rolling status, dark-declaration rule SHAs now pinned only in DECISIONS' resolution log; SPEC/TOKENS/GATES/README state rolling status (merged via #1538). Playbook rows PR 1/2 done, PR 3/4 partial. TOKENS fall-through section replaced with the standing rule: a colour role added to the light block is added to the dark block in the same commit (ink contract-enforced). Resolution log gains the dark-ink bug record and this hygiene pass. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(design-system): close DoseLine calc() and playbook status drift Sentry Bugbot correctly flagged DoseLine's left-padding arbitrary value: pl-[calc(...)] was missing the calc() closer, so browsers dropped the declaration and dose text could sit under the inset rule. Also finish the truth-sweep playbook rows this PR claimed: PR 1 done (#1538), PR 2 partial (HCM block landed; computed assertions still open). Co-Authored-By: Cursor <cursoragent@cursor.com> Co-authored-by: BigSimmo <BigSimmo@users.noreply.github.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: BigSimmo <BigSimmo@users.noreply.github.com>


Summary
claude/clinical-kb-design-system-333a69): opt-in.ckb-v2token layer (src/app/ckb-v2-tokens.css, the canonical single token file per docs/design-system/TOKENS.md), 26 components undersrc/components/ui/, previews, and contract tests. Nothing is adopted by any product surface — zero visual change ships.59e4c3dfc):--shadow-wellrole, evidence-spine + status-mark families, dark--clinical-chat-documentfix,answer-cardnamedleading-prosestep..ckb-v2, dark via.dark .ckb-v2, .ckb-v2.dark, never:not(.dark)), the v2forced-colorsblock over all three selectors (elevation flattened, system-colour mapping),Button.dangerpaired with--danger-solid-contrast,AsyncButtondefaultstype="button". Contract test's block parser updated in the same commit.origin/main(one conflict,tests/source-metadata.test.ts, resolved keeping both sides' tests: main's optional-normalization test + the branch's browser-safe diagnostics-seam trace test).RAG impact: no retrieval behaviour change — design-system layer and components only; no file under
src/lib/rag/**, clinical-search, retrieval-selection, ranking, eval harness, golden fixtures, or retrieval RPCs is touched.Verification
vitesttoken + component contracts after the cascade/HCM/danger changes — 67 passed (67); after the main merge,source-metadata+ both token contracts — 74 passed (74).tscpass · lint pass · unit 4 689/1 (environmental#149)/3 ·verify:ui344 passed · design-system contract pass (625 files).verify:pr-local— deferred to this PR's CI (multi-worktree box, contention false-reds); typecheck of the merged union runs in CI.Risk and rollout
class="ckb-v2"(none exist).Clinical Governance Preflight
Clinical KB Database(sjrfecxgysukkwxsowpy)Notes
disabled:opacitysites), PR 4 unions, PR 5b/5c value changes, PR 6–13. Each stays its own tranche.🤖 Generated with Claude Code