Skip to content

Phase 1 / Scene / Cooking .scene.etch → .scene.bin#32

Merged
guysenpai merged 21 commits into
mainfrom
phase-1/scene/scene-cook
Jun 26, 2026
Merged

Phase 1 / Scene / Cooking .scene.etch → .scene.bin#32
guysenpai merged 21 commits into
mainfrom
phase-1/scene/scene-cook

Conversation

@guysenpai

Copy link
Copy Markdown
Contributor

Milestone M1.0.4 — Cooking .scene.etch.scene.bin. Brief: briefs/M1.0.4-scene-cook.md (Status: CLOSED, closed 2026-06-27).

Delivers the offline, World-free cook of direct-entity scenes into the zero-copy .scene.bin the M1.0.5 runtime loader will mmap. New Tier-0 codec under src/core/scene/ (SceneHeader + §10 Schema Registry + writer + zero-copy accessor, the accessor reused verbatim by M1.0.5) + the Etch cook driver src/etch/scene_cook.zig (reuses compileTypeDecl + evalConst, groups entities by ComponentSignature into flat SoA columns). scene_cook CLI. Rejects instance of (M1.0.6) + unsupported field kinds with clear diagnostics.

Notes de fin

  • What worked:
    • Maximal reuse, as the brief intended: the cook reuses interp.compileTypeDecl (refactored to *Registry) + evalConst + ecs_bridge.writeValueAsBytes; the only genuinely new surface is the .scene.bin codec. Up-front parallel brick-mapping (signatures + file:line for every reused symbol) meant near-zero signature surprises during implementation.
    • The format.columnOffset/columnsRegionEnd shared helper made writer and accessor agree on SoA column placement by construction. The E3 mixed bool+f64 archetype case exercised real inter-column padding (not a no-op) and passed — locking that agreement.
    • Determinism fell out of deterministic ordering (schemas sorted by ascending id, tables in model order, XxHash64(0) over content-after-header) — re-cook byte-identity confirmed by both the test and the CLI cmp.
  • What deviated from the original spec:
    • interp.compileTypeDecl refactored *World*Registry + made pub (in interp.zig, outside the brief file list) — approved deviation, World-free registration reuse.
    • On-disk component identity = §10 Schema-Registry index → component name (correction demo: README-only CI duration probe (do not merge) #2), not raw ComponentId; SceneHeader gained schema_count + schema_table_offset.
    • Entity uuid is mandatory (error.MissingUuid, correction Phase -1 / Bootstrap / Repo and CI #1) — reverses E1's zero-fill.
    • format.zig (nominally E2) was created in E1 (the cook model is typed against it); the writer serializes the full file incl. the resources block in E2 (one cohesive codec), with the resource round-trip assertions added in E3.
    • Hash is std.hash.XxHash64 per the brief Note (overrides the spec's "xxHash3").
  • What to flag explicitly in review:
    • The fixture is a multi-construct .etch (component/resource/enum decls + one scene), not a strict §21 single-scene file: M1.0.4 cooks one self-contained program; cross-file import resolution at cook time is future work. The cook parses in general mode and rejects only instance of.
    • Name-based on-disk identity ⇒ the M1.0.5 loader remaps via idOf(name); the M1.0.4 round-trip is in-process (the cook returns its own Registry).
    • Reserved-empty Extensions/Cross-refs sections + FieldKind-dispatch keep M1.0.6 (cross-refs/extensions) and any new 3D/handle FieldKind additive (no on-disk/loader change).
  • Final measurements:
    • No perf gate (offline cook). Determinism: re-cook byte-identical (round-trip test + CLI cmp). Cooked arena_wave1.scene.bin = 344 bytes, WSCN magic @0, 64-byte header. zig build test EXIT 0 (debug + ReleaseSafe via pre-push), zig fmt --check + zig build lint clean.
  • Residual risk / technical debt left deliberately:
    • The accessor caps components-per-archetype at 256 (stack scratch for columnOffset); a malformed file beyond that trips an assert rather than a graceful error — fine for cook-produced files; the M1.0.5 loader may add input validation.
    • Resource field-level schema (§10 "champs") is not serialized — Phase-1 identity is the name; resource-layout migration/validation is future.
    • No cross-file import resolution at cook time (single self-contained program per cook).

Étape 4 — validation (all green)

  • All "Scope" deliverables present (E1 cook driver · E2 format/writer/accessor · E3 resources/determinism/CLI/CLAUDE.md)
  • No drift into "Out-of-scope" (no new FieldKind, no instance of flatten, no .prefab.bin, no runtime loader)
  • All "Acceptance criteria › Tests" pass in debug and ReleaseSafe (pre-push runs both)
  • Benchmarks: none required for this milestone
  • Observable behaviour demonstrable — zig build scene-cook -- --output … tests/fixtures/scene/arena_wave1.scene.etchWSCN magic + 64-byte header; re-run byte-identical (cmp)
  • zig build, zig build test, zig fmt --check, zig build lint green
  • tests/scene/ target rooted (its tests are counted) per engine-zig-conventions.md §13
  • CLAUDE.md §3.4 updated on the branch (docs(claude-md): update for M1.0.4) — État courant + Tags v0.10.4-scene-cook + open decisions (incl. dynamic-collections home + additive-future sections) + date
  • Brief "Notes de fin" filled
  • Brief Status: CLOSED, Close date: 2026-06-27, final commit docs(brief): close M1.0.4

Acted deviations (traced in the brief)

  1. compileTypeDecl*Registry — made pub and reparameterized from *World to *Registry so the World-free cook reuses the exact registration path; interp.zig was outside the brief file list (approved in-session).
  2. Entity uuid mandatoryparseEntityUuid returns error.MissingUuid on an absent uuid: (reverses the E1 zero-fill); explicit identity required, the cook never auto-generates.
  3. On-disk identity = Schema Registry index → name (engine-ecs-internals.md §10), never a raw runtime ComponentId; the in-memory CookModel keeps its ComponentId, only the encoding is schema-indexed; M1.0.5 remaps via idOf(name).

Merge strategy: squash-and-merge (one milestone = one commit on main). Not merged, not tagged — left to Guy after review (the v0.10.4-scene-cook tag is posted post-merge).

🤖 Generated with Claude Code

@guysenpai guysenpai merged commit 5e95c84 into main Jun 26, 2026
10 checks passed
@guysenpai guysenpai deleted the phase-1/scene/scene-cook branch June 26, 2026 23:53
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