Skip to content

feat(rag): eval-gate ON #213's ranking wins (diversity demotion + linear freshness) - #242

Merged
BigSimmo merged 1 commit into
mainfrom
claude/rag-flip-213
Jul 3, 2026
Merged

feat(rag): eval-gate ON #213's ranking wins (diversity demotion + linear freshness)#242
BigSimmo merged 1 commit into
mainfrom
claude/rag-flip-213

Conversation

@BigSimmo

Copy link
Copy Markdown
Owner

Summary

#213 shipped two retrieval-time ranking improvements config-gated and default-OFF, to be flipped on only after eval-gating. This PR does the eval-gating and turns them on by default:

  • documentDiversityPenalty 0 → 0.02 — gentle same-document crowding demotion (capped 0.12; RC7/CI-16).
  • freshness.mode step → linear — ramped freshness decay instead of the harsh cliff (CI-17).

It also fixes a latent bug in resolveRankingConfig: the freshness mode fallback was hardcoded to "step" instead of derived from defaultRankingConfig, so changing the default alone would not have taken effect at runtime without an explicit RAG_RANKING_CONFIG override. The override path is unchanged; setting documentDiversityPenalty:0 + freshness.mode:"step" restores exact pre-flip behavior.

Eval evidence (live)

MetricBefore (default OFF)After (this PR)
Golden retrieval mrr@100.72830.7569
document/content recall@51.01.0
golden failed cases00
grounded_supported_rate0.9671.0
unsupported_correct_rate0.9167*0.9167*
citation / numeric failure0 / 00 / 0

*The one failing unsupported case (unsupported-close-title-noise) fails identically on baseline — it's a pre-existing flaky false-positive control, not caused by this change. The flip also cleared the two agitation grounding cases in the after-run.

  • verify:cheap: green, 980/980. Confirmed the flip takes effect by default (clean env): golden mrr@10=0.7569.

Clinical governance preflight

  • Retrieval: strict improvement — golden recall@5 stays 1.0, mrr improves, 0 failures.
  • Answer generation / grounding:grounded_supported improves to 1.0; unsupported_correct unchanged (safety bar held); citation/numeric-grounding failure stay 0; no source-governance change.
  • Behavior reversibility: fully revertible via RAG_RANKING_CONFIG without a code change.
  • Privacy / production env: no changes.

🤖 Generated with Claude Code

…on + linear freshness)
#213 shipped documentDiversityPenalty and the linear freshness curve config-gated and
default-OFF, to be turned on only after eval-gating. Live evals show a strict improvement
with no regression on the safety bar, so both are now ON by default:
- documentDiversityPenalty 0 -> 0.02 (gentle same-document crowding demotion, capped 0.12)
- freshness.mode step -> linear (ramped decay instead of the harsh cliff)
Also fixes resolveRankingConfig, which hardcoded the freshness `mode` fallback to "step"
instead of deriving it from defaultRankingConfig, so changing the default alone would not
have taken effect at runtime without an explicit env override.
Eval evidence (golden retrieval + eval:quality --rag-only, live):
- retrieval mrr@10 0.7283 -> 0.7569, document/content recall@5 stays 1.0, 0 failures
- grounded_supported 0.967 -> 1.0, unsupported_correct unchanged, citation/numeric failure 0
- verify:cheap green (980/980)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@BigSimmo
BigSimmo merged commit 4b7e18e into mainJul 3, 2026
4 checks passed
@BigSimmo
BigSimmo deleted the claude/rag-flip-213 branch July 3, 2026 12:17
BigSimmo added a commit that referenced this pull request Aug 8, 2026
BigSimmo added a commit that referenced this pull request Aug 8, 2026
… not only the first adoption (#1742)
`validateCandidateSourceBinding` required `candidateSourceHead` to name a commit
whose `AWAITING_BASELINE` still declared the canonical six, and the current tree to
declare none. That models the FIRST adoption and nothing else. After #1729 landed,
no commit on main declares the six again, so no future capture head could ever
satisfy it -- the binding was satisfiable exactly once, and that once has passed.
The consequence is only latent today, and this commit does not pretend otherwise:
`validateLinuxVisualBaselineSet` short-circuits on `declaredPaths.length === 0` and
no surface yet declares `baseline.status: "committed"`, so the whole contract is
dormant and refreshing a golden is currently ungated. The defect bites the moment
those surfaces are declared (#242) -- at which point the first intentional design
change would leave the goldens red with no supported way to re-adopt them, which is
precisely backwards for a gate meant to make design changes provable.
So the binding now accepts either shape:
FIRST ADOPTION candidate head declares the six, current declares none.
REFRESH both ends empty, suite byte-identical.
A refresh is the ordinary case once baselines exist: a surface is deliberately
re-shot and its goldens replaced while the suite itself does not change at all.
Normalisation already blanks the AWAITING values on both sides, so the
"suite changed beyond the AWAITING declaration" check stays exact for both.
Nothing is loosened beyond that. A candidate head with five ids, seven ids, a
dynamic set, a spread or a duplicate still fails, as do a non-empty current list, a
non-ancestor head, a hash mismatch, a wrong platform and an unreviewed set. The one
previously-untested shape -- a refresh -- now has its own case, because the gap was
invisible precisely because nothing exercised it.
Verified: tests/design-system-adoption.test.ts 51 passed (51), including the new
refresh case; check:design-system-adoption and check:design-system-contract exit 0;
format:check clean.
Refs #242, #118
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.

1 participant

@BigSimmo