Skip to content

feat(packs): @import("pack").Registry — the sanctioned string-keyed surface (#498 PR 3) - #545

Merged
apotema merged 1 commit into
mainfrom
feat/498-registry-bridge
Jul 5, 2026
Merged

apotema merged 1 commit into
mainfrom
feat/498-registry-bridge

Conversation

@apotema

@apotema apotema commented Jul 5, 2026 •

Copy link
Copy Markdown
Contributor

PR 3 of the #498 train — the Registry bridge + self-import, making @import("pack").Registry the sanctioned string-keyed surface.

What lands

  • __pack_root.zig Registry tail: pub const Registry = if (@hasDecl(root, "<prefix>_pack_view")) root.<prefix>_pack_view else <own-components fallback> — the @import("root") bridge (the std_options mechanism; lazy analysis keeps root↔pack non-circular). In a generated game it resolves to the PR 1 PackView (own <pack>__ names + .global components; foreign-private names @compileError in the engine's ComponentView); under the tests target / preview shells the @hasDecl guard falls back to the pack's own components, no globals. Component-less packs get the empty fallback — uniform authoring surface.
  • Self-import: overrideImport(pack__<p>_mod, "pack", pack__<p>_mod) so authored code never hardcodes its prefix.
  • docs/packs.md — first assembler-side packs doc: the wall's import table, Registry semantics, the deliberately-open holes (game.ComponentRegistry via anytype stays lint territory; scenes/prefabs are data), and the generator invariants.

Proof on the real two-pack project

  • ✅ citizens script: comptime { if (Registry.getType("citizens__Counter") != Counter) @compileError(...) } — builds green, so the bridge resolves through the root view to the exact type the relative import reaches.
  • ❌ production script calling Registry.getType("citizens__Counter") — dies at comptime (here via the component-less fallback; a components-bearing consumer routes through the engine's ComponentView visibility message — PR 6's fixture pins that wording).

Tests

Suite 46/46 steps, 1268/1272 (4 skipped, 0 failed): renderer asserts for the bridge (root-view resolution + namespaced fallback fields + empty fallback for prefab-only packs), the build-wiring self-import, and the contracts direction check tightened to tolerate every pack's own "pack" self-import while still forbidding contracts←dependent wiring.

Next: PR 4 (exposes surface modules + depends_on), PR 5 (lint demotion + doc truth-up + the root.zig/build_files.zig >1000 splits), PR 6 (examples/packs-demo + CI e2e).

Part of #498

https://claude.ai/code/session_01P7YLw4hXFCCaY2LAUt4G1j

Summary by CodeRabbit

  • Documentation

    • Added guidance for the new Packs architecture, including pack boundaries, import rules, registry access, and generator behavior.
  • Bug Fixes

    • Pack code can now reliably import its own pack surface.
    • Registry access now falls back safely when a pack view is unavailable.
  • Tests

    • Expanded coverage for pack/module wiring, registry bridging, and fallback behavior.

…urface (#498 PR 3)

Every __pack_root.zig now tails with the Registry bridge: resolved via
@import("root") to the <prefix>_pack_view main.zig emits (PR 1) — the
pack's own <pack>__ names + .global components, foreign-private names
@CompileError in the engine's ComponentView. Root modules with no
generated views (tests target, preview shells) fall back to a registry
of the pack's own components only via the @hasDecl guard; lazy decl
analysis keeps root↔pack non-circular. Component-less packs get the
empty fallback so the authoring surface is uniform.

emitPackModules wires the self-import — overrideImport(mod, "pack",
mod) — so authored code writes @import("pack").Registry without ever
hardcoding its prefix.

docs/packs.md declares the wall + sanctioned surfaces (import table,
Registry semantics, the deliberate anytype/scene/prefab holes, and the
generator invariants).

Smoke-proven on the real two-pack project: a citizens script comptime-
asserts Registry.getType("citizens__Counter") == its relatively-
imported Counter type (builds green); a production script calling
getType("citizens__Counter") dies at comptime.

Part of #498

Claude-Session: https://claude.ai/code/session_01P7YLw4hXFCCaY2LAUt4G1j
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@coderabbitai

coderabbitai Bot commented Jul 5, 2026 •

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: ffff6f53-97c5-4eec-b996-6657c70a666d

📥 Commits

Reviewing files that changed from the base of the PR and between 7e5e3dd and 96a690f.

📒 Files selected for processing (4)
  • docs/packs.md
  • src/build_files.zig
  • src/codegen/pack_root.zig
  • test/pack_scan_tests.zig

📝 Walkthrough

Walkthrough

This PR adds documentation for the Packs architecture and implements a generated per-pack Registry bridge accessible via @import("pack").Registry, along with a self-import override so pack modules can @import("pack") themselves. Tests are updated to verify both behaviors.

Changes

Pack Registry Bridge

Layer / File(s) Summary
Packs architecture documentation
docs/packs.md
New doc explaining pack module walls, permitted/prohibited imports, sanctioned @import("pack").Registry access pattern, open (unenforced) areas, and generator invariants.
Pack module self-import wiring
src/build_files.zig
emitPackModules now emits overrideImport so each generated pack__<prefix>_mod maps its own "pack" import to itself.
Generated Registry constant in pack root
src/codegen/pack_root.zig
renderPackRoot now emits a Registry constant that resolves via @hasDecl(root, "{prefix}_pack_view"), falling back to a ComponentRegistry built from the pack's own components using idents.pathToPascal; adds related doc comments and an idents import.
Test coverage for Registry bridge and self-import
test/pack_scan_tests.zig
Extends PACK_ROOT_RENDER and PACK_MODULE_BUILD tests to assert the Registry bridge, empty-component fallback, "pack" self-import override, and that contracts modules don't override-import other pack names.

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

Possibly related issues

Possibly related PRs

Poem

A rabbit hops through walls of code,
Each pack now knows its own abode.
@import("pack") points back home,
No stray sibling left to roam.
Registry bridged, fallback spun,
Hop hop hooray, the wiring's done! 🐇✨

🚥 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 matches the main change: adding the sanctioned @import("pack").Registry surface for packs.
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 unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/498-registry-bridge

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

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request implements the self-import and Registry bridge mechanism for packs, allowing pack code to uniformly access its own module root and sanctioned string-keyed registry via @import("pack").Registry. This is achieved by generating a Registry bridge in the pack root that resolves to the root module's generated PackView or falls back to a local ComponentRegistry of the pack's own components. The build system is updated to inject the self-import override, and corresponding documentation and tests have been added. There are no review comments, so I have no feedback to provide.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

@apotema
apotema merged commit 0210f6a into main Jul 5, 2026
4 checks passed
@apotema
apotema deleted the feat/498-registry-bridge branch July 5, 2026 14:54
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