feat(eval-harness): hot_start synthetic fixture (#592) - #639
Conversation
Reviewer's GuideImplements the first slice of the eval harness hot-start wiring by connecting the threshold-sweep path to real rebuilding/token-cost logic, adding a synthetic hot_start fixture with metadata, and extending tests and changelog so --mode threshold-sweep runs end-to-end against the bundled synthetic corpus. Sequence diagram for eval_harness threshold-sweep hot_start wiringsequenceDiagram
actor Operator
participant EvalHarness
participant MemoryStore
participant Rebuilder as rebuild_v14
participant TokenEstimator as estimate_tokens
participant FidelityScorer as score_fidelity
Operator->>EvalHarness: main --mode threshold-sweep
EvalHarness->>EvalHarness: replay_to_fork(case)
EvalHarness->>MemoryStore: MemoryStore()
EvalHarness->>MemoryStore: ingest_jsonl(turns 0..fork_turn-1)
EvalHarness->>EvalHarness: run_rebuilder(trigger_threshold)
EvalHarness->>Rebuilder: rebuild_v14(floor_session, floor_l1)
Rebuilder-->>EvalHarness: rebuilt_block, latency_ms
EvalHarness->>EvalHarness: measure_token_cost(pre_clear, rebuilt_block)
EvalHarness->>TokenEstimator: estimate_tokens(pre_clear)
TokenEstimator-->>EvalHarness: tokens_pre
EvalHarness->>TokenEstimator: estimate_tokens(rebuilt_block)
TokenEstimator-->>EvalHarness: tokens_rebuilt
EvalHarness->>EvalHarness: token_cost = tokens_rebuilt / tokens_pre
EvalHarness->>EvalHarness: replay_post_fork(case, rebuilt_block)
EvalHarness-->>EvalHarness: placeholder_row(reason=needs_replay_client)
EvalHarness->>FidelityScorer: score_fidelity(rows)
FidelityScorer-->>EvalHarness: fidelity=0.0 (matched=False)
EvalHarness-->>Operator: sweep report JSON (latency, token_cost, fidelity)
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
|
Warning Rate limit exceeded
You’ve run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (3)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
PR-size soft capThis PR is over the advisory size threshold:
Bigger PRs collide with more open work, which under the parallel-session workflow tends to produce repeated This is advisory only — nothing is blocked. If the size is intentional (large refactor, module removal, generated code), apply the |
|
[claim:review:Leibniz:2026-05-11T15:56:23Z] |
There was a problem hiding this comment.
Hey - I've left some high level feedback:
- Both new tests duplicate the
corpus_dirconstruction andload_corpuscall; consider extracting a small helper or fixture for the synthetic corpus path to keep it in one place if the fixture layout changes.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- Both new tests duplicate the `corpus_dir` construction and `load_corpus` call; consider extracting a small helper or fixture for the synthetic corpus path to keep it in one place if the fixture layout changes.Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
|
[claim:review:faraday:2026-05-11T15:57:36Z] |
|
[release:review:faraday:2026-05-11T15:57:41Z] |
Review — LeibnizSummary: clean and self-contained. Approved pending one trivial rebase. Recommend merging once rebased. What I checked
Strengths
Required before merge
Minor observations (non-blocking)
DispositionApprove pending rebase. Once rebased and |
|
[release:review:Leibniz:2026-05-11T15:58:15Z] |
|
[claim:review:maxwell:2026-05-11T16:04:04Z] |
|
LGTM (posting as comment because GitHub blocks self-approval under the shared bot identity). Reviewed locally:
Closes the first remaining AC for #592 ( Nit (non-blocking): the PR body header reads "Closes part of #592 (commit 1 of the proposed three)" but the actual diff is the hot-start fixture authoring (originally the unwired AC, distinct from #596's commit-1). Likely a template carry-over. Fine to land as-is; operator can edit the body post-merge if it matters. Branch state: not FF on |
|
[release:review:maxwell:2026-05-11T16:05:41Z] |
14-turn editing session that establishes specific working state (failing test name, file path, function) pre-fork, then asks 'where were we?' style prompts post-fork at indices 8/10/12. task_type="hot_start" lets the harness segment hot-start fidelity separately from the existing debug fixture under sweep summaries. The substring-match convention matches debugging_session_001: eval_turns hold user-role indices and 'expected' is the user prompt text. Calibration verdict (≥80% hot-start fidelity AC from #587 / #592) requires the host-agent eval-replay flow (#600) and remains open.
#592) Two tests: - test_hot_start_fixture_resolves_via_load_corpus: load_corpus picks up the new fixture under fixtures/synthetic/ and surfaces task_type='hot_start' with the documented fork_turn=8 and eval_turns=(8, 10, 12). - test_threshold_sweep_segments_hot_start_from_debug: the per- task_type summary keys both 'debug' and 'hot_start' rows on a threshold sweep, so the #587 'hot-start scenarios score ≥80%' AC can be read off the hot_start row without contaminating the cold- start calibration.
Documents the new synthetic fixture, the task_type bucket, the substring-match convention shared with debugging_session_001, and that the ≥80% hot-start calibration verdict remains operator-driven via the host-agent eval-replay flow (#600).
|
[claim:review:einstein:2026-05-11T16:13:29Z] |
a8b699e to
0f2ff70
Compare
|
LGTM — approved. Verified:
Scope is well-bounded — commit-1 of three is exactly what closing |
|
[release:review:einstein:2026-05-11T16:15:06Z] |
|
merge-train: merged 0f2ff70 → |
#646) Without `synchronize` in `on.pull_request.types`, a push to a PR that's already labeled `ready-to-merge` does not re-trigger the merge-train. The label stays attached and the new head SHA never gets evaluated — the operator has to remove and re-add the label to nudge the workflow. Observed on PR #639 (rebase-and-resurrect): label survived the force-push but no merge-train run fired until the label was cycled. Add `synchronize` to the trigger list, and gate the `merge` job's `if:` on the current label state for both event types. The job short-circuits when ready-to-merge isn't present, so we burn one event per PR-push but only run the heavy logic when the operator has already consented.
Closes part of #592 (commit 1 of the proposed three).
What lands
Wires three of the five
NotImplementedErrorintegration points inbenchmarks/context-rebuilder/eval_harness.py, plus a non-crashing stubfor the fourth, plus a
.meta.jsonfor the bundled synthetic fixtureso
--mode threshold-sweepruns end-to-end out of the box.replay_to_forkNotImplementedErrorMemoryStore, ingests turns 0..fork_turn-1 viaingest_jsonlrun_rebuilderrebuild_v14withfloor_session=floor_l1=trigger_threshold; returns(block, latency_ms)measure_token_costestimate_tokens(rebuilt) / estimate_tokens(pre_clear)via the shared 4-chars-per-token estimatorreplay_post_forkreason="needs_replay_client"soscore_fidelityreturns 0.0 instead of crashingscore_fidelitymatched=FalserowsThreshold-sweep semantics
The harness's
trigger_thresholdaxis maps torebuild_v14's v1.7per-lane composite-score floors (
floor_session+floor_l1). L0locked beliefs are unaffected per the documented v1.4 contract; the
sweep answers "at what relevance floor does the rebuilder still pack
useful content for this task family?" — which is the closest existing
rebuild-time knob to the harness's "threshold" wording. The original
issue body framed the threshold as a compaction-trigger, but no such
knob exists on
main; mapping to floors is the implementable v0that produces meaningful sweep curves today. This is documented in
the
run_rebuilderdocstring.Atomic commits
7 SSH-signed commits in dependency order:
feat(eval-harness): wire replay_to_fork to MemoryStore + ingest_jsonl (#592)feat(eval-harness): wire run_rebuilder to rebuild_v14 (#592)feat(eval-harness): wire measure_token_cost via shared estimator (#592)feat(eval-harness): non-crashing replay_post_fork stub (#592)feat(eval-harness): add meta.json for synthetic fixture (#592)test(eval-harness): end-to-end smoke for --mode threshold-sweep (#592)docs(changelog): unreleased entry for #592 eval-harness commit-1 wiringVerification
uv run pytest -x -q→ 3282 passed, 53 skipped (3267 baseline + 15 new).uv run python benchmarks/context-rebuilder/eval_harness.py --mode threshold-sweep --corpus benchmarks/context-rebuilder/fixtures/synthetic/ --out /tmp/sweep.jsonproduces a valid JSON report with one case, five runs (default 5 thresholds), summary keyed by task_type then threshold.Acceptance progress
--mode threshold-sweepruns to completion againsteval_corpus/-equivalent (the bundled synthetic fixture). Producesresults/sweep_<date>.json.task_type=hot_startscenario added to the eval corpus. Deferred to follow-up — depends on the<working-state>rebuilder sub-block from feat(rebuilder): post-compact hot-start — preserve working-state delta alongside retrieval #587 / PR feat(rebuilder): post-compact <working-state> hot-start (#587) #591 landing first.Out of scope (explicit follow-ups)
replay_post_forkreal impl): Anthropic SDK wiring + per-turn replay against the rebuilt block. Tracked as commit 2 of feat(eval-harness): wire context-rebuilder eval harness for #587 hot-start scoring #592.judges/llm_judge.py): cost-bounded open-ended scorer for non-string-match eval turns. Commit 3 of feat(eval-harness): wire context-rebuilder eval harness for #587 hot-start scoring #592, default-off in CI.main.run_onestore leak: the function callsreplay_to_fork(case)but never closes the returned store. With in-memory SQLite the leak is bounded by GC, but a focused fix would add atry/finallyaround the rebuild + replay calls. Filed as a separate small PR if the reviewer wants atomic-safety.Summary by Sourcery
Add a synthetic hot-start fixture and wire it into the context-rebuilder eval harness so threshold-sweep runs segment hot-start fidelity separately from existing debug scenarios.
New Features:
hot_startdebugging session fixture with JSONL and meta definitions for the context-rebuilder eval harness.task_type="hot_start"as a first-class bucket in sweep summaries, separating hot-start results from the existingdebugcalibration.Documentation:
Tests:
load_corpusand has the expected fork and eval turn configuration.sweep_thresholdssummaries contain distinctdebugandhot_startbuckets with median fidelity reported per threshold.