Skip to content

Fix signed-out answer search fallback - #319

Merged
BigSimmo merged 6 commits into
mainfrom
cursor/fix-public-answer-search-2a07
Jul 6, 2026
Merged

Fix signed-out answer search fallback#319
BigSimmo merged 6 commits into
mainfrom
cursor/fix-public-answer-search-2a07

Conversation

@BigSimmo

@BigSimmo BigSimmo commented Jul 6, 2026

Copy link
Copy Markdown
Owner

Summary

  • Keep unauthenticated answer/search/read requests working when the durable anonymous limiter is unavailable by using the existing in-memory limiter fallback for public read paths.
  • Add a visible non-production demo fallback for invalid Supabase API-key configuration across /api/search, /api/answer, and streamed /api/answer/stream, while production remains fail-closed.
  • Fix the client answer stream reader so final SSE events render immediately, enable preview fallback search from the UI, and close the command menu after submit.
  • Add regression coverage for anonymous search, non-streamed answers, streamed answers, upload fallback boundaries, and production guards.

signed_out_answer_search_final.mp4

Verification

  • npm run verify:cheap
  • npm run verify:ui when UI, routing, styling, browser behavior, reduced-motion, or forced-colors behavior changed
  • npx playwright test tests/ui-tools.spec.ts:1007 --project=chromium
  • GitHub CI verify passed on latest commit aa7bd2e
  • GitHub CI ui-smoke passed on latest commit aa7bd2e
  • GitHub Secret Scan Gitleaks passed on latest commit aa7bd2e
  • npm run verify:release before release or handoff confidence claims
  • npm run format:check
  • npm run eval:retrieval:quality (must stay 23/23) when retrieval, ranking, selection, chunking, or scoring behavior changed — not run; access/fallback/client-stream fix does not change retrieval/ranking/scoring.
  • npm run eval:rag -- --limit 15 + npm run eval:quality -- --rag-only when answer generation, the synthesis prompt, or answer post-processing changed — not run; no synthesis/prompt/post-processing changes.
  • npm run check:production-readiness when clinical workflow, privacy, environment, Supabase, source governance, or deployment behavior changed
  • npm run check:deployment-readiness when deployment startup, hosting, or rollout 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)
  • Service-role keys and private document access remain server-only
  • Demo/synthetic content remains clearly separated from real clinical sources
  • Source metadata, review status, and outdated/unknown-source behavior remain conservative
  • Deployment classification/TGA SaMD impact was checked when clinical decision-support behavior changed

Notes

  • Current Cloud Agent Supabase keys are rejected by Supabase as an unregistered API key; this PR keeps non-production/preview search usable with clearly marked synthetic fallback data, but production still requires corrected live Supabase secrets.

To show artifacts inline, enable in settings.

Open in Web Open in Cursor 

cursoragent and others added 5 commits July 6, 2026 06:21
Co-authored-by: BigSimmo <BigSimmo@users.noreply.github.com>
Co-authored-by: BigSimmo <BigSimmo@users.noreply.github.com>
Co-authored-by: BigSimmo <BigSimmo@users.noreply.github.com>
Co-authored-by: BigSimmo <BigSimmo@users.noreply.github.com>
Co-authored-by: BigSimmo <BigSimmo@users.noreply.github.com>
@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 09:10
@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.

Co-authored-by: BigSimmo <BigSimmo@users.noreply.github.com>
@BigSimmo
BigSimmo merged commit 20485c9 into main Jul 6, 2026
5 checks passed
@BigSimmo
BigSimmo deleted the cursor/fix-public-answer-search-2a07 branch July 8, 2026 16:25
BigSimmo pushed a commit that referenced this pull request Aug 14, 2026
…flight

CI failed `docs:check-links` on this branch with

  Error: cancel request 2e791c01... targets missing pending request
  210e3db5...

`check-docs-links.mjs` replays the inbox batch to resolve link targets, so
an unresolvable request fails it. The cause was a race, not a bad record:
PR #1936 reconciled 75 queued requests -- 210e3db5 among them -- while
this branch was already in flight. Reconciling moves the request file
into `docs/outstanding-issues-inbox/applied/` and allocates it a canonical
row, so by the time this branch merged main there was no pending request
left for the cancellation to name.

Cancelling was the right call against a pending request and is the wrong
one against a reconciled row. The cancel is dropped and replaced with a
`done` against `#319`, the row 210e3db5 became. That is also the better
record: the work is finished rather than withdrawn, so the ledger should
carry its outcome and its guard, which a cancellation would have thrown
away.

Also merges origin/main (this branch was 3 behind) and files two findings
the PR preflight surfaced, both deliberately not fixed here:

  - `check:medication-lexicon-report` has been failing on main for every
    local `verify:pr-local`, and no CI job runs it -- a grep over
    .github/workflows finds nothing. It is the last step of the local
    chain, so it fails preflights while CI stays green. The stale file is
    a clinical-facing generated document; regenerating it inside a
    CSS-token PR would bundle a clinical-risk artefact with unrelated
    chores.
  - Claude Code web containers can ship Node 22 with no node_modules,
    which fails `npm ci` on engine-strict before any repo script can run.

