Skip to content

feat(career): host higher venues as opt-in content packs - #1023

Merged
byrongamatos merged 6 commits into
got-feedBack:mainfrom
mhglover:feat/venue-packs-opt-in
Jul 22, 2026
Merged

feat(career): host higher venues as opt-in content packs#1023
byrongamatos merged 6 commits into
got-feedBack:mainfrom
mhglover:feat/venue-packs-opt-in

Conversation

@mhglover

@mhglover mhglover commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

What

Moves the club and arena career venue packs (~678 MB of crowd MP4s) out of the desktop bundle and downloads them on demand, keeping the bar starter bundled so career works offline. Uses career's existing pack pipeline (_download_pack: stream → sha256 → extract → validate → swap), which already degrades gracefully when a pack is absent. First (POC) slice of the nightly-slimming effort feedBack-desktop#122. Self-contained; PRs 2/3 build on it but nothing here depends on them.

Why this is a real POC

arena is already published and verified (venue-arena-v1), so on a build of this branch a player can cross 150★ and download + play the real 351 MB arena pack — the whole opt-in model demonstrated end-to-end against a live release asset, not a mock. club shows "coming soon" until its release is cut.

What's here

  • venues.json — club/arena gain pack URLs (per-pack, versioned, immutable releases venue-<id>-v<N>). Arena's sha256/bytes are the real published asset; club is a placeholder until published.
  • Placeholder gating — a pack is only offered once a publish has stamped its real size (_pack_published); until then the card reads "coming soon" and the download endpoint 404s, so there's never a button that can only fail.
  • tools/content_packs.py — reusable, reproducible pack build/publish/manifest tool (byte-identical output → hash known before upload; create_system pinned so Windows and Unix runners agree). Rejects files the downloader would refuse before publishing. --local/--publish, --selfcheck.
  • .github/workflows/content-packs.ymlworkflow_dispatch automation that builds/publishes packs and opens the manifest-bump PR. Dispatch inputs are validated and passed via env (no shell interpolation).
  • tests — round-trip through career's real _download_pack; placeholder-not-offered + rejected-extra-file regressions.

Verification

  • End-to-end against the live release: career downloads the real arena-pack-v1.zip, sha verifies, extracts, validates, installs. ✅
  • Confirmed inside a full electron-builder macOS .app: career = bar only, ~678 MB off. ✅
  • Career suite + tool selfcheck pass. ✅

Companion PRs (separate, not required to merge this)

  • Desktop feedBack-desktop#123: stop bundling club/arena (merge together with this).
  • Follow-up: publish venue-club-v1 → club flips to downloadable automatically.

feedpak surface

  • This PR does not change how the app reads/writes feedpaks (manifest keys, pack files, folder layout)
  • …or it does, and the spec change landed first via the FEP process — FEP / spec PR: got-feedback/feedpak-spec#___ (once it merges, re-run this PR's checks and the gate goes green)

Career venue packs are crowd-media content packs, not song feedpaks — no manifest key, folder-layout, or reader/writer change. The feedpak-spec conformance gate is green.

Checklist

  • CHANGELOG.md [Unreleased] updated (user-visible changes) — entry written; lands with the signed-off push below
  • Tests added/updated for new behaviour
  • Commits are DCO signed off (git commit -s) — pending: re-signing the branch with the correct email (see below)

Summary by CodeRabbit

  • New Features
    • Added optional career venue media packs for Club and Arena venues, downloadable on demand.
    • Added SHA-256 verification and file-size metadata to improve download integrity.
    • Preserved the bundled Bar venue pack for offline play.
  • Bug Fixes
    • Unpublished or placeholder venue packs are no longer shown as available or offered for download.
  • Documentation
    • Updated the changelog with details about opt-in venue packs and offline fallback behavior.

Move the club and arena venue packs (~678 MB of crowd MP4s) out of the
bundle and download them on demand, keeping the bar starter bundled so
career still works offline. Leans on career's existing pack pipeline
(_download_pack: stream -> sha256 -> extract -> validate -> swap), which
already degrades gracefully when a pack is absent.

- venues.json: club/arena gain `pack` URLs pointing at per-pack, versioned,
  immutable releases (venue-<id>-v<N>, matching the existing venue-arena-v1).
  Arena's sha256/bytes are the real published asset (verified end-to-end);
  club is a placeholder until its release is published.
- tools/content_packs.py: reusable, reproducible pack build/publish/manifest
  tool. Byte-identical output for identical media (fixed order/mtime/perms,
  STORED) so a pack's hash can be known before upload. --local (file://) for
  offline tests, --publish for the per-pack release. Has a --selfcheck.
