Skip to content

feat(career): gigs backend — propose a setlist, log the completed set#954

Merged
byrongamatos merged 2 commits into
mainfrom
feat/career-gigs-backend
Jul 13, 2026
Merged

feat(career): gigs backend — propose a setlist, log the completed set#954
byrongamatos merged 2 commits into
mainfrom
feat/career-gigs-backend

Conversation

@byrongamatos

@byrongamatos byrongamatos commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Career v3, workstream 3 (backend half). A gig is career's verb:

  • POST /gigs/propose — setlist from the passport's stubs: qualifying songs (family-aware badge bar) shuffled per call (free re-roll), topped with the highest-accuracy near-bar songs as stakes, surplus-qualifying backfill so a mature passport always fills the bill, and unplayed genre songs for a young passport (the first gig is how stubs start). Names the highest venue the current stars can book.
  • POST /gigs — logs a completed set only (abandoned sets never log — no fail state). Per-song accuracy reads the newest song_stats row (the set's own play — a MAX(last_accuracy) would happily log a stale higher score from another instrument's old session); encore requires the whole set scored at the data-driven bar (one scored song must not earn an encore for a set that was 4/5 unheard). Log capped at 500 entries.
  • Passports carry their gig log (newest first, 20 shown); instruments their gig_count (lights up the profile wall's line).
  • Config junk-tolerant: a typo'd passports.json gig block falls back instead of 500ing; a legitimate stakes_songs: 0 is respected.

Review notes

Internal review pass (Codex quota-locked) caught: cross-arrangement stale accuracy, the partial-scoring encore vector, surplus-qualifying starvation, config 500s on junk, and the unbounded log — all fixed with regression tests.

Testing

34 career pytest green (propose mix/stakes/backfill/young-passport, newest-row accuracy, full-set encore rule, validation, no-fail-state).

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Added career-mode “gigs” setlist proposals via POST /api/plugins/career/gigs/propose, using current career progression and instrument/genre matching.
    • Added gig completion logging via POST /api/plugins/career/gigs, including persisted gig history and computed encore status.
    • Updated career passport views to show recent gig history and per-instrument gig counts.
    • Introduced configurable gig requirements (set size range, stakes/near-bar behavior, encore accuracy threshold).
  • Bug Fixes
    • Improved accuracy tracking so logged gig outcomes use the newest recorded performance for each song.

@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 39b2fa36-b1e5-408d-81fc-481c807e879e

📥 Commits

Reviewing files that changed from the base of the PR and between 34447de and 72212e7.

📒 Files selected for processing (5)
  • CHANGELOG.md
  • plugins/career/passports.json
  • plugins/career/routes.py
  • tests/plugins/career/conftest.py
  • tests/plugins/career/test_passports.py

📝 Walkthrough

Walkthrough

Adds configurable career gig proposals, completed-gig logging with encore scoring, venue selection, and recent gig history in passport responses.

Changes

Career Gigs

Layer / File(s) Summary
Gig configuration and selection foundations
plugins/career/passports.json, plugins/career/routes.py
Adds gig sizing, stake-song, and encore settings, plus helpers for configuration, venue selection, and unplayed genre songs.
Gig proposal and completion APIs
plugins/career/routes.py, tests/plugins/career/conftest.py, tests/plugins/career/test_passports.py, CHANGELOG.md
Adds proposal and completion endpoints, newest-row accuracy handling, encore calculation, career-state persistence, validation, test database support, coverage, and changelog documentation.
Passport gig history reporting
plugins/career/routes.py, tests/plugins/career/test_passports.py
Adds recent matching gigs and gig_count to passport responses.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant CareerRoutes
  participant MetadataDB
  participant CareerState
  Client->>CareerRoutes: Propose a career gig
  CareerRoutes->>MetadataDB: Read genre songs and accuracy
  MetadataDB-->>CareerRoutes: Return song data
  CareerRoutes-->>Client: Return setlist and venue
  Client->>CareerRoutes: Log completed gig
  CareerRoutes->>MetadataDB: Read newest accuracy and titles
  MetadataDB-->>CareerRoutes: Return song metadata
  CareerRoutes->>CareerState: Store completed gig
  CareerRoutes-->>Client: Return stored gig
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main backend change: proposing and logging career gigs.
Description check ✅ Passed The description covers the feature, rationale, review notes, and testing, but it omits the template checklist items and an issue link.
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 feat/career-gigs-backend

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

@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

🧹 Nitpick comments (1)
plugins/career/routes.py (1)

691-694: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Minor: chain the original exception for clearer tracebacks.

Ruff (B904) flags the bare raise inside the except clause.

♻️ Proposed fix
         try:
             size = int((body or {}).get("size") or 4)
-        except (TypeError, ValueError):
-            raise HTTPException(400, "size must be a number.")
+        except (TypeError, ValueError) as err:
+            raise HTTPException(400, "size must be a number.") from err
🤖 Prompt for 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.

In `@plugins/career/routes.py` around lines 691 - 694, Update the exception
handling around the size parsing in the route to explicitly chain the caught
TypeError or ValueError when raising HTTPException, preserving the existing
status code and message while satisfying Ruff B904.

Source: Linters/SAST tools

🤖 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 `@plugins/career/routes.py`:
- Around line 696-722: Fix the surplus-qualifying backfill in the gig song
selection flow by tracking the number of qualifying songs initially added,
rather than using len(picks) after rest songs may have been appended. Update the
logic around _played_by_instrument_genre and qualifying so it iterates only over
unused qualifying entries, preserving the existing size limit and fallback
behavior.

---

Nitpick comments:
In `@plugins/career/routes.py`:
- Around line 691-694: Update the exception handling around the size parsing in
the route to explicitly chain the caught TypeError or ValueError when raising
HTTPException, preserving the existing status code and message while satisfying
Ruff B904.
🪄 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: eb48f0ad-e2c2-4303-a8dd-5309b47b3afe

📥 Commits

Reviewing files that changed from the base of the PR and between 831117f and e84adc1.

📒 Files selected for processing (5)
  • CHANGELOG.md
  • plugins/career/passports.json
  • plugins/career/routes.py
  • tests/plugins/career/conftest.py
  • tests/plugins/career/test_passports.py

Comment thread plugins/career/routes.py
byrongamatos added a commit that referenced this pull request Jul 13, 2026
CodeRabbit on #954: after the stakes loop appends near-bar songs,
qualifying[len(picks):] overshoots and skips eligible qualifying songs
— a stocked passport could still get a short set.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
byrongamatos and others added 2 commits July 14, 2026 01:26
Career v3, WS3 (backend half). A gig is career's verb:

- POST /gigs/propose {instrument, genre, size}: setlist from the
  passport's own stubs — qualifying songs (per the genre's badge bar,
  family-aware) shuffled for a free re-roll, topped with the
  highest-accuracy near-bar songs as stakes, and filled from UNPLAYED
  genre songs when the passport is young (the first gig is how stubs
  start). Names the highest venue the current stars can book.
- POST /gigs: logs a COMPLETED set only (abandoned sets never log — no
  fail state). Per-song accuracy = MAX(last_accuracy) from song_stats,
  freshly written by the set's own plays; encore = avg ≥ the data-driven
  bar (passports.json gig.encore_accuracy, 0.75). Appends to the career
  state file (same atomic _save_json pattern).
- Passports view: per-passport gigs (newest first, capped 20) and
  per-instrument gig_count — the profile wall's gig line lights up.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
CodeRabbit on #954: after the stakes loop appends near-bar songs,
qualifying[len(picks):] overshoots and skips eligible qualifying songs
— a stocked passport could still get a short set.

Co-Authored-By: Claude Fable 5 <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