feat(navigation): one shared home page, mode-routed search - #1744
Conversation
The mode pill at the top of the screen was a navigation control: picking a mode ran router.push(appModeHomeHref(mode)) and replaced the whole page, so the app had 13 front doors and no single home. `/` is now the common home for every mode — the "How can I help?" hero with the composer. The pill no longer navigates; it only decides where the composer sends you on submit. Picking DSM keeps the page and swaps the placeholder; submitting lands on /dsm/search?q=… appModeHomeHref already mapped (mode, query) to the right search destination, so the routing table is essentially unchanged. Tools keeps opening its own home (/tools?q=…&run=1) because it has no search route — the requested exception falls out for free. Main changes: - Mode selection stops navigating. On the shared home it rewrites `?mode=` with history.replaceState (no push, so Back still leaves home) and lets the existing render-time URL sync own searchMode — never an optimistic set, per the hero-vs-dock rule in docs/search-chrome-behaviour.md. Off the home, a query in play is carried into the newly picked mode instead of dropped. - ask() gains a navigation branch. It previously navigated for documents only; every other mode ran executeSearch in place, which was safe only while `/` plus a namespaced mode was unreachable. That is now the normal state, so submitting in DSM would otherwise have run an in-dashboard search. - showAnswerHome becomes showSharedHome, gated on the pathname rather than the mode, and sits at the top of the mode-content chain. - Bare /?mode=X renders the home with X preselected; a submitted deep link (q plus run=1) still resolves to the mode's own search surface. - The last selected mode is remembered per browser, seeded only on a cold `/` visit so a shared or reloaded ?mode= link never flips after hydration. - Documents and Medication gain real homes at /documents and /medications. They were the only modes without their own route, so the shared home would otherwise have left their content unreachable. /medications was previously a 307 alias for /?mode=prescribing. - The sidebar gains a "More modes" group for the six modes it never listed, keeping every mode home reachable now that the pill does not open them. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Wa7MTVhAJMztFMMhzJf2J4
`/?mode=tools&q=…` without run=1 now prefills the shared home's composer rather than rendering Tools content on `/`, so this journey asserts the launcher from its canonical surface instead. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Wa7MTVhAJMztFMMhzJf2J4
…e change The cold-`/` seeding effect re-fired whenever `searchMode` changed and rewrote `?mode=` back to the remembered mode, silently undoing in-app mode changes that do not touch the URL — openDocumentsDrawer sets the mode directly, so "Add document" bounced straight back to Answer. Guard it with a ref so it seeds at most once per mount, and drop `searchMode` from the dependencies entirely so an in-app change can never retrigger it. Caught by the Chromium journeys (ui-accessibility, ui-formulation); both specs are green again — 23 passed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Wa7MTVhAJMztFMMhzJf2J4
…ey updates /medications is in alwaysStandaloneShellPathPrefixes, so ClinicalDashboard never mounts there — that exclusion is what stopped the duplicate page-root testids under CI load, so the route must render its own body like /tools and /services do. Without it the new mode home rendered header and composer over empty content. Also retargets the remaining journeys that assumed a mode's content lives on `/`: /?mode=tools now prefills the shared home, so Tools assertions use /tools, and the tablet rail expects the new "More modes" group instead of asserting the specialist catalogues are absent. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Wa7MTVhAJMztFMMhzJf2J4
The "Medications" breadcrumb built its href with the drug slug as a query, which resolved to /?mode=prescribing&q=<slug>. That was the Medication home before this change; it is now the shared home, so the breadcrumb landed on `/` with the drug name prefilled instead of on Medications. Drop the query so it resolves to /medications. Also fixes the Documents deferred-requests journey: waitForDemoDashboardReady looks for "Open answer options", but the actions trigger is named for the active mode, which is Documents on that route. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Wa7MTVhAJMztFMMhzJf2J4
…lur in the journey ClinicalDashboard owns the body on /documents (dashboardOwnedModeHomePaths), so it owns composer placement too, exactly as it does on `/`. Declaring a shell hero on top of that gave the route two hero owners. Drop the shell-side placement. The deferred-requests journey also needed a real dismissal: Escape closes the scope popover but leaves the composer's command dropdown open, and that dropdown overlays the home actions beneath it. Blur the composer the way a user would. Previously the test switched mode after scoping and that re-render reset the composer for free; the Documents home is now its own route. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Wa7MTVhAJMztFMMhzJf2J4
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:8 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 (12)
📝 WalkthroughWalkthroughThe change adds standalone ChangesMode routing and home surfaces
Estimated code review effort: 4 (Complex) | ~60 minutes Sequence Diagram(s)sequenceDiagram
participant User
participant GlobalSearchShell
participant ClinicalDashboard
participant Router
User->>GlobalSearchShell: Select an app mode
GlobalSearchShell->>ClinicalDashboard: Preserve mode and query context
ClinicalDashboard->>Router: Replace shared mode URL or push search destination
User->>ClinicalDashboard: Submit a search
ClinicalDashboard->>Router: Navigate to the mode-owned search route
Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 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_01Wa7MTVhAJMztFMMhzJf2J4
BigSimmo
commented
Aug 8, 2026
@cursoragent Work the current open PR end-to-end. 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, including any local-only ledger commits; do not discard dirty work, and do not treat a local-ahead commit as the reviewed tip. Do not merge the PR, force-push, rebase, or arm auto-merge unless I explicitly ask. No provider-backed gates without separate approval. If you cannot push or resolve threads, diagnose and comment only; if inline replies fail, resolve when possible and put dispositions in the summary comment. If auto-merge is already armed, push only for a real blocker, and avoid pushes that would cancel in-flight required CI unless the push itself clears that blocker. If the PR is already merged or closed: confirm the head and merge commit, note required-CI outcome, post one summary, and stop. Goal: deep review plus Bugbot, fix actionable issues with the smallest correct changes, clear merge / required-CI / thread blockers, run strong local offline verification, push fixes, append the review ledger, and post one PR summary. Prefer thoroughness over speed. Regenerate large assets only when a fix requires it; then run the asset check and keep compatibility aliases byte-identical where the repo uses them. Snapshot the GitHub head SHA: tip, base, 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, advisory separately, unresolved actionable threads. Missing checks while dirty are not green. If the tip moves mid-work, re-snapshot and continue from the new head. Ledger-lookup against that GitHub head under the heavy review-and-fix scope for this PR. Already reviewed at this head with clean merge-tree, green required checks, and no new actionable threads → summarize, comment, stop unless I asked for a fresh superseding pass. Follow the repo review protocol. Unblock once: real conflict → merge origin/main (prefer main’s shared queues; keep this PR’s notes); behind-but-clean → one sync, late if required CI is in flight; clean → leave. Labels like skip-branch-sync 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. Review high-confidence delta risks only. Separate PR-introduced defects from pre-existing re-emitted debt. For generated assets, review contracts, aliases, cache, and manifests—not every generated line. If protected RAG or ranking surfaces are touched, say so before editing; fix PR-body policy text only when wrong or missing. Ignore bot noise. No nit spam or broad rewrites. Escalate verification by touched risk: clinical / RAG / privacy / migrations / auth → domain check plus production-readiness when warranted; UI / phone-chrome / routing / styling → ensure plus phone-chrome or UI gates when warranted; generated assets or docs inventory/links → asset or docs checks when warranted. Fix P0/P1 always; clear scoped P2 when locally provable; else disposition and resolve. Required-check failures on this tip only; ignore advisory. Prefer reverting a bad autofix commit. After fixes: format and commit before push; smallest targeted proof; repo cheap gate; repo PR-local gate. No release, lighthouse, live eval, or live provider gates without approval. Push only this PR’s fix commits. Append ledger for the final GitHub head under the heavy scope. Never push a ledger-only tip—include ledger in a real fix push, or leave a no-change ledger append local and unpushed. One PR comment: tip, sync/merge-tree, fixed versus dispositioned, threads, required CI, decisive local gate lines, residual risks; merge left to me. Inline only for remaining human-needed P0/P1. Stop when merge-tree is clean on the current GitHub tip, actionable threads are clear, required checks are green or clearly in progress, heavy gates for scope passed, summary posted, merge left to me. |
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit:3a0bdd6246
ℹ️ 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".
Uh oh!
There was an error while loading. Please reload this page.
BigSimmo
commented
Aug 8, 2026
@codex resolve actionable Codex review findings for this pull request and current head using the repository instructions. This is the pull request's single automatic repair pass: do not perform a fresh review, create new standalone findings, or request another review. Work only the existing unresolved Codex threads on the current head. The only repository destination is BigSimmo/Database, and the only branch destination is the pull request head branch claude/mode-routing-search-pages-jabe17 at starting commit 468cc3f; never publish fixes to a detached or synthetic work branch and never create a stacked pull request. Use the authenticated GitHub connector to commit each approved fix to BigSimmo/Database:claude/mode-routing-search-pages-jabe17, then verify that the pull request head contains the published commit before reporting success. Always fix P0 and P1 findings. For P2 and lower findings, fix only clear, scoped, low-risk issues; otherwise disposition them with a concise reason. For a fixed thread, reply with as the first line and as the second line. For a no-code disposition, use followed by . These result markers authorize the workflow to close that exact thread only after it verifies a fixed commit is the pull request head; a local-only commit is not a fix. If publication or verification fails, do not use either result marker, do not claim success, and leave the thread open with the blocker. If human input or new authorization is required, do the same. Finish only after every actionable thread is fixed or dispositioned and closed, or explicitly left open for a human decision. Do not update the branch from main, address unrelated reviews, broaden scope, or create more than one scoped fix commit. Do not use external APIs, paid services, credentials, dependency changes, or broad refactors unless explicitly authorized. Add targeted tests where behavior changes and run the narrowest relevant validation. |
Co-authored-by: BigSimmo <BigSimmo@users.noreply.github.com>
Codex Review: Didn't find any major issues. Already looking forward to the next diff. Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
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". |
BigSimmo
commented
Aug 8, 2026
@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 #1744 tip
The dirty/conflict signal in the prompt was for stale tip Required CI: mergeability/policy/SAST/gitleaks green; main CI run Merge left to you when CI goes green. |
…e homes Unsubmitted /documents mounts ClinicalDashboard with autoRunSearch always true, so every composer keystroke fired search. Gate it on run=1 like bare /. Also point the PWA Medication shortcut and settings landing at real mode homes, restore /medications?q&run=1 deep links to prescribing results, and let settings landing win over remembered-mode seeding on cold /. Co-authored-by: BigSimmo <BigSimmo@users.noreply.github.com>
Co-authored-by: BigSimmo <BigSimmo@users.noreply.github.com>
PR #1744 review-and-fix summaryTip: Sync
Fixed (pushed in |
| Sev | Issue | Fix |
|---|---|---|
| P1 | /documents always set autoRunSearch=true, so composer keystrokes fired /api/search | Gate autoRunSearch on run=1 for dashboard-owned mode homes (isDashboardOwnedModeHomePath) |
| P2 | PWA Medication shortcut still opened /?mode=prescribing (shared home, not Medication home) | Manifest → /medications?focus=1 |
| P2 | Settings landing lost to remembered-mode replaceState race; landing also targeted bare /?mode= | Landing navigates to /documents or /tools; last-mode seed skips when landing is set |
| P2 | /medications?q=&run=1 deep links no longer reached prescribing results after removing the blanket 307 | Server redirect to prescribing results when submitted |
RAG/ranking surfaces: not touched.
Threads (inline replies FORBIDDEN for this token — dispositions here; threads resolved)
- Codex P2 landing vs last-mode → fixed at
ef895b874302c9d3d80f77e4a4a7eecae8e2535d. - Sentry/Bugbot tools query loss → no-change:
/tools?q=is filled by the shared shell SearchCommandProvider / ClinicalDashboard ToolsHub; covered bytests/ui-tools.spec.ts.
Required CI
- Restarted on the synced tip; in progress at comment time (
PR mergeabilityalready green). Advisory ignored.
Local gates (decisive)
npm run verify:pr-localon fix tip PASS —Test Files 524 passed (524)/Tests 5614 passed | 4 skipped (5618).- Focused ownership/manifest/audit vitest: 68 passed.
- Not run (no approval):
verify:release, live evals, provider checks.
Residual risks
- Shared-home behavioural change for bare
/?mode=Xbookmarks remains intentional product risk (called out in PR body). - Review ledger row for this tip is local/unpushed (to avoid a ledger-only tip after the main sync); working tree has
pr-1744 heavy review-and-fix@7c19b35a.
Merge left to you.
PR #1744 unblock summaryTip: What blocked (stale context)The reported What I did this pass
Required CI
ResidualWait for required CI (incl. Production UI when selected) to finish on Merge left to you. |
CI triageCI failed on this PR. Automated classification of the 2 failed job(s):
Compared with main CI run #9220 (cancelled). Classification is evidence routing, not permission to ignore a failure. Exact quarantined Playwright identities remain governed by the flake ledger. |
…lity budget Merge origin/main (ledger auto-resolved). Move dashboard payload types, constants, and clinicalQueryModeOptions into clinical-dashboard-payloads.ts and the cold-/ mode seed effect into use-home-mode-seed.ts so ClinicalDashboard.tsx stays within the 4140-line no-growth budget (4124). Update the route-ownership contract test to pin the extracted hook.
…search state Co-authored-by: BigSimmo <87357024+BigSimmo@users.noreply.github.com>
Head branch was pushed to by a user without write access
After /?mode=differentials&q=…&run=1 redirects to /differentials, assert the results surface (not the home template), the mode chrome, and the submitted query heading. Matches the adjacent submitted-route smoke test.
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 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 `@docs/design-system/adoption-manifest.json`:
- Line 1959: Update the adoption manifest entry for the medications route so it
no longer lists ClinicalDashboard, since the route is standalone and renders
MedicationsHomeClient. If the manifest requires a sanctioned pattern, replace it
with the actual pattern mounted by that route.
In `@docs/site-map.md`:
- Line 28: Update the route descriptions in the site map: describe /medications
as the Medication mode home rather than a blanket redirect, set the Documents
mode-page index route to /documents, and describe /?mode=documents as the shared
root home with Documents preselected. Apply these corrections to the entries
around lines 28, 50–76, and 1105 while preserving the rest of the route
documentation.
In `@src/app/`(search-app)/page.tsx:
- Around line 39-43: Preserve the complete parsed search navigation context when
rewriting mode URLs: in src/app/(search-app)/page.tsx#L39-L43, pass it to
appModeHomeHref; in src/app/(search-app)/medications/page.tsx#L34-L39, retain
focus and all supported navigation parameters; and in
src/components/clinical-dashboard/use-home-mode-seed.ts#L38-L42, retain focus
and the same navigation context when adding the remembered mode.
🪄 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: c1aa39bc-604a-41e3-8a12-d2beb2ff9ed5
📒 Files selected for processing (41)
docs/branch-review-ledger.mddocs/codebase-index.mddocs/design-system/ADOPTION.mddocs/design-system/adoption-contract.jsondocs/design-system/adoption-manifest.jsondocs/site-map.mdsrc/app/(search-app)/documents/documents-home-client.tsxsrc/app/(search-app)/documents/page.tsxsrc/app/(search-app)/medications/medications-home-client.tsxsrc/app/(search-app)/medications/page.tsxsrc/app/(search-app)/medications/route.tssrc/app/(search-app)/page.tsxsrc/app/manifest.tssrc/components/ClinicalDashboard.tsxsrc/components/clinical-dashboard/ClinicalSidebar.tsxsrc/components/clinical-dashboard/clinical-dashboard-payloads.tssrc/components/clinical-dashboard/global-search-shell.tsxsrc/components/clinical-dashboard/master-search-header.tsxsrc/components/clinical-dashboard/medication-record-page.tsxsrc/components/clinical-dashboard/use-app-preferences.tssrc/components/clinical-dashboard/use-home-mode-seed.tssrc/components/clinical-dashboard/use-last-app-mode.tssrc/lib/app-modes.tssrc/lib/legacy-home-redirect.tssrc/lib/search-route-ownership.tssrc/lib/search-shell-props.tssrc/lib/tools-catalog.tstests/app-modes.test.tstests/audit-navigation-auth-regressions.test.tstests/design-system-adoption.test.tstests/favourites-auth-gate.dom.test.tsxtests/mode-menu-prefetch.dom.test.tsxtests/pwa-manifest.test.tstests/search-pins-menu.dom.test.tsxtests/search-results-band-adoption.test.tstests/search-route-ownership.test.tstests/site-map.test.tstests/ui-route-coverage.spec.tstests/ui-smoke.spec.tstests/ui-stress.spec.tstests/ui-tools.spec.ts
💤 Files with no reviewable changes (1)
- src/app/(search-app)/medications/route.ts
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Resolve ui-smoke deferred-requests conflict by retaining the Documents home click-away dismiss (shared-home PR) and main's closed-suggestions assertion, without switching modes on /documents.
BigSimmo
commented
Aug 8, 2026
@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 #1744 tip
No sync or code fix this pass — a push would only cancel in-flight CI. Required CI run 31270228126 is pending on this tip. Summary comment posted; ledger left local/unpushed. Merge left to you when CI goes green. |
Co-authored-by: BigSimmo <BigSimmo@users.noreply.github.com>
Co-authored-by: BigSimmo <BigSimmo@users.noreply.github.com>
… docs Include run=1 when Medication search updates the URL so refresh keeps results instead of the shared home. Preserve queryMode/scope/focus on submitted root and /medications redirects. Point Documents home and Medication site-map metadata at the real mode homes and clear the false ClinicalDashboard adoption hit on /medications. Co-authored-by: BigSimmo <BigSimmo@users.noreply.github.com>
PR #1744 review + conflict summaryTip: Previous CI failure (answered)On tip
Merge conflictsReal conflict vs Review findings fixed this pass
CodeRabbit threads for those docs/context items: resolved. Local gates
Residual
Merge left to you when required CI finishes. |
PR #1744 unblock summaryTip: What blockedNothing on this tip for mergeability or review threads. Prior dirty/conflict signals were behind-but-clean and are already cleared on this head. What I did this pass
Required CI
ResidualWait for required CI (incl. Production UI when selected) to finish on Merge left to you. |
Uh oh!
There was an error while loading. Please reload this page.
…mode (#1760) * fix(navigation): keep focus and search context when seeding the home mode The cold-`/` seed rewrote the URL with `appModeSelectionHref(lastAppMode)` and nothing else, so a visit carrying `focus=1` or scope/queryMode context lost it. Seeding only runs when the URL names no mode or query, but those params can still be present, and dropping them silently discarded a requested composer focus and any scoped-search context. Carry the parsed navigation context through, reusing readSearchNavigationContext the same way the root and /medications routes already do. Raised by CodeRabbit on PR #1744. The two sibling sites it flagged (`(search-app)/page.tsx`, `medications/page.tsx`) already preserve the context; this was the only one left. The contract test pinned the old single-line replaceState call, so it now pins the behaviour instead: replaceState rather than push, plus the context being carried. Its fixed 1800-character slice window is gone too — the window had already stopped covering the effect once the doc comment grew, which is exactly how a source-contract test goes quietly blind. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Wa7MTVhAJMztFMMhzJf2J4 * issues: record the web-container Node floor (#285), the pr-handoff-stop false regression (#286), and a third #255 reproduction Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Wa7MTVhAJMztFMMhzJf2J4 * ledger: record the PR #1760 handoff for the home-mode seed follow-up Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Wa7MTVhAJMztFMMhzJf2J4 --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: BigSimmo <BigSimmo@users.noreply.github.com>


Summary
/is now the common home for every one of the 13 modes — the "How can I help?" hero with the composer. The mode pill at the top no longer navigates: it only decides where the composer sends you when you submit. Picking DSM keeps the page exactly where it is and swaps the placeholder to "Search DSM diagnoses or criteria…"; submitting then lands on/dsm/search?q=…. Previously each mode pick ranrouter.push(appModeHomeHref(mode))and replaced the whole page, so the app had 13 front doors and no single home.appModeHomeHrefalready mapped(mode, query)to each mode's search destination, so this is not a routing rewrite. Tools keeps opening its own home (/tools?q=…&run=1) because it has no search route — the requested exception falls out for free. Factsheets routes to its existing/factsheets/search.ask()gained a navigation branch. It previously navigated fordocumentsonly; every other mode ranexecuteSearchin place. That was safe only while "/plus a namespaced mode" was unreachable, which is now the normal state — without this, submitting in DSM would have silently run an in-dashboard search. The branch reusesisDashboardModeHref, soanswer/prescribing/documentsfall through unchanged and every namespaced mode navigates.?mode=withhistory.replaceState(no push, so Back still leaves home rather than stepping through mode picks) and lets the existing render-time URL sync ownsearchMode— never an optimistic state set, per the hero-vs-dock rule indocs/search-chrome-behaviour.md. Off the home, a query in play is carried into the newly picked mode instead of being dropped./?mode=Xrenders the home with X preselected; a submitted deep link (qplusrun=1) still resolves to the mode's own search surface. This is a deliberate meaning change for bare?mode=bookmarks./visit so a shared or reloaded?mode=link never flips after hydration./documentsand/medications. They were the only two modes without their own route, so the shared home would otherwise have left their content — the Documents "Start here" panel with Recent documents / Browse library / Open a source PDF, and the Medication home — unreachable./medicationswas previously a 307 alias for/?mode=prescribing.Two bugs were caught by the Chromium journeys that the unit suite could not see, and are fixed here:
searchModechange and rewrote?mode=back, silently undoing in-app mode changes that do not touch the URL — "Add document" bounced straight back to Answer. It now seeds at most once per mount and never readssearchMode./medicationsis listed inalwaysStandaloneShellPathPrefixes, a documented set of routes that must never mountClinicalDashboard(that exclusion is what fixed duplicate page-rootdata-testids under CI load). The new mode home therefore rendered header and composer over an empty body. It now owns its own body, exactly as/toolsand/servicesdo.Verification
Verification not run: npm run verify:pr-localandUI verification not run: npm run verify:ui— both stop atcheck:installed-lock-paritybefore executing anything, because this container ships Playwright 1.62.0 against a locked 1.62.1. That mismatch is pre-existing and unrelated to this diff, andnpm cicannot repair it here (Node is 24.13.0 whilejsdom@30.0.1requires^24.15.0underengine-strict). No manifest or lockfile was modified to work around it.Everything those two gates would have run was therefore run directly, and the browser evidence is real rather than skipped:
Chromium journeys — the full PR set, via the repo's own runner and isolated production server (
npm run test:e2e:pr, withPLAYWRIGHT_CHROMIUM_EXECUTABLE_PATHpointed at the container's Chromium, since its bundled rev 1194 predates the rev 1234 the packaged versions expect):406 passed, 2 failed (11.5m).bc33d41, so neither is caused by this diff:ui-pwa.spec.ts"has a browser-valid manifest…" (Chromium reports installability errorin-incognito) andui-smoke.spec.ts"document viewer puts the PDF preview first with pinned evidence after it on mobile". This diff touches no manifest, service-worker, icon, or document-viewer file.Unit suite:
Test Files 522 passed | 1 failed (523)/Tests 5608 passed | 1 failed | 4 skipped (5613). The single failure istests/pr-handoff-stop.test.ts, which also fails on a clean checkout of the base commit.npm run lint: clean.npx tsc --noEmit: clean (exit 0).npm run sitemap:check,docs:check-index(all 50 repository roots/modules/routes … indexed),docs:check-inventory,check:design-system-contract(53 components and 7 guidelines),check:outstanding-issues(275 rows … unique ids): all pass.npm run formatwas run and committed.npm run verify:releasebefore release or handoff confidence claimsNot a release handoff, and it is provider-backed.
npm run eval:retrieval:qualityRAG impact: no retrieval behaviour change— no file undersrc/lib/rag/**, clinical-search, retrieval-selection, ranking-config, answer-ranking, the eval harness, or the golden fixture is touched.classifyPullRequestFilesreportsragRanking: false. Only which URL the composer navigates to changed; retrieval, ranking and answer generation are untouched.npm run check:production-readinessNo clinical workflow, privacy, environment, Supabase, source-governance, or deployment behaviour changed.
Risk and rollout
ClinicalDashboard.tsx, which owns the answer flow, document search, the medication workspace, and the Tools and Favourites hubs in one large component. The shared home is inserted as a single branch above that chain, which shadows five existing branches. It is gated strictly on "home route and nothing submitted", so every submitted path still reaches exactly the branch it reached before. The second risk is behavioural rather than structural: bare/?mode=Xchanges meaning from "redirect to/X" to "home with X preselected", so an existing bookmark of a bare?mode=URL now lands on the shared home instead of the mode page. Submitted deep links are preserved.localStoragekey (clinical-kb-last-app-mode), which is read defensively and falls back to Answer for any absent, malformed, or retired value.Clinical Governance Preflight
Clinical KB Database(sjrfecxgysukkwxsowpy)This change is navigation only. It alters which URL the shared composer routes to and which surface
/renders; it does not touch retrieval, ranking, answer generation, answer verification, citation rendering, source governance, or document access scoping. Owner-scoping and private-scope handling are unchanged, and the conservative source-only degradation path is untouched.Notes
/?mode=documentsand/?mode=prescribingwere hardcoded in the sidebar, the tools catalogue, and a number of Playwright specs. Those are mechanical repoints to the new/documentsand/medicationshomes, but they are worth an eye at review.tailwind-mergewas declared inpackage.jsonbut absent fromnode_modules(restored at its locked3.6.0), andnpm cicannot complete here because Node is 24.13.0 whilejsdom@30.0.1requires^24.15.0underengine-strict. No manifest or lockfile was modified.therapy-compassstill reaches its search page through a serverredirect()rather than the helper's path swap. That asymmetry predates this change and is left alone.Generated by Claude Code
Summary by CodeRabbit
/documentsand/medicationshome pages.