- .github/workflows/content-packs.yml: workflow_dispatch automation that
  builds/publishes packs and opens the venues.json manifest-bump PR, so
  publishing is never a manual checklist.
- test: round-trips a tool-built pack through career's real _download_pack.

Part of the nightly-slimming effort (feedBack-desktop#122). The desktop
bundle change (stop shipping club/arena) is a companion PR.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 21, 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: c9d4797f-394b-49c3-9d9c-264ff538f0b8

📥 Commits

Reviewing files that changed from the base of the PR and between 90791c1 and 08eb7b8.

📒 Files selected for processing (2)
  • CHANGELOG.md
  • tools/content_packs.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • tools/content_packs.py

📝 Walkthrough

Walkthrough

Adds deterministic career venue-pack ZIP creation and GitHub publishing, updates venue manifest metadata through a manual workflow, and prevents placeholder packs from appearing or downloading until they have non-zero published sizes.

Changes

Career content pack pipeline

Layer / File(s) Summary
Deterministic pack builder
tools/content_packs.py, tests/plugins/career/test_routes.py
Builds flat reproducible ZIPs, generates {url, sha256, bytes} manifest entries, publishes versioned release assets, and validates archive compatibility and reproducibility.
Workflow and venue manifest update
.github/workflows/content-packs.yml, plugins/career/venues.json, CHANGELOG.md
Adds manual publishing inputs, updates venue metadata from the generated manifest, creates a manifest-bump pull request, and documents opt-in venue packs.
Published-pack route gating
plugins/career/routes.py, tests/plugins/career/test_routes.py
Requires non-zero bytes metadata for state availability and downloads, with coverage for placeholders, locked venues, duplicate downloads, and pack round-tripping.

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

Sequence Diagram(s)

sequenceDiagram
  participant Maintainer
  participant Workflow as content-packs workflow
  participant ContentPacks as tools/content_packs.py
  participant Venues as plugins/career/venues.json
  participant PullRequest as manifest-bump pull request
  Maintainer->>Workflow: provide venues and version
  Workflow->>ContentPacks: build and publish venue packs
  ContentPacks-->>Workflow: write packs manifest
  Workflow->>Venues: update URL, SHA-256, and bytes
  Workflow->>PullRequest: create venue manifest PR
Loading

Possibly related PRs

Suggested reviewers: topkoa

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 44.44% 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 clearly summarizes the main change: making higher venue packs opt-in content packs.
Description check ✅ Passed The description covers What, feedpak surface, and Checklist, with enough detail to match the template.
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

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

A committed venues.json entry carries a 0-byte placeholder (and all-zero sha)
until its release exists. Previously has_pack was true as soon as a `pack`
object was present, so the UI showed a "Download" button that could only fail
(the placeholder URL 404s). Gate on a real, publish-stamped size via
_pack_published(): the card shows "coming soon" and the download endpoint 404s
until the pack is actually published. Caught by a real bundle+runtime smoke.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@mhglover
mhglover marked this pull request as ready for review July 21, 2026 04:44
@mhglover

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@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: 3

🤖 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 @.github/workflows/content-packs.yml:
- Around line 47-52: Update the workflow’s content-pack publishing step to stop
interpolating github.event.inputs.venues and github.event.inputs.version
directly into Bash: expose both through the step env, validate venues and
version against their expected safe formats, build the content-pack paths in a
Bash argument array, and invoke tools/content_packs.py using that array while
preserving the existing --publish behavior.

In `@tools/content_packs.py`:
- Around line 43-57: Update the packing flow around the file collection and
archive creation to reject any top-level source file whose archive name is not
accepted by the downloader’s whitelist, reusing the existing shared
validation/contract symbol rather than duplicating rules. Ensure validation
occurs before publishing the ZIP, and add a test covering a rejected extra file
such as .DS_Store.
- Around line 54-57: Set ZipInfo.create_system explicitly when constructing the
ZipInfo in the archive-writing flow, using a fixed platform value to ensure
identical hashes across operating systems. Keep the existing fixed timestamp,
compression, permissions, and writestr behavior unchanged.
🪄 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: 5d2dfbaf-f524-4581-8977-17533e942567

📥 Commits

Reviewing files that changed from the base of the PR and between a9be210 and c5256d1.

📒 Files selected for processing (5)
  • .github/workflows/content-packs.yml
  • plugins/career/routes.py
  • plugins/career/venues.json
  • tests/plugins/career/test_routes.py
  • tools/content_packs.py

Comment thread .github/workflows/content-packs.yml Outdated
Comment thread tools/content_packs.py
Comment thread tools/content_packs.py
@mhglover

Copy link
Copy Markdown
Contributor Author

Ready to go — the POC slice of #122 (slim the nightly). Moves the club + arena career venue packs (~678 MB of crowd MP4s) out of the bundle and lets career fetch them on demand; the bar starter stays bundled for offline play.

What to look at:

  • tools/content_packs.py — reproducible flat-zip pack builder (sorted names, fixed mtime/perms, ZIP_STORED) → {url, sha256, bytes}.
  • .github/workflows/content-packs.ymlworkflow_dispatch publish + venues.json bump PR.
  • plugins/career/venues.jsonarena points at the live venue-arena-v1 release (real sha/bytes); bar stays null (bundled); club is a placeholder pending its release.
  • plugins/career/routes.py — the _pack_published gate.

club is not published yet, and that's fine to merge on — the _pack_published gate means an unpublished pack (0 bytes / zero sha) is never offered for download. Club simply shows "Venue pack coming soon — plays with the standard stage for now" until venue-club-v1 lands, at which point its sha/bytes get filled in (same as arena). No dead buttons, no failed downloads.

Behavior in the next nightly: arena downloads live today; club coming-soon (graceful); bar plays offline. Progress is untouched — unlocked is stars-based, independent of pack presence (test_unlocked_venue_survives_media_being_unbundled). 25 career route tests pass.

Merge note: land together with (or just before) got-feedBack/feedBack-desktop#123, which strips the packs from the bundle — the desktop strip shouldn't merge ahead of this download path.

@mhglover

Copy link
Copy Markdown
Contributor Author

cc @byrongamatos @OmikronApex — you were CodeRabbit's suggested reviewers for this one; would appreciate a look when you have a moment. (Couldn't add you via the reviewer field from my fork.) The desktop companion is got-feedBack/feedBack-desktop#123.

