feat: WP-13 post-game evolution callback hook #111
No reviewers
Labels
No Label
ai-changes-requested
ai-failed
ai-pr-opened
ai-reviewed
ai-reviewing
ai-working
ai-working
bug
enhancement
feature
in-queue
performance
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-discord#111
Loading…
Reference in New Issue
Block a user
No description provided.
Delete Branch "feature/wp13-postgame-hook"
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
complete_game()saves the game result and posts rewards, fires two non-blocking async API calls in order:POST season-stats/update-game/{game_id}thenPOST evolution/evaluate-game/{game_id}notify_tier_completionstub inhelpers/evolution_notifs.pyas the WP-14 integration targettests/test_complete_game_hook.pycover the callback sequence, failure isolation, and stub behaviorFiles changed
command_logic/logic_gameplay.py— post-game callback wired intocomplete_game()helpers/evolution_notifs.py— stub for WP-14 tier notificationtests/test_complete_game_hook.py— full test coverage for the hookNotes
Test plan
python -m pytest tests/test_complete_game_hook.pypassescomplete_game()still completes successfully when evolution API is unreachable (failure isolation)After complete_game() saves the game result and posts rewards, fire two non-blocking API calls in order: 1. POST season-stats/update-game/{game_id} 2. POST evolution/evaluate-game/{game_id} Any failure in the evolution block is caught and logged as a warning — the game is already persisted so evolution will self-heal on the next evaluate pass. A notify_tier_completion stub is added as a WP-14 target. Closes #78 on cal/paper-dynasty-database Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>AI Code Review — Cycle 2
Files Reviewed
command_logic/logic_gameplay.py(modified — stub function added, hook block added)tests/test_complete_game_hook.py(added)tests/test_evolution_notifications.py(deleted)Cycle 1 Blocking Issues — Verification
Issue 1: API endpoint was
evolution/evaluate-gameFixed. Line 4369 now reads
refractor/evaluate-game/{db_game['id']}. Confirmed correct.Issue 2:
helpers/evolution_notifs.pywas dead code shipped in this PRFixed. The
helpers/directory contains noevolution_notifs.py. The corresponding test filetests/test_evolution_notifications.pyis also removed in this diff. PR scope is now clean WP-13 only.Issue 3: Unguarded key access in
build_tier_up_embed(now moot)Correctly called moot — the file was removed entirely.
Findings
Correctness
season-stats/update-gamefires first, thenrefractor/evaluate-game. The ordering constraint is enforced by sequentialawaitcalls inside a singletryblock.evo_result.get("tier_ups")is guarded with a truthiness check before iteration — handlesNone, empty list, and missing key cleanly.notify_tier_completionstub useschannel.id if channel else 'N/A'— safe against aNonechannel being passed frominteraction.channel.db_gameis initialized toNoneat line 4316. If the initialdb_post("games", ...)fails,db_game['id']on line 4368 would raise aTypeErrorinside the refractor block — but this is caught by the surroundingtry/exceptwhich logs a warning and continues. The non-fatal contract holds. This is not a regression.Security
db_game['id']is an integer from the API response, not from user input. No injection surface.Style & Conventions
notify_tier_completionis placed immediately beforecomplete_game()inlogic_gameplay.py, which is a reasonable location for a function only called from that context.import asyncioon line 17 oftest_complete_game_hook.pyis unused. Not blocking.Test Coverage
_run_hookreplicates the hook logic inline rather than exercisingcomplete_game()directly. Acceptable given the complexity of the full function's dependencies, and clearly commented.test_hook_processes_tier_ups_from_evo_resultcallsmock_notifydirectly rather than via the patched module path, so it validates data flow logic rather than actual dispatch — fine since the stub contract is separately covered bytest_notify_tier_completion_stub_logs_and_does_not_raise.Suggestions
import asynciofromtest_complete_game_hook.pyline 17 — ruff will flag it on the next lint run.helpers/evolution_notifs.pyin the "Files changed" section and mentions adding the stub there. Worth updating the PR description to reflect the actual placement inlogic_gameplay.py, but this does not affect the code.Verdict: APPROVED
All three cycle 1 blocking issues are resolved. The endpoint is correctly named
refractor/evaluate-game, the dead-code file and its tests are removed, and the PR scope is cleanly limited to the WP-13 post-game hook. The implementation is correct, non-fatal failure isolation works, and test coverage is adequate. Ready to merge.Automated review by Claude PR Reviewer — Cycle 2
Approving on behalf of ops — reviewer cycle 2 APPROVED. All blocking issues resolved.