Scene I/O — the .vscn format & roundtrip idempotence
A vgai scene is a plain .vscn.json file. The format isn’t ad-hoc: it’s defined by Zod schemas in
the engine, so loading a scene validates it, and saving one produces a file that loads back to
the same thing. This is a terminal proof of that round-trip (real captured output below).
# transcript pending capture — run: node site/media/capture-cli.mjs site/media/capture-cli.mjs -
Parse → serialize → parse is stable.
parseSceneFile(engine/src/scene/parse.ts) runs the raw JSON throughSceneFileSchema.safeParse— applying defaults and rejecting anything invalid. Re-stringifying the parsed result and parsing it again yields a byte-identical object (stable: true). The format is idempotent: a save never silently mutates a scene. -
The three I/O modules. The
lsshows the scene I/O spine:parse.ts—parseSceneFile(validate raw JSON → typedSceneFile).scene-serializer.ts—serializeScene(scene, meta)(a liveTHREE.Scene→SceneFile).scene-diff.ts— the structural diff that merges external edits (a.vscnchanged on disk underneath you) back into the live editor. Since T4.5 it has a proven inverse:applyDiff(engine/src/scene/scene-apply.ts) applies aSceneDiffpatch to a scene file — surfaced asnpm run vgai -- apply-diff <scene> <patch> [--report], the canonical programmatic edit op (validates scene + patch + result; writes nothing on failure).
Recap
New functionality
- Proved a .vscn round-trips (parse → serialize → parse) identically
- Listed the three scene I/O modules
New concepts & skills
- parseSceneFile validates raw JSON against the Zod SceneFileSchema (defaults + rejection)
- serializeScene turns a live THREE.Scene back into a SceneFile
- autosave writes the full serialized document to the loaded .vscn path; scene-diff merges external edits — one format, idempotent
Next lesson → Editor architecture