fix(rag): don't rescue bare cross-reference answers in source-backed recovery - #538
Conversation
…recovery shouldPreserveSourceBackedGeneratedAnswer was preserving a bare "Refer to <document> ... for further information" pointer to grounded=true on the cited sources' structured-chunk signals alone, shipping an off-topic redirect as a grounded clinical answer. Add a narrow isBareCrossReferenceAnswer guard (lead sentence must be BOTH a directive and a "for further information" redirect, evaluated on the same sanitized text the gate judged) so these degrade to source-only, without regressing the terse paraphrase rescues the gate legitimately exists for. Extend the already-merged discharge acceptSourceOnly eval treatment to the two duress cases, which surface the identical boilerplate; still guarded by expectedHit && citations so a real retrieval regression fails. Verified: typecheck/prettier/eslint clean; targeted vitest 78/78; live eval:retrieval:quality 36/36 and eval:quality --rag-only grounded-supported 0.9667 against the equivalent change. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This pull request has been ignored for the connected project Preview Branches by Supabase. |
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughSummary by CodeRabbit
WalkthroughThe change updates duress evaluation cases to allow source-only answers and adds detection that prevents bare cross-reference responses from being accepted by the source-backed recovery gate. Tests cover fixture configuration and recovery behavior. ChangesRAG quality evaluation
Estimated code review effort: 3 (Moderate) | ~20 minutes Sequence Diagram(s)sequenceDiagram
participant RagAnswer
participant finalizeRagAnswerQuality
participant shouldPreserveSourceBackedGeneratedAnswer
RagAnswer->>finalizeRagAnswerQuality: provide cleaned answer and source signals
finalizeRagAnswerQuality->>shouldPreserveSourceBackedGeneratedAnswer: evaluate recovery eligibility
shouldPreserveSourceBackedGeneratedAnswer->>finalizeRagAnswerQuality: reject bare cross-reference or preserve paraphrase
Caution Pre-merge checks failedPlease resolve all errors before merging. Addressing warnings is optional.
❌ Failed checks (1 error)
✅ Passed checks (10 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
✨ Simplify code
Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit:74d2226a01
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit:bd41d4f12c
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Uh oh!
There was an error while loading. Please reload this page.
Addresses the Codex P2 on PR #538: the directive + "for further information" redirect also matched passive clinical referral facts such as "Patients are referred to the community team for further information and support.", which would wrongly turn a valid cited answer into an evidence gap. Require the lead sentence to also name a document-style object (guideline/policy/procedure/ appendix/...), so referrals to a team, person, or service survive the guard. Adds regression tests for the passive-referral and see-your-GP cases. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit:abb648e0bd
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Note Docstrings generation - SUCCESS |
Docstrings generation was requested by @BigSimmo. * #538 (comment) The following files were modified: * `src/lib/rag-extractive-answer.ts`
… pass (#562) Addresses the Codex P2 on PR #538: scoreAnswerQualityEvalCase's acceptSourceOnly relevance branch accepted any source-only/unsupported answer without checking that it still surfaced the expected documents, so a retrieval regression that stopped returning e.g. MHSP.Duress.pdf / MHSP.Discharge.pdf could hide in the quality canary (contradicting the "expectedFiles keeps the retrieval guard" intent). Wire the existing citesOrNamesExpectedDocument helper into the acceptSourceOnly branch so a source-only answer must still cite or name the expected doc. Updates the discharge test to assert both the cited (relevant) and uncited (not relevant) cases. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Docstrings generation was requested by @BigSimmo. * #538 (comment) The following files were modified: * `src/lib/rag-extractive-answer.ts` Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Summary
Fixes a latent RAG grounding false-positive: the source-backed recovery gate was rescuing a bare cross-reference extract —
"Refer to the RKPG Guidelines to Writing for Clinical Policy for further information about Scope of Practice."— togrounded=truepurely on the cited sources' structured-chunk signals, even though the answer text has zero query overlap and answers nothing itself. This surfaced as the nightly Eval Canary's flappingdischarge-documentationswing case (grounds locally, source-only in CI); the same boilerplate also affectedduress-procedure.Fix (
src/lib/rag-extractive-answer.ts): newisBareCrossReferenceAnswerguard.shouldPreserveSourceBackedGeneratedAnswerno longer preserves a "refer to<document>… for further information" pointer. The guard is deliberately narrow — the lead sentence must be both a directive (refer to/see/consult/as per…) and a "for further information"-style redirect — so it leaves untouched the terse paraphrases the gate legitimately rescues (e.g."Depot antipsychotic follow-up is covered by the cited local pathway.", which shares no query tokens yet answers the query). It evaluates the same sanitized text the quality gate judged, so a stripped leading-noise fragment can't hide the redirect lead. A blanket "minimum token overlap" rule was intentionally avoided because it would regress those valid paraphrase rescues.Eval (
src/lib/rag-eval-cases.ts): the full quality run showedduress-procedureis the same false-positive (identical RKPG extract), so it correctly degrades to source-only. Extended the existing dischargeacceptSourceOnlytreatment to the two duress cases (duress-procedure+quality-duress-pathway), guarded byexpectedHit && citations>0so a real retrieval regression still fails.Verification
Offline (this branch):
npm run typecheck— cleannpm run lint(eslint--max-warnings 0) — cleannpm run format:check(prettier) — cleantests/source-backed-recovery-cross-reference.test.ts(10 cases: pure predicate + control/treatment throughfinalizeRagAnswerQuality) +tests/rag-eval-cases.test.tsduress assertion +tests/rag-answer-fallback.test.ts(existing recovery regression guard) all greenProvider-side (run against the equivalent change; retrieval is unaffected by an answer-post-processing change, so results carry over):
npm run eval:retrieval:quality→ 36/36 PASS,content_mrr@10=0.9255(baseline unchanged)npm run eval:quality -- --rag-only --fail-on-threshold→ PASS, grounded_supported_rate 0.9667 ≥ 0.9, Failed cases: 0A diagnostic run confirmed the guard fires only on the RKPG boilerplate and correctly spares other off-topic-but-not-cross-reference extracts.
verify:cheapequivalents run individually)npm run eval:retrieval:quality(36/36) — answer-post-processing change; ran anyway for safetynpm run eval:quality -- --rag-only— grounded-supported 0.9667, citation-failure 0Clinical Governance Preflight
Clinical KB Database(sjrfecxgysukkwxsowpy) — unchangedacceptSourceOnlystill requires expected docs to be citedNotes
acceptSourceOnlymachinery; no schema, migration, env, or dependency changes.🤖 Generated with Claude Code