Skip to content

feat(answer): adopt AnswerCard on the live answer surface; resolve #207 vs #227 - #1658

Merged
BigSimmo merged 13 commits into
mainfrom
claude/answer-shell-ds-adoption
Aug 7, 2026
Merged

feat(answer): adopt AnswerCard on the live answer surface; resolve #207 vs #227#1658
BigSimmo merged 13 commits into
mainfrom
claude/answer-shell-ds-adoption

Conversation

@BigSimmo

@BigSimmo BigSimmo commented Aug 6, 2026

Copy link
Copy Markdown
Owner

Summary

  • Completes the answer-shell adoption. VerificationNotice and RetrievalStateBanner were already mounted on the live surface; AnswerCard was not, so the design system owned the wording but the product still owned the composition and ordering. The card now owns the query echo, the notice, the banner and their document order, on screen and on print alike. Adoption moves from 27 to 29 of 53 registered components.

  • Resolves a direct conflict between two documented clinical decisions that had never been reconciled. Neither referenced the other:

    • #207 (pinned in tests/ui-v2-answer-safety.dom.test.tsx) required a retrieval banner on every degraded state, on the reasoning that "the adoption failure this guards is a silent one — the card renders, the prose is fine, and the caution the product shows today is simply gone."
    • #227 (in answer-result-surface.tsx) deliberately suppressed the banner for ungrounded and source_only, having measured the duplicate on a one-sentence answer: three renderings of one warning, eleven lines of caution around one line of answer, 147px of scroll against a phone budget of 8.

    Resolved in favour of #227. #207 protects that the caution survives, not that a banner carries it — and it does survive: VerificationNotice states ungrounded and source_only in words, and the card carries data-state. The banner now renders for exactly the two kinds where it says something the notice cannot: stale_evidence names which sources are overdue, partial_retrieval names how much was missed. Three identical alarms teach a reader to skip all three, so the duplicate is the dangerous outcome, not the omission.

  • onOpenSource stays required for every degraded state (DECISIONS §Q1). A degraded answer must remain re-verifiable whether or not a banner renders.

  • The #207 test now pins the duplicate OUT rather than in. It asserts the two channels that genuinely carry the state for ungrounded, and asserts the banner is absent — so a banner reappearing there fails as the #227 regression it would be. Added coverage for source_only and for both kinds that keep the banner.

  • #228's attribution derivation is preserved verbatim — attribution comes from the quality tier, never the state kind, so source_only cannot announce "AI-generated" directly above a disclosure saying no model wrote it.

  • Test-guard change is an inversion, not a removal. The reference-only assertion in design-system-adoption.test.ts is a snapshot of adoption state, so AnswerCard/Quantity moving out of it is the expected shape of an adoption change. It is replaced with the inverse guard: an adopted component must also carry a production v2 mount, so "adopted" can never mean an import with no production shell behind it.

AnswerFooter and DoseLine remain unadopted — the live surface has no provenance or dose payload to pass them yet. Not stubbed.

Clinical Governance Preflight

  • Source-backed claims still require linked source verification before clinical use — unchanged; this PR alters which caution component renders, never whether a claim is source-linked. Citation and source-link paths are untouched.
  • No patient-identifiable document workflow was introduced or expanded without explicit governance approval — no document workflow touched; no new data enters or leaves the surface.
  • Supabase target remains Clinical KB Database (sjrfecxgysukkwxsowpy) — no Supabase, migration, or env change in this diff.
  • Service-role keys and private document access remain server-only — no key handling and no access-path change; this is client-side answer composition only.
  • Demo/synthetic content remains clearly separated from real clinical sources — unchanged; the demo corpus path is untouched.
  • Source metadata, review status, and outdated/unknown-source behavior remain conservative — this is the substantive item. Behaviour is unchanged for stale_evidence and partial_retrieval, which keep the banner naming overdue and missing sources. For ungrounded and source_only the caution is still stated by VerificationNotice and still exposed as data-state; only the verbatim second rendering is removed. Degradation remains conservative: no state loses its caution, and onOpenSource remains required so every degraded answer keeps its route back to source.
  • Deployment classification/TGA SaMD impact was checked when clinical decision-support behavior changed — no change to classification. The answer content, its grounding, and its retrieval are untouched; this changes the presentation of an existing warning, reducing repetition of the same statement without removing it.

scripts/pr-policy.mjs returns clinicalRisk: false for these paths, so this preflight is not machine-required. It is included because the repo's broader PR risk detection covers clinical output, and this diff changes what a clinician sees when an answer is ungrounded — the narrow classifier is a floor, not a closed enumeration.

