Skip to content

fix(rag): recover fast-route final-gate source gaps extractively (packet S1d) - #2054

Merged
BigSimmo merged 15 commits into
mainfrom
claude/s1d-final-gate-gap-recovery-dxgrn2
Aug 17, 2026
Merged

fix(rag): recover fast-route final-gate source gaps extractively (packet S1d)#2054
BigSimmo merged 15 commits into
mainfrom
claude/s1d-final-gate-gap-recovery-dxgrn2

Conversation

@BigSimmo

Copy link
Copy Markdown
Owner

Summary

  • Packet S1d (A1 final-gate gap recovery, docs/rag-improvement/HANDOVER.md §3): a hedged, cited, confidence:"low", grounded fast-route answer whose lead misses providerSourceGapLeadPattern but whose body matches the finalizer's broad gap-like regex used to be converted by finalizeRagAnswerQualityCore into a citation-free evidence_gap (final_quality_gate:provider_source_gap) with no extractive recovery, while the same failure shape caught in the generation loop or the outer generation-fallback catch recovers to a source-backed extractive answer. Model phrasing alone chose the branch: the post-S1b canary run 32038751592 failed summary-discharge-guidance on the citation-free branch (grounded false, 0 citations), while re-run 32039841070 and 3/3 cache-bypassed live probes on identical retrieval (36/36, live index unchanged) took the extractive branch (grounded, 4 citations).
  • Fix, entirely inside src/lib/rag/rag-extractive-answer.ts: new private helper recoverFinalGateGapExtractively runs at the top of the gap-conversion branch. When the answer is routingMode:"fast", its routingReason carries strong_routine_retrieval, answer.sources is non-empty, and the query class is not comparison/medication_dose_risk/table_threshold, it rebuilds a deterministic source-backed answer with the in-file buildExtractiveAnswer from the answer-carried artifacts, rebuilds the smart API plan for the extractive route, and ships it only if it passes the existing isSafeExtractiveFallbackCandidate validation battery (grounded, cited, zero unverified numeric tokens, not a bare cross-reference). Any gate or validation failure returns null and the citation-free gap ships exactly as before.
  • The recovered answer carries the same greppable telemetry signature as the existing outer-catch recovery (generation_fallback:provider_source_gap; source_backed_extractive_fallback) plus the in-file recovery marker final_quality_gate_source_backed_recovery:provider_source_gap, and deliberately does not carry the terminal final_quality_gate: token, so recovered and terminal outcomes stay distinguishable in rag_queries. modelUsed is cleared so applyProviderLabels labels it source_only with degradedMode.active, matching the existing recovery paths.
  • Terminal behaviour is preserved and now pinned by tests: genuinely empty retrieval, strong-route gaps, comparison-class gaps, dose/threshold-class gaps, and non-routine-retrieval routes all still produce the citation-free evidence_gap. The dose/threshold exclusion is deliberately stricter than the outer catch's comparison-only gate because that path pairs those classes with dedicated single-chunk candidate handling (never stitch dose/threshold figures across chunks), which a finalizer-local multi-chunk rebuild would bypass.
  • Docs: one bullet added to docs/rag-behaviour/behaviour-map.md §7 describing the new recovery and its terminal exclusions; docs/rag-improvement/HANDOVER.md §2 S1d status row updated in this PR.
  • Ledger: queued an immutable inbox cancellation for the pending S1d add request from PR docs(rag): record the S1b canary pair, add packet S1d, mark S4/T4 merged #2048 (docs/outstanding-issues-inbox/776405e0-c2d9-4dec-b688-e26c22143f04.json). A npm run issues:done request cannot be produced yet because the S1d add has not been reconciled into the canonical ledger (done requests fingerprint the canonical row), so the supported cancellation mechanism prevents a stale open row from materializing; if the cancellation loses the race to an earlier reconcile, the reconcile reports it and the materialized row should then be closed with issues:done citing this PR.

RAG impact: behaviour change — canary pair 32039841070 (e6ad0d5, latest green baseline) -> post-merge dispatch (owner-approved, requested below). Non-inferiority argument: the change only widens recovery to a validated path that already exists on two adjacent branches (in-loop fast-failure recovery and the outer generation-fallback catch), whose selection today is decided by model phrasing alone on identical retrieval; every recovered answer must pass the same extractive validation battery those paths use; anything failing validation degrades to today's exact citation-free gap; retrieval, ranking, routing, and all terminal gap classes are untouched.

