Comprehensive Remediation Plan: CO High School Baseball Projection System

Reference Documents:

adversarial_review_comparison_claude_251216.md (Independent Cross-Validation)

adversarial_review_comparison_gemini_251216.md (Consolidated Analysis)

adversarial_review_report_gemini_251216.md (Mathematical Logic Focus)

  1. Executive Summary

This plan synthesizes the findings from two independent adversarial reviews (Claude and Gemini). The reviews revealed that while the system’s architecture is sound, it suffers from specific “Invisible Failures”—bugs that do not crash the code but produce statistically invalid results.

Claude identified that the “Generic Player” logic is polluting team strength calculations by assigning pitching stats to batters, and that NaN values are silently zeroing out valid offensive production for some players.

Gemini identified a fundamental domain error where baseball inning notation (e.g., “10.1” innings) is being treated as a literal decimal, causing a ~2.3% systemic error in all rate statistics.

The following roadmap outlines the code changes required to bring the system to a production-ready state.

  1. Phase 1: Critical Fixes (Data & Math Integrity)

Objective: Ensure that every number output by the system is mathematically valid and statistically consistent.

Task 1.1: Fix “Decimal IP” Calculation Error (Gemini Finding)

Problem: The system treats 10.1 IP as 10.1 decimal. In baseball, .1 represents 1/3 of an inning. Target File: src/utils/utils.py (New Utility) & src/models/advanced_ranking.py Action:

Create a helper function convert_ip_to_decimal(ip_val) in utils.py.

Update calculate_pitching_score in advanced_ranking.py to use this converted value for calculations.

Task 1.2: Prevent NaN Propagation in Runs Created (Claude Finding)

Problem: If a player has Hits but NaN for Doubles/Triples, the formula results in NaN, which fillna(0) later converts to 0.0 total RC. Target File: src/models/advanced_ranking.py Action:

Explicitly fill NaN with 0 for 2B, 3B, HR, HBP, and SF before performing the vector arithmetic.

Update the RC formula to include HBP and SF (as noted in the fresh review) for better accuracy.

Task 1.3: Fix Generic Profile Role Contamination (Claude Finding)

Problem: “Generic Batters” have calculated ERAs because the source sophomores were two-way players. This pollutes the team pitching rankings. Target File: src/workflows/profile_generator.py Action:

In generate_tiers(), implement masking logic:

If role == ‘Batter’, set [‘IP’, ‘ERA’, ‘K_P’, ‘ER’] to 0.

If role == ‘Pitcher’, set [‘H’, ‘AB’, ‘HR’, ‘RBI’] to 0.

  1. Phase 2: Statistical Methodology Improvements

Objective: Reduce projection noise and account for systemic biases in high school data.

Task 2.1: Mitigate Survivor Bias (Consolidated Finding)

Problem: Historical multipliers are based only on players who didn’t quit, inflating expected development for the full roster. Target File: src/workflows/roster_prediction.py Action:

Apply a global “Churn Penalty” or “Regression Factor” to the multipliers.

Reduce applied multipliers by ~5-10% (e.g., multiplier * 0.95) to conservatively estimate growth for the average rostered player.

Task 2.2: Raise Replacement Level Thresholds (Gemini Finding)

Problem: 10th percentile generic profiles are based on players with ~12 PA, creating “replacement” players that are effectively non-existent. Target File: src/workflows/profile_generator.py Action:

Increase MIN_PA_FOR_BATTER_PROFILE from 10 to 25.

Increase MIN_IP_FOR_PITCHER_PROFILE from 3 to 10.

Task 2.3: Smooth Rare Event Multipliers (Consolidated Finding)

Problem: Rare events (Triples, HR allowed) show wild volatility (e.g., 0.5x or 0.0x) due to small denominators. Target File: src/workflows/development_multipliers.py Action:

Implement Laplacian Smoothing (Add 1) for rate-based stats or enforce a minimum count floor before calculating a specific multiplier.

  1. Phase 3: Cosmetic & Output Hygiene

Task 4.1: Standardize IP Output Format

Problem: Output CSVs show IP like 3.02. Target File: src/workflows/roster_prediction.py Action:

Implement a format_ip(decimal_val) function that converts 3.33 back to 3.1 for final reporting.

Task 4.2: Update Documentation

Target File: README.md Action:

Update the “Methodology” section to reflect the new IP conversion logic and the inclusion of HBP/SF in RC calculations.

  1. Verification Checklist (Post-Implementation)

Run these checks to confirm the remediation is successful:

Denver North Check: Verify S. Vital and D. Sanudo (from Claude’s report) have RC_Score > 0 in 2026_roster_prediction.csv.

Generic Pitching Check: Filter 2026_roster_prediction.csv for Name contains “Generic Batter” and verify Pitching_Score is exactly 0.

ERA Check: Manually calculate ERA for a projected player with x.1 IP to ensure it treats it as 1/3 inning.


Copyright © 2025 Tim Coultas

This site uses Just the Docs, a documentation theme for Jekyll.