Repository navigation
Conversation
…tures scripts/schema-inventory.cjs lists every object, material, geometry and texture type, image form and userData key the app constructs, sends and saves (src/, the modules repo, the templates, the scenes repo, the test fixtures, captured wire messages). tests/e2e/schema-capture.test.cjs builds every Add-menu object and every switchable material kind on the base build and records the saved scene, a prefab element and the outgoing object messages under tests/fixtures/schema-1.65/ (excluded from the battery: a fixture generator). inventory.json is the fixture list the object schema is written from. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
userModules.importModuleText had no callers in core, the tests or the modules repo; behaviours compile through behaviours/source.js compileBehaviour with the caller's importer. CLAUDE.md now names that loader. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
One pure module, built on loadGuardCore's rules, validates every ObjectLoader JSON and every materials payload in place: object, material and geometry types from fixed lists (an unknown material type becomes the standard fallback, an unknown object type an Object3D, an unknown geometry type an empty buffer geometry), per-type field tables with value rules (unknown or invalid fields are stripped), embedded images under a size cap, userData keys with their inventoried kinds and plain JSON under a size cap, and depth / list caps. Every change is a dropped row with its path and reason. tests/unit/sceneSchema.test.js: every template, every test fixture (the 1.65 capture included) and, with SCENES_DIR, every scene of the scenes repo round-trips with nothing dropped and byte-identical JSON; a set of out-of-schema payloads is cleaned, counted and still parses. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ial load loadGuard.checkObjectJson / checkMaterialSet now run the schema, so every route that already goes through parseCheckedObject (peer objects, scene loads, imports, prefabs, levels, the library, history, autosave) and the new parseCheckedMaterials (the materials message) is validated and counted, with the schema's changes in the same counters and the same one toast per session. The thumbnail fallback in sessions.js parses through the checked helper too. wireValidate: the object row (ObjectLoader form) and the objectParameters materials row call the schema's verdicts instead of allowing anything. scripts/check-loaders.cjs (CI + npm run check:loaders): a generic loader call anywhere in src/ outside src/lib/loadGuard.js fails the build. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
validateGltfElement (sceneSchema.js): loadGuardCore's glTF rules first, then every extras block three copies into userData (scenes, nodes, meshes, primitives, cameras, animations, materials, textures, punctual lights, the document) under the ObjectLoader userData rules. A parsed document is cleaned in place; a JSON text or .glb that breaks a rule is refused. loadGuard.checkGltf runs it, so every glTF load path is counted the same way. Unit: the 37 glTF messages of the 1.65 handshake capture and every shipped .glb pass unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…schema tests/e2e/schema-ab.test.cjs: every template, the 1.65 capture and the scenes repo load with the load check changing nothing, and the first frame (frozen clock, the saved view) is compared with the base build's (AB_WRITE=1 on the base first). Battery: excluded as an A/B driver. tests/e2e/schema-two-peers.test.cjs: A builds every Add-menu kind, ten material types, maps, a map slot with tiling, params, a multi-slot material, a group and its duplicate; B (connected) has the same scene, C (late joiner) the same objects, slots and maps; the load check changes nothing on B or C. Battery: optional. OPEN-CORE.md section 6: the object schema is a contract, not a hook. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The handshake sync sends a mesh as glTF, so on the v1.65.1 base too a late joiner gets non-PBR materials as MeshStandardMaterial, a space in a name as _, and no mesh with a Normal / Depth material (measured: the same 6 / 2 / 2 on both builds). The suite now fails on any difference of another kind. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Roadmap 101 F2 + F7: objects and materials are validated on receive and on load.
Do not merge before 17 Nov (roadmap 101 order).
What changes
src/lib/sceneSchema.js(new, pure): the allowlist for three.js object JSON,materialspayloads and glTF elements, built on the v1.65.1 load check (loadGuardCore.js).Object3D, the standard fallback material or an emptyBufferGeometry.userDataand glTFextrasmust be plain JSON under a size cap. The keys core and the shipped modules write keep a per-key kind.{path, reason}row, counted in the wire diagnostics with one toast per session.src/lib/loadGuard.js:checkObjectJson,checkMaterialSetandcheckGltfrun the schema.parseCheckedMaterialsis now the one parse for thematerialsmessage.wireValidate: theobjectrow (ObjectLoader form) and the objectParametersmaterialsrow call the schema's non-mutating verdicts.scripts/check-loaders.cjs(npm run check:loaders, plus a CI step): fails onObjectLoader(,.parseMaterials(orMaterialLoader(anywhere insrc/outsideloadGuard.js.importModuleTextis removed (exported, no callers).OPEN-CORE.md: new section "6. Object schema". It is a contract, not a hook: the inventory shows the modules need no registration call.Evidence
scripts/schema-inventory.cjs, output kept astests/fixtures/schema-1.65/inventory.json. It covers 55 files and 2,348 elements: 9 object types, 10 material types, 17 geometry types and 37 userData keys.tests/e2e/schema-capture.test.cjs(a generator, excluded from the battery) wrotecapture.tpscene,prefab.jsonandwire.jsonon v1.65.0. They cover every Add-menu object, 10 material types, maps, map slots, tiling, params, a multi-slot material and the handshake sync.tests/unit/sceneSchema.test.js,checkLoaders.test.js):.glb.schema-ab(A/B driver against a v1.65.1 snapshot): 45 scenes (templates, the capture, the scenes repo). The load check changed nothing on any of them. 38 scenes render the same on two base runs. On 32 of those the lane frame is identical to the base (0.000 %), and the worst of the rest is 0.156 %. The football frame differs only in toasts. The other 7 scenes (fluid, water, jelly, castle, forest, film set, game plot) differ between two base runs too, so frames cannot judge them.schema-two-peers(new; battery: optional): green on the lane and on v1.65.1. The connected peer matches exactly. The late joiner matches too, apart from gaps the glTF handshake already had on v1.65.1, with identical counts on both builds: non-PBR materials arrive as MeshStandardMaterial, meshes with a Normal or Depth material are absent, and spaces in names become_. These are a follow-up, not changed here.npm run buildrc=0, check:loaders clean.🤖 Generated with Claude Code