Skip to content

Remove Evidence-based and All sources chips from answer footer - #285

Closed
BigSimmo wants to merge 20 commits into
cursor/fix-all-db-issues-5f13from
cursor/remove-answer-bar-chips-8b1a
Closed

Remove Evidence-based and All sources chips from answer footer#285
BigSimmo wants to merge 20 commits into
cursor/fix-all-db-issues-5f13from
cursor/remove-answer-bar-chips-8b1a

Conversation

@BigSimmo

@BigSimmoBigSimmo commented Jul 5, 2026

Copy link
Copy Markdown
Owner

Summary

Removes the Evidence-based and All sources footer chips from the answer-mode composer on all screen sizes. The answer bar now shows only the input pill and send button.

Scope and evidence remain reachable via the integrated + menu (Scope and Evidence map actions).

Changes

  • master-search-header.tsx: Hide footer chip row when searchMode === "answer" only (other modes unchanged).
  • ui-accessibility.spec.ts / ui-smoke.spec.ts: Open document scope via + menu (Scope) instead of removed footer chip.
  • capture-chrome-parity.ts: Drop selectors for removed chip buttons.

Verification

  • npm run test:e2e:accessibility — 2 passed (on PR branch)
  • demo answer flow reaches a source-backed answer smoke test — passed (on PR branch)
  • Screenshot capture script added: scripts/capture-answer-bar-screenshot.ts

Notes

  • Do not replace with showFooterSearchChips = false — that hides chips for all modes. The correct guard is searchMode !== "answer".
  • Other modes (documents, forms, services, etc.) keep their footer chips unchanged.
  • Optional follow-up: tighten answer-mode bottom padding in ClinicalDashboard.tsx now that the chip row is gone.
Open in WebOpen in Cursor

BigSimmoand others added 19 commits July 3, 2026 21:00
The golden retrieval set was 100% lexical fast-path (embedding_skipped_rate=1.0), so
it could not measure whether a re-index changes vector/embedding retrieval quality.
- forceEmbedding option on searchChunksWithTelemetry (SearchChunksArgs): bypasses every
lexical text-fast-path so retrieval always exercises the embedding/vector stage.
Diagnostic/eval-only; folded into the search cache key; never set on production paths.
- eval-retrieval.ts: per-case `forceEmbedding` field + a global `--force-embedding` flag.
- 10 `vector-*` cases (psychiatric monographs: PTSD, OCD, panic, anorexia, GAD, Tourette,
postnatal, bipolar, ADHD, opioid) with forceEmbedding=true. Each is a clinical query that
must be answered by vector retrieval of the right monograph — verified live at
document_recall@5=1.0, content_recall@5=1.0, all via strategy=hybrid (embedding used).
Rationale: forcing embedding is the correct instrument for re-index measurement — you want
to measure the vector index directly, not have a lexical shortcut mask a regression. Wording
alone can't reliably force the vector path (the fast-path is driven by emergent lexical-match
strength), so the flag makes these probes deterministic.
Live golden eval: 34/34 pass (24 existing + 10 new), no regression. verify:cheap green (980).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Wire forceEmbedding through eval runners and retrieval cache keys, bypass coverage/lexical shortcuts when forced, and add golden-case failure metrics so vector regressions cannot hide behind text-fast-path or cache hits.
…board
Delete post-extraction dead code left in the monolith and trim unused imports. Also fix minor lint issues in favourites-hub, visual-evidence, and services-navigator.
…rdening
fix(access): complete public retrieval scope and production access hardening
fix: restore anonymous production setup-status for psychiatry.tools
@supabase

supabaseBot commented Jul 5, 2026

Copy link
Copy Markdown

This pull request has been ignored for the connected project sjrfecxgysukkwxsowpy due to reaching the limit of concurrent preview branches.
Go to Project Integrations Settings ↗︎ if you wish to update this limit.


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

@BigSimmo
BigSimmo marked this pull request as ready for review July 5, 2026 16:38
@cursor

