Blocked by: none — prerequisites met (Phase 9 /improve-bot-evolve operational; Phase EL shipped)
Build doc: documentation/plans/evolve-judging-plan.md
Track: 10 (Statistical robustness / evolve substrate) — alongside Phase R
Goal
Ship the six cheapest high-value changes from the 2026-07-05 evolve-judging investigation into /improve-bot-evolve's judging gates, all flag-gated with byte-identical defaults. The fitness gate's strict-majority bar lets a no-effect improvement pass ~61% of the time eventually (through the retry/bench ladder), and truly-neutral stacks get destroyed by coin-flip rollbacks. EJ.1/EJ.2/EJ.5 cut the null inflow before games are spent; EJ.3/EJ.4 stop the regression gate destroying whole generations on coin flips while keeping a hard drift backstop; EJ.6 reclaims stranded wall-clock. These compound: fewer nulls entering means the relaxed regression bar's lower catch rate matters less. Empirical games remain the final promotion authority throughout — nothing here adds an LLM judge to the gate path (SKILL.md safety-rail constraint).
Work (8 steps)
Sequencing: EJ.1–EJ.6 (#282–#287) all edit scripts/evolve.py (argparse + loop) → run serially, no parallel worktrees (plan §4). EJ.7/EJ.8 are operator/wait gates.
Acceptance
- Every flag defaults OFF → byte-identical to today, enforced by regression tests (
is/exact-equality), not just review. The ONE deliberate default-visible change is the reworded priors prompt line (src/orchestrator/evolve.py L1484) in EJ.1 — its golden test update is intentional, not drift.
- For every code step:
uv run pytest (≥ 1799 baseline), uv run mypy src bots --strict, uv run ruff check . clean.
- EJ.7 flags-on real-SC2 smoke completes without crash; every triggered EJ mechanism leaves its audit row; a defaults-off run shows zero behavior change.
- EJ.8 overnight A/B soak produces a comparison table + default-flip recommendation. NOT gated on showing improvement — a negative result is valid and blocks default flips.
Effort
6 code steps (EJ.1–EJ.6) run serially (shared scripts/evolve.py), then 1 operator smoke (EJ.7) + 1 overnight wait soak (EJ.8).
Kill criterion
None hard — all changes ship flag-gated OFF, so production is byte-identical by default and nothing regresses. A negative EJ.8 result blocks the default-flip recommendation, not the merge. Flipping any default ON is a post-EJ.8 operator decision, explicitly out of this phase's scope.
Relationship to Phase R
The investigation partially supersedes Phase R: SPRT is rejected (negative LLR drift inside the indifference zone at the ~0.6 true win rates this loop produces, at ~3× the game cost of EJ.3's posterior rule). Phase R's Wilson-CI reporting idea remains valid backlog; Phase R should be re-scoped after Phase EJ ships.
Blocked by: none — prerequisites met (Phase 9
/improve-bot-evolveoperational; Phase EL shipped)Build doc: documentation/plans/evolve-judging-plan.md
Track: 10 (Statistical robustness / evolve substrate) — alongside Phase R
Goal
Ship the six cheapest high-value changes from the 2026-07-05 evolve-judging investigation into
/improve-bot-evolve's judging gates, all flag-gated with byte-identical defaults. The fitness gate's strict-majority bar lets a no-effect improvement pass ~61% of the time eventually (through the retry/bench ladder), and truly-neutral stacks get destroyed by coin-flip rollbacks. EJ.1/EJ.2/EJ.5 cut the null inflow before games are spent; EJ.3/EJ.4 stop the regression gate destroying whole generations on coin flips while keeping a hard drift backstop; EJ.6 reclaims stranded wall-clock. These compound: fewer nulls entering means the relaxed regression bar's lower catch rate matters less. Empirical games remain the final promotion authority throughout — nothing here adds an LLM judge to the gate path (SKILL.md safety-rail constraint).Work (8 steps)
Sequencing: EJ.1–EJ.6 (#282–#287) all edit
scripts/evolve.py(argparse + loop) → run serially, no parallel worktrees (plan §4). EJ.7/EJ.8 are operator/wait gates.Acceptance
is/exact-equality), not just review. The ONE deliberate default-visible change is the reworded priors prompt line (src/orchestrator/evolve.py L1484) in EJ.1 — its golden test update is intentional, not drift.uv run pytest(≥ 1799 baseline),uv run mypy src bots --strict,uv run ruff check .clean.Effort
6 code steps (EJ.1–EJ.6) run serially (shared
scripts/evolve.py), then 1 operator smoke (EJ.7) + 1 overnight wait soak (EJ.8).Kill criterion
None hard — all changes ship flag-gated OFF, so production is byte-identical by default and nothing regresses. A negative EJ.8 result blocks the default-flip recommendation, not the merge. Flipping any default ON is a post-EJ.8 operator decision, explicitly out of this phase's scope.
Relationship to Phase R
The investigation partially supersedes Phase R: SPRT is rejected (negative LLR drift inside the indifference zone at the ~0.6 true win rates this loop produces, at ~3× the game cost of EJ.3's posterior rule). Phase R's Wilson-CI reporting idea remains valid backlog; Phase R should be re-scoped after Phase EJ ships.