Skip to content

refactor(server): extract shop + inject get_progression_content into the seam (R3) - #851

Merged
byrongamatos merged 1 commit into
mainfrom
refactor/r3-progression-substrate
Jul 10, 2026
Merged

refactor(server): extract shop + inject get_progression_content into the seam (R3)#851
byrongamatos merged 1 commit into
mainfrom
refactor/r3-progression-substrate

Conversation

@byrongamatos

@byrongamatos byrongamatos commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

The progression-content substrate, proven by its first consumer (shop).

_get_progression_content — a lazy, double-checked-locking content cache — is now published into the appstate seam as a callable. The cache global, its lock, and the function all stay in server.py (startup uses it, and test_progression_api patches server._progression_content directly), so zero test retargeting — routers just call appstate.get_progression_content().

Since the accessor is defined at server.py:1152 but the import-top configure() runs at :346, a second appstate.configure(get_progression_content=…) publishes it right after the def (configure is idempotent/additive).

First consumer: routers/shop.py (3 routes). Bodies verbatim. This unblocks stats / progression / profile next — they all share the accessor.

server.py: 7,880 → 7,845.

Verification

  • Route table identical (143); pyflakes clean.
  • pytest 2401 passed — including test_progression_api, whose server._progression_content patch still works because the cache stayed put.
  • Boot smoke: GET /api/shop 200 (drives appstate.get_progression_content); buy 400 on bad body. npm run lint 0; Codex 0 findings.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Added a cosmetics shop where players can view available items and their wallet balance.
    • Players can purchase cosmetics using Decibels, with validation for unavailable items, duplicate purchases, and insufficient funds.
    • Players can equip owned cosmetics in compatible slots or unequip them.
  • Documentation
    • Updated the project’s line-count register and router coverage details.

@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The cosmetics shop endpoints moved from server.py into a dedicated router. appstate now accepts the progression-content accessor, and server.py configures and mounts the extracted router.

Changes

Cosmetics shop router extraction

Layer / File(s) Summary
Progression content appstate seam
lib/appstate.py, server.py
The progression-content accessor is added to the appstate injection slots and configured for router access.
Shop router behavior
lib/routers/shop.py
The shop router implements listing, purchase, and equip endpoints with wallet, ownership, slot, and item validation.
Server router wiring
server.py, docs/size-exemptions.md
The shop router is imported and mounted, inline shop handlers are removed, and the documented server metrics are updated.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main refactor: extracting shop routes and exposing get_progression_content through the appstate seam.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/r3-progression-substrate

Comment @coderabbitai help to get the list of available commands.

…ntent into the seam (R3)

The progression-content substrate: `_get_progression_content` (a lazy,
double-checked-locking content cache) is now published into the appstate seam as
a CALLABLE. The cache global + lock + the function stay in server.py (startup
uses it, and test_progression_api patches `server._progression_content`
directly), so ZERO test retargeting — routers just call
`appstate.get_progression_content()`.

Because the accessor is defined at server.py:1152 but the import-top configure()
runs at :346, a second `appstate.configure(get_progression_content=...)` publishes
it right after the def (configure is idempotent/additive).

First consumer: routers/shop.py (3 routes: buy/equip/list). Bodies verbatim;
@app -> @router, meta_db -> appstate.meta_db, _clean_str from reqfields,
_get_progression_content() -> appstate.get_progression_content(). This unblocks
stats/progression/profile next (all share the accessor).

server.py: 7,880 -> 7,845.

Verified: pyflakes clean; route table IDENTICAL (143); pytest 2401 passed
(test_progression_api's server._progression_content patch still works via the
kept cache); packaging guard; eslint 0. Boot smoke: GET /api/shop 200 (drives
appstate.get_progression_content), buy 400 on bad body.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@byrongamatos
byrongamatos force-pushed the refactor/r3-progression-substrate branch from 69367ab to 37ac50a Compare July 10, 2026 21:38

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/size-exemptions.md`:
- Around line 58-59: Update the size metrics in the affected entry of
docs/size-exemptions.md to match the PR objective’s reported reduction from
7,880 to 7,845 lines, replacing the conflicting 7,798 and 14,037 values while
preserving the surrounding ratcheting context.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 57f3e87a-65ff-450f-a0c7-493dd40adeec

📥 Commits

Reviewing files that changed from the base of the PR and between ea88348 and 37ac50a.

📒 Files selected for processing (4)
  • docs/size-exemptions.md
  • lib/appstate.py
  • lib/routers/shop.py
  • server.py

Comment thread docs/size-exemptions.md
@byrongamatos

Copy link
Copy Markdown
Contributor Author

The register value 7,798 is correct for the current branch state. This PR was rebased onto #850 (library_extras, which took server.py 7,880 → 7,833); shop's cut then brought it to 7,798 (verified: wc -l server.py = 7798). The '7,845' in the PR description was the pre-rebase number when this branched directly off main — the register (the canonical value) reflects the actual post-rebase file. No code change needed.

@byrongamatos
byrongamatos merged commit 5f58af4 into main Jul 10, 2026
5 checks passed
byrongamatos added a commit that referenced this pull request Jul 10, 2026
…sion.py (R3) (#853)

4 routes (overview/add-paths/onboarding/events, spec 010) + their EXCLUSIVE
helpers (_goal_ui_progress, _progression_overview 112L) + the
_PROGRESSION_EVENT_TYPES whitelist. Bodies verbatim; @app -> @router,
meta_db -> appstate.meta_db, _clean_str from reqfields.

The two SHARED server accessors read through the seam: get_progression_content
(added for shop #851) and builtin_diagnostic_filename (new slot — a trivial
const-returning fn shared with the stats router's api_record_stats). Both are
injected via the second appstate.configure() after their defs (the import-top
configure runs before them). The cache + fns stay in server.py, so
test_progression_api's server._progression_content patch is untouched — 0 retarget.

server.py: 7,798 -> 7,594.

Verified: pyflakes clean; route table IDENTICAL (143); both seam accessors wired;
pytest 2401 passed (63 in test_progression_api); eslint 0. Boot smoke: GET
/api/progression 200 (drives _progression_overview + both accessors), events
400 on bad body.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant