fix(rl): eval_summary aggregates across all b_size accounts (E.4-E.5)
Replaces the broken single-account + scale-mismatch slicing block in
alpha_rl_train.rs eval phase with proper per-account aggregation.
Pre-fix (cluster v11 alpha-rl-8ll7j, b=1024):
head_before_eval = sim.read_total_trade_count() // aggregate=1,203,376
all_records = sim.read_trade_records(0) // backtest 0 only, ≤1024
// 1.2M > 1024 → wrap branch fires → eval_records = ALL 1024 records
// from account 0, mixing train+eval trades
eval_summary: n_trades=1024 pnl=$61,513 wr=0.217 — MEANINGLESS
Post-fix (this commit, b=16 local smoke):
head_before_per_b = sim.read_per_backtest_trade_counts()
all_per_b = sim.read_trade_records_all()
// for each backtest: slice ring by per-account head_before vs head_after,
// handle wrap correctly, aggregate eval-only records
eval_summary: n_trades=226 pnl=$-41,137 wr=0.376
n_eval_trades_seen=226 (= captured) n_dropped=0 n_pre_eval_wrapped=0
Local smoke validation (b=16, 1k train + 250 eval, fold 1 ES.FUT all):
- n_trades jumped 58 → 226 (4× — confirms aggregation across 16 accts)
- per-account pre-eval heads: min=16 max=59 sum=596 (correct scale)
- n_eval_trades_seen == n_trades (no wrap at this scale)
- eval_summary.json gained 4 new fields:
n_eval_trades_seen, n_eval_trades_dropped,
n_pre_eval_trades_wrapped, b_size
Existing keys (n_trades, total_pnl_usd, profit_factor, sharpe_ann,
max_drawdown_usd, win_rate) preserved for downstream G8-gate / Argo
aggregator consumers (per spec §3).
Cluster validation pending Phase A cluster (alpha-rl-jz48s) completion
to avoid alpha_rl_train.rs branch conflict. After Phase A merges,
this fix can submit alongside.
Spec: docs/superpowers/specs/2026-05-31-eval-summary-trade-aggregation-design.md
Plan: docs/superpowers/plans/2026-05-31-eval-summary-trade-aggregation.md
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>