@mhglover

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

- workflow: stop interpolating dispatch inputs into Bash (template
  injection flagged by zizmor). Pass venues/version via env, validate
  formats, use an argument array.
- content_packs: reject top-level files the career downloader would
  refuse (PACK_FILENAME_RE) before publishing — a stray .DS_Store would
  otherwise ship and fail _validate_pack_dir for every client. + test.
- content_packs: pin ZipInfo.create_system=3 so packs hash identically
  across Windows/Unix runners (was the documented reproducibility caveat).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@mhglover

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

mhglover and others added 3 commits July 22, 2026 17:52
Signed-off-by: Matthew Harris Glover <matthew@harrisglover.com>
Signed-off-by: byrongamatos <xasiklas@gmail.com>

# Conflicts:
#	CHANGELOG.md
--publish is a flag (no tag arg) and publish() deliberately omits
--clobber; the docstring said otherwise.

Signed-off-by: byrongamatos <xasiklas@gmail.com>
@byrongamatos
byrongamatos merged commit 59bcf33 into got-feedBack:main Jul 22, 2026
6 checks passed
byrongamatos added a commit that referenced this pull request Jul 22, 2026
Rebased onto merged main (was stacked on #1023/#1024, whose venue work is
now in main) so it no longer carries a stale content_packs.py that would
revert 1023's build_pack fixes.

- build_vst_pack: slice a fat .vst3 tree to one platform (keep its binary
  dir + shared bundle files, drop the two foreign platform dirs and src/
  build trees). Pins create_system=3 like build_pack — without it the same
  tree hashes differently on a Windows runner (native .vst3 are built there),
  breaking the precomputable-hash guarantee exactly where it matters.
- Publish wiring: 'python tools/content_packs.py <vst-root> --vst --version N
  --publish' builds+uploads vst-<plat>-vN releases for mac/win/linux and emits
  a platform-keyed {url,sha256,bytes} manifest — the shape rig_builder's
  data/vst_packs.json consumes. publish() refactored onto a shared
  _publish_release helper (venue behaviour unchanged).
- Tests: slice keeps target+shared/drops foreign, per-platform binary,
  reproducibility, unknown-platform reject, and a simulated-win32 guard that
  fails if the create_system pin is dropped. selfcheck covers the VST path.

Original build_vst_pack by Matthew Harris Glover; reworked for the create_system
fix, publish wiring, and rebase.

Signed-off-by: byrongamatos <xasiklas@gmail.com>
Co-authored-by: byrongamatos <xasiklas@gmail.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@mhglover
mhglover deleted the feat/venue-packs-opt-in branch July 22, 2026 23:42
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.

2 participants