Skip to content

feat(career): gigs frontend — poster, runner strip, summary, encore#956

Merged
byrongamatos merged 3 commits into
mainfrom
feat/career-gigs-ui
Jul 13, 2026
Merged

feat(career): gigs frontend — poster, runner strip, summary, encore#956
byrongamatos merged 3 commits into
mainfrom
feat/career-gigs-ui

Conversation

@byrongamatos

@byrongamatos byrongamatos commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Career v3, workstream 3 (frontend half), on the merged gigs backend (#954):

  • Book a gig from any opened passport: the proposal renders as a gig poster (venue presents GENRE NIGHT, numbered bill) with re-roll and Save/Copy poster.
  • Play the gig: the set rides playQueue (raw filenames — the queue encodes internally; pre-encoding was caught in review and would have broken loading + the stats join). The gig borrows the stage: venue override + Venue viz are stashed and restored when the set ends or is abandoned (unlike "Play here", an explicit persistent choice).
  • Floating gig strip (body-level, pointer-events none, z 35 per the chrome invariant) tracks the set and names what's next.
  • Completion: final song:ended on OUR live gig queue (source + active checked — a cleared/foreign queue can never log a gig) → waits for the last song's stats:recorded (or a timeout — unscored plays never emit one) so /gigs reads the set's real accuracies → summary poster with per-song results; encore fires the crowd eruption + confetti. Escape closes poster/summary overlays; quitting mid-set abandons silently (no log, no fail state).
  • Gig log renders as dated rows in the passport book; shared exportCanvasPng helper dedups the card/poster export plumbing.

Review notes

Internal review pass caught: the double-encoding bug, the completion/stats race, the foreign-queue completion hole, the Escape gap, the unrestored stage, and the export duplication — all fixed.

Testing

Live end-to-end: booked a real 2-song classical gig, both songs played + auto-advanced (strip verified per song), summary poster with accuracies, gig logged with gig_count, viz restored, zero page errors. vm tests for runner advance/abandon semantics. Full JS glob 1172, career pytest green.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Added “Gigs (the career verb)” to the career passport, including booking gig posters, proposing, and re-rolling from the current genre.
    • Gig playback now logs the full setlist into the passport book with a completion summary and optional encore celebration.
    • Added gig progress visuals (“gig strip” and “Gigs played” log), alongside improved passport card export options.
  • Bug Fixes
    • Improved cleanup when dismissing the gig poster or closing the passport overlay mid-workflow.
    • Expanded Escape-key behavior to close the passport book when the overlay is visible.
  • Tests
    • Added unit coverage for gig run lifecycle, including progression and proper abandonment/clearing when the play queue is inactive.

Career v3, WS3 (frontend half), rebuilt cleanly on merged main (v3-a/b/c
in) after git interleaved the structurally-similar canvas functions:

- Book a gig from any opened passport: /gigs/propose renders as a GIG
  POSTER (venue presents GENRE NIGHT, numbered bill) with re-roll and
  Save/Copy poster (natively-drawn canvas via blob-io, audible failure
  paths, slash-safe filenames).
- Play the gig: venue override + Venue viz handoff, then
  playQueue.start(..., {source:'gig'}) — the queue's auto-advance runs
  the set; zero new playback machinery.
- Floating gig strip (body-level, pointer-events none, z 35 per the
  chrome invariant) tracks set position and names what's next.
- Completion = song:ended with an empty queue → POST /gigs → summary
  poster overlay with per-song accuracies; encore fires the crowd
  celebrate + confetti (reduced-motion: neither). song:stop with a dead
  queue = abandoned (no log); end-of-song teardown (queue still active)
  must NOT abandon.
- Gigs played render as dated rows in the passport book.

vm tests: runner advance/abandon semantics via the queue-state seam.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: df68cf8f-dea2-4eba-9315-d22873347438

📥 Commits

Reviewing files that changed from the base of the PR and between f0298ab and b6bf8a2.

📒 Files selected for processing (1)
  • docs/size-exemptions.md

📝 Walkthrough

Walkthrough

Adds a Career “Gigs” flow for proposing setlists, playing them through the queue, tracking completion, recording results in the passport book, and exporting gig posters.

Changes

Career gigs

Layer / File(s) Summary
Gig booking and poster UI
plugins/career/screen.js, plugins/career/assets/career.css, docs/size-exemptions.md
Adds passport-book gig actions, poster proposals with re-roll and export controls, gig log rendering, state cleanup, shared PNG export handling, poster styling, and size-planning documentation.
Gig playback and completion lifecycle
plugins/career/screen.js, plugins/career/tests/passports.test.js, CHANGELOG.md
Runs proposed sets through playback, handles song lifecycle events, records completed or abandoned gigs, displays summaries and encore feedback, exposes test helpers, and documents the feature.

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

Possibly related PRs

Sequence Diagram(s)

sequenceDiagram
  participant PassportBook
  participant CareerAPI
  participant GigPoster
  participant CareerRunner
  participant PlayQueue
  PassportBook->>CareerAPI: POST /api/plugins/career/gigs/propose
  CareerAPI-->>GigPoster: Return proposed setlist
  GigPoster->>CareerRunner: Start proposed gig
  CareerRunner->>PlayQueue: Start setlist playback
  PlayQueue-->>CareerRunner: Emit song lifecycle events
  CareerRunner->>CareerAPI: POST /api/plugins/career/gigs
  CareerAPI-->>PassportBook: Return recorded gig summary
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 15.38% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately summarizes the new career gigs frontend feature and its poster/runner/summary flow.
Description check ✅ Passed The description is mostly complete and covers behavior, testing, and review notes; it only lacks the template's formal checklist formatting.
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 unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/career-gigs-ui

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: 2

🤖 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/screen.js`:
- Around line 1500-1502: Reduce plugins/career/screen.js below the 1500-line max
enforced by lint by extracting the gig-related block, including poster, runner,
and summary logic around the gig handlers and setGigRun/getGigRun state, into a
small module. Preserve the existing public handlers and behavior while updating
imports or exports as needed.
- Around line 1118-1129: Update the override setup around the restore variable
so failures from localStorage operations still clear restore as appropriate, but
a throwing window.setViz('venue') call does not set restore to null. Keep the
previously captured venue and viz values, and treat only the setViz invocation
as best-effort so restoreGigStage() can restore the user's state.
🪄 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: 4586f9b7-7db7-4ef8-91dd-dd7e929adaae

📥 Commits

Reviewing files that changed from the base of the PR and between 7c897e9 and 82edbb7.

📒 Files selected for processing (4)
  • CHANGELOG.md
  • plugins/career/assets/career.css
  • plugins/career/screen.js
  • plugins/career/tests/passports.test.js

Comment thread plugins/career/screen.js Outdated
Comment thread plugins/career/screen.js
byrongamatos and others added 2 commits July 14, 2026 01:47
CodeRabbit on #956: a setViz failure nulled the restore snapshot AFTER
the overrides were written, permanently borrowing the stage — snapshot
now captured before any write, write failures keep it intact. Also
registers career screen.js in docs/size-exemptions.md 'Planned, not
exempt' (1,516 lines; max-lines WARNS non-blocking — the split plan
needs Byron's sign-off).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…empt)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@byrongamatos

Copy link
Copy Markdown
Contributor Author

The setViz-throw restore bug is fixed in f0298ab: the restore snapshot is now captured before any override write, and a write/setViz failure no longer nulls it — restoreGigStage can always return the stage.

@byrongamatos
byrongamatos merged commit dd1927e into main Jul 13, 2026
6 checks passed
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