Specifiers builder: correct the one-of mapping, and show each option's review status - #2726
Specifiers builder: correct the one-of mapping, and show each option's review status#2726BigSimmo wants to merge 4 commits into
Conversation
Two gaps left by the catalogue-driven builder, both about what the screen implies rather than what it computes. The builder shows a catalogue option at the moment the clinician picks it and copies it into a note, but showed nothing about that item's review state. Of the 585 catalogued specifiers, 71 have verified sources and every one is still pending qualified clinician review. The detail and reference pages already carry ReviewStatusBadge for exactly this reason, so carry it on the option rows too: the state is visible when it is acted on, not only if the record is opened afterwards. Generated definitions stay withheld, as before. The single-select step also read as though its one-of rule came from the manual. It does not. singleSelectGroupLabels is an aide-memoire grouping of the dataset's 50 group labels, so a group wrongly marked exclusive would quietly block a valid combination. Say so in the step body rather than letting the radio imply authority it does not have. No behaviour change: the curated mood path is untouched and shows no badges, selection rules and wording output are unchanged. Verified: 20 unit tests pass with a new case pinning that every catalogue item carries a renderable status and that the needs-review state is present. In the running app, Autism Spectrum Disorder shows 3 badges on its 3 severity options and 5 on its 5 co-occurring options, the curated MDD path shows none, and there is no horizontal overflow at 320, 390, 768 or 1440. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011RJFStNCUPhDrEdAJe2r4i
|
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_b8cead28-f187-4a09-8a50-672d84d49ad2) |
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. |
|
This pull request has been ignored for the connected project Preview Branches by Supabase. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d1e882a533
ℹ️ 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".
Both are correct and both are in the code this PR added. 1. The single-select step said the group "reads as a single graded axis". That is false for the nominal groups the rule also covers - Type (erotomanic, grandiose, jealous), Attraction, Classes and Current Episode are categorical, not degrees - so it handed clinicians a wrong rationale for the enforced one-of behaviour. Drop the claim about why and keep only what is true: that treating the group as one-of is an aide-memoire grouping, not a verified manual rule. 2. The option inputs set aria-label, which overrides the label's descendant text in the accessible-name computation, so the new badge was visible but silent. A screen-reader user picking a specifier heard the label alone and none of the review state, which is the whole point of showing it there. Wire aria-describedby to the badge so the status is announced with the control. Verified: the computed description on each Autism Spectrum Disorder severity radio now resolves to its badge text, checked in the running app - for example "Level 2: Requiring substantial support" described by "Review due". The step copy was confirmed against Delusional Disorder, whose Type group is nominal. A new DOM test asserts every catalogue option's aria-describedby resolves to a renderable status, so the silent-badge regression cannot return. 21 unit tests pass, typecheck, lint and formatting clean, drift ratchet unchanged at 233/233. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011RJFStNCUPhDrEdAJe2r4i
The catalogue builder decides whether a specifier group is one-of from a
hand-authored list of group labels. The dataset carries no exclusivity
field, so that list is a judgement, and a wrong entry makes a valid
combination unreachable with nothing on screen to say why.
Four labels were wrong against the manual and are now multi-select:
* Classes - concurrent alcohol, cannabis and tobacco use disorders are
ordinary and each is coded in its own right.
* Clusters - personality disorders across clusters are common and are
coded as both.
* Aetiology - the neurocognitive list pairs a certainty term with the
aetiology itself, so probable Alzheimer's disease needs two picks,
and delirium has to allow more than one contributor.
* Attraction - limited to incest is a separate axis, applied alongside
the attraction type rather than instead of it.
Type stays one-of, but specific phobia opts out of it: the manual asks
for every applicable phobia type to be coded. That needed a per-disorder
exception, so builderGroupSelection now takes the disorder too.
The wider fix is that the mapping is no longer able to block anything.
Every single-select group carries a control that reopens it as a
checkbox list, so a mapping error costs a default rather than a
combination the clinician cannot record. The step copy says so.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011RJFStNCUPhDrEdAJe2r4i
Neither can be closed by code, and both would otherwise be lost when the
session that found them ends.
* P2 - the DSM-5-TR specifier catalogue has no clinician sign-off. 585
items, 71 source-verified, none reviewed, dataset last updated
2026-05-09. PR #2726 makes that state visible at the point of
selection, which is as far as code reaches.
* P3 - the fifteen remaining one-of group labels are authored here
rather than reviewed. The reopen control added in #2726 bounds the
consequence to a default rather than an unrecordable combination, so
this is a confirmation pass, not a blocker.
Both are inbox requests, not ledger rows, so they stay merge-safe until
a reconcile runs.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011RJFStNCUPhDrEdAJe2r4i
Summary
Three gaps left by the catalogue-driven builder in PR #2676. None is a computation bug — all three are about what the screen implies versus what the data supports.
singleSelectGroupLabelsdecides whether a specifier group renders as radios. The dataset carries no exclusivity field — a group is a label and a list — so that mapping is authored in this repo, and a wrong entry makes a combination unreachable with nothing on screen to say why. Four labels were wrong against the manual and are now multi-select:Classes(concurrent alcohol, cannabis and tobacco use disorders are ordinary and each is coded in its own right),Clusters(personality disorders across clusters are common and coded as both),Aetiology(the neurocognitive list pairs a certainty term with the aetiology itself, so probable Alzheimer's disease needs two picks, and delirium has to allow more than one contributor), andAttraction(limited to incest is a separate axis, applied alongside the attraction type).Typestays one-of, but specific phobia opts out of it, since the manual asks for every applicable phobia type to be coded — sobuilderGroupSelectionnow takes the disorder as well as the label.SpecifierReferencePageand the detail routes already renderReviewStatusBadgefor exactly this reason, so the option rows now carry it too. Generated definitions stay withheld, unchanged.The curated mood path is untouched throughout: it renders no badges (those are hand-authored records, not catalogue rows), keeps its own fit and exclusion rules, and its wording output is identical. Deep links and the copied phrase are unchanged.
Scope: one library file, one component file, one unit test, plus two issues-inbox request files.
Verification
npm run verify:pr-localVerification not run: verify:pr-local selects heavy scope for an executable change (lint, typecheck, full test, build and the static suite), which duplicates the verdict CI reaches on this PR.The gates actually run locally, with their real output:node ./node_modules/typescript/bin/tsc -p tsconfig.typecheck.json --noEmit— clean, no output.eslinton all three changed source/test files--max-warnings 0— clean.npx prettier --checkon every changed file, the two inbox requests included —All matched files use Prettier code style!npx vitest related --runacross the specifier suites —Test Files 3 passed (3) / Tests 25 passed (25). Four new cases pin the corrected mapping: that the four relaxed labels are multi-select, that specific phobia opts out of the label-wideTyperule while delusional disorder does not, that two substance classes can be held at once, and thatrelaxBuilderGroupsreopens a named group without mutating the original or touching its siblings.npm run check:design-drift-ratchet—✓ inline style={{ }} attributes: 233 (ceiling 233). No new inline styles; this gate caught a regression on Specifiers builder: offer every catalogued base diagnosis, not five hardcoded mood presets #2676 so it is run deliberately.node scripts/ledger-inbox.mjs check—Ledger inbox check passed: 36 pending request(s), 1080 applied.npm run verify:uiwhen UI, routing, styling, browser behavior, reduced-motion, or forced-colors behavior changedFocused browser proof, not the full UI gate.
npm run plan:browserselected levelfocusedand attributed the changed component to its owning specs:Every existing builder journey passed unchanged, including
blocks incompatible specifiers and preserves severe psychotic-features wording(the curated mood path's own exclusion rules, a separate mechanism from the catalogue mapping),keeps the guided builder readable without horizontal overflow on phone, and the reduced-motion / forced-colors journeys. The fullverify:uisuite is left to CI.npm run verify:releasebefore release or handoff confidence claimsRisk and rollout
Clinical Governance Preflight
/specifiers/<slug>record, and its review status is now visible before selection rather than only after opening that record.Clinical KB Database(sjrfecxgysukkwxsowpy) — untouched.Review dueat the point of selection, and generated definitions remain withheld exactly as on the reference pages.What this PR does not close, and where it is now recorded
Both remaining gaps need a qualified clinician rather than a code change, so both are queued as issues-inbox requests in this PR (merge-safe request files, not ledger rows;
npm run issues:reconcileapplies them after it lands):lastUpdated2026-05-09. This PR makes that state honest at the point of selection, which is as far as code reaches.🤖 Generated with Claude Code
https://claude.ai/code/session_011RJFStNCUPhDrEdAJe2r4i