issues: close #PM9SP1 with the full over-claim outcome, file the mode-home footer contradiction, record measured bundle drift - #2503
Conversation
… pin design-system figures and token drift The app told users four times that it was clinical decision support while its own privacy page says the opposite. Two design-system documents had also drifted far enough from the code to mislead, and one silent trap had no gate at all. Clinical copy (the reason this change exists) - Differentials (3 sites) and Specifiers (1) said "Clinical decision support only" / "Use this as structured decision support". The privacy page and CLAUDE.md both scope this product as "a clinical reference prototype, not validated clinical decision support", and the PR preflight carries a device-classification item, so the clinical surfaces were the ones out of step. - All four now read "Clinical reference - not validated decision support", the wording already recorded as the clinical-owner copy decision on #PM9SP1. - The fifth site was the copied/exported differential text in src/lib/differential-detail.ts, which carried the same claim into anything a clinician pastes elsewhere. Its pinned assertion moved with it. - Therapy Compass was already correct and is untouched. New gate: token-layer divergence (scripts/token-layer-divergences.mjs) layout.tsx mounts .ckb-v2 on <html>, so .ckb-v2.ckb-v2 (0,2,0) beats :root (0,1,0) and for any role both stylesheets declare the v2 value paints while the globals.css one is dead - editing it changes nothing, with no lint, type or screenshot signal. 53 roles are in that state today (29 light, 24 dark). The v2 migration is deliberate and unfinished, so divergence is pinned rather than banned: docs/design-system/token-layer-divergences.json is the reviewed set, and a role that starts diverging OR stops diverging fails. The comparison covers globals' @theme block as well as :root, which is where the structural roles live. Wired into the existing check:design-system-contract, so no gate-manifest change was needed. Mutation-verified both directions. New gate: GATES.md figures are generated (scripts/generate-gates-figures.mjs) GATES.md carried the same metric as three different hand-typed values in three sections. Measured against the baseline: interactiveTapFloorDeclarations appeared as 9, 32 and 2 (true value 2); rawMarginLiterals as 74 and 53 (34); legacyShadowAliases as 231, 224 and 87 (34). Nearly every figure overstated remaining debt, which costs a session in exactly the way the document's own section 5 warns about. A generated section 0 is now the single current count, with the prose figures in sections 2, 4 and 5 explicitly marked as the historical record. Comparison is normalised cell-wise so Prettier's table padding cannot report false drift. Mutation-verified both directions. Breakpoint tokens: reconciled toward the code, not away from it GATES.md 3b banned --breakpoint-* tokens; globals.css has five, added four days after that decision. The obvious fix - delete the three device-band names, which have zero product call sites - was attempted and reverted in the same session: MIN_WIDTH_BREAKPOINT_BANDS in design-system-contract-utils.mjs hard-codes them as same-threshold aliases of sm/md/lg, and they are the only fixtures exercising the tap-floor gate's alias-collision path. "Nothing imports it" was necessary and nowhere near sufficient, exactly as AGENTS.md warns. All five stay, with the real reason recorded in both the stylesheet and 3b, and the wrong "(Task #336)" attribution removed. AGENTS.md bundle-budget route list Documented five budgeted routes; the config has two. The config is right: /therapy-compass, /dsm and /forms became redirect stubs rendering the same shared home as /, so budgeting them measured / three more times (see tests/check-lighthouse-budget.test.ts, COMMITTED_ROUTES). Corrected the document and recorded why, so the next reader does not "fix" the config back. Also: indexed the one mockup route missing from mockups/README.md (answer-loading-redesign), taking that index to 79 of 79. Verification npm run verify:cheap exit 0. Full unit suite 934 files / 11,771 tests passed, 1 skipped, 0 failures. lint and typecheck clean. Clean-build bundle check passed (production 1742.1 KiB gzip, / at 240.0 KiB); it reports a +5.2% drift warning against a baseline commit that no longer resolves, which is pre-existing and tracked as #QSHHGK, not caused here. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015uQ7pGjA4hBxi9TRNsfjAL
…app-review-sxd0mm # Conflicts: # data/outstanding-issues-snapshot.json # data/repo-awareness-snapshot.json
Resolve conflicts: - data/outstanding-issues-snapshot.json: keep main (superset pending incl. privacy inbox items) - data/repo-awareness-snapshot.json: keep main (includes docs landed on main) - package.json: keep main deps/engines; take PR design-system gate scripts
Codex P2: reject hand-edited/merge-skewed counts when divergences are unchanged.
…les in the new token-divergence gate Two independent audits ran against the previous commit. Both found real defects, and both are fixed here. Clinical over-claim sweep — two more surfaces The earlier fix found its sites by grepping one phrase. A sweep for the whole class found two it missed, both on the medication/prescribing surface, which is the highest-consequence screen in the app: - `patient-profile-panel.tsx` (rendered by the prescribing workspace, the medication record page, and the patient-details dock) said "Decision support, not medical advice" under the panel where a clinician enters renal/hepatic function, allergies and a current medication list to get a per-patient interaction verdict. This asserted the feature IS decision support — worse than the five sites already corrected, which merely said "not ... decision support". - `medication-record-page.tsx`'s standing footer claimed PsychSift "provides evidence summaries", an authority claim the product does not make anywhere else, and disclaimed with a generic "not medical advice" rather than the house governance phrasing every comparable mode uses. Both now match the wording used on the other surfaces. Production is clean: the only remaining "decision support" strings in src are the document-intent taxonomy (classifying UPLOADED guideline documents, not the app's own voice) and the privacy page's own boundary statement. Token-divergence gate — four holes, three of them live An adversarial review of the gate added in the previous commit demonstrated four false passes. The parser has been rewritten: 1. **Forced colours was unmonitored.** Both stylesheets declare a third theme in `@media (forced-colors: active)`, and the same specificity trap applies there. Editing a real Windows High Contrast value produced no complaint. Three roles are genuinely diverging in it today and are now pinned: `--clinical-accent-border`, `--overlay-backdrop`, `--text-soft`. 2. **Indentation-sensitive parsing.** The old regex required exactly two leading spaces, so re-indenting a declaration — no rendered effect — dropped it from the comparison, and the tool then reported the divergence as RESOLVED. Acting on that advice removed a still-dead token from tracking and left the gate green. Parsing is now indentation-insensitive. 3. **`var()` aliases were never resolved.** Two layers can declare identical alias text and still paint different colours when the alias itself diverges: dark `--clinical-chat-document` is `var(--surface-inset)` on both sides while `--surface-inset` differs. Values are now resolved within their own layer before comparison, which also removes three false FAILS where different text resolved to the same value (dark `--text`, `--text-heading`, `--clinical-accent-soft`). 4. **Ambiguous markers in GATES.md** silently retargeted both the comparison and the `--write` overwrite at the wrong slice. Now a hard error. Block extraction uses real brace matching instead of slicing to the next line-initial `}`, so an `@media` wrapper is context rather than a terminator, and comments are stripped before selectors are read. An empty result for any theme is a hard error, never a quiet pass. Counts move from light 29 / dark 24 to light 29 / dark 22 / forcedColors 3 — the dark drop is the three false fails above, the forced-colours three are newly visible real divergences. One review claim was checked and NOT adopted: the review reported forced-colours `--border`/`--border-strong`/`--border-lux` as diverging. globals.css declares them twice in that media context and the later value already matches v2, so they are not divergent; the manual diff had only read the first block. Verification Full unit suite 937 files / 11,796 tests passed, 1 skipped, 0 failures. lint, typecheck and the design-system contract chain all clean. Each of the four holes was re-attacked against the hardened code: the forced-colours edit and the duplicated marker now fail as they should, and the re-indented declaration is proven still tracked rather than silently dropped. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015uQ7pGjA4hBxi9TRNsfjAL
…sxd0mm' into claude/design-system-app-review-sxd0mm # Conflicts: # data/outstanding-issues-snapshot.json # data/repo-awareness-snapshot.json
…app-review-sxd0mm # Conflicts: # docs/design-system/token-layer-divergences.json # scripts/generate-gates-figures.mjs # scripts/token-layer-divergences.mjs
Resolve dirty/behind after #2498: keep main regenerated snapshots and deps; overlay PR intentional clinical copy + token-divergence gate hardening.
…base theme comparison Codex P2 on #2499, verified and confirmed. `collect()` filtered only on `forced-colors`, so every OTHER `@media` block was admitted into the unconditional theme map and its override replaced the base declaration. Comparing a narrow-viewport override against an unconditional v2 declaration compares two different contexts, and it reports "identical" for a pair that diverges everywhere the condition does not apply. Proven on real data, not argued: before this change the light compat map held `--mode-home-copy-reserve` as the `(min-width: 412px)` override (`calc(var(--text-hero) * …)`) rather than its unconditional declaration at globals.css:1240 (`calc(2 * var(--text-hero) * …)`). globals.css has three such `:root` blocks today — `--mode-home-copy-reserve` twice and `--spacing-mode-home-composer-wide` once. Reproduced as a false pass with the synthetic wide-viewport case the review asked for: base compat `--radius-md: 0.7rem`, an override at `(min-width: 9999px)` matching v2's `0.625rem`, v2 unconditionally `0.625rem`. The old predicate reported no divergence; the new one flags it. Latent rather than live today only because the v2 layer declares none of the three affected names. Base themes now take unconditional blocks only. Conditional non-forced-colors blocks are excluded rather than merged, which is the conservative direction: a token declared only under such a condition goes uncompared instead of being compared wrongly. Forced colours remains its own theme — it is a condition, and it is modelled as one rather than treated as base. Also fixes the return typing of `readLayers`, which inferred `{}` and broke `npm run typecheck` for the new test's consumers. Verification Full unit suite 937 files / 11,798 tests passed, 1 skipped, 0 failures. lint, typecheck and the design-system contract chain clean; pin unchanged at light 29 / dark 22 / forcedColors 3, confirming this was latent. The new regression test is mutation-verified: restoring the old predicate fails it, and it asserts against the real stylesheet rather than a fixture, so it tracks the file as it changes. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015uQ7pGjA4hBxi9TRNsfjAL
…sxd0mm' into claude/design-system-app-review-sxd0mm
… measured bundle drift on #QSHHGK - done #PM9SP1: the decision-support over-claim is fixed at seven sites across PRs #2497 and #2499, two of them (the prescribing patient-profile panel and the medication record footer) not named in the original row and worse than those that were. Production verified clean. - add: the row's second clause, 'mount the footer on the other mode homes', contradicts a recorded decision at mode-home-template.tsx:216-219. Filed for an owner ruling rather than carried silently into the close. - update #QSHHGK: clean-build measurement puts production at +5.2% (drift warning, over half way to the 10% ceiling), and the recorded baselineSource is unreachable even on a full 5415-commit clone, so the distance cannot be attributed to any reviewed change set. Requests only; docs/outstanding-issues.md is untouched and reconciliation runs on its own fresh-base branch. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015uQ7pGjA4hBxi9TRNsfjAL
…app-review-sxd0mm
Two pending done-mutations on #PM9SP1 made reconciliation ambiguous, which the inbox correctly refuses to guess at. 44e5f87c (queued 2026-08-27 by PR #2448) records only the Therapy Compass relabel; c772a1b8 records the same close plus the five further sites the 2026-09-01 sweep found, including the prescribing patient-profile panel and the medication record footer. Cancelling the narrower one so the archived outcome describes everything that was wrong rather than a subset. Nothing is lost - the surviving outcome states Therapy Compass had already been corrected. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015uQ7pGjA4hBxi9TRNsfjAL
|
This pull request has been ignored for the connected project Preview Branches by Supabase. |
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Team Run ID: Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_743598bd-1ad5-48a7-93d0-9b3723cfc2a3) |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8893dd29a1
ℹ️ 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".
The previous close outcome asserted that the only remaining 'decision support' strings under src/ were the document-intent taxonomy and the privacy page. That is literally false: the agreed replacement wording is 'not validated decision support', so all seven corrected sites still contain the phrase. A re-grep found three further categories the claim omitted - the document-intent filter placeholder, four negative guidance strings in calculator-fixtures.ts, and one in hub-panels.ts. Every occurrence is benign and the conclusion is unchanged: the app makes no positive decision-support claim in its own voice. But an archived row must not carry a false inventory, because a future auditor grepping the phrase will find hits and conclude the sweep was unreliable. The replacement enumerates all four categories and says to grep for positive claims rather than the bare phrase. Replaced rather than edited, per the inbox immutability rule. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015uQ7pGjA4hBxi9TRNsfjAL
|
Codex P2 (Correct the false production-string inventory) — verified and fixed in The finding is correct, and a re-grep shows the claim was wrong in one more way than the comment identified. The outcome asserted that the only remaining
The conclusion is unchanged — the app makes no positive decision-support claim in its own voice anywhere in production — but the point stands that an archived row must not carry a false literal inventory, because a future auditor grepping the phrase will find hits and conclude the sweep was unreliable. Fix: This is the second time on this branch that the right response to a queued-request defect was cancel-and-replace rather than an edit. Generated by Claude Code |
Ledger requests only.
docs/outstanding-issues.mdis untouched; reconciliation runs on its own fresh-base branch.Summary
Four immutable inbox requests, capturing the loose ends from the design-system and app review that landed in #2497 and #2499.
done #PM9SP1— the decision-support over-claim is fixed. The row named three Therapy Compass sites; a sweep for the whole class rather than the literal phrase found seven live sites, all now corrected across fix(clinical): stop four surfaces calling themselves decision support, and pin two drifting design-system documents #2497 and fix(clinical): the prescribing panel calls itself decision support; close four holes in the new token-divergence gate #2499. Two were not in the row and were worse than any that were:patient-profile-panel.tsxasserted the feature is "Decision support, not medical advice" on the surface computing per-patient medication interaction verdicts, andmedication-record-page.tsxclaimed PsychSift "provides evidence summaries".lib/differential-detail.tscarried the claim into copied/exported text, outside the app entirely. Production verified clean: the only remaining strings undersrc/are the document-intent taxonomy (classifying uploaded guideline documents) and the privacy page's own boundary statement.cancel 44e5f87c— a seconddonefor#PM9SP1was already pending, queued 2026-08-27 by PR feat(clinical): add Form 12A statutory manifest, CV medications, and therapy compass governance copy (#DTSABC, #4AM8Z0, #PM9SP1) #2448, recording only the Therapy Compass relabel. Two pending mutations on one row made reconciliation ambiguous, whichledger-inboxcorrectly refuses to guess at. The narrower one is cancelled so the archived outcome describes everything that was wrong rather than a subset — a later reader would otherwise never learn the prescribing surface had over-claimed. Nothing is lost: the surviving outcome states Therapy Compass had already been corrected before that session.add(P3, issue) —#PM9SP1's second fix clause, "mount the footer on the other mode homes", contradicts a recorded decision atmode-home-template.tsx:216-219("No mode home renders this any more…"). One source says mount it everywhere, the other says it was deliberately taken off everywhere. Filed for an owner ruling rather than carried silently into the close. Low priority: every surface rendering retrieved clinical content already carries its own scope line — the open question is the shared composer footer only.update #QSHHGK— clean-build measurement (rm -rf .nextfirst, per the AGENTS.md measuring rule): production 1742.1 KiB gzip across 145 routes vs a 1656.0 KiB baseline = +5.2%, tripping the >5% drift warning and over half way to the 10% failure ceiling. Mockups 645.1 KiB vs 613.1 KiB, inside its 25% tolerance. Routes:/240.0 KiB (30 chunks),/documents/search243.1 KiB (32 chunks), both under baseline. The configuredbaselineSource0764fb58…still does not resolve even on a full 5,415-commit clone aftergit fetch --deepen=2000— so this is not the shallow-clone case the 2026-08-23 note anticipated; the recorded commit is genuinely unreachable, and the +5.2% cannot be attributed to any reviewed change set.Verification
npm run verify:cheap— exit 0. It initially failed, and correctly:planRequestBatchthrew on the two pending#PM9SP1mutations. That is the gate working, not noise — resolved by the cancel above rather than by forcing past it.npm run check:outstanding-issues—in step (81 open, 88 pending).npm run check:ledger-write-discipline—self-test passed/passed for 99f0d28394bd..HEAD.npx prettier --check docs/outstanding-issues-inbox/— clean.No source, test or generated product file is touched, so no build, browser or domain gate applies.
origin/mainwas merged in so it is an ancestor and this diff is exactly the four request files.Risk and rollout
Notes
Why a cancel rather than an edit. Inbox requests are immutable by design; the sanctioned correction is a new request, and the tool names
cancelas the path for a rejected mutation. The alternative — cancelling my own and queueing anupdateto enrich the older outcome — hits the same two-pending-mutations conflict, since a row cannot be updated and closed in one batch.Still open for the owner, deliberately not filed here: the Calculators mode carries no standing scope statement on any of its pages while its heading asserts "Validated psychiatry scores". It is a clinical copy decision, and
mainreceived calculator safety work the same day (#2491), so filing a competing row now risks colliding with in-flight work. Raised in session instead.Generated by Claude Code
Note
Low Risk
Documentation-only inbox mutations with no application, test, or runtime changes; reconciliation gates apply separately when the ledger is merged.
Overview
Adds four immutable ledger inbox requests under
docs/outstanding-issues-inbox/(the canonicaldocs/outstanding-issues.mdis unchanged until reconciliation).donefor#PM9SP1records closure of the clinical over-claim work from PRs #2497/#2499: seven UI/copy sites now use Clinical reference - not validated decision support, including prescribing surfaces that were worse than the original row; the “mount footer on mode homes” clause is explicitly not closed here.canceldrops a narrower pendingdone(44e5f87c…, from PR #2448) so reconciliation is not blocked by two competing closes on the same row and the archived outcome stays complete.add(P3) opens a follow-up issue:#PM9SP1fix text still says mount the scope footer on every mode home, whilemode-home-template.tsxdocuments that footers were deliberately removed from all mode homes.updateon#QSHHGKappends a 2026-09-01 clean-build bundle measurement (+5.2% production gzip vs baseline, warning threshold) and notes the configuredbaselineSourcecommit still does not resolve even on a full clone.Reviewed by Cursor Bugbot for commit 8893dd2. Configure here.