Skip to content

Fix search page defects across documents, services, forms, favourites, and differentials#320

Merged
BigSimmo merged 1 commit into
mainfrom
claude/search-pages-review-f4xmhp
Jul 6, 2026
Merged

Fix search page defects across documents, services, forms, favourites, and differentials#320
BigSimmo merged 1 commit into
mainfrom
claude/search-pages-review-f4xmhp

Conversation

@BigSimmo

@BigSimmo BigSimmo commented Jul 6, 2026

Copy link
Copy Markdown
Owner

Summary

  • Reviewed every search surface (root dashboard modes, /documents/search, /services, /forms, /favourites, /differentials) and fixed the confirmed defects:
  • URL builder (src/lib/app-modes.ts): appModeHomeHref built malformed double-? URLs for prescribing/tools mode homes (e.g. /?mode=prescribing?focus=1), which failed mode parsing and dropped users into Answer mode. It now uses the right separator, and namespaced modes only emit run=1 alongside a query.
  • Documents search (master-document-flow-mockups.tsx): the results filter OR-ed the query, type, and default-slug predicates, so the query never filtered anything and the type tabs could only ever add results — now query AND type, with an explicit no-results state. Result rows surface evidence matching the active type tab (instead of always evidence[0] with a hardcoded table icon), documents with no extracted evidence no longer borrow the clozapine fixture's evidence in search rows, reader evidence tab counts are derived from the document rather than hardcoded to 1, "Open document" from evidence context preserves the viewed evidence page/chunk, and the evidence sidebar shows the document's own source path and updated date.
  • Services (services-navigator-page.tsx, services/page.tsx): the navigator no longer flashes a false "No matches" while the registry loads (skeleton + loading header band); the "ATSI-specific" quick chip now searches "Aboriginal Torres Strait Islander" (the term the catalogue actually contains — atsi appears nowhere and the chip previously matched on the word "specific"); the server wrapper normalizes an array-valued run param the same way it already normalized q/query.
  • Forms (forms-search-results-page.tsx): the empty state now offers a working "try an example" action (mirrors services); result badge codes map to the form record by slug instead of row position, so ranking changes can no longer disagree with the pathway panel (4A = Transport order etc.); the "Matched because" column interpolates the actual query instead of a hardcoded "transport".
  • Favourites (favourites-library-nav.tsx, favourites-command-library-page.tsx): selecting a Quick View clears a lingering set filter whose sidebar highlight would otherwise disappear while still filtering results; the sort control is disabled in the Recently used view it cannot affect; the continue strip is gated on scope-filtered items so it can't advertise an item absent from the list below; run-action saved searches are labelled "Saved search" instead of "Source".
  • Differentials (src/lib/differentials.ts): snapshot loaders now drop markdown-header preset artifacts (the literal # Scenario Presets pill in "Recent work") and numeric field-weight alias entries (e.g. tags → ["1.1"]) that made /api/differentials query expansion match unrelated records by number substrings.

Review findings deliberately not changed: the forms ranker's services guard and injected catalogue tokens are intentional (asserted by tests/forms.test.ts), and /differentials?q=…&run=1 / /forms?q=…&run=1 already render working results via the GlobalSearchShell layout override.

Verification

  • npm run verify:cheap
  • npm run verify:ui when UI, routing, styling, browser behavior, reduced-motion, or forced-colors behavior changed — not run: this environment has no configured browser project secrets; npm run typecheck, lint, and the full vitest suite (1097 passing) were run instead
  • npm run verify:release before release or handoff confidence claims — not applicable to this PR
  • npm run format:check
  • npm run eval:retrieval:quality (must stay 23/23) — not run: requires live Supabase/OpenAI keys unavailable in this environment. RAG retrieval/ranking/chunking/scoring code paths are untouched; the only search-logic changes are to client-side fixture filtering (documents mockup) and the differentials static-catalog alias map (which previously matched records on leaked numeric weights)
  • npm run eval:rag / eval:quality — answer generation and synthesis are untouched
  • npm run check:production-readiness — no clinical workflow, privacy, environment, Supabase, or deployment behavior changed
  • npm run check:deployment-readiness — no deployment behavior changed

Clinical Governance Preflight

  • Source-backed claims still require linked source verification before clinical use
  • No patient-identifiable document workflow was introduced or expanded without explicit governance approval
  • Supabase target remains Clinical KB Database (sjrfecxgysukkwxsowpy) — no env or Supabase changes
  • Service-role keys and private document access remain server-only
  • Demo/synthetic content remains clearly separated from real clinical sources (documents search rows now stop borrowing another document's fixture evidence, improving this separation)
  • Source metadata, review status, and outdated/unknown-source behavior remain conservative
  • Deployment classification/TGA SaMD impact was checked when clinical decision-support behavior changed — no clinical decision-support behavior changed

Notes

  • The documents /documents/search surface is fixture-backed by design; the filter fix makes the sample behave like a real search (query narrows, tabs narrow, empty state reachable).
  • The differentials snapshot itself was left untouched; junk rows are filtered at the loader so regeneration cannot reintroduce the bug silently.

🤖 Generated with Claude Code

https://claude.ai/code/session_015rc3tTjs65D4gFBuCQhZGs


Generated by Claude Code


Note

Medium Risk
Touches shared URL building and several user-facing search flows (including differentials query expansion), but changes are defensive fixes to filtering and routing rather than new clinical logic or backend retrieval.

Overview
Fixes search and navigation defects across multiple clinical surfaces so queries, filters, and deep links behave consistently.

appModeHomeHref now uses & when appending params to mode homes that already contain ?, and only adds run=1 when a query is present—avoiding broken URLs and spurious “submitted search” states.

Documents search mockup tightens filtering to query AND evidence type (replacing OR logic that ignored the query), adds empty states, and aligns rows with the active evidence tab. Documents without extracted evidence show snippets and “No extracted evidence” instead of borrowing another fixture; reader/evidence links preserve page/chunk; evidence tab counts and sidebar metadata come from the active document.

Services shows a loading skeleton and header loading state while the registry loads (no premature empty state), normalizes array run search params on the server route, and maps the ATSI quick chip to catalogue-friendly search text.

Forms wires empty-state “try an example” through appModeHomeHref, maps pathway badge codes by form slug, and surfaces the user’s query in “Matched because” copy.

Favourites clears set filters when switching Quick views, disables sort in Recently used, gates the continue strip on scope-filtered items, and labels run-action source items as Saved search.

Differentials loader filters markdown-header preset junk and numeric-only search aliases from generated snapshots so API search expansion does not match unrelated records.

Reviewed by Cursor Bugbot for commit 4a31942. Configure here.

…, and differentials

Review of every search surface found and fixed:

- app-modes: appModeHomeHref built malformed double-? URLs for
  prescribing/tools mode homes (e.g. /?mode=prescribing?focus=1), which
  dropped users into Answer mode; run=1 is now only emitted with a query
  on namespaced modes as well.
- Documents search: result filter OR-ed the query, type, and default-slug
  predicates so the query never filtered anything; now query AND type with
  an explicit no-results state. Result rows surface evidence matching the
  active type tab instead of always evidence[0] with a hardcoded table
  icon, documents without extracted evidence no longer borrow the
  clozapine fixture on search rows, reader evidence tab counts are derived
  from the document, and Open document links from evidence context keep
  the viewed evidence page/chunk. Evidence sidebar shows the document's
  own source path and updated date.
- Services: navigator no longer flashes "No matches" while the registry
  loads (skeleton + loading header band), the ATSI-specific chip now
  searches terms that exist in the catalogue, and the server wrapper
  normalizes an array-valued run param like it already did for q/query.
- Forms: empty state gains a working "try an example" action, result
  badge codes map to the form record instead of row position (so codes
  agree with the pathway panel), and the "Matched because" column reflects
  the actual query instead of a hardcoded "transport".
- Favourites: quick views clear a lingering (and hidden) set filter, the
  sort control is disabled in the Recently used view it cannot affect,
  the continue strip respects command scopes, and run-action saved
  searches are labelled "Saved search" instead of "Source".
- Differentials: generated snapshot loaders drop markdown-header preset
  artifacts ("# Scenario Presets" pill) and numeric field-weight entries
  that polluted search alias expansion with substring matches like "1.1".

Verified with npm run typecheck, lint, test (1097 passing), format:check,
and verify:cheap.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015rc3tTjs65D4gFBuCQhZGs
@supabase

supabase Bot commented Jul 6, 2026

Copy link
Copy Markdown

This pull request has been ignored for the connected project sjrfecxgysukkwxsowpy because there are no changes detected in supabase directory. You can change this behaviour in Project Integrations Settings ↗︎.


Preview Branches by Supabase.
Learn more about Supabase Branching ↗︎.

@BigSimmo
BigSimmo marked this pull request as ready for review July 6, 2026 12:37
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@BigSimmo
BigSimmo merged commit 4172a73 into main Jul 6, 2026
5 checks passed
BigSimmo pushed a commit that referenced this pull request Jul 6, 2026
…generator fixes, session hook

Follow-up to PR #320's search page review, addressing the remaining items:

- Services navigator: stop silently rendering fixture records when the
  registry is unauthorized or errored - show the same session-expired /
  load-error notices as the services home and detail pages. Demo mode is
  unaffected (the registry API serves fixtures as status ready).
- Documents flow: findEvidence no longer borrows another document's
  fixture evidence, so deep links to documents without extracted evidence
  render an explicit "No extracted evidence" state in the reader hit
  panel and a dedicated notice page on the evidence detail route.
- Differentials export parser: drop the markdown preamble section that
  became a bogus "# Scenario Presets" preset and "# Red Flag Flows" flow,
  and drop bare-number field-weight rows from the search alias table;
  cleaned the checked-in snapshot to match and added parser regression
  tests. Runtime loader filters from #320 remain as defence in depth.
- Differentials search results: rank the real catalogue with
  rankDifferentialRecords/searchPresentationWorkflows when a query is
  present (the acute-confusion walkthrough remains the empty-query demo),
  and reword the demo-content notice accordingly.
- Forms results: inert mock controls (secondary tabs, refine rail, view
  full pathway, mobile filters) are now disabled with "Coming soon"
  affordances matching the documents page; "View all forms" links to
  /forms and "Open Form 4A" links to the transport order form.
- Favourites: drop the key={query} remount so clearing a search no longer
  wipes set/type/view/sort selections, and span the empty row correctly
  on both sides of the lg breakpoint.
- Deleted the unused ServicesNavigatorPreview component (no importers,
  hardcoded overflow badge, fixture-only search).
- Added a web-only SessionStart hook that installs Node 24 (the repo is
  engine-strict node 24.x) into a cached location and runs npm ci when
  node_modules is missing, so remote sessions are productive immediately.
- Lint: removed the unused AnswerEmptyState onPickSample prop and two
  unused type imports; added the derived canUsePrivateApis to the
  DocumentViewer fetch effect deps (no behavioural change - its inputs
  were already dependencies).
- Documented the answer-thread Back-button URL/state question in
  docs/process-hardening.md as an open product decision with a guardrail.

Verified with typecheck, lint, vitest (1142 passing), format:check, and
npm run verify:ui (106 chromium Playwright tests passing).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015rc3tTjs65D4gFBuCQhZGs
BigSimmo pushed a commit that referenced this pull request Jul 6, 2026
…generator fixes, session hook

Follow-up to PR #320's search page review, addressing the remaining items:

- Services navigator: stop silently rendering fixture records when the
  registry is unauthorized or errored - show the same session-expired /
  load-error notices as the services home and detail pages. Demo mode is
  unaffected (the registry API serves fixtures as status ready).
- Documents flow: findEvidence no longer borrows another document's
  fixture evidence, so deep links to documents without extracted evidence
  render an explicit "No extracted evidence" state in the reader hit
  panel and a dedicated notice page on the evidence detail route.
- Differentials export parser: drop the markdown preamble section that
  became a bogus "# Scenario Presets" preset and "# Red Flag Flows" flow,
  and drop bare-number field-weight rows from the search alias table;
  cleaned the checked-in snapshot to match and added parser regression
  tests. Runtime loader filters from #320 remain as defence in depth.
- Differentials search results: rank the real catalogue with
  rankDifferentialRecords/searchPresentationWorkflows when a query is
  present (the acute-confusion walkthrough remains the empty-query demo),
  and reword the demo-content notice accordingly.
- Forms results: inert mock controls (secondary tabs, refine rail, view
  full pathway, mobile filters) are now disabled with "Coming soon"
  affordances matching the documents page; "View all forms" links to
  /forms and "Open Form 4A" links to the transport order form.
- Favourites: drop the key={query} remount so clearing a search no longer
  wipes set/type/view/sort selections, and span the empty row correctly
  on both sides of the lg breakpoint.
- Deleted the unused ServicesNavigatorPreview component (no importers,
  hardcoded overflow badge, fixture-only search).
- Added a web-only SessionStart hook that installs Node 24 (the repo is
  engine-strict node 24.x) into a cached location and runs npm ci when
  node_modules is missing, so remote sessions are productive immediately.
- Lint: removed the unused AnswerEmptyState onPickSample prop and two
  unused type imports; added the derived canUsePrivateApis to the
  DocumentViewer fetch effect deps (no behavioural change - its inputs
  were already dependencies).
- Documented the answer-thread Back-button URL/state question in
  docs/process-hardening.md as an open product decision with a guardrail.

Verified with typecheck, lint, vitest (1142 passing), format:check, and
npm run verify:ui (106 chromium Playwright tests passing).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015rc3tTjs65D4gFBuCQhZGs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants