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".
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".
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".
|
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