feat(WP-11): /evo status slash command (#76) #92
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#92
Loading…
Reference in New Issue
Block a user
No description provided.
Delete Branch "feature/wp11-evo-status"
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?
Closes cal/paper-dynasty-database#76
Summary
/evo statusslash command showing paginated evolution progress for a team's cards[========--] 120/149 (PA+TB×2) Initiate → Rising[==========] FULLY EVOLVED (PA+TB×2) T4 — Evolvedplayers_new/__init__.pyTest plan
AI Code Review
Files Reviewed
cogs/players_new/evolution.py(added)tests/test_evolution_commands.py(added)cogs/players_new/__init__.py(modified)Findings
Correctness
render_progress_bar(120, 149, width=10)produces[========--] 120/149. The ratio 120/149 = 0.805,round(8.054) = 8, confirmed correct.is_close_to_tierupcorrectly uses>= threshold_pct * next_threshold. The boundary test at exactly 80% (119.2 >= 119.2) returns True as specified.next_threshold=Noneor<= 0yields[==========] FULLY EVOLVED, matching the PR spec.format_evo_entrycorrectly routes toT4 — Evolvedwhenfully_evolved=True, independent of the progress bar.min(current_value / next_threshold, 1.0)caps the fill at 100%, correct.current_tier + 1fornext_tier. Valid for tiers 0-3; at tier 4 thefully_evolvedflag guards the branch so a tier-5 lookup is never attempted.team_idresolution:team.get("team_id") or team.get("id")handles both possible API response shapes correctly.total_countis captured before the client-sideclosefilter runs, so the footer will reflect the full pre-filter page count (e.g. "10 total cards") even when only 3 "close" cards are shown. Minor cosmetic inconsistency, not a correctness bug.Security
team_idoriginates from an authenticated team lookup.typeandtierfilter values are forwarded as query params todb_get— responsibility for validation sits with the database API, which is the correct layer for this.Style & Conventions
get_team_by_ownerandis_ephemeral_channelboth confirmed to exist inhelpers/main.py(lines 91 and 1199). Imports resolve correctly.db_getwithnone_okay=Truematches the established read-operation pattern across other cogs.await interaction.response.defer(...)before any async work correctly handles the 3-second Discord interaction timeout.Evolutioncog registration in__init__.pyis properly placed and the trailing-whitespace cleanup is a net improvement.typeshadows the Python builtin. This is an established pattern in Discord cog commands in this repo where parameter names become slash command option names — acceptable by project conventions.per_page = 10is redefined in the footer block, duplicating the value already set inparams. Minor — could be a module-level constant to keep the two in sync, but not a bug at current scale.Suggestions
test_fully_evolved_entryasserts"Evolved" in result, which also matches the substring inside"FULLY EVOLVED". The more precise assertion would be"T4 — Evolved" in result. Not wrong, just imprecise.Verdict: APPROVED
Clean, focused implementation. Logic is correct, helpers imports resolve, the Discord interaction pattern (defer-then-followup) is correct, error handling is explicit, and the 15 tests cover all pure-function paths with clear docstrings. No blocking issues found.
Automated review by Claude PR Reviewer
@ -0,0 +155,4 @@f"Failed to fetch evolution data for team {team_id}",exc_info=True,)await interaction.followup.send(The
closefilter runs aftertotal_countis captured (line 152), so the pagination footer will show the pre-filter total even when fewer cards are displayed after filtering. This is an intentional tradeoff of client-side filtering on a paginated response — a brief comment here would help future readers understand why.@ -0,0 +176,4 @@items = [s for s in items if is_close_to_tierup(s)]if not items:await interaction.followup.send("No cards are close to a tier-up right now.",per_page = 10is already defined implicitly in theparamslist on line 136. Consider extracting to a module-levelPAGE_SIZE = 10constant so the two stay in sync automatically.LGTM — reviewed by automation.