cursorBot commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

@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

Copy link
Copy Markdown
OwnerAuthor

Closing because the base branch (\cursor/fix-all-db-issues-5f13, PR #281) was closed as superseded/conflicted.

If this UX change is still wanted, cherry-pick onto a fresh branch from current \main\ and open a new PR targeting \main.

@BigSimmoBigSimmo closed this Jul 5, 2026

@cursorcursorBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 6 potential issues.

Fix All in Cursor

Bugbot Autofix prepared fixes for all 6 issues found in the latest run.

  • ✅ Fixed: Answer dock inset still includes chips
    • Reduced the default composer inset from 132px to 88px for the chipless answer footer and added a screen-reader-only scope trigger so focus restoration still works when footer chips are hidden.
  • ✅ Fixed: One-shot commit script in repo
    • Deleted scripts/commit-access-rag-fix.mjs so the one-shot auto-commit maintenance script is no longer in the repository.
  • ✅ Fixed: Signed-in answers skip public corpus
    • Updated retrieval_owner_matches so owner-scoped retrieval also matches public rows (owner_id IS NULL), aligning hybrid RAG with withOwnerReadScope for signed-in users.
  • ✅ Fixed: Tool selection jumps while typing
    • Pinned the selected tool id while the detail panel is open so typing in the search box no longer re-derives the highlighted tool mid-edit.
  • ✅ Fixed: Public uploads invisible to uploaders
    • Anonymous public uploads now persist with owner_id null and a public/ storage prefix so list, read, and retrieval paths that scope to public rows can see them immediately.
  • ✅ Fixed: Upload rate limit bucket missing
    • Added the document_upload bucket to ApiRateLimitBucket with default and anonymous limit maps so upload rate limiting resolves configured limits instead of undefined.

You can send follow-ups to the cloud agent here.

Reviewed by Cursor Bugbot for commit 7a0166d. Configure here.

const phoneMediaQuery = "(max-width: 639px)";

// Reserved height for the fixed answer footer composer (pill + chips + safe area).
const defaultComposerInsetPx = 132;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Answer dock inset still includes chips

Medium Severity

In answer mode, footer chips are no longer rendered. This causes two issues: the useCollapseWhenContentBelow hook's composerInsetPx (132px) is too large, leading to the Clinical notes/Evidence row collapsing prematurely, becoming inert, and blocking taps on mobile. Additionally, focus restoration after closing a document scope fails because the scopeSummaryRef is missing.

Additional Locations (1)
Fix in CursorFix in Web

Reviewed by Cursor Bugbot for commit 7a0166d. Configure here.

);
execSync('git commit -m "fix(rag): scope anonymous retrieval to public documents via owner sentinel"', {
stdio: "inherit",
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One-shot commit script in repo

High Severity

The commit-access-rag-fix.mjs script is a one-shot maintenance script that overwrites core library and schema files and then automatically commits the changes. This creates a serious footgun, risking unintended local commits and data corruption if executed in dev or CI environments.

Additional Locations (1)
Fix in CursorFix in Web

Reviewed by Cursor Bugbot for commit 7a0166d. Configure here.

/** Scope reads to public rows (owner_id IS NULL) and, when signed in, the caller's owned rows. */
export function withOwnerReadScope<T extends OwnerScopedQuery<T>>(query: T, ownerId: string | undefined): T {
if (ownerId) return query.eq("owner_id", ownerId);
if (ownerId) return query.or(`owner_id.eq.${ownerId},owner_id.is.null`);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Signed-in answers skip public corpus

Medium Severity

Document reads for signed-in users now include public rows via withOwnerReadScope, but answer retrieval still passes allowGlobalSearch: !access.ownerId, so hybrid RPCs filter to the user’s owner_id only. Public indexed guidelines visible in the library can be excluded from source-backed answers while signed in.

Additional Locations (1)
Fix in CursorFix in Web

Reviewed by Cursor Bugbot for commit 7a0166d. Configure here.

queryKey: (controlledQuery ?? "").trim().toLowerCase(),
id: initialToolId(controlledQuery),
}));
const selectedId = selection.queryKey === normalizedQuery ? selection.id : queryDerivedId;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tool selection jumps while typing

