feat: Refractor Phase 2 foundation — boost functions, schema, tests #176
No reviewers
Labels
No Label
ai-changes-requested
ai-failed
ai-merged
ai-pr-opened
ai-reviewed
ai-reviewing
ai-reviewing
ai-working
bug
enhancement
evolution
performance
phase-0
phase-1a
phase-1b
phase-1c
phase-1d
security
tech-debt
todo
No Milestone
No project
No Assignees
2 Participants
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: cal/paper-dynasty-database#176
Loading…
Reference in New Issue
Block a user
No description provided.
Delete Branch "feature/refractor-phase2-foundation"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
app/services/refractor_boost.py(new, 315 lines) — Pure functions for computing boosted card ratings at tier-up:apply_batter_boost(fixed +0.5 to 4 offensive columns),apply_pitcher_boost(1.5 TB-budget priority algorithm),compute_variant_hash(deterministic variant ID). All use Decimal arithmetic internally and preserve the 108-sum invariant.app/db_engine.py— AddRefractorBoostAuditmodel (audit trail for tier boosts),Card.variant,BattingCard.image_url,PitchingCard.image_url,RefractorCardState.variantfields.tests/conftest.py— RegisterRefractorBoostAudit+ FK parents in test model list.migrations/2026-03-28_refractor_phase2_boost.sql— Additive DDL:refractor_card_state.variantcolumn +refractor_boost_audittable (JSONB, UNIQUE constraint, transactional).tests/test_refractor_boost.py(new, 26 tests) — Comprehensive coverage: 108-sum invariant, correct deltas, truncation handling, TB accounting, determinism, x-check protection, variant hash behavior, and edge cases.Review notes
on_delete='CASCADE',applied_atdefault,BEGIN/COMMITwrapper, TextField/JSONB commentTest plan
python -m pytest tests/test_refractor_boost.py -v— 26/26 passedpython -m pytest) to verify no regressionsssh pd-database)🤖 Generated with Claude Code
AI Code Review
Files Reviewed
app/services/refractor_boost.py(added, 315 lines)app/db_engine.py(modified — 4 new ORM fields +RefractorBoostAuditmodel)migrations/2026-03-28_refractor_phase2_boost.sql(added)tests/test_refractor_boost.py(added, 26 tests)tests/conftest.py(modified)Findings
Correctness
last_delta = total_actually_reduced - running_sumwith a zero-floor ensures the sum of positive applications equals what was actually taken from negative columns. ✓compute_variant_hashzero-remap:variant=0is reserved and correctly remapped to 1. ✓RefractorBoostAuditFK ordering in_TEST_MODELS:BattingCardandPitchingCardare inserted aboveRefractorBoostAuditand below their own FK parent (Player). Dependency order is valid. ✓battingcard.image_url,pitchingcard.image_url, andcard.variantwere already added to the DB by2026-03-17_add_evolution_tables.sql. Phase 2 migration correctly adds only the newrefractor_card_state.variantcolumn andrefractor_boost_audittable. No missing migrations. ✓applied_at = DateTimeField(default=datetime.now): Callable reference (not a called value) — correct. ✓UNIQUE(card_state_id, tier): Prevents double-application of a boost at the same tier on retry. Correct safety guard. ✓Security
No issues found. Pure functions with no I/O, no SQL construction, no user-controlled input paths. Migration uses parameterless DDL.
Style & Conventions
Naming inconsistency —
evolution_tierparameter: Thecompute_variant_hashfunction usesevolution_tieras the parameter name, but the entire system was renamed from "Evolution" to "Refractor" in PR #131. New code in this PR should userefractor_tier(or justtier) to stay consistent with the established convention. The docstring compounds the issue by sayingevolution_tier: Refractor tier (0–4)— it uses both names simultaneously.boost_delta_jsonmulti-line formatting: The parentheses aroundTextField()are redundant and non-idiomatic:The comment itself is valuable and should be kept.
Test Coverage
26 tests across 8 test classes. Coverage is thorough:
No issues found.
Verdict: COMMENT
Clean, well-tested implementation. Core algorithms are correct and the migration is complete. The only notable finding is the
evolution_tierparameter name incompute_variant_hash��� it contradicts the refractor naming convention established by PR #131. Since this is a pure function signature that callers will import and use, fixing the name now avoids a later rename ripple. All other findings are cosmetic.Automated review by Claude PR Reviewer
AI Code Review — Re-review (APPROVED)
Previous findings addressed
Both findings from the initial review (commit
4a1251a) have been resolved:evolution_tierrenamed torefractor_tier— Function signature, docstring, hash input dict key, and test docstrings all updated. Sincecompute_variant_hashis new in this PR and no variant hashes exist in the database yet, changing the dict key (which changes the hash output) is safe.Redundant parentheses on
boost_delta_json— Simplified to single-lineTextField()declaration. Comment preserved.Test results
test_list_cards_evaluated_only_false_includes_unevaluated—isoformat()bug inrefractor.py:55, exists onmain)Verdict: APPROVED
All review findings addressed. Core algorithms remain correct, 108-sum and 79-sum invariants preserved, naming now consistent with refractor conventions. Ready to merge.
Automated re-review by Claude PR Reviewer
Approved via pd-pr
Approved via pd-pr