From 931416a7c71c2afa22d1913fdbe2cc606bd8003f Mon Sep 17 00:00:00 2001 From: Cal Corum Date: Thu, 26 Feb 2026 23:58:55 -0600 Subject: [PATCH] Add FullCard migration status doc for session continuity Documents current branch state, what's built, what's left, known bugs, and decision points so the next session can pick up without re-investigating. Co-Authored-By: Claude Opus 4.6 --- docs/FULLCARD_MIGRATION_STATUS.md | 89 +++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 docs/FULLCARD_MIGRATION_STATUS.md diff --git a/docs/FULLCARD_MIGRATION_STATUS.md b/docs/FULLCARD_MIGRATION_STATUS.md new file mode 100644 index 0000000..f9b3b67 --- /dev/null +++ b/docs/FULLCARD_MIGRATION_STATUS.md @@ -0,0 +1,89 @@ +# FullCard Migration Status + +**Branch:** `feature/fullcard-migration` (5 commits ahead of main) +**Last Updated:** 2026-02-26 + +## What This Branch Does + +Moves card-building logic (fitting continuous chances to discrete 2d6×d20 card mechanics) from the database to Python. Previously, Python sent raw continuous values and the database fitted them — meaning what you sent ≠ what got stored. Now Python builds the complete discrete card structure before POSTing. + +### New Files + +| File | Purpose | +|------|---------| +| `card_layout.py` | Core card models: PlayResult, CardResult, CardColumn, FullCard, FullBattingCard, FullPitchingCard. Ported from database's `card_creation.py`. Uses `col_*` key names. | +| `batters/card_builder.py` | `build_batter_full_cards()` — takes vL/vR ratings, returns two FullBattingCard objects | +| `pitchers/card_builder.py` | `build_pitcher_full_cards()` — same for pitchers | +| `batters/models.py` | Extracted `BattingCardRatingsModel` from `calcs_batter.py` | +| `pitchers/models.py` | Extracted `PitchingCardRatingsModel` from `calcs_pitcher.py` | +| `offense_col_resolver.py` | Maps player→offense_col for retrosheet pipeline (fixed 883 silent KeyErrors) | +| `tests/test_rate_stats_formulas.py` | Tests for extracted rating model formulas | + +### Integration Path + +``` +retrosheet_data.py → calcs_batter.py → build_batter_full_cards() → card_output() → vl_dict.update() + → calcs_pitcher.py → build_pitcher_full_cards() → card_output() → vr_dict.update() +``` + +Card builders are called inside a `try/except` in `calcs_batter.py:339` and `calcs_pitcher.py:134`. On failure, logs a warning and the card still posts without col_* layout data (backwards compatible). + +## Commits on Branch + +1. `a72abc0` — Add FullCard/CardColumn/CardResult models and card builder pipeline +2. `39c652e` — Extract BattingCardRatingsModel and PitchingCardRatingsModel into models.py files +3. `2bf3a6c` — Fix SLG formula drift in extracted rating models +4. `32cadb1` — Fix two bugs in pitcher card builder dispatch logic +5. `db38225` — Add offense_col resolver for retrosheet pipeline to fix 883 silent KeyErrors + +## What's Left Before Merge + +### 1. Database Migration (BLOCKING if you want col_* data persisted) + +The database repo (`paper-dynasty-database`) has a parallel `feature/fullcard-migration` branch with: +- 9 new nullable TextFields on `BattingCardRatings` and `PitchingCardRatings` tables +- Pydantic model updates in `routers_v2/battingcardratings.py` and `pitchingcardratings.py` +- Migration SQL documented but **intentionally not run** + +Without this migration, the col_* fields in `card_output()` are computed but silently ignored by the API. The card-creation side works either way — it's a no-op until the DB accepts those fields. + +### 2. `live_series_update.py` Not Integrated + +This file has its own inline card generation — does NOT use `calcs_batter`/`calcs_pitcher`. Only the retrosheet pipeline benefits from the new card builders. Live series integration is a separate effort. + +### 3. No Tests for Core New Code + +`card_layout.py` (1015 lines), `batters/card_builder.py` (802 lines), `pitchers/card_builder.py` (776 lines) have zero test coverage. Priority targets: +- `get_chances()` — maps continuous values to discrete EXACT_CHANCES +- `CardColumn.add_result()` / `FullCard.card_fill()` — the filling algorithm +- `card_output()` — serialization to col_* dict format +- End-to-end: feed known ratings → assert expected card structure + +### 4. Test Failures (Pre-existing, Not From This Branch) + +- `test_wh_singles` — `wh_singles(12, .45)` returns `8.0` vs expected `Decimal('7.95')`. Fails on main too. The test file has a 1-line diff on this branch (import change). +- 11 failures in `test_automated_data_fetcher.py` — mock setup issues, no diff on this branch. + +## Key Bugs Fixed During Development + +1. **Float/Decimal mismatch** — card_layout uses Decimal internally, models use float. Fix: wrap `card_fill()` outputs with `float()` in `assign_bchances()`/`assign_pchances()`. +2. **PitchingCardRatingsModel xcheck defaults** — Non-zero defaults (xcheck_ss=7.0, etc.) corrupted accumulation. Fix: explicitly zero all xcheck fields in `new_ratings` constructor. +3. **Pitcher dispatch logic** — Two bugs in how pitcher card builder routed plays to columns. +4. **offense_col KeyError** — Retrosheet pipeline had no offense_col resolver, causing 883 silent failures. + +## Architecture Reference + +Full design doc: `docs/architecture/CARD_BUILDER_REDESIGN.md` + +Migration phases: +- **Phase 1 (Extract & Validate)** — Done +- **Phase 2 (Python Adoption)** — In progress (retrosheet pipeline wired up) +- **Phase 3 (Database Simplification)** — Pending DB migration + removing fitting logic from DB +- **Phase 4 (Enhancements)** — Future (contracts/card personalities, preview endpoint) + +## Decision Points for Next Session + +1. **Merge as-is?** Branch is safe to merge — col_* fields are computed but harmlessly ignored until DB migrates. Card generation behavior is unchanged. +2. **Add tests first?** Recommended but not strictly required since card builders are behind try/except. +3. **Run DB migration?** Enables end-to-end persistence. Requires deploying database branch too. +4. **Wire up live series?** Separate PR recommended — different pipeline, different concerns.