RAG impact: no retrieval behaviour change — this diff touches only client-side answer presentation. No file under src/lib/rag/**, clinical-search, retrieval-selection, ranking-config, answer-ranking, the eval harness, or the golden fixture is modified.

Verification

  • npm run typecheck — exit 0
  • npm run lint — exit 0
  • tests/ui-v2-answer-safety.dom.test.tsx69 passed
  • tests/design-system-adoption.test.ts51 passed
  • tests/answer-support-priority.dom.test.tsx, tests/answer-state-contract.test.ts — passed in the same run (146 passed across the four suites before the guard update)
  • npm run test (full suite, before the manifest regeneration) — 5 444 passed, 3 skipped. The one unrelated failure is tests/installed-lock-parity.test.ts (installed playwright 1.62.0 vs locked 1.62.1), environmental and pre-existing — issue #149.

Not run, with reasons:

  • npm run verify:ui — this box had 83 node processes active; a contended Chromium run yields false reds rather than signal. This PR changes the visual structure of the primary answer screen (the answer now sits inside the card's bordered, raised surface rather than the transparent answerSurface), so the Chromium job on this PR is the meaningful check and should be read carefully before merge.
  • npm run check:production-readiness — fails on absent local Supabase/OpenAI env in this worktree, the documented offline-profile gap. Not introduced by this diff, and provider keys were deliberately not set.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Standardized answer displays with a unified answer card experience.
    • Added verification details across answer states.
    • Preserved source navigation for degraded answers.
  • Bug Fixes

    • Removed duplicate retrieval messaging for ungrounded and source-only answers.
    • Retrieval banners now appear only for stale-evidence and partial-retrieval states.
    • Improved consistency across ready and degraded answer presentations.
  • Documentation

    • Updated design-system adoption records to reflect current production usage.

… vs #227

The answer shell was half-adopted: `VerificationNotice` and `RetrievalStateBanner`
were mounted, `AnswerCard` was not. Completing it surfaced a direct conflict
between two documented, measured clinical decisions that had never been
reconciled — neither referenced the other.

  - `#207` (tests/ui-v2-answer-safety.dom.test.tsx) required a retrieval banner on
    EVERY degraded state: "the adoption failure this guards is a silent one — the
    card renders, the prose is fine, and the caution the product shows today is
    simply gone."
  - `#227` (answer-result-surface.tsx) deliberately suppressed the banner for
    `ungrounded` and `source_only`, having measured the duplicate on a
    one-sentence answer: three renderings of one warning, eleven lines of caution
    around one line of answer, 147px of scroll against a phone budget of 8.

Resolved in favour of `#227`, on the owner's decision. `#207` protects that the
caution survives, not that a *banner* carries it — and it does survive:
`VerificationNotice` states `ungrounded` and `source_only` in words, and the card
carries `data-state`. The banner now renders for exactly the two kinds where it
says something the notice cannot: `stale_evidence` names WHICH sources are
overdue, `partial_retrieval` names HOW MUCH was missed.

`onOpenSource` stays required for every degraded state (DECISIONS §Q1) — a
degraded answer must remain re-verifiable whether or not a banner renders.

The `#207` test now pins the two channels that genuinely carry the state and pins
the duplicate OUT, so a banner reappearing for `ungrounded` fails as the `#227`
regression it would be. Added coverage for `source_only` and for both kinds that
keep the banner.

The surface splits on `ready` vs degraded only because `AnswerCardProps`
discriminates on `state` to make `onOpenSource` required for a degraded card; a
union-typed `state` cannot narrow that at the call site. Verification props and
prose are built once so both arms stay identical. `#228`'s attribution derivation
(quality tier, never state kind) is preserved verbatim.

Adoption: 27 -> 29 of 53 registered components product-adopted. `AnswerFooter` and
`DoseLine` remain unadopted — the live surface has no provenance or dose payload
to pass them yet.

The reference-only assertion in design-system-adoption.test.ts is a snapshot of
adoption state, so `AnswerCard`/`Quantity` moving out of it is the expected shape
of an adoption change. Replaced with the inverse guard: an adopted component must
also carry a production v2 mount, so "adopted" can never mean an import with no
shell behind it.

Verification: typecheck 0 · lint 0 · design-system-adoption 51 passed ·
ui-v2-answer-safety 69 passed. Full unit suite before the manifest regen: 5 444
passed, the only unrelated failure being tests/installed-lock-parity.test.ts
(playwright 1.62.0 vs locked 1.62.1, issue #149, environmental).
check:production-readiness fails on absent local Supabase/OpenAI env in this
worktree — the documented offline-profile gap, not this diff.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@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.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 3 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 @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

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 configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 431d861f-b1a4-4bd6-86d0-5aa1977fcfe4

📥 Commits

Reviewing files that changed from the base of the PR and between ec5cbfe and ebb97dc.

📒 Files selected for processing (3)
  • src/components/clinical-dashboard/answer-result-surface.tsx
  • src/components/ui/answer-card.tsx
  • tests/ui-smoke.spec.ts
📝 Walkthrough

Walkthrough

Changes

AnswerCard answer rendering

Layer / File(s) Summary
AnswerCard state behavior
src/components/ui/answer-card.tsx, tests/ui-v2-answer-safety.dom.test.tsx
AnswerCard keeps verification notices for all states and renders retrieval banners only for stale-evidence and partial-retrieval states.
Answer surface composition
src/components/clinical-dashboard/answer-result-surface.tsx, tests/ui-smoke.spec.ts
The answer surface renders ready and degraded answers through AnswerCard with shared verification metadata, answer prose, and degraded-state source navigation. UI smoke tests use answer-card-query for active answers.
Adoption records and validation
docs/design-system/adoption-contract.json, docs/design-system/adoption-manifest.json, docs/design-system/COMPONENTS.md, tests/design-system-adoption.test.ts
Adoption records and tests mark AnswerCard and Quantity as production-mounted components and update related product-import counts.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant AnswerResultSurface
  participant AnswerCard
  participant VerificationNotice
  participant RetrievalStateBanner
  AnswerResultSurface->>AnswerCard: provide answer prose and verification metadata
  AnswerCard->>VerificationNotice: render verification state
  AnswerCard->>RetrievalStateBanner: render stale_evidence or partial_retrieval details
  AnswerCard-->>AnswerResultSurface: provide degraded-answer source navigation
Loading

Possibly related PRs

  • BigSimmo/Database#487: Both changes modify answer rendering in answer-result-surface.tsx.
  • BigSimmo/Database#1576: This change integrates the AnswerCard, RetrievalStateBanner, and VerificationNotice contracts introduced there.
  • BigSimmo/Database#1595: This change refines the answer-card rendering and adoption flow modified there.

Suggested reviewers: copilot, cursoragent

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description is detailed and covers the change, governance, and verification, but it omits the required Risk and rollout section for a clinical output change. Add the Risk, Rollback, and Provider or production effects fields under Risk and rollout, even if the effects are unchanged.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the main change: adopting AnswerCard on the live answer surface and resolving the related issue conflict.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/answer-shell-ds-adoption

Comment @coderabbitai help to get the list of available commands.

@supabase

supabase Bot commented Aug 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 ↗︎.

Prior CI run cancelled/timed out while queued during the GitHub
Actions major outage. Empty commit to re-fire checks on current tip.

Co-authored-by: BigSimmo <BigSimmo@users.noreply.github.com>

@coderabbitai coderabbitai Bot 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.

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`:
- Around line 3053-3058: Update the sanctioned patterns record for this
answer-surface entry to remove VerificationNotice, leaving the adopted
AnswerResultSurface and RetrievalStateBanner patterns unchanged.

In `@src/components/clinical-dashboard/answer-result-surface.tsx`:
- Around line 271-289: Pass query={query} to both AnswerCard instances in the
answer-state conditional so the query echo renders for ready and non-ready
states. Ensure answer-result-surface shows only this single AnswerCard-provided
query echo, removing or avoiding any duplicate visible echo on the surrounding
surface.

In `@src/components/ui/answer-card.tsx`:
- Around line 91-110: Correct the Ledger date wording in the shared rationale
comments: in src/components/ui/answer-card.tsx lines 91-110, replace the
inaccurate completed-decision claim with the actual decision date or explicitly
describe August 7, 2026 as planned/effective; align the related rationale
comments in tests/ui-v2-answer-safety.dom.test.tsx lines 525-530 and
tests/design-system-adoption.test.ts lines 1145-1149 with the same corrected
date and status.
🪄 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: 5b869876-dec3-4f5b-8de9-30b51e0db424

📥 Commits

Reviewing files that changed from the base of the PR and between c839b97 and a5f6419.

📒 Files selected for processing (6)
  • docs/design-system/COMPONENTS.md
  • docs/design-system/adoption-manifest.json
  • src/components/clinical-dashboard/answer-result-surface.tsx
  • src/components/ui/answer-card.tsx
  • tests/design-system-adoption.test.ts
  • tests/ui-v2-answer-safety.dom.test.tsx

Comment thread docs/design-system/adoption-manifest.json
Comment thread src/components/clinical-dashboard/answer-result-surface.tsx
Comment thread src/components/ui/answer-card.tsx Outdated
cursoragent and others added 6 commits August 6, 2026 23:00
Remove VerificationNotice from answer-surface sanctioned patterns now that
AnswerCard owns that composition; pass query into AnswerCard and drop the
duplicate UserQuestionBubble echo; correct #227 decision date to 3 Aug 2026.

Co-authored-by: BigSimmo <BigSimmo@users.noreply.github.com>
@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

CI triage

CI failed on this PR. Automated classification of the 2 failed job(s):

  • Production UI (2)needs investigation: inspect the failing step and uploaded diagnostics; rerun only after classifying the cause.
  • PR requiredneeds investigation: inspect the failing step and uploaded diagnostics; rerun only after classifying the cause.

Compared with main CI run #8618 (cancelled).

Classification is evidence routing, not permission to ignore a failure. Exact quarantined Playwright identities remain governed by the flake ledger.

cursoragent and others added 3 commits August 7, 2026 01:41
AnswerCard nested inside padded answerSurface with dual pad-panel stacks
added ~60px phantom scroll (#227). Drop the outer surface pad, tighten
card vertical density, and keep the query echo above table-aside grids so
desktop prose/table alignment stays under the smoke budget.

Co-authored-by: BigSimmo <BigSimmo@users.noreply.github.com>
BigSimmo added a commit that referenced this pull request Aug 7, 2026
…family (#1663)

Section D, the half that carries no conflict with the two open PRs: this touches
only `src/app/globals.css` and the contract scripts, none of which #1655 or #1658
holds.

Corrects the measurement first. The backlog and the audit both quote the
letterspacing sprawl as ~371 sites across 31 values; that number counts
`*-mockups.tsx`, which is design scratch and gate-exempt by policy. Production
only: 110 sites across 18 values. The gate's AST pass — which sees statically
resolvable class roots — counts 68 across 40 files, and that is the number a
ratchet can act on.

The real defect turns out to be sharper than sprawl. 57 of the 110 production
sites are one value, 0.06em, while the single pre-existing token
`--tracking-eyebrow` is declared at 0.08em. The token has almost no consumers
because it was named for a number nobody writes.

Adds five named roles sized to the measured production mass, not to the
mockup-inflated spread:

  --tracking-display  -0.02em   absorbs the six-site negative cluster
  --tracking-normal    0
  --tracking-label     0.06em   absorbs 66 sites including the 57-site mass
  --tracking-eyebrow   0.08em   pre-existing, value deliberately unchanged
  --tracking-kicker    0.12em   absorbs 23 sites

Five roles rather than seven: production does not justify a second wide step or
a separate tight-display step. No fold moves a call site by more than 0.04em.

`--tracking-eyebrow` keeps 0.08em on purpose. Retuning it to the more common
0.06em would silently move every current consumer of the token — a different
change from naming the scale, and one that wants its own measured step.

Adds an `arbitraryTracking` metric to the design-system contract, mirroring the
existing literal-shadow ratchet exactly, baselined per path at today's 68 so the
family cannot regrow while the call-site migration waits for the open PRs to
land. `tracking-[var(--…)]` is the sanctioned token form and is not counted, the
same exemption `text-[color:var(--…)]` has in the type-scale check.

No call sites migrated in this commit — that is 40 files including
`ui-primitives.tsx`, which #1655 owns.

Ratchet proven to bite, not assumed: injecting `tracking-[0.077em]` into
mode-nav.tsx failed the checker with "arbitraryTracking increased from 68 to 69"
and the per-path line, then the file was restored clean.

Verification: check:design-system-contract exit 0 · typecheck 0 · lint 0 ·
ckb-v2-token-contract + design-token-contract + design-system-contract-utils
85 passed. Pre-existing baseline metrics were asserted unchanged before the
baseline was rewritten; only `arbitraryTracking` was introduced.

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
@BigSimmo
BigSimmo merged commit d922138 into main Aug 7, 2026
25 checks passed
@BigSimmo
BigSimmo deleted the claude/answer-shell-ds-adoption branch August 7, 2026 03:01
cursor Bot pushed a commit that referenced this pull request Aug 7, 2026
Co-authored-by: BigSimmo <BigSimmo@users.noreply.github.com>
cursor Bot pushed a commit that referenced this pull request Aug 7, 2026
Co-authored-by: BigSimmo <BigSimmo@users.noreply.github.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