Verification

  • npm run verify:pr-local — exit 0, heavy scope: completed: check:runtime, check:installed-lock-parity, format:changed, lint, typecheck, test, build, eval:rag:offline, check:medication-interactions, check:medication-lexicon-report — failed: (none) — not reached: (none)
  • npm run eval:rag:offlineTest Files 25 passed (25), Tests 604 passed (604), Offline RAG fixture and production-contract checks passed.
  • npm run check:rag:fixturesOffline RAG fixture and manifest validation passed (36 golden cases, 25 suites).
  • Focused vitest: npx vitest run tests/extractive-answer-formatting.test.ts tests/rag-answer-fallback.test.tsTests 227 passed (227) including the six new S1d tests; adjacent suites tests/rag-trust.test.ts tests/source-backed-recovery-cross-reference.test.ts tests/rag-extractive-procedural-artifact.test.ts tests/rag-generation-failure-diagnostics.test.ts tests/rag-imputation-contract.test.tsTests 91 passed (91).
  • Discriminating-fixture proof: with the src/lib/rag/rag-extractive-answer.ts diff stashed, the two new recovery tests fail (Tests 2 failed | 225 skipped); with the diff restored, all pass.
  • npm run check:maintainability-budgetsMaintainability hotspot budgets passed. (src/lib/rag/rag.ts untouched at its 4362-line budget; all changes live in rag-extractive-answer.ts, which has no budget entry.)
  • npm run check:production-readiness — code checks PASS (Node runtime, query-hash boot guard); the two FAILs are Missing server env config: NEXT_PUBLIC_SUPABASE_URL, SUPABASE_SERVICE_ROLE_KEY and Missing OPENAI_API_KEY, the documented provider capability gap of this offline cloud session (no .env.local/secrets), not a regression of this diff.
  • Verification not run: npm run eval:retrieval:quality and the live canary dispatch — provider-backed and owner-approval-gated; retrieval/ranking/selection are untouched by this diff, and the required live canary pair is requested post-merge per docs/rag-behaviour/safeguards.md (baseline run 32039841070 on e6ad0d5db -> post-merge eval-canary dispatch).
  • Verification not run: npm run verify:ui — no UI, routing, or styling change.

Risk and rollout

  • Risk: low and fail-closed. The new path runs only where today's behaviour is a citation-free evidence_gap; every recovered answer passes the existing isSafeExtractiveFallbackCandidate battery (grounded, cited, zero unverified numeric tokens, no bare cross-reference), and any failure returns the branch to today's exact terminal gap. Recursion terminates structurally: the rebuilt candidate is routingMode:"extractive", which cannot re-enter the fast-gated recovery. Strong-route, empty-retrieval, comparison, and dose/threshold gaps are pinned unchanged by new tests.
  • Rollback: single-commit revert of the squash commit restores the previous terminal-gap behaviour byte-for-byte.
  • Provider or production effects: None from this PR itself (the change adds zero provider calls — it replaces a terminal conversion with a deterministic rebuild). The post-merge eval-canary dispatch is a separately owner-approved action.

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

  • Canary-pair request for the owner: after merge, dispatch the standard eval-canary run and compare against baseline run 32039841070 (e6ad0d5db) with npm run eval:retrieval:compare -- <baseline.json> <post.json> --fail-on-regression; the failing case summary-discharge-guidance should now take the recovered extractive branch deterministically.
  • docs/branch-review-ledger record appended for this branch head under docs/branch-review-records/.

🤖 Generated with Claude Code

https://claude.ai/code/session_01S5QKovS1ZhbZA5kETfQoaR


Generated by Claude Code

…ket S1d)
A hedged, cited, low-confidence fast answer whose body matches the
finalizer's broad gap-like regex used to collapse into a citation-free
evidence_gap (final_quality_gate:provider_source_gap) with no recovery,
while the identical failure shape caught in the generation loop or the
outer generation-fallback catch rebuilds a source-backed extractive
answer — model phrasing alone chose the branch (canary 32038751592 red
vs 32039841070 green on identical retrieval).
finalizeRagAnswerQualityCore's gap conversion now first attempts the
same source-backed extractive recovery (recoverFinalGateGapExtractively)
when the route was fast + strong_routine_retrieval and answer-input
results exist, validated by the existing isSafeExtractiveFallbackCandidate
battery and stamped with the established generation_fallback /
source_backed_extractive_fallback markers plus
final_quality_gate_source_backed_recovery:<reason>. Empty-retrieval,
strong-route, comparison, and dose/threshold gaps stay terminal and are
now pinned by tests. No rag.ts change (4362-line budget untouched).
Also queues an inbox cancellation for the pending S1d ledger add from
PR #2048 (a done request cannot fingerprint a not-yet-reconciled row)
and documents the recovery in docs/rag-behaviour/behaviour-map.md §7.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S5QKovS1ZhbZA5kETfQoaR
@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

coderabbitaiBot commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

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:43 minutes

Limit details: You’ve used all 1 included review currently available under your plan. You completed 96 included PR reviews in the past 7 days; at that activity level, included reviews refill at 1 review per hour.

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: f357bcb5-2277-45cb-9e4a-b9ce7a0aa1f6

📥 Commits

Reviewing files that changed from the base of the PR and between 5a0ed07 and 33e8c12.

📒 Files selected for processing (7)
  • docs/branch-review-records/ce864242309b87ec27f7947bddac2350e40dcd2241dfeea7fdcafbb6733823f3.record.md
  • docs/outstanding-issues-inbox/776405e0-c2d9-4dec-b688-e26c22143f04.json
  • docs/rag-behaviour/behaviour-map.md
  • docs/rag-improvement/HANDOVER.md
  • src/lib/rag/rag-extractive-answer.ts
  • tests/extractive-answer-formatting.test.ts
  • tests/rag-answer-fallback.test.ts

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

@supabase

supabaseBot commented Aug 17, 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 ↗︎.

@BigSimmo
BigSimmo enabled auto-merge August 17, 2026 16:49
@github-actions

Copy link
Copy Markdown
Contributor

CI triage

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

  • Lighthouse budgetneeds 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 #11609 (success).

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

@BigSimmo
BigSimmo merged commit 0bbd64f into mainAug 17, 2026
24 checks passed
@BigSimmo
BigSimmo deleted the claude/s1d-final-gate-gap-recovery-dxgrn2 branch August 17, 2026 19:47
Sign up for freeto 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

@BigSimmo@claude