Skip to content

Fit the answer-wait evidence preview under the stream cap instead of losing it at the boundary - #2641

Merged
BigSimmo merged 5 commits into
mainfrom
claude/admiring-newton-s6ptw6
Sep 5, 2026
Merged

Fit the answer-wait evidence preview under the stream cap instead of losing it at the boundary#2641
BigSimmo merged 5 commits into
mainfrom
claude/admiring-newton-s6ptw6

Conversation

@BigSimmo

@BigSimmo BigSimmo commented Sep 5, 2026

Copy link
Copy Markdown
Owner

Summary

  • The answer wait showed no source cards on every non-fast answer, exactly the long strong-route waits the rail exists for. Root cause: the preview builder sized its unit by source count alone (up to 12), while isDeliverableVerifiedUnit bounds a unit at 64,000 JSON characters. A real trimmed source is ~7,000 characters (the ≤900-char snippet is carried twice, plus scoring, labels, indexing quality and relevance), so a twelve-source unit was ~83,000 characters: built, handed to toPublicAnswerProgressEvent, and dropped there as contract_rejected with nothing on screen. Fast routine answers select four passages and never hit the cap, which is why the mocked browser proof stayed green through the previous fixes.
  • src/lib/answer-preview.ts: the builder now validates the exact unit it will emit with the same contract function and shrinks from the tail until it fits, preserving retrieval order. A source the contract rejects on its own (for example a NaN similarity) is excluded individually rather than taking the rail down. When nothing can ship, the setup-status diagnostic records a new undeliverable reason instead of emitting a unit that will be thrown away. selectedContextCount still names what governance let through.
  • src/lib/answer-stream-contract.ts: comment only, correcting the "with headroom" sizing assumption. No validation change.
  • tests/answer-incremental-delivery.test.ts: adds a production-sized 12-source fixture and proves the builder output survives the route boundary, that a malformed source is dropped alone, and that the undeliverable reason is recorded.
  • docs/verified-answer-incremental-delivery-design.md: amendment recording the sizing defect and the builder-side fit rule.

Before/after, same 12 real-sized sources through a mocked stream in the local app: before, the line reads "Writing the answer…" with zero cards (the reported screenshot); after, "6 sources found · writing the answer…" with six cards.

Verification

  • npm run test:focused -- --files src/lib/answer-preview.ts src/lib/answer-stream-contract.ts tests/answer-incremental-delivery.test.tsTest Files 71 passed (71), Tests 1090 passed (1090)
  • npm run format (committed), eslint on changed files clean, npm run typecheck[gate-receipts] recorded a pass for "typecheck:internal"
  • npm run verify:cheap — all 38 static gates, lint and typecheck green; unit suite Tests 3 failed | 16873 passed | 2 expected fail | 6 skipped (16884). The three failures (clinical-hazard-controls, privacy-readiness-contract, rag-plan-package-parity) each look up a historic commit hash absent from this container's clone (reviewedCommit does not exist …, reconciledBase is unavailable locally …) and fail identically on the untouched main head cd5b901 in a throwaway worktree. Environmental, not this diff; CI has full history.
  • npm run verify:pr-local — Verification not run: it routes this diff to the heavy scope (full test, build, eval:rag:offline), which is the verdict CI is about to reach; deferred to CI.
  • UI verification not run: no client component, styling or browser behaviour changed. The existing tests/answer-progress-ui-smoke.spec.ts rail journeys run in CI; the before/after screenshots above were taken against the local app with the builder's real output.

Risk and rollout

  • Risk: low. Server-only change to the preview builder; the final answer payload, retrieval, ranking and selection are untouched. Worst case the preview carries fewer sources than before, which it always did once the boundary dropped it.
  • Rollback: revert this PR, or set RAG_INCREMENTAL_EVIDENCE_PREVIEW=false (the existing first rollback step).
  • Provider or production effects: None. Deploys with the next merge to main via Railway auto-deploy; no migration, no env change.
  • RAG impact: no retrieval behaviour change — only the streamed preview unit's size is fitted to the existing contract; modelContextResults, ranking, selection and the final payload are byte-identical.

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

🤖 Generated with Claude Code

https://claude.ai/code/session_01Ron4eHAhoccBetbyqAJVvP


Note

Low Risk
Server-only change to wait-time preview sizing; final answer payload, retrieval, and stream contract validation are unchanged—worst case is fewer preview cards than before, when the boundary previously showed none.

Overview
Fixes the answer-wait evidence rail showing zero source cards on non-fast (strong-route) answers: the preview builder used to pack up to 12 trimmed sources while isDeliverableVerifiedUnit enforces a 64,000 JSON character ceiling—production-sized sources (~7k each) produced ~83k units that toPublicAnswerProgressEvent dropped as contract_rejected.

answer-preview.ts now runs the same isDeliverableVerifiedUnit check on the unit it will emit, drops sources from the tail (retrieval order) until the payload fits, and filters out individually invalid sources (e.g. NaN similarity) instead of failing the whole rail. When nothing can ship, diagnostics record a new undeliverable reason rather than emitting a doomed unit. selectedContextCount still reflects the full governed selection, not only the shipped subset.

answer-stream-contract.ts updates comments only (no validation change). Design doc records the sizing defect and builder-side fit rule. Tests add a production-sized 12-source fixture and assert boundary survival, per-source exclusion, and undeliverable reporting.

Reviewed by Cursor Bugbot for commit 2b98607. Configure here.

… losing it at the boundary

The wait showed no source cards on every non-fast answer. The preview
builder sized its unit by source count alone (up to 12), while the stream
contract bounds it by JSON size (64,000 chars). A real trimmed source is
~7,000 chars, not the ~900 the cap assumed, so a twelve-source unit was
~83,000 chars: built, sent to the route boundary, and dropped there as
contract_rejected with nothing on screen. Fast routine answers select four
passages and never hit the cap, which is why the browser proof stayed green.

The builder now validates the exact unit it will emit with the same
contract function and shrinks from the tail until it fits, in retrieval
order. A source the contract rejects on its own is excluded individually.
When nothing can ship, the wait records the new `undeliverable` reason for
the setup-status diagnostic instead of emitting a unit that will be thrown
away. selectedContextCount still names what governance let through.

Adds a production-sized fixture to the offline contract proof so the
builder's output is checked against the boundary it must cross.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ron4eHAhoccBetbyqAJVvP
@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.

@cursor

cursor Bot commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_33c40173-cfc5-4009-91c4-e8c126b0755e)

@supabase

supabase Bot commented Sep 5, 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 ↗︎.

@coderabbitai

coderabbitai Bot commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Team

Run ID: a633d882-273d-44cd-8151-a12464e78d7c


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@BigSimmo
BigSimmo enabled auto-merge September 5, 2026 10:11
@cursor

cursor Bot commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_ccd3a1c3-cdaf-4f7f-86fa-1a501a3226f1)

@BigSimmo
BigSimmo merged commit 4ac7ea8 into main Sep 5, 2026
27 checks passed
@BigSimmo
BigSimmo deleted the claude/admiring-newton-s6ptw6 branch September 5, 2026 11:31
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