feat(rag): figure-aware extractive selection for dose/monitoring answers (E-3c PR-C)#1039
Conversation
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EXsJcLrbZUXwnBeG91cVo9
…ers (E-3c PR-C) Dose and monitoring answers must carry the asked-for figure/schedule when a cited chunk verbatim supports it (run-#58 baseline: targeting 1/5 on both intents, every miss = missing figure). Lead-slot promotion swaps/appends the first later figure-bearing fact ONLY when no lead carries one, guarded by the claim-support atom corpus (sourceEvidenceText, now exported) so a promoted figure can never convert a grounded answer into an evidence gap - the guard proven load-bearing by red-testing it disabled. The dose/threshold generation fallback now prefers the safe candidate that carries the intent figure over the first safe one; the safety gate itself is unchanged. Fallback helpers extracted to rag-extractive-answer (cycle-check verified); rag.ts 4908->4901. Six discriminating tests, each verified failing on prior code. Full suite 3068 passed / 1 known container artifact. RAG impact: behaviour change (extractive answer composition + fallback candidate preference only) - E-4 pair vs banked #57/#58/#59 baselines post-merge; retrieval, ranking, selection ordering untouched. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EXsJcLrbZUXwnBeG91cVo9
…wer P2) Both reviewers converged on the gap: bare-number intervals like 'every 6 weeks' match the monitoring figure pattern yet yield no clinical value atom, so the atom-only guard passed them trivially - a figure sourced only from adjacent context could then be promoted and nuked by claim support (safe direction, but converts a shippable answer into an evidence gap). Zero-atom figures now require the matched figure substring verbatim in the citing chunk's claim-support corpus (intentFigureMatchText). Proven both directions by three new tests; comment-precision nit on the corpus lockstep folded in. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EXsJcLrbZUXwnBeG91cVo9
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
This pull request has been ignored for the connected project Preview Branches by Supabase. |
📝 WalkthroughWalkthroughThe RAG extractive pipeline now promotes evidence-supported dose and monitoring figures into lead answers and selects figure-bearing candidates during generation-failure recovery. Shared fallback helpers, tests, and review ledger records were added. ChangesExtractive RAG recovery
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant RAG
participant ExtractiveAnswer
participant ClaimSupport
participant CitedEvidence
RAG->>ExtractiveAnswer: build extractive answer
ExtractiveAnswer->>ClaimSupport: validate figure-bearing facts
ClaimSupport->>CitedEvidence: inspect cited source text
CitedEvidence-->>ClaimSupport: supported figure evidence
ClaimSupport-->>ExtractiveAnswer: eligible lead fact
ExtractiveAnswer-->>RAG: figure-aware answer or fallback candidate
Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
src/lib/rag/rag-extractive-answer.ts (1)
1094-1109: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winHand-mirrored atom key risks silent drift.
promotionAtomKeyduplicates the field list/order of a privateatomKeyinrag-claim-support.tspurely by comment convention ("Mirrors the private atom identity..."). IfClinicalValueAtomgains/reorders a field and only one of the two key builders is updated, the promotion guard and claim-support corpus check would silently disagree, defeating the "keep the two in lockstep" intent documented at Lines 215-221 of rag-claim-support.ts.Consider exporting the real
atomKey(or a shared key-builder) fromrag-claim-support.tsand importing it here instead of maintaining a parallel hard-coded field list.🤖 Prompt for 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. In `@src/lib/rag/rag-extractive-answer.ts` around lines 1094 - 1109, The promotionAtomKey helper duplicates the private atom identity logic and can drift from claim assessment. Export the existing atomKey or move it to a shared key-builder in rag-claim-support.ts, then import and reuse that symbol in the promotion guard here, removing the local hard-coded field list while preserving identical key behavior.
🤖 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 `@src/lib/rag/rag-extractive-answer.ts`:
- Around line 374-378: Update monitoringIntervalFigurePattern so the
unit-bearing “every N” alternative is evaluated before the bare “every N”
alternative, ensuring matches include the full interval such as “every 6 weeks.”
Apply the same ordering fix to the corresponding pattern near
monitoringUnitRangeFigurePattern, and add coverage for mismatched units sharing
the same number.
In `@tests/extractive-answer-formatting.test.ts`:
- Around line 461-473: The test case around “refuses a bare-number interval that
lives only in adjacent context” does not match its setup or assertion. Either
remove this duplicate, or update it to place the interval exclusively in the
chunk’s adjacent_context and assert the interval is not promoted; if retaining a
distinct content-vs-adjacent-context case, add assertions that directly verify
the interval’s presence or absence.
---
Nitpick comments:
In `@src/lib/rag/rag-extractive-answer.ts`:
- Around line 1094-1109: The promotionAtomKey helper duplicates the private atom
identity logic and can drift from claim assessment. Export the existing atomKey
or move it to a shared key-builder in rag-claim-support.ts, then import and
reuse that symbol in the promotion guard here, removing the local hard-coded
field list while preserving identical key behavior.
🪄 Autofix (Beta)
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 Plus
Run ID: 9f5445cf-8d84-422c-9d93-5418461ab15e
📒 Files selected for processing (6)
docs/branch-review-ledger.mdsrc/lib/rag/rag-claim-support.tssrc/lib/rag/rag-extractive-answer.tssrc/lib/rag/rag.tstests/extractive-answer-formatting.test.tstests/rag-answer-fallback.test.ts
…erage
CodeRabbit review on the P2 guard: reorder monitoringIntervalFigurePattern so
the unit-bearing "every N unit" alternative precedes bare "every N" — exec()
now returns the full schedule instead of a truncated "every 6". Digit+unit
intervals turn out to produce quantity atoms (6/week), so atom identity already
refuses unit mismatches; the reorder hardens the verbatim fallback against
atom-coverage drift, and both comments claiming "every 6 weeks" is zero-atom
are corrected. The non-discriminating first guard test is replaced with a
mismatched-unit pin (shared number, different unit, figure only in adjacent
context) plus two genuinely zero-atom tests ("annually") that exercise the
verbatim-corpus path both directions. promotionAtomKey hand-mirror replaced by
exporting clinicalValueAtomKey from rag-claim-support.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EXsJcLrbZUXwnBeG91cVo9
Summary
E-3c PR-C — attacks the worst finding of the run-#58 targeting baseline: dose 1/5 and monitoring 1/5, with every miss the same defect — the answer omits the concrete figure or schedule the clinician asked for, while a cited chunk contains it (the extractive sorter prefers the shortest same-priority sentence, which is usually the figure-less one).
clinicalValueAtomKeynow exported from rag-claim-support), and verbatim-substring for genuinely zero-atom figures like "annually" (the post-review P2 fix, proven both directions). Digit+unit intervals such as "every 6 weeks" turn out to yield quantity atoms, so atom identity refuses unit mismatches; the interval pattern's full-match alternation ordering (CodeRabbit critical, fixed in 02b5c78) hardens the verbatim fallback against any future regex/atom-coverage drift. A promoted figure therefore always survives both numeric verification and claim support; the guard was proven load-bearing by red-testing it disabled.rag-extractive-answer.ts(cycle-check verified);rag.tsdown to 4901/5030.Both reviewer subagents pre-push, no P0/P1:
promotionAtomKeyhand-mirror deleted in favour of the exported key.Six original discriminating tests each verified failing on prior code. Full suite 3068 passed pre-P2-fix; subsequent fixes re-verified across the focused extractive/claim-support/fallback suites (135 tests) + typecheck + lint.
RAG impact: behaviour change — canary pair: baselines #57/#58/#59 (banked) -> E-4 dispatch immediately post-merge; extractive answer composition + fallback candidate preference only; retrieval, ranking, and selection ordering untouched (adversarially verified); regression = single-commit revert per the proven drill.
Verification
npm run test— 3068 passed / 1 known container-only pdf artifact (pre-P2-fix tree; later fixes re-verified focused)Risk and rollout
Clinical Governance Preflight
Clinical KB Database(sjrfecxgysukkwxsowpy) — no access changes🤖 Generated with Claude Code
https://claude.ai/code/session_01EXsJcLrbZUXwnBeG91cVo9
Summary by CodeRabbit
New Features
Bug Fixes