5.4 KiB
| title | description | type | domain | tags | ||||
|---|---|---|---|---|---|---|---|---|
| Refractor Phase 2: Integration — boost wiring, tests, and review | Implemented apply_tier_boost orchestration, dry_run evaluator, evaluate-game wiring with kill switch, and 51 new tests across paper-dynasty-database. PRs #176 and #177 merged. | context | paper-dynasty |
|
Refractor Phase 2: Integration — boost wiring, tests, and review
Date: 2026-03-30
Branch: feature/refractor-phase2-integration (merged to main)
Repo: paper-dynasty-database
What Was Done
Full implementation of Refractor Phase 2 Integration — wiring the Phase 2 Foundation boost functions (PR #176) into the live evaluate-game endpoint so that tier-ups actually create boosted variant cards with modified ratings.
- PR #176 merged (Foundation) — Review findings fixed (renamed
evolution_tiertorefractor_tier, removed redundant parens), then merged via pd-ops evaluate_card(dry_run=True)— Added dry_run parameter to separate tier detection from tier write.apply_tier_boost()becomes the sole writer ofcurrent_tier, ensuring atomicity with variant creation. Addedcomputed_tierandcomputed_fully_evolvedto return dict.apply_tier_boost()orchestration — Full flow: source card lookup, boost application per vs_hand split, variant card + ratings creation with idempotency guards, audit record with idempotency guard, atomic state mutations viadb.atomic(). Display stat helpers compute fresh avg/obp/slg.evaluate_game()wiring — Calls evaluate_card with dry_run=True, loops through intermediate tiers on tier-up, handles partial multi-tier failures (reports last successful tier),REFRACTOR_BOOST_ENABLEDenv var kill switch, suppresses false notifications when boost is disabled or card_type is missing.- 79-sum documentation fix — Clarified all references to "79-sum" across code, tests, and docs to note the 108-total card invariant (79 variable + 29 x-check for pitchers).
- 51 new tests — Display stat unit tests (12), integration tests for orchestration (27), HTTP endpoint tests (7), dry_run evaluator tests (6). Total suite: 223 passed.
- Five rounds of swarm reviews — Each change reviewed individually by swarm-reviewer agents. All findings addressed: false notification on null card_type, wrong tier in log message, partial multi-tier failure reporting, atomicity test accuracy, audit idempotency gap, import os placement.
- PR #177 merged — Review found two issues (import os inside function, audit idempotency gap on PostgreSQL UNIQUE constraint). Both fixed, pushed, approved by Claude, merged via pd-ops.
Decisions
Display stats computed fresh, not set to None
The original PO review note suggested setting avg/obp/slg to None on variant cards and deferring recalculation. Cal decided to compute them fresh using the exact Pydantic validator formulas instead — strictly better than stale or missing values. Design doc updated to reflect this.
Card/ratings creation outside db.atomic()
The design doc specified all writes inside db.atomic(). Implementation splits card/ratings creation outside (idempotent, retry-safe via get_or_none guards) with only state mutations (audit, tier write, Card.variant propagation) inside the atomic block. This is pragmatically correct — on retry, existing card/ratings are reused. Design doc updated.
Kill switch suppresses notifications entirely
When REFRACTOR_BOOST_ENABLED=false, the router skips both the boost AND the tier_up notification (via continue). This prevents false notifications to the Discord bot during maintenance windows. Initially the code fell through and emitted a notification without a variant — caught during coverage gap analysis and fixed.
Audit idempotency guard added
PR review identified that RefractorBoostAudit has a UNIQUE(card_state_id, tier) constraint in PostgreSQL (from the migration) that the SQLite test DB doesn't enforce. Added get_or_none before create to prevent IntegrityError on retry.
Follow-Up
- Phase 3: Documentation updates in
card-creationrepo (docs only, no code) - Phase 4a: Validation test cases in
databaserepo - Phase 4b: Discord bot tier-up notification fix (must ship alongside or after Phase 2 deploy)
- Deploy Phase 2 to dev: run migration
2026-03-28_refractor_phase2_boost.sqlon dev DB - Stale branches to clean up in database repo:
feat/evolution-refractor-schema-migration,test/refractor-tier3
Files Changed
paper-dynasty-database:
app/services/refractor_boost.py— apply_tier_boost orchestration, display stat helpers, card_type validation, audit idempotency guardapp/services/refractor_evaluator.py— dry_run parameter, computed_tier/computed_fully_evolved in return dictapp/routers_v2/refractor.py— evaluate_game wiring, kill switch, partial multi-tier failure, isoformat crash fixtests/test_refractor_boost.py— 12 new display stat tests, 79-sum comment fixestests/test_refractor_boost_integration.py— 27 new integration tests (new file)tests/test_postgame_refractor.py— 7 new HTTP endpoint teststests/test_refractor_evaluator.py— 6 new dry_run unit tests
paper-dynasty (parent repo):
docs/refractor-phase2/01-phase1-foundation.md— 79-sum clarificationsdocs/refractor-phase2/02-phase2-integration.md— atomicity boundary, display stats updates