feat(medications): patient details dock pill and drug-interaction alerting - #1874
Conversation
…rting Adds a docked "Patient details" pill to the prescribing results view and cross-checks each medication against the patient's current medication list, surfacing red/amber/green/grey verdicts on result rows and matched interactions on the medication detail page. The patient-considerations engine already existed (physiology only, session -scoped). This extends the same profile with a medication list and adds a second engine beside it: - `data/medication-interaction-index.json` (generated) resolves the catalogue's prose `Key Interactions` rows to catalogue targets using the curated `medication-interaction-lexicon.ts`. 400 of 523 rows resolve; the rest are recorded as unresolved rather than dropped. - `medication-interactions.ts` matches those rows against the entered list. - `composeMedicationVerdict` folds both engines into one tone, and makes green unreachable whenever either engine left something unassessed or unresolved — those degrade to a neutral "needs manual review" state. The pill portals into a new phone-dock addon slot, inheriting the composer's fixed positioning, safe area and scroll-hide transform rather than adding a second scroll owner. `data-footer-addon` is now derived from an addon kind instead of hardcoding the differentials claimant. Regulatory status is unchanged and still open: this materially widens the surface tracked in docs/samd-classification-medication-considerations.md, which is updated to say so. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X12okkARLhFQ2zgcPoFp54
|
This pull request has been ignored for the connected project Preview Branches by Supabase. |
|
Warning Review limit reachedYou’ve reached a temporary PR review limit under our Fair Usage Limits Policy. Next review available in: 35 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 (1)
📝 WalkthroughWalkthroughThis change adds catalogue-based medication interaction indexing, bounded patient medication profiles, fail-safe verdict composition, prescribing-result and medication-detail interaction surfaces, and a mobile patient-details dock action. ChangesPatient interaction alerts
Estimated code review effort: 5 (Critical) | ~120 minutes Mergeability Score: 🟠 High · up to The interaction alert can currently display “No interaction found” even when some interaction data remains unresolved, which could cause clinicians to interpret incomplete data as a clean result. Merge should be blocked until the clear-result message is suppressed for incomplete evaluations. Sequence Diagram(s)sequenceDiagram
participant PatientProfilePanel
participant PatientProfileContext
participant MedicationPrescribingWorkspace
participant MedicationInteractionCallout
PatientProfilePanel->>PatientProfileContext: select catalogue medication
PatientProfileContext->>MedicationPrescribingWorkspace: persist medication profile
MedicationPrescribingWorkspace->>MedicationInteractionCallout: provide composed verdict
MedicationInteractionCallout->>PatientProfilePanel: open patient details or interaction section
Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
Comment |
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X12okkARLhFQ2zgcPoFp54
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d87f7b115d
ℹ️ 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".
CI triageCI failed on this PR. Automated classification of the 2 failed job(s):
Compared with main CI run #10297 (cancelled). Classification is evidence routing, not permission to ignore a failure. Exact quarantined Playwright identities remain governed by the flake ledger. |
There was a problem hiding this comment.
Pull request overview
Adds patient-context-driven UI and data plumbing to the medications/prescribing surfaces: a docked “Patient details” pill on phone, a session-scoped current-medications list, and a generated interaction index + runtime evaluation to surface drug–drug interaction alerts and conservative “needs manual review” states.
Changes:
- Introduces a phone dock addon registry (
PhoneDockAddonKind) and wires a new “patient-details” addon through the dashboard/shell/header reserve + CSS contracts. - Adds patient profile medication-list storage + UI picker, plus a docked pill that portals into the phone dock and opens the existing patient details sheet.
- Adds a generated medication-interaction index (build script + checks) and runtime interaction evaluation, integrating verdict tones into prescribing result rows and the medication detail page.
Reviewed changes
Copilot reviewed 31 out of 32 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/phone-dock-addon-contract.test.ts | New contract test pinning addon registry, exclusivity, and coupled CSS/TS reserve wiring. |
| tests/patient-profile-medications.dom.test.tsx | New DOM tests for the current-medications picker, storage sanitisation, and profile-emptiness semantics. |
| tests/patient-details-dock-action.dom.test.tsx | New DOM tests ensuring the dock pill portals correctly, respects breakpoint, and opens the sheet accessibly. |
| tests/medication-interactions.test.ts | New unit tests for interaction evaluation, naming, unresolved-row behavior, and verdict composition. |
| tests/medication-interaction-surfaces.dom.test.tsx | New DOM tests for interaction rendering on detail page and verdict presentation contracts across surfaces. |
| tests/medication-interaction-lexicon-coverage.test.ts | New ratchet-style coverage tests + deny-list pins for lexicon resolution safety. |
| tests/helpers/style-contracts.ts | Adds style-contract exemption entries for new unlayered CSS classes. |
| src/lib/patient-profile-storage.ts | Extends persisted patient profile with medications, adds slug sanitisation + max-list cap. |
| src/lib/mode-home-composer.ts | Adds the PhoneDockAddonKind registry and new addon slot id for patient details. |
| src/lib/medication-patient-alerts.ts | Extends PatientProfile type + emptiness check to treat medications as “profile populated”. |
| src/lib/medication-interactions.ts | New runtime interaction evaluation + verdict composition utilities backed by generated index JSON. |
| src/lib/medication-interaction-lexicon.ts | New curated lexicon mapping prose interaction counterparties to catalogue targets with explicit traps/denylists. |
| src/components/ClinicalDashboard.tsx | Wires prescribing mode to claim the patient-details addon slot/kind and reserve behavior. |
| src/components/clinical-dashboard/patient-profile-panel.tsx | Adds medication picker UI into the patient profile panel. |
| src/components/clinical-dashboard/patient-profile-context.tsx | Adds toggleMedication to context and ensures clear includes medications. |
| src/components/clinical-dashboard/patient-details-dock-action.tsx | New dock pill that portals into the phone dock addon slot and opens the patient details sheet. |
| src/components/clinical-dashboard/mobile-composer-reserve.ts | Adds patient-details reserve constant and resolver branches for dashboard/shell. |
| src/components/clinical-dashboard/medication-prescribing-workspace.tsx | Integrates interaction evaluation + composed verdict into prescribing result rows and phone/desktop styling. |
| src/components/clinical-dashboard/medication-considerations.tsx | Adds interaction block on medication detail page and verdict helper exports for rows/badges. |
| src/components/clinical-dashboard/master-search-header.tsx | Derives data-footer-addon from addon kind (with fallback), and accepts addon kind prop. |
| src/components/clinical-dashboard/global-search-shell.tsx | Ensures shell only claims the differentials addon and passes addon kind consistently. |
| src/app/globals.css | Adds unlayered CSS for patient details pill, verdict borders for phone cards, and addon-kind dock wiring. |
| scripts/build-medication-interaction-index.ts | New build/check script producing the interaction index artefact from snapshot + lexicon. |
| package.json | Adds medications:interactions and check:medication-interactions scripts. |
| docs/search-chrome-behaviour.md | Documents the phone dock addon slot rules, registry, and coupled constants/contracts. |
| docs/scripts-index.md | Updates script/file counts after adding the new script and package entries. |
| docs/samd-classification-medication-considerations.md | Notes that interaction alerting widens the clinical decision-support scope under review. |
| docs/design-system/COMPONENTS.md | Updates generated design-system component inventory count. |
| docs/design-system/adoption-manifest.json | Adds the new component to the design-system adoption manifest snapshot. |
| docs/codebase-index.md | Updates architecture index with the new patient-context/interaction subsystem. |
| docs/branch-review-ledger.md | Appends a branch review ledger entry for this PR’s work. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
…ery verdict Three follow-ups on the interaction work. Interactions are now stated on the medication page itself, not only behind the patient sheet. `MedicationInteractionCallout` renders above the record when the entered profile matches: the three highest-severity interactions, each naming the counterparty as a link to its own record, the verbatim catalogue wording, a "+N more" count, and buttons through to the full Key Interactions section and the patient sheet. Arriving from a result row flagged "2 interactions" no longer means hunting for them. The counterparty is also linked from each row of the in-sheet block. The tab the "See Key Interactions" control switches to is derived from the section-type table via `medicationTabForSectionType` rather than hardcoded, so a section that moves between tabs cannot leave the control pointing at the tab it used to be in. Every verdict tone now carries its own glyph on the result cards — shield -check for "no interaction found", help-circle for "needs manual review", alongside the existing ban and triangle. `ClinicalBadge` only auto-ices danger and warning to keep ordinary badges quiet; that default is right in general and wrong for a safety verdict, where "checked, nothing found" and "could not check" have to be told apart without reading the border colour. Overridden for this badge only, not in the shared default. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X12okkARLhFQ2zgcPoFp54
|
@codex Address all currently unresolved inline review comments on this PR against the current GitHub head. Treat the interaction findings as clinical-safety defects: absence of index data must never produce green, preserve relevant later interaction clauses, keep mixed unresolved mechanisms incomplete, evaluate pair edges bidirectionally, make the stale-index check formatting-stable, remove render-phase state reset, and scope the dock MutationObserver to phone mode. Add focused regressions for methadone+diazepam, cetirizine+diazepam, reverse naltrexone/buprenorphine-naloxone, missing index data, and UI state/observer behavior. Run proportionate verification and push minimal fixes. Do not merge, close, rebase, force-push, deploy, or alter auto-merge. Please report the exact commit SHA and test results. |
|
@codex Work PR #1874 from current head |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 76a22e4a11
ℹ️ 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".
Summary
Testing
|
|
@copilot Fix all seven currently unresolved review comments on this PR at current head |
Agent-Logs-Url: https://github.com/BigSimmo/Database/sessions/7cbf3386-3bdf-4ffd-bf65-c3ee5f5322f5 Co-authored-by: BigSimmo <87357024+BigSimmo@users.noreply.github.com>
Head branch was pushed to by a user without write access
There was a problem hiding this comment.
Actionable comments posted: 12
🧹 Nitpick comments (3)
src/lib/medication-interaction-lexicon.ts (1)
84-93: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winExclude opioid antagonists by rule, not only by slug.
subclassIncludes: ["Opioid"]also matches the subclass "Opioid Antagonist". Only the two current antagonist slugs are denied. If the catalogue adds another antagonist, it becomes an "opioid" counterparty silently.Add a negative subclass condition, for example
subclassExcludes: ["Antagonist"], and keepdenySlugsfor one-off traps.🤖 Prompt for 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. In `@src/lib/medication-interaction-lexicon.ts` around lines 84 - 93, Update the opioids catalogue entry’s select configuration to add a subclassExcludes rule for “Antagonist” alongside subclassIncludes: ["Opioid"]. Retain denySlugs for the existing naltrexone and naloxone exceptions.tests/medication-interaction-lexicon-coverage.test.ts (1)
51-57: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winAdd the named clinical regressions the PR comments request.
The PR comments require focused regressions for methadone with diazepam, cetirizine with diazepam, and reverse naltrexone with buprenorphine-naloxone. This suite pins counts and deny-lists but none of those pairs. Ratchet counts do not fail when a specific pair is lost.
Do you want me to draft these three pinned cases?
🤖 Prompt for 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. In `@tests/medication-interaction-lexicon-coverage.test.ts` around lines 51 - 57, Add focused regression tests to the “interaction lexicon coverage” suite for methadone with diazepam, cetirizine with diazepam, and reverse naltrexone with buprenorphine-naloxone. Assert each pair resolves as expected and is not excluded by the suite’s deny-list logic, while preserving the existing resolvedRows and sourceRowCount ratchets.tests/medication-interaction-surfaces.dom.test.tsx (1)
125-134: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winCompare the last occurrence of the selected-row rule.
indexOffinds the first[data-selected="true"]rule only. A duplicate of that rule placed after the verdict rule keeps this test green while the cascade regresses. UselastIndexOffor the selected rule.♻️ Proposed change
- const selectedAt = css.indexOf('.medication-mobile-result[data-selected="true"]'); + const selectedAt = css.lastIndexOf('.medication-mobile-result[data-selected="true"]');🤖 Prompt for 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. In `@tests/medication-interaction-surfaces.dom.test.tsx` around lines 125 - 134, Update the selected-row rule lookup in the test to use lastIndexOf instead of indexOf, while leaving the verdict rule lookup and source-order assertion unchanged. This ensures the assertion compares the verdict rule against the final occurrence of the [data-selected="true"] selector.
🤖 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/build-medication-interaction-index.ts`:
- Around line 127-142: Update counterpartySegment to retain counterparties named
in later sentences instead of truncating body to the first clause, while
continuing to exclude mitigation-advice clauses by identifying and filtering
clauses that begin with mitigation language. Preserve severityToken extraction
and ensure examples such as methadone with diazepam remain indexed without
treating mitigation mentions as counterparties.
- Around line 166-179: Update the surface-length filtering in the drugSurfaces
construction to address the four-character floor: either document its
intentional false-negative tradeoff where both filters are applied, or lower the
minimum length and rely on mentions for boundary safety. Keep the existing
deduplication, dosage-form stripping, and sorting behavior unchanged.
- Around line 288-302: Update the checkOnly branch around serialised and current
so staleness is determined by comparing parsed JSON values rather than
byte-for-byte text, while preserving the existing stale-file error, success
message, and exit behavior.
- Around line 188-255: Update the interaction consumer around
evaluateMedicationInteractions to match both directions: retain direct
INDEX.bySlug[slug] counterparties and also include records whose rows list the
evaluated slug as a counterparty. Deduplicate the resulting interactions and
preserve existing severity, term, and unresolved-row handling, so evaluating
either medication finds the same relationship.
In `@src/app/globals.css`:
- Around line 2468-2471: Update the patient-details hidden-state selector to
target the dashboard dock class `.dashboard-composer-edge` instead of
`.document-mobile-search-edge`, while preserving the existing patient-details
attributes and overshoot transform.
In `@src/components/clinical-dashboard/medication-considerations.tsx`:
- Around line 86-117: Update verdictSummaryBadge so that when findings are
present and verdict.incomplete is true, the returned label also communicates
that manual review is needed; preserve the existing interaction and alert
counts, and keep the current zero-findings incomplete behavior unchanged.
In `@src/components/clinical-dashboard/patient-profile-context.tsx`:
- Around line 58-63: Update toggleMedication to sanitize the computed next
medication list with sanitizeMedicationSlugs before passing it to
writePatientProfile, ensuring the persisted profile never exceeds the
40-selection cap. Add a regression test that toggles 41 distinct medications and
verifies the persisted/evaluated selection remains capped at 40.
In `@src/components/clinical-dashboard/patient-profile-panel.tsx`:
- Around line 3-4: Update the React import used by MedicationPicker to include
useEffect alongside useId and useState, so its existing useEffect call resolves
during TypeScript compilation.
In `@src/lib/medication-interactions.ts`:
- Around line 166-175: Update the missing-entry branch in
medication-interactions.ts around INDEX.bySlug and composeMedicationVerdict so
absent index data is explicitly reported and treated as incomplete, preventing a
success verdict. Add or update the unknown/unindexed slug assertion in
tests/medication-interactions.test.ts lines 69-74, and add the
missing-medication rendering case in
tests/medication-interaction-surfaces.dom.test.tsx lines 41-81 to expect the
manual-review notice instead of the clear notice.
In `@tests/medication-interaction-lexicon-coverage.test.ts`:
- Around line 65-70: Strengthen the test around the unresolved-row assertion by
selecting a row whose termIds are all mechanism terms and whose counterparties
are empty, then assert that specific row is unresolved. Use the existing
mechanism-term classification symbols from the test or implementation rather
than accepting any unresolved row.
In `@tests/medication-interaction-surfaces.dom.test.tsx`:
- Around line 41-81: Add a test in the interactions block for a medication
absent from the interaction index, using seedProfile and renderFor with an
appropriate unknown medication. Assert the UI shows the intended manual-review
message from the medication-interactions flow and does not present the
medication as clear.
In `@tests/medication-interactions.test.ts`:
- Around line 69-74: Extend the unknown-slug test around
evaluateMedicationInteractions and composeMedicationVerdict to assert that an
unindexed medication does not produce a success verdict. Keep the existing
empty-result and zero-count assertions unchanged, and verify the verdict is any
non-success status.
---
Nitpick comments:
In `@src/lib/medication-interaction-lexicon.ts`:
- Around line 84-93: Update the opioids catalogue entry’s select configuration
to add a subclassExcludes rule for “Antagonist” alongside subclassIncludes:
["Opioid"]. Retain denySlugs for the existing naltrexone and naloxone
exceptions.
In `@tests/medication-interaction-lexicon-coverage.test.ts`:
- Around line 51-57: Add focused regression tests to the “interaction lexicon
coverage” suite for methadone with diazepam, cetirizine with diazepam, and
reverse naltrexone with buprenorphine-naloxone. Assert each pair resolves as
expected and is not excluded by the suite’s deny-list logic, while preserving
the existing resolvedRows and sourceRowCount ratchets.
In `@tests/medication-interaction-surfaces.dom.test.tsx`:
- Around line 125-134: Update the selected-row rule lookup in the test to use
lastIndexOf instead of indexOf, while leaving the verdict rule lookup and
source-order assertion unchanged. This ensures the assertion compares the
verdict rule against the final occurrence of the [data-selected="true"]
selector.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: a10e83be-78a5-4700-96b7-6613a7459727
📒 Files selected for processing (36)
data/medication-interaction-index.jsondocs/branch-review-ledger.mddocs/codebase-index.mddocs/design-system/COMPONENTS.mddocs/design-system/adoption-manifest.jsondocs/samd-classification-medication-considerations.mddocs/scripts-index.mddocs/search-chrome-behaviour.mdpackage.jsonscripts/build-medication-interaction-index.tssrc/app/globals.csssrc/components/ClinicalDashboard.tsxsrc/components/clinical-dashboard/global-search-shell.tsxsrc/components/clinical-dashboard/master-search-header.tsxsrc/components/clinical-dashboard/medication-considerations.tsxsrc/components/clinical-dashboard/medication-nav-header.tsxsrc/components/clinical-dashboard/medication-prescribing-workspace.tsxsrc/components/clinical-dashboard/medication-record-page.tsxsrc/components/clinical-dashboard/mobile-composer-reserve.tssrc/components/clinical-dashboard/patient-details-dock-action.tsxsrc/components/clinical-dashboard/patient-profile-context.tsxsrc/components/clinical-dashboard/patient-profile-panel.tsxsrc/lib/medication-interaction-lexicon.tssrc/lib/medication-interactions.tssrc/lib/medication-patient-alerts.tssrc/lib/mode-home-composer.tssrc/lib/patient-profile-storage.tstests/helpers/style-contracts.tstests/in-page-nav-route-sections.dom.test.tsxtests/medication-interaction-lexicon-coverage.test.tstests/medication-interaction-surfaces.dom.test.tsxtests/medication-interactions.test.tstests/medication-record-page.dom.test.tsxtests/patient-details-dock-action.dom.test.tsxtests/patient-profile-medications.dom.test.tsxtests/phone-dock-addon-contract.test.ts
|
@claude Address every currently unresolved inline review thread on this PR against the current GitHub head. First distinguish outdated duplicate threads from still-live findings and resolve outdated duplicates only after verifying their underlying fix remains present. For live findings: (1) document or safely lower the four-character drug-surface floor without increasing false positives; (2) fix the patient-details hidden-state selector so the prescribing/dashboard dock receives the required overshoot; (3) when findings exist but the interaction verdict is incomplete, surface the manual-review caveat alongside the counts; (4) enforce the 40-medication cap before persistence using the existing sanitizer and add a 41-selection regression; (5) strengthen the mechanism-only unresolved-row test to prove the specific mechanism condition. Preserve all prior clinical-safety fixes including missing-index fail-safe behavior, later-clause parsing, mixed mechanism incompleteness, bidirectional edges, formatting-stable staleness checks, post-render picker reset, and phone-only MutationObserver lifecycle. Run focused interaction/profile/dock tests plus typecheck/format as proportionate, push only minimal fixes to this PR branch, reply with exact pushed SHA and verification, and resolve every satisfied thread. Do not merge, close, rebase, force-push, deploy, alter auto-merge, or call live providers. |
|
Hi @BigSimmo — thanks for the @claude mention. Open this in Claude Code on the web to continue here: https://claude.ai/code Context: Automated backlink from the Claude backlink workflow. Claude Code can pick up the mention and push a scoped fix to the branch. |
The committed `data/medication-interaction-index.json` no longer matched the lexicon and build script on this branch — several commits changed both without regenerating the artefact the UI actually reads, so the app was serving safety verdicts derived from an older resolution pass. Nothing caught it: I added `check:medication-interactions` when the artefact was introduced but never wired it into `verify:pr-local`, so a stale index sailed through a green gate. It now runs on every executable scope, alongside `check:rag:fixtures`, with the plan self-test updated to match. Regenerating moves two numbers in opposite directions, and both are improvements: - `resolvedRows` 400 → 355, because a row carrying any unenumerated mechanism is now unresolved even when it also matched a named drug. "CYP3A4 inhibitors (Clarithromycin, Ketoconazole)" used to resolve on clarithromycin and count as fully read, implying the whole class had been checked. More medications now hold at grey. - `rowsWithCatalogueTarget` 381 → 417, from the shorter catalogue-name matching floor. The coverage ratchet is re-anchored accordingly and now pins both numbers, because a single "resolved rows" figure conflates coverage with resolution strictness and would otherwise fight a legitimate tightening. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X12okkARLhFQ2zgcPoFp54
|
@claude This PR is currently |
|
Hi @BigSimmo — thanks for the @claude mention. Open this in Claude Code on the web to continue here: https://claude.ai/code Context: Automated backlink from the Claude backlink workflow. Claude Code can pick up the mention and push a scoped fix to the branch. |
|
Claude encountered an error after 2s —— View job I'll analyze this and get back to you. |
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/components/clinical-dashboard/medication-considerations.tsx (1)
404-408: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winDo not show a clear result for incomplete interaction data.
If
result.dataAvailableis false orresult.unresolvedRowCountis positive, this branch still states “No interaction found.” Lines 442-453 then state that the result needs manual review. Suppress the clear-result notice unless all rows were evaluated.Proposed fix
- ) : result.interactions.length === 0 ? ( + ) : result.interactions.length === 0 && result.dataAvailable && result.unresolvedRowCount === 0 ? ( <InlineNotice tone={result.unresolvedRowCount > 0 ? "neutral" : "success"}> No interaction found between this medication and the {medicationCount}{" "} {medicationCount === 1 ? "medication" : "medications"} entered. Always confirm against source. </InlineNotice> + ) : result.interactions.length === 0 ? null : ( - ) : ( <div className="space-y-2">🤖 Prompt for 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. In `@src/components/clinical-dashboard/medication-considerations.tsx` around lines 404 - 408, Update the zero-interactions branch in the medication interaction result rendering so the “No interaction found” InlineNotice is shown only when result.dataAvailable is true and result.unresolvedRowCount is zero. Preserve the existing manual-review path for incomplete or unresolved results, including when interactions.length is zero.
🤖 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.
Outside diff comments:
In `@src/components/clinical-dashboard/medication-considerations.tsx`:
- Around line 404-408: Update the zero-interactions branch in the medication
interaction result rendering so the “No interaction found” InlineNotice is shown
only when result.dataAvailable is true and result.unresolvedRowCount is zero.
Preserve the existing manual-review path for incomplete or unresolved results,
including when interactions.length is zero.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: aa1d9280-c3b4-42c3-b050-4a87ccdff599
📒 Files selected for processing (24)
data/medication-interaction-index.jsondocs/design-system/COMPONENTS.mddocs/design-system/adoption-manifest.jsondocs/scripts-index.mdpackage.jsonscripts/build-medication-interaction-index.tsscripts/verify-pr-local.mjssrc/app/globals.csssrc/components/ClinicalDashboard.tsxsrc/components/clinical-dashboard/global-search-shell.tsxsrc/components/clinical-dashboard/medication-considerations.tsxsrc/components/clinical-dashboard/medication-nav-header.tsxsrc/components/clinical-dashboard/medication-prescribing-workspace.tsxsrc/components/clinical-dashboard/patient-details-dock-action.tsxsrc/components/clinical-dashboard/patient-profile-context.tsxsrc/components/clinical-dashboard/patient-profile-panel.tsxsrc/lib/medication-interaction-lexicon.tssrc/lib/medication-interactions.tstests/in-page-nav-route-sections.dom.test.tsxtests/medication-interaction-lexicon-coverage.test.tstests/medication-interaction-surfaces.dom.test.tsxtests/medication-interactions.test.tstests/patient-details-dock-action.dom.test.tsxtests/patient-profile-medications.dom.test.tsx
🚧 Files skipped from review as they are similar to previous changes (16)
- docs/scripts-index.md
- tests/in-page-nav-route-sections.dom.test.tsx
- package.json
- tests/patient-profile-medications.dom.test.tsx
- src/components/clinical-dashboard/medication-nav-header.tsx
- src/components/clinical-dashboard/global-search-shell.tsx
- src/components/ClinicalDashboard.tsx
- docs/design-system/COMPONENTS.md
- tests/medication-interaction-lexicon-coverage.test.ts
- src/components/clinical-dashboard/patient-profile-context.tsx
- tests/medication-interactions.test.ts
- tests/medication-interaction-surfaces.dom.test.tsx
- src/lib/medication-interactions.ts
- src/app/globals.css
- src/components/clinical-dashboard/patient-profile-panel.tsx
- src/components/clinical-dashboard/medication-prescribing-workspace.tsx
Final post-merge review-and-fix summaryFinal state
Issues and review threadsThe completed review cycle addressed or dispositioned the high-confidence PR-introduced findings, including:
Final thread snapshot: 22/22 review threads resolved and no actionable thread remains open. Independent review coverage came from Codex, Copilot, CodeRabbit, and Sentry passes. A new post-merge adversarial pass was not started because the repository protocol requires stopping code review activity once the PR is already merged. CodeRabbit's last incremental pass was rate-limited, which is retained as a review-tool limitation rather than described as a clean fresh pass. Verification evidenceRecorded local evidence in the PR before hosted finalisation:
I did not rerun local commands during this post-merge verification because no code was changed and no local checkout was used. The final head was instead verified against GitHub's exact-head checks. Exact-head required CIAll repository-required checks completed successfully on
Selected Production UI matrix:
Advisory checks and residual risk
Ledger
I did not merge or close this PR. GitHub shows that it had already merged before this final verification pass. |
Summary
<form>, so it inherits the dock's fixed positioning, z-index, safe-area padding and scroll-hide transform rather than adding a second scroll owner or any bottom-offset arithmetic. Single 48px row (the--spacing-tapfloor), quiet while the profile is empty and accent-filled with a count once it is populated. Tapping it opens the existingSheetaroundPatientProfilePanel.data-footer-addonis now derived from an addon kind instead of being hardcoded to"differentials-compare"whenever any slot id was present, which would have silently mislabelled a second claimant's dock. The two claimants are mutually exclusive by surface (differentials vs prescribing) andtests/phone-dock-addon-contract.test.tspins that, along with the four coupled numbers each kind needs: clearance tokens, reserve constant and resolver branches, backdrop scrim heights, and the hide-transform overshoot.PatientProfile.medications(catalogue slugs only) in the same session-scopedsessionStoragestore, with a search-and-add picker in the panel. Slugs are shape-validated in the storage layer rather than against the catalogue, deliberately, so the medication catalogue is not pulled into the global shell bundle viaPatientProfileProvider.Key Interactionsrows are prose, not structured pairs ("CRITICAL — MAOIs, Tramadol, Tapentadol, St John's Wort."), and only ~58% name a catalogue drug literally.scripts/build-medication-interaction-index.ts(npm run medications:interactions) resolves them through the curatedsrc/lib/medication-interaction-lexicon.tsinto the generateddata/medication-interaction-index.json, staleness-gated bynpm run check:medication-interactions. 400 of 523 rows resolve; the remaining 123 are recorded as unresolved rather than dropped, because dropping them would manufacture a false all-clear.src/lib/medication-interactions.tsmatches the index against the entered medication list.composeMedicationVerdictfolds it together with the existing physiology engine into the single tone a result row wears, taking the highest tone across both — with one override that is the point of the function: if either engine left anything unassessed or unresolved, a would-be green degrades to a neutral "needs manual review". Green is unreachable on incomplete data.Two notes on things found while building, rather than assumed:
.medication-mobile-result[data-verdict="…"]), not a Tailwind utility. The existing[data-selected="true"]rule is unlayered and pinsborder-color, so a utility lost to it on exactly the top hit — the row most likely to be prescribed would have rendered its interaction warning with a neutral edge. Desktop rows keepring-*, matching the mechanism that surface already used, so no surface mixesborder-*andring-*./medicationsand/medications/[slug]deliberately do not claim the addon./medicationsis a standalone mode home with the composer in the hero and no dock to portal into, and the detail route already opens the same patient sheet from its own nav header — a pill there would be a second entry point to one destination, and claiming the addon would inflate the dock reserve for a pill that never mounts.Verification
npm run verify:pr-local— all 16 stages green:completed: check:runtime, check:installed-lock-parity, format:changed, check:npm-ci-dry-run, sitemap:check, docs:check-index, docs:check-inventory, docs:check-scripts, docs:check-links, check:branch-review-ledger, check:outstanding-issues, lint, typecheck, test, build, check:rag:fixtures/failed: (none).Test Files 567 passed (567),Tests 6206 passed | 4 skipped.tests/medication-interactions.test.ts,tests/medication-interaction-lexicon-coverage.test.ts,tests/medication-interaction-surfaces.dom.test.tsx,tests/patient-details-dock-action.dom.test.tsx,tests/patient-profile-medications.dom.test.tsx,tests/phone-dock-addon-contract.test.ts— 96 assertions across the six.Test Files 9 passed (9),Tests 129 passed (129).npm run check:bundle-budget—production (what users download, 101 routes): 1314.1 KiB gzip — baseline 1279.1 KiB, within tolerance.The interaction index costs ~15 KiB gzip; it was restructured mid-build from 661 KB to 249 KB raw by dropping the row text and counterparty names, both of which every consumer already holds.UI verification not run:
npm run verify:phone-chromecannot complete its browser stages in this environment — the image ships Chromium 1194 while Playwright 1.62.1 wants 1234 (the drift tracked as/issues #255), anddocs/testing.mdsays not to force a mismatched browser path. Its static contract stage passed as above; the Chromium journeys are delegated to CI Production UI.Manual phone-viewport proof was captured against a local dev server at 390×844 instead, confirming: the pill renders at 48px above the composer with
data-footer-addon="patient-details"; the sheet opens and the picker adds medications; result rows take red edges with "2 interactions" / "1 interaction" badges; and on scroll down the dock takesdata-scroll-hidden="true"and the pill moves from y=729 to y=860 (off-screen) and back on scroll up, with no peep strip at the viewport edge.npm run check:production-readiness— run; the two FAILs are the documented offline-Cloud provider gap (Missing server environment variables: NEXT_PUBLIC_SUPABASE_URL, SUPABASE_SERVICE_ROLE_KEY,Missing OPENAI_API_KEY), not introduced by this diff. The two PASS lines (Node runtime, query-hash HMAC boot guard) are unaffected.RAG impact: no retrieval behaviour change — nothing under
src/lib/rag/**, clinical-search, retrieval-selection, ranking-config, answer-ranking, the eval harness or the golden fixture is touched. The change is confined to the medication catalogue surfaces and phone dock chrome;check:rag:fixturespassed unchanged (36 golden cases, 23 suites).Risk and rollout
tests/medication-interaction-lexicon-coverage.test.tsratchets that figure so it cannot silently regress, and pins the two class-matching traps by name: clozapine and olanzapine must never resolve as benzodiazepines (their subclasses areSGA / DibenzodiazepineandSGA / Thienobenzodiazepine), and naltrexone must never resolve as an opioid (Opioid Antagonist). The secondary risk is alert fatigue from over-matching; counterparty resolution is therefore restricted to the first sentence after the severity token, so mitigation advice later in a row ("cover with PPI if combined") cannot flag a patient's PPI as interacting."differentials-compare", so the dock returns to its prior single-claimant behaviour.Clinical Governance Preflight
Clinical KB Database(sjrfecxgysukkwxsowpy) — no Supabase file, migration, env value or client call is touched by this change.data/medications-snapshot.jsoncatalogue export and carries provenance (slug,rowKey,rowIndex) back to it for every row; no demo corpus is involved.docs/samd-classification-medication-considerations.mdis updated in this PR to record that interaction alerting materially widens the surface its OPEN question covers. Interaction checking is a canonical clinical-decision-support function, and unlike the physiology considerations it produces an alert about a specific combination the clinician has entered. The note's status is unchanged and this PR does not resolve it; the reviewer's open questions now need answering for this surface too, and a named clinical + regulatory reviewer is still required.Notes
.phone-footer-layer'ssm:fixed, deliberately not the 1023px the two existing Compare bars use — between 640px and 1023px those portal into a slot on a form that is not fixed. That pre-existing mismatch is left alone here rather than fixed in passing, but is called out indocs/search-chrome-behaviour.mdso it is not copied again.min-height: 3rem) is the regression worth catching there — worth a follow-up rather than an unverifiable browser assertion added blind.Generated by Claude Code
Summary by CodeRabbit
New Features
Documentation
Tests