| name | heater-appb-trade-rec-review |
| description | Use when assessing whether a HEATER trade output is worth acting on — Trade Analyzer/Build evaluations (/api/trade/evaluate), Trade Finder suggestions, trade-targets (partner/acquire/category-fix/position-fix tabs) — "is this trade actually good?", "would they even accept?", "review what the finder suggested", or before proposing any trade it recommends. |
Trade Recommendation Review
REQUIRED BACKGROUND: heater-appb-manager-rec-review (league truth, data, verdicts). Payload fields: evaluate → grade (Phase-1 weighted-SGP, THE authority), grade_range{low,center,high}, warnings[] (reshuffle/IP-floor/ghost), delta_playoff_prob/delta_champ_prob, dominance {FSD|SSD|none|indistinguishable} (api/contracts/trade.py:30-55); finder → TradeSuggestion{grade, partner_record, category_impacts, partner_rationale} + reason; targets → acceptance tier: likely|possible|longshot + adds_remaining_this_week (api/contracts/trade_targets.py:37-65).
The checklist
- Grade↔surplus consistency. Grade sign must match the SGP surplus sign and
grade == grade_range.grade. Failure story: live output once showed grade=B beside surplus −1.58 (an MC overlay clobbered Phase-1; Bug A, 2026-05-23; guards test_phase1_is_grade_authority.py, test_grade_range_consistency.py). Seeing this in live output today = P0, not a judgment call.
- The reshuffle test — could we capture this WITHOUT trading? Read
warnings. A promote-only reshuffle means most of the "surplus" comes from setting our own lineup better. Failure story: a +3.97 SGP reshuffle (251% of the trade's surplus) was once silently hidden (Bug B). If reshuffle ≈ surplus: DO-NOT-ENACT as a trade; set the lineup instead.
- Both-sides test. A trade nobody accepts is noise.
partner_rationale must show the partner improving in categories THEY need (the z-score need-gate); acceptance tier=longshot → at most ENACT-WITH-CAVEATS as an opener. Sanity-check partner value too: Bug C priced a .215/.288 hitter at +54.84 to the league's best-AVG teams (missing rate-volume blending) — if the partner side looks absurd, it probably is.
- Category fit for US.
category_impacts vs our live standings gaps and punt list: gains in conceded/punted cats are ≈worthless (engine weights them 0.05×) and gains in already-locked cats are cheap paper value. The win comes in winnable, contested cats.
- Roster mechanics. 2-for-1 / 1-for-2 changes roster-spot count: verify the implied drop/fill is legal — can't-drop restricts DROPS only (rounds 1–3; the trade itself is legal); IL players keep weighted value (a zeroed-IL valuation made dropping an IL ace look free — the Crochet/Kirk incident, PR #90); position caps respected. Trades count against the 10/week combined budget — check
adds_remaining_this_week on the payload.
- IP floor. Post-trade weekly IP ≥ 20 (
ip_tracker.py:16); honor the IP-floor warning — trading away starts in a floor-risk week can forfeit pitching cats outright.
- Small-sample honesty. For every named player pull the pool row: does the value reflect actual 2026 production? Failure story: the finder's projection-only valuation graded "give 2 studs for a scrub" as A/"You win" until the 2026-06-29 overhaul (actual YTD + need-weighting + small-sample guard + honest floors). Thin
ytd_pa/ytd_ip behind a big claimed value → CAVEAT minimum.
- Horizon match.
delta_playoff_prob/delta_champ_prob should agree in sign with the grade for rest-of-season trades; a this-week rental judged on ROS surplus (or vice versa) is a mismatch — say which horizon the numbers answer.
- Dominance screen.
dominance is a diagnostic that never overrides the grade (by contract, trade.py:30-34) — but for ENACTMENT, being on the dominated side of FSD/SSD is disqualifying: a fine point-estimate can hide a strictly-worse championship distribution. indistinguishable = say so.
- Freshness + live truth. Partner rosters still contain the offered players (Yahoo sync age); no interim add/drop/trade; values not computed on a degraded-projection day (Marcel-only → grades shift; check
refresh_log).
- Honest-empty ≠ broken. Finder/targets
reason enums (team_not_resolved, no_totals, grade_error…) explain empties — two silent bugs once hid behind a quiet [] for weeks (emoji team-name key + all_team_totals=None, WS4). An empty WITH a reason is working honesty.
Verdict
ENACT only when 1–8 pass and 9–11 raise nothing; otherwise ENACT-WITH-CAVEATS (named), DO-NOT-ENACT (named check), or DATA-DEGRADED. Present evidence, not preference — the trade decision is the manager's (standing no-editorializing rule).
When NOT to apply
Valuation-methodology work (SGP/VORP/MC internals) → heater-appb-fantasy-math-invariants. Building new trade surfaces → endpoint-slice + math-feature-dev. Multi-player Analyzer evaluations work today; only the FINDER caps auto-suggestions at 2-for-1 — that's a known scope choice, not a bug.