Skip to content

Phase 1 / Scene / Runtime loader .scene.bin → ECS#33

Merged
guysenpai merged 18 commits into
mainfrom
phase-1/scene/scene-load
Jun 27, 2026
Merged

Phase 1 / Scene / Runtime loader .scene.bin → ECS#33
guysenpai merged 18 commits into
mainfrom
phase-1/scene/scene-load

Conversation

@guysenpai

Copy link
Copy Markdown
Contributor

Milestone brief: briefs/M1.0.5-scene-load.md

Runtime loader .scene.bin → ECS World: open + integrity-check the cooked binary (reusing the M1.0.4 accessor verbatim), remap on-disk schema identity to runtime ComponentIds, instantiate every entity per-entity (spawnDynamicWithValues), build the UUID→handle map, fire on_spawned in a two-phase pass (every entity exists before any hook), and load resources (including string fields interned into the now-Tier-0 persistent heap). No new ECS storage primitive.

Delivered across three review gates: E1 (open + schema-identity remap), E2 (per-entity instantiation + UUID map + two-phase on_spawned + LoadResult + bench), E3 (persistent heap → Tier 0, resource loading, Etch cook→load integration, CLAUDE.md).

Closing notes

  • What worked: The central hypothesis held — the M1.0.4 zero-copy accessor (reused verbatim) + the existing M0.1 spawn surface + the M1.0.2 ObserverRegistry were sufficient to materialize a cooked scene into a live World with no new ECS storage primitive. The genuinely new code is small: loader.zig + one public observer entry (dispatchOnSpawned). The two-phase on_spawned gives the "all entities exist before any on_spawned" ordering cleanly. The persistent-heap move to Tier 0 was mechanical (tier-neutral, runDrop a no-op).
  • What deviated from the original spec (all traced in the brief's Accepted deviations): E1/E2 mmap-ownership structuring + loadFromBytes byte-level core; error.MalformedScene (authorized correction); persistent heap moved to src/core/memory (Claude.ai amendment); resource install is install-or-overwrite (spec-grounded, engine-spec.md §19.1); T6 inline in interp.zig (brief-permitted); core/root.zig wires the memory submodule (single Zig module, not build.zig).
  • What to flag explicitly in review: All reviewed + validated across the E1/E2/E3 gates. Nothing outstanding.
  • Final measurements: scene_load_bench (zig build bench-scene-load -Doptimize=ReleaseFast, Apple M4 Pro): median 1.050 ms / 10 000 entities (min 0.907, max 2.111; 50 runs). Far under the spec ~10–50 ms/10k reference → per-entity confirmed; bulk SoA column-copy is a genuine YAGNI — no bulk-spawn milestone scheduled. The instantiate step keeps a clean boundary so a bulk path could later swap its body without touching loadScene's signature.
  • Residual risks / deliberately-left technical debt:
    • LoadResult.deinit == scene unload, not just mmap release: it destroys the resource_strings blocks the installed resources still reference. Safe in M1.0.5 (no unload, no post-deinit reads); to be framed at the unload/streaming milestone.
    • Non-transactional load: a mid-load error leaves partial state in the World (only the loader's own heap allocations are reclaimed via errdefer); the caller deinits the World.
    • Reserved cross-refs/extensions tables checked via std.debug.assert (stripped in ReleaseFast); the format-version gate is the real guard. M1.0.6 owns those tables.
    • Parent ordinals validated (MalformedScene on violation) + UUID→handle map is the seam, but no runtime hierarchy component is written (hierarchy milestone).

Validation (Étape 4 — all green)

  • All Scope deliverables present (E1 / E2 / E3)
  • No out-of-scope drift (no bulk-spawn, no getOrCreateArchetype/appendRowFromBytes, no parent-link application, accessor.zig untouched)
  • Acceptance tests pass debug + ReleaseSafe: T1/T2/T3 (load_roundtrip_test.zig) + loadScene mmap path, T4 (load_resources_test.zig), error invariants inline in loader.zig (CorruptScene / UnknownComponent / SchemaMismatch / MalformedScene — per the E1-gate decision to keep them inline), T6 integration inline in interp.zig
  • Bench runs + reports a median (measurement, not a gate): 1.050 ms / 10k (M4 Pro, ReleaseFast)
  • Observable behaviour demonstrable (T6 cook→load: 3 entities, 3 emitted events, resource string round-trip)
  • zig build, zig build test (debug + ReleaseSafe), zig fmt --check, zig build lint green; commit-msg hook green on every commit
  • Closing notes filled; CLAUDE.md §3.4 patched on the branch
  • Status: CLOSED, close date set, final docs(brief): close M1.0.5

🤖 Generated with Claude Code

@guysenpai guysenpai merged commit 5049395 into main Jun 27, 2026
10 checks passed
@guysenpai guysenpai deleted the phase-1/scene/scene-load branch June 27, 2026 19:40
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