Low Severity

selectedId falls back to queryDerivedId whenever the query string differs from selection.queryKey, so editing the search box re-derives the highlighted tool before the user submits or picks a row. An open detail panel can switch tools mid-typing.

Fix in CursorFix in Web

Reviewed by Cursor Bugbot for commit 7a0166d. Configure here.

const uploadOwnerId = access.ownerId ?? (publicUploadsEnabled() ? publicWorkspaceOwnerId() : null);
if (!uploadOwnerId) {
return NextResponse.json({ error: "Public uploads are not configured for this workspace." }, { status: 503 });
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Public uploads invisible to uploaders

High Severity

Anonymous public uploads are stored with owner_id set to PUBLIC_WORKSPACE_OWNER_ID, but anonymous document reads and global RAG only include rows where owner_id is null (via withOwnerReadScope and PUBLIC_OWNER_FILTER_SENTINEL). After a successful upload, the same anonymous user cannot list, open, or retrieve that document in search/answer until it is promoted to a public row.

Additional Locations (2)
Fix in CursorFix in Web

Reviewed by Cursor Bugbot for commit 7a0166d. Configure here.

supabase: adminSupabase,
subject: access.rateLimitSubject,
bucket: "document_upload",
allowInMemoryFallbackOnUnavailable: allowRateLimitInMemoryFallbackOnUnavailable(),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Upload rate limit bucket missing

Medium Severity

The upload route passes document_upload to consumeSubjectApiRateLimit, but that bucket is not defined in ApiRateLimitBucket or the default limit maps. Anonymous upload rate limiting has no configured limits and can throw when resolving defaults if this path runs.

Additional Locations (1)
Fix in CursorFix in Web

Reviewed by Cursor Bugbot for commit 7a0166d. Configure here.

BigSimmo pushed a commit that referenced this pull request Aug 8, 2026
cursorBot pushed a commit that referenced this pull request Aug 8, 2026
…tionHeader rows
Conflict on docs/outstanding-issues.md: main owned #285 (jsdom/Node floor);
renumber this PR's authorizationHeader trap to #286 and bump next-id to 287.
cursorBot pushed a commit that referenced this pull request Aug 8, 2026
Resolve docs/outstanding-issues.md by keeping #285/#286 and next-id=287
from the branch (superset of main's single #285 row).
Co-authored-by: BigSimmo <BigSimmo@users.noreply.github.com>
cursorBot pushed a commit that referenced this pull request Aug 8, 2026
…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>
BigSimmo added a commit that referenced this pull request Aug 9, 2026
… header (#1766)
* feat(in-page-nav): convert the six information routes onto the shared header
PR 2 of the in-page navigation series. PR 1 (#1740) extracted the
DocumentViewer in-page navigation template into src/components/in-page-nav/
and converted the differentials detail page as proof. This converts the six
routes still drawing the shell-owned "On this page" pill rail — services,
forms, specifiers (record and catalogue reference), formulation, and the two
DSM diagnosis routes — then deletes the rail behind them.
Three things the conversion needed first:
- InPageNavHeader's `actions` was a render prop. Four of the seven components
in scope are Server Components, and React cannot pass a function across that
boundary, so `actions` is widened to `ReactNode | ((close) => ReactNode)`.
`onSelectSection` and `PageSection.icon` have the same problem, so those four
pages mount the header through a small "use client" sibling module that owns
the section table and the hooks and takes `actions` as a slot.
- Both sheets now derive their open state from the current pathname, so
navigating closes them. Server-passed action JSX is mostly <Link>s and has no
way to call close().
- Information-page sections carried no scroll-mt at all. A shared `inPageAnchor`
token consumes `--inpage-anchor-offset`, published from the live chrome height
by useInPageChromeMetrics, which InPageNavHeader calls itself.
The measurement behind both anchor offsets is now useStickyChromeMetrics in
src/components/sticky-chrome-metrics.ts, shared with the document viewer.
use-document-chrome-metrics.ts keeps its selector and custom-property literals
verbatim, because header-scroll-hide-contract.test.ts pins that file's source.
Two DSM routes declared section anchors that nothing rendered, so
/dsm/diagnoses/<slug>/differentials drew one nav entry out of four declared and
/dsm/diagnoses/<slug> drew three out of five. Both are wired in, asserted
against rendered DOM rather than a source grep (/issues #256's stop rule) by the
new tests/in-page-nav-route-sections.dom.test.tsx, which covers all seven
components including present-and-absent cases for the conditional anchors.
Rail removal: hasLocalInformationPageNavigation collapses to isInformationPage,
because every information page now owns its navigation; the `section` kind and
its scroll spy leave secondary-navigation.tsx. That leaves the component with no
production constructor at all — RegistryModeNav renders ModeNav, not
SecondaryNavigation — which is folded into /issues #271 rather than resolved
here.
Also corrects /issues #256: its Forms half was stale, all six form anchors
render. Records /issues #285 for a pre-existing ui-smoke phone scroll-hide flake
at base commit 9ab3b73, proven on pristine source in the same worktree.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* docs(ledger): record the in-page-nav PR 2 review
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* fix(in-page-nav): repair the service-detail test mock and share the slug-detail test
`InPageNavHeader` calls `usePathname()`, so every test that renders a converted
page needs it on the `next/navigation` mock. `tests/service-detail-page.dom.test.tsx`
mocked only `useRouter`, which failed three cases in CI's Unit coverage job with
`No "usePathname" export is defined on the "next/navigation" mock`. It was the
only such gap: the other eight test files mocking `next/navigation` without
`usePathname` render no converted page.
Review follow-ups:
- `tests/in-page-nav-header.dom.test.tsx` resets its module-level `pathname` in
`beforeEach`. The route-change case left it at `/specifiers/compare`, so
outcomes depended on file order.
- `header-addon-slot.ts` now calls the exported `isSlugDetail` from
`information-pages.ts` instead of its own hand-copied equivalent. Every
claimant route it names must also be `isInformationPage`, and two slug tests
are how that agreement would silently diverge.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
BigSimmo pushed a commit that referenced this pull request Aug 9, 2026
…lready require
jsdom@30 requires Node ^24.15.0, but engines.node said "24.x" and every gate
compared majors only. A container on 24.13.0 therefore passed check:runtime and
the preinstall hook, then failed `npm ci` with an opaque EBADENGINE for a
transitive package. That blocked local verification on PRs #1611, #1697, #1705
and #1740, each worked around by hand.
- package.json: engines.node "24.x" -> ">=24.15.0 <25", declaring the floor the
dependency tree already imposes. This cannot newly break any environment that
currently installs, since jsdom enforces the same floor during `npm ci`.
- check-node-engine.cjs (npm preinstall): compare the full version against that
range instead of the major, so the failure names the real requirement. Kept
import-free — the Dockerfile COPYs this file alone before `npm ci` — with the
range restated as a literal and pinned to package.json by test.
- check-runtime.ts: add NODE_MINIMUM_VERSION and reject a matching major below
it. This gate fronts verify:cheap, :ui, :release and :pr-local.
- session-start.sh: provision 24.19.0, and make the install guard floor-aware.
The old major-only test meant a cached container already on 24.13 skipped the
install entirely, so bumping the pin alone would not have upgraded it.
- check-codex-cloud-setup.mjs: accept the range form, still requiring its major
to track .node-version.
Closes#285.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XZHZjz6kX8Ly1qBvvCg29C
Sign up for freeto 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.

1 participant

@BigSimmo