Repository navigation
[Phase 2] Extend the harness to prompts/deep-review.md via an LLM-judge scorer #585
Copy link
Copy link
Closed
Labels
dev-leadFor dev-lead agent pickupFor dev-lead agent pickupinitiativeEpic / initiative tracking issueEpic / initiative tracking issue
Description
Story
As a skill maintainer,
I want a held-out case set for deep-review plus an LLM-judge scoring adapter for its non-deterministic output,
so that proves the harness generalizes beyond a deterministic skill to a second high-traffic skill.
Acceptance Criteria
- skills/evals/deep-review/cases.jsonl exists with held-out cases capturing the expected risk classification / approve-vs-escalate decision and the key findings deep-review.md should surface.
- run-eval.sh supports a per-skill scorer mode — deterministic (triage) vs LLM-judge (deep-review) — selected by per-skill config, not hardcoded branching on skill name in the comparator core.
- The LLM-judge runs on a Haiku-tier model and emits a numeric per-case score; the judge prompt is itself a versioned file under skills/evals/ and is CODEOWNER-gated like the cases.
- Offline tests cover the judge-mode plumbing with a stubbed judge (no network).
Tasks / Subtasks
- Author skills/evals/deep-review/cases.jsonl from deep-review.md risk taxonomy + decision section (AC: test issue from agent #1)
- Add a per-skill scorer-mode config and an LLM-judge adapter to run-eval.sh (AC: Go-live improvements for PR review agent #2, Add @claude delegation, auto-merge, and rebase handling #3)
- Versioned judge prompt under skills/evals/
- Numeric score per case
- Add offline judge-mode tests with a stubbed judge (AC: Optimize review: small-PR and incremental fast paths #4)
Dev Notes
- deep-review.md outputs a findings array plus a decision/risk (not a single boolean), so deterministic equality cannot score it. The idea explicitly allows 'a deterministic check or a Haiku-tier LLM-judge' — use the judge here.
- engine.sh's triage tier is already a Haiku-tier model (set_engine_config) — reuse that tier for the judge to keep cost low. Drive it through run_triage/run_agentic rather than a new invocation path.
- Keep the comparator core generic: select scorer mode from per-skill config so adding a third skill later needs no edits to the core. The judge prompt is a skill-quality input, so version it and CODEOWNER-gate it exactly like cases (reward-hacking guard).
- Cite the shared risk taxonomy (prompts/shared.md) when authoring expected classifications.
Project Structure Notes
Reuses the skills/evals/ tree and run-eval.sh from Phase 1; adds deep-review cases and a versioned judge prompt alongside the triage assets.
References
- prompts/deep-review.md
- prompts/shared.md
- scripts/engine.sh#set_engine_config
- scripts/engine.sh#run_agentic
- skills/evals/run-eval.sh
Likely target surface
skills/evals/deep-review/cases.jsonlskills/evals/judge.mdskills/evals/run-eval.shtests/test_skill_evals.bats
Story prepared by the BMAD Scrum Master (Bob) for epic #581. Status: ready-for-dev.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
dev-leadFor dev-lead agent pickupFor dev-lead agent pickupinitiativeEpic / initiative tracking issueEpic / initiative tracking issue
Activity
don-petry commentedon Jun 14, 2026
Dev-Lead Implementation Plan
Issue: #585 — [Phase 2] Extend the harness to prompts/deep-review.md via an LLM-judge scorer
Scope
Add a held-out
deep-revieweval set plus a config-driven LLM-judge scorer mode to the existing Phase-1 harness, so non-deterministic deep-review output is scored by a Haiku-tier judge selected per-skill (no skill-name branching in the comparator core).Path mapping (issue surface → actual repo)
The issue's
skills/evals/*paths map to the repo's real tree:scripts/evals/run-eval.shevals/deep-review/{dev,holdout}/cases.jsonl(both splits required byvalidate-cases.py)evals/judge.mdtests/test_skill_evals.batsImplementation Checklist
evals/deep-review/holdout/cases.jsonl+evals/deep-review/dev/cases.jsonl— held-out cases capturing risk classification, approve-vs-escalate decision, and key findings (grounded in deep-review.md + shared.md risk taxonomy). Disjoint ids across splits.evals/judge.md— versioned, CODEOWNER-gated LLM-judge prompt emitting a numeric score.evals/deep-review/scorer.json— per-skill config selectingllm-judgemode (+ judge prompt + pass threshold). Absent config defaults todeterministic, so triage is unchanged.scripts/evals/run-eval.sh— read per-skillscorer.json; dispatch a generic scorer mode (deterministic vs llm-judge); add an LLM-judge adapter that builds the judge prompt and invokes the judge viaEVAL_JUDGE_CMD(defaultrun_triage, Haiku-tier). Per-case numeric score..github/CODEOWNERS— explicit owner-lock forevals/judge.md(reward-hacking guard, like cases).Tests to Write
scorepresent in judge-mode results.holdout/; never writes the cases file.validate-cases.pyaccepts the new deep-review split (committed-tree test).Test Command
bats tests/test_skill_evals.bats tests/test_validate_cases.bats && python3 evals/validate-cases.py && shellcheck scripts/evals/run-eval.sh && bash .dev-lead/scripts/dev-lead-lint.shdon-petry commentedon Jun 14, 2026
Dev-Lead: Implementation Complete
Plan Execution
evals/deep-review/holdout/cases.jsonl(5 held-out cases) +evals/deep-review/dev/cases.jsonl(2 proposer-visible cases), capturing the approve-vs-escalate decision, risk classification,escalate_to_opusrouting, and the key findings deep-review.md must surface — grounded in the shared risk taxonomy (prompts/shared.md) and deep-review.md's Decision section (AC test issue from agent #1).evals/deep-review/scorer.json) and made the comparator core inscripts/evals/run-eval.shdispatch on$SCORER_MODE(deterministic|llm-judge) read from that config — no skill-name branching. Absent config defaults todeterministic, so triage is untouched (AC Go-live improvements for PR review agent #2).EVAL_JUDGE_CMD(defaultrun_triage, the Haiku-tier engine), parsing a numeric per-casescoreand passing the case when it meetspass_threshold(default 0.7) (AC Add @claude delegation, auto-merge, and rebase handling #3).evals/judge.mdand CODEOWNER-gated it (/evals/judge.mdin.github/CODEOWNERS), alongside the existing holdout gating + the [Guardrail] Hard CI check: fail any proposer-authored PR that touches evals/ #692 CI immutability guard that already covers anyevals/path (AC Add @claude delegation, auto-merge, and rebase handling #3, reward-hacking guard).Path note
The issue's "likely target surface" used
skills/evals/*; the live tree isscripts/evals/run-eval.sh(scorer) andevals/<skill>/{dev,holdout}/cases.jsonl(cases) from Phase 1. The judge prompt lives atevals/judge.md. Implemented against the live paths.Test Results
Files Changed
scripts/evals/run-eval.sh: config-driven scorer mode;score_deterministic+score_llm_judgefunctions;EVAL_JUDGE_CMDinjectable engine command; per-case numericscore; aggregate report shape unchanged (score = passed/total).evals/deep-review/holdout/cases.jsonl,evals/deep-review/dev/cases.jsonl: new held-out + dev splits (disjoint ids).evals/deep-review/scorer.json: selectsllm-judgemode + judge prompt + pass threshold.evals/judge.md: versioned LLM-judge rubric emitting{"score": <0..1>, "reason": ...}..github/CODEOWNERS: owner-lock/evals/judge.md.tests/test_skill_evals.bats: 6 new tests covering judge-mode plumbing (stubbed, offline) + the deterministic-default guarantee.Notes
scorer.json; a third skill needs only its own config + cases — no edits to the comparator core.run_triageto keep cost low, per the Dev Notes.$OUTPUT_FILErather than stdout, while the scorer (like the Phase-1 triage scorer) captures stdout. Real end-to-end deep-review scoring would need a small prompt/harness adaptation to emit the verdict on stdout; the offline judge plumbing (AC Optimize review: small-PR and incremental fast paths #4) is what this story scopes.feat: implement issue #585 — [Phase 2] Extend the harness to prompts/…