Skip to content

perf(rerank): judgments persist and replay — the judge stops re-buying opinions it already owns - #568

Merged
runyourempire merged 3 commits into
mainfrom
worktree-apply-recs-wave2
Aug 31, 2026
Merged

perf(rerank): judgments persist and replay — the judge stops re-buying opinions it already owns#568
runyourempire merged 3 commits into
mainfrom
worktree-apply-recs-wave2

Conversation

@runyourempire

Copy link
Copy Markdown
Collaborator

Approved rec #2 from the 2026-08-31 recommendation set (operator green-lit).

The measured waste

42% of rerank judgments over the last 48h (808 provenance rows / 466 distinct items / 17 passes; adjacent-pass overlap 13/48) re-judged items an earlier pass had already judged with the same model identity and prompt version. The feed's top band is sticky by construction, so every ~10-minute analysis cycle re-bought verdicts it already owned.

What changed

Schema 116 adds advisor_judgments — one row per (source_item_id, identity_hash, prompt_version), newest wins, ON DELETE CASCADE (Phase-115 precedent). Coordinated on the board: Lane F confirmed no competing migration; 115 was taken by #564.

apply_llm_reranking now partitions candidates: fresh-enough memo rows (20h window — judged content is immutable post-ingest; the user's context is what drifts, and it re-judges daily) replay through the reconciler with zero API calls; only the remainder is LLM-judged. Doctrinal guardrails:

  • Replays never re-stamp provenance or calibration samples — a stored judgment re-entering the calibration set would double-count and, at the limit, feed the fitter its own output (the 2026-08-11 degenerate-curve incident class).
  • The uniform-advisor circuit breaker runs on fresh judgments only (it catches an advisor broken now; replays already passed it), and only breaker-surviving passes are memoized.
  • Identity-strict: a swapped model or bumped prompt version never replays a predecessor's opinions (unit-tested).

Replayed items get byte-identical adjustments to a fresh judgment, so there is deliberately no PIPELINE_VERSION bump. The memo mounts as a #[path] submodule of analysis_rerank (the analysis_dedup precedent) — no lib.rs churn. The rerank completion log now reports fresh= / replayed=.

Effect

A stable top band costs one judgment per item per day instead of ~9; the freed (paced) token budget rotates to items the judge has never seen — coverage up, spend down. Compounds with #565's oldest-first drain per Lane F.

Verification

  • cargo test --lib: 4,748 passed / 0 failed (5 new memo tests: freshness aging, identity/prompt isolation, upsert newest-wins, empty no-op)
  • clippy --all-features -D warnings clean; fmt clean; check-file-sizes warn-only (948/1000)
  • Deploy note: schema 113→116 path exercised by the migration suite; both binaries rebuilt together at deploy per doctrine

🤖 Generated with Claude Code

https://claude.ai/code/session_019RTCgzAcaopjz3KZnaqNrj

…g opinions it already owns

Approved rec #2 (2026-08-31 set). Measured on the live corpus: 42% of
rerank judgments over 48h (808 provenance rows / 466 distinct items / 17
passes) re-judged items an earlier pass had already judged with the SAME
model identity and prompt version — the feed's top band is sticky by
construction, so every ~10-minute cycle re-bought identical verdicts.

Schema 116 adds advisor_judgments — one row per (source_item_id,
identity_hash, prompt_version), newest wins, ON DELETE CASCADE per the
Phase-115 precedent. apply_llm_reranking now:

- loads fresh-enough memo rows (20h window: judged content is immutable
  post-ingest; what drifts is the user's context, which re-judges daily),
- LLM-judges only the remainder, and REPLAYS the memoized judgments
  through the reconciler — same adjustments, same explanations, zero API
  calls,
- stamps provenance and calibration samples for FRESH judgments only — a
  replay re-entering the calibration set would double-count the sample and
  feed the fitter its own output (2026-08-11 incident class),
- runs the uniform-advisor circuit breaker on fresh judgments only (its
  job is catching an advisor broken NOW; replays passed it in the pass
  that produced them), and memoizes only breaker-surviving passes,
- keys strictly on identity_hash + prompt_version: a swapped model or
  bumped prompt never replays a predecessor's opinions.

Effect: a stable top band costs one judgment per item per day instead of
~9, and the freed (paced) budget rotates to items the judge has never
seen — coverage up, spend down. Scores for replayed items are identical
to what a fresh judgment would produce, so no PIPELINE_VERSION bump.

The memo lives as a #[path] submodule of analysis_rerank (the
analysis_dedup precedent) — no lib.rs churn. rerank log line now carries
fresh= and replayed= counts.

Verification: cargo test --lib 4748 passed / 0 failed (5 new memo tests:
freshness aging, identity/prompt isolation, upsert semantics); clippy
--all-features -D warnings clean; fmt clean; check-file-sizes warn-only.
Schema 116 coordinated with the fleet (Lane F confirmed no competing
migration; 115 = #564).

Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_019RTCgzAcaopjz3KZnaqNrj
@runyourempire
runyourempire enabled auto-merge (squash) August 31, 2026 04:43
@runyourempire
runyourempire disabled auto-merge August 31, 2026 07:34
@runyourempire
runyourempire added this pull request to the merge queue Aug 31, 2026
Merged via the queue into main with commit f6c98fc Aug 31, 2026
16 checks passed
@runyourempire
runyourempire deleted the worktree-apply-recs-wave2 branch August 31, 2026 07:54
Sign up for free to 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