Re-verified after the merge: the tracked tree still holds zero
`--shadow-tight` references, and every pinned ratchet still measures
exactly its baseline, so the merge moved no metric and the pins stay
honest.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XsBPUoxpsvTwvFMJzrNoyz
BigSimmo added a commit that referenced this pull request Aug 14, 2026
…bt rows (#1942)

* refactor(tokens): re-land the --shadow-tight retirement onto --e1

PR #1803 retired the --shadow-tight role alias in favour of the --e1
elevation tier across 49 files and squash-merged as 9d8370a on
2026-08-10. The acf78bf merge on 2026-08-11 silently reverted it, along
with six other PRs. This re-applies the retirement against current main:
130 call sites across 67 files, plus both declarations.

The alias was a pure pass-through -- `--shadow-tight: var(--e1)` in the
light and dark role blocks -- so the substitution is value-preserving.
Confirmed for forced-colors too rather than assumed: the
`@media (forced-colors: active)` block scopes `:root, .dark`, the same
`html` element the alias is declared on, so `--shadow-tight` already
resolved through the flattened `--e1: none` there. The .ckb-v2
redeclaration hazard does not bite for the same reason -- .ckb-v2 sits on
<html> and .ckb-v2.ckb-v2 outspecifies :root, so both spellings
substitute against the winning v2 tier.

Two comments survived acf78bf while the code they describe did not: the
globals.css note that "the resting-hairline role is gone", and the token
test's "unlike the --shadow-tight assertion above". Both are accurate
again.

The token contract test now sweeps the tracked src tree for both
spellings (declaration and var() consumer) instead of only asserting the
declaration. A declaration-only check would have caught this particular
revert, but only because the declarations happened to come back with the
call sites; sweeping both makes the gate independent of which half of a
bad merge lands. Mutation-verified in both directions.

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

* chore(design-system): re-pin the contract ratchets to their measured values

`scripts/design-system-contract-baseline.json` is a ceiling, so paying
debt down leaves silent headroom behind. Ledger #302 records that
pattern: legacyShadowAliases was pinned at 220 against a measured 193,
27 units of unguarded slack, up from 3 units on 2026-08-10.

With the previous commit's --shadow-tight retirement applied the gap is
wider still -- 220 pinned against 119 measured -- because the reland pays
down the debt the acf78bf revert had re-hidden. Four other ratchets had
accumulated slack from unrelated work in the same window.

  legacyShadowAliases        220 -> 119
  edgeOwnershipConflicts      27 -> 25
  rawPaddingLiterals          67 -> 63
  rawGapLiterals              34 -> 32
  layoutTransitionExceptions  12 -> 11

Regenerated with --print-debt-baseline rather than hand-edited, so the
per-path debtByPath counts move with the totals -- those are what
findDebtPathRegressions compares, and the retirement moved them
wholesale. Every metric in the diff decreases; nothing is absorbed
upward.

This is not the baseline refresh #262 warns against. That stop rule
forbids refreshing to hide the movement; this pins the movement in so it
cannot silently drift back a second time.

Mutation-verified: reintroducing one alias in button.tsx now fails at
both the total (119 -> 120) and the per-path level. Under the old 220
ceiling the same addition passed.

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

* refactor(tokens): hold the search-band count bubble in a spacing token

The active-filter badge sized itself with a raw `h-[1.0625rem]
min-w-[1.0625rem]` pair. Ledger #275 tracks that value as leaked debt:
it had reached five files, so the fix has always been to tokenise once
rather than edit a call site.

Re-measured on merged main, the badge role is down to a single call
site. #170's convergence landed in the meantime -- document-search-
results.tsx now renders the shared control and therapy-compass/
filter-sheet.tsx was deleted outright -- so the leak this row was
written about has already been reabsorbed by the extraction. Holding
the value in @theme is what stops it leaving again.

Two arbitrary values in the same component are deliberately left raw:

  pr-[0.6875rem] and min-[414px]:max-[429px] -- the repo defines no
  --breakpoint-* tokens at all, and eight peer sites use the same raw
  min-[]/max-[] form (359px, 389px, 414px). Naming one window while the
  peers stay raw is the same drift #275 warns about on another axis, and
  Tailwind named breakpoints would add variants across the whole utility
  surface. That belongs in a repo-wide decision, filed separately.

The three remaining 1.0625rem hits in mode-nav.tsx and nav-slot-ink.tsx
are NOT this token. They size <Icon> glyphs -- a 17px icon against a
12/14/16/20/24 --spacing-icon-* scale -- so folding them under a badge
token would merge two roles that only happen to share a number.
check:icon-scale deliberately does not flag arbitrary h-[Nrem], so they
are a real but separate finding, filed rather than guessed at.

The token is also registered in CLINICAL_TWMERGE_THEME.spacing, which
tests/tailwind-merge-config.test.ts asserts against the @theme block --
without it `cn()` cannot resolve a conflict on the new utility. Safe by
that file's own `tap` reasoning: the single call site is a static string
carrying no competing h-*/min-w-* class and never passes through `cn()`,
so there is no same-variant pair for declaration to hand to the later
class. The entry is protective for future use, not load-bearing today.

Value-preserving, and proven rather than inferred: compiling globals.css
through @tailwindcss/postcss emits
  .h-search-band-badge { height: var(--spacing-search-band-badge) }
  .min-w-search-band-badge { min-width: var(--spacing-search-band-badge) }
No ratchet moved, so the ceilings pinned in the previous commit still sit
at zero slack.

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

* docs(design-system): close out DS Track A3 and refresh the stale gate rows

Track A3 is `#262`. Its three parts are now all settled, each checked
against code rather than against the row that describes it.

Part 1 is the --shadow-tight retirement re-landed earlier in this PR.
Part 3 shipped in PR #1780 per `#301`: rawPaddingLiterals,
rawRadiusLiterals and rawLineHeightLiterals are live baseline keys
enforced over both the class and CSS-declaration spellings, plus
rawGapLiterals beyond the original ask.

Part 2 needs no work, and that had already been adjudicated -- GATES.md
section 3 records it, which is why nothing here builds it. The decidable
half of step selection shipped on 9 Aug inside check:design-system-
contract: a declared @theme step no production surface selects fails the
build. The remaining half -- which existing step a component picks -- is
documented there as something "nothing mechanical can" gate, being a
judgement about the rendered design rather than a property of the source,
with a standing instruction not to duplicate the arbitrary-value check
check:type-scale already ships. Reading `#262` alone would have sent a
session to build it; that is the `#301` failure mode, so the closure
record says so explicitly.

Section 3's live status rows carried numbers this PR moved. `#301`'s
lesson is that a row understating shipped work is a duplicate-work
generator, so they are corrected in the same change:

  legacyShadowAliases        224 -> 119, and the alias is now retired
                             outright rather than "224 left to retire"
  edgeOwnershipConflicts      27 -> 25
  rawPaddingLiterals          67 -> 63
  rawGapLiterals              34 -> 32
  layoutTransitionExceptions  12 -> 11

Section 5 is left alone deliberately: it is a dated record measured
against 8db1e53, not a live status surface, and rewriting its figures
would destroy the provenance it exists to hold.

Ledger records are queued as immutable inbox requests: `#262`, `#302` and
`#275` closed; two carve-outs split out of `#275` filed as their own rows
(the repo-wide breakpoint-token decision, and three 17px mode-nav icon
glyphs that sit off the --spacing-icon-* scale with no gate covering
them). The queued re-land request 210e3db5 is cancelled rather than
reconciled -- its headline "67 files on main still use the retired alias"
is false as of this branch, so it would open a row wrong on arrival. The
request file and the cancellation both survive as provenance for the
acf78bf merge loss.

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

* chore(ledger): record the design-token relands review

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

* fix(issues): retarget the reland record after main reconciled it mid-flight

CI failed `docs:check-links` on this branch with

  Error: cancel request 2e791c01... targets missing pending request
  210e3db5...

`check-docs-links.mjs` replays the inbox batch to resolve link targets, so
an unresolvable request fails it. The cause was a race, not a bad record:
PR #1936 reconciled 75 queued requests -- 210e3db5 among them -- while
this branch was already in flight. Reconciling moves the request file
into `docs/outstanding-issues-inbox/applied/` and allocates it a canonical
row, so by the time this branch merged main there was no pending request
left for the cancellation to name.

Cancelling was the right call against a pending request and is the wrong
one against a reconciled row. The cancel is dropped and replaced with a
`done` against `#319`, the row 210e3db5 became. That is also the better
record: the work is finished rather than withdrawn, so the ledger should
carry its outcome and its guard, which a cancellation would have thrown
away.

Also merges origin/main (this branch was 3 behind) and files two findings
the PR preflight surfaced, both deliberately not fixed here:

  - `check:medication-lexicon-report` has been failing on main for every
    local `verify:pr-local`, and no CI job runs it -- a grep over
    .github/workflows finds nothing. It is the last step of the local
    chain, so it fails preflights while CI stays green. The stale file is
    a clinical-facing generated document; regenerating it inside a
    CSS-token PR would bundle a clinical-risk artefact with unrelated
    chores.
  - Claude Code web containers can ship Node 22 with no node_modules,
    which fails `npm ci` on engine-strict before any repo script can run.

Re-verified after the merge: the tracked tree still holds zero
`--shadow-tight` references, and every pinned ratchet still measures
exactly its baseline, so the merge moved no metric and the pins stay
honest.

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

* docs(design): retire shadow-tight guidance

* docs(design): retire shadow-tight guidance

* docs(design): retire shadow-tight guidance

* docs(design): retire shadow-tight guidance

---------

Co-authored-by: Claude <noreply@anthropic.com>
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