Skip to content

fix(generate): empty pack (only pack.labelle) no longer breaks generate — Closes #590 - #592

Merged
apotema merged 1 commit into
mainfrom
fix/590-empty-pack
Jul 10, 2026
Merged

fix(generate): empty pack (only pack.labelle) no longer breaks generate — Closes #590#592
apotema merged 1 commit into
mainfrom
fix/590-empty-pack

Conversation

@apotema

@apotema apotema commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Problem

A light pack shipping ONLY pack.labelle — no convention subdirs (components/, events/, prefabs/, hooks/, scripts/) and no verb files (queries.zig/commands.zig) — broke full generate().

Every scanPackSubdir call no-ops on its missing source (copyAndScanAbs tolerates a missing dir and returns an empty list), so scanPack never created <target>/packs/<name>/. The later writePackModuleRoots then hit a raw error.FileNotFound opening that dir to write __pack_root.zig.

Fix

Chose behavior (a): clean no-op — a pack.labelle-only light pack is legitimately allowed (light packs are module-less convention bundles). scanPack now creates its target pack dir up front, so an empty pack produces a valid, empty __pack_root.zig and generate() completes cleanly. No validation error needed.

Test

Adds a regression test in test/pack_scan_tests.zig (SCAN_PACK) that stages a pack.labelle-only pack, asserts scanPack returns empty scans + lays down the target dir, and reproduces the exact scanner.writeFile("packs/<name>/__pack_root.zig", …) seam that used to throw FileNotFound — now succeeds.

Verification

zig build test: 1482/1488 pass. The only failure is the pre-existing, unrelated flow_catalog.emitFlowCatalogSidecar test (shown twice, once per runner step).

https://claude.ai/code/session_017pW3ifKf9wgxNg4viy6okw

…ite (#590)

A light pack shipping ONLY `pack.labelle` — no convention subdirs
(components/ events/ prefabs/ hooks/ scripts/) and no verb files — broke
full `generate()`. Every `scanPackSubdir` no-ops on its missing source, so
`scanPack` never created `<target>/packs/<name>/`, and the later
`writePackModuleRoots` hit a raw FileNotFound opening that dir to write
`__pack_root.zig`.

An empty light pack is a legitimate no-op, so `scanPack` now creates its
target pack dir up front (behavior (a) from the issue). The empty pack then
produces a valid, empty `__pack_root.zig` and generate completes cleanly —
no validation error needed.

Adds a regression test staging a `pack.labelle`-only pack and asserting
scanPack lays down the target dir + the exact `scanner.writeFile` seam that
used to throw now succeeds.

Closes #590

Claude-Session: https://claude.ai/code/session_017pW3ifKf9wgxNg4viy6okw
@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@apotema, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 49 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: c001c551-94d5-41fe-b95d-bd3b79f35dff

📥 Commits

Reviewing files that changed from the base of the PR and between 38c8c67 and 922f409.

📒 Files selected for processing (2)
  • src/root/pack_scan.zig
  • test/pack_scan_tests.zig
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/590-empty-pack

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.

@gemini-code-assist

Copy link
Copy Markdown

Warning

You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again!

@apotema
apotema merged commit 33786ff into main Jul 10, 2026
4 checks passed
@apotema
apotema deleted the fix/590-empty-pack branch July 10, 2026 19:23
apotema added a commit that referenced this pull request Jul 10, 2026
…592) (#595)

Engine v2.0.0 (#592) removed three pre-#560 legacy aliases; legacy
example scenes now hard-fail at load with error.InvalidFormat, breaking
the "Examples integration test" CI job on asset-streaming-smoke.

Migrate every affected example scene to the unified format:
- top-level "entities" -> "children"
- non-empty top-level "assets" -> bundle "meta.assets" header
- empty top-level "assets" -> removed

No prefab reference carried a "components" wrapper, so rule 2
(reference "components" -> "overrides") had no sites. fantasy-dungeon
and camera-builtin were already unified and left untouched.

Verified: asset-streaming-smoke generates + builds + runs headless on
the null backend against engine v2.0.0 (exit 0), with
SceneAssetManifests.main = &.{ "sprites", "jump" } preserved from the
bundle meta.assets header.

Claude-Session: https://claude.ai/code/session_017pW3ifKf9wgxNg4viy6okw
apotema added a commit that referenced this pull request Jul 11, 2026
…relay) (#610)

Advance the #607 showcase set with three more small complete games, each
scaffolded following the parallax-scroll conventions and verified end to
end (generate -> zig build -> deterministic headless run on .null):

- coin-collector: a full gameplay loop — per-frame ECS queries, homing
  movement via getPosition/setPosition, radius-overlap pickup,
  destroyEntity, and a win condition. Clears the 5-coin field by frame 87
  and logs `[collector] cleared` (verified).
- ruby-orbit: the ticket's Ruby scripting seed — a ruby/orbit.rb script
  drives the real engine through the Script Runtime Contract via the
  labelle-scripting plugin (local sibling, language=ruby) over the
  labelle-null sibling backend. Emits the exact ordered RUBY_* transcript
  (verified after compiling the vendored mruby).
- event-relay: the pure-Zig game event bus — a script emits a custom
  Pulse event (events/pulse.zig) that a game-root hook
  (hooks/pulse_watcher.zig) receives at dispatchEvents, proving the
  assembler's events/ + hooks/ auto-scan end to end (verified).

Also:
- Fix parallax-scroll for engine v2.0 (#592): the pre-#560 top-level
  "entities" scene key is now REJECTED at runtime; migrate it (and author
  the new scenes) with file-level entities under "children".
- Update docs/showcase-plan.md: expand the grid to reflect the games now
  in-repo (incl. camera-builtin / fantasy-dungeon / scripting-smoke that
  landed separately), document the unified scene-format requirement, and
  note the labelle-null-sibling pin the scripting games need.

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