@vgai/engine 0.5.41 → 0.5.44

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (129) hide show
  1. package/dist/adapter/adapter-module.d.ts +28 -29
  2. package/dist/adapter/adapter-module.d.ts.map +1 -1
  3. package/dist/adapter/adapter-module.js +11 -34
  4. package/dist/adapter/authoring-seam-contract.d.ts +10 -0
  5. package/dist/adapter/authoring-seam-contract.d.ts.map +1 -1
  6. package/dist/adapter/authoring-seam-contract.js +2 -0
  7. package/dist/adapter/authoring.d.ts +31 -0
  8. package/dist/adapter/authoring.d.ts.map +1 -1
  9. package/dist/adapter/finders/finder-result.d.ts +2 -2
  10. package/dist/adapter/finders/finder-result.d.ts.map +1 -1
  11. package/dist/adapter/finders/index.d.ts +15 -2
  12. package/dist/adapter/finders/index.d.ts.map +1 -1
  13. package/dist/adapter/finders/index.js +38 -10
  14. package/dist/adapter/finders/prefabs-from-stories.d.ts.map +1 -1
  15. package/dist/adapter/finders/registry.d.ts +45 -0
  16. package/dist/adapter/finders/registry.d.ts.map +1 -0
  17. package/dist/adapter/finders/registry.js +56 -0
  18. package/dist/adapter/ingest/scene-capture.d.ts.map +1 -1
  19. package/dist/adapter/ingest/scene-capture.js +50 -20
  20. package/dist/adapter/system-adapter.d.ts +3 -1
  21. package/dist/adapter/system-adapter.d.ts.map +1 -1
  22. package/dist/canvas-react/pixi-react-root-factory.d.ts.map +1 -1
  23. package/dist/canvas-react/pixi-react-root-factory.js +21 -11
  24. package/dist/data/vite-plugin-data.d.ts +1 -1
  25. package/dist/data/vite-plugin-data.d.ts.map +1 -1
  26. package/dist/data/vite-plugin-data.js +2 -2
  27. package/dist/ecs/user-data.d.ts +6 -0
  28. package/dist/ecs/user-data.d.ts.map +1 -1
  29. package/dist/ecs/user-data.js +4 -0
  30. package/dist/index.d.ts +1 -1
  31. package/dist/index.d.ts.map +1 -1
  32. package/dist/index.js +1 -1
  33. package/dist/input/host-pointer.d.ts +18 -0
  34. package/dist/input/host-pointer.d.ts.map +1 -1
  35. package/dist/input/host-pointer.js +54 -5
  36. package/dist/input/input-manager.d.ts +83 -1
  37. package/dist/input/input-manager.d.ts.map +1 -1
  38. package/dist/input/input-manager.js +357 -8
  39. package/dist/manifest/configuration-kinds.d.ts +97 -0
  40. package/dist/manifest/configuration-kinds.d.ts.map +1 -0
  41. package/dist/manifest/configuration-kinds.js +148 -0
  42. package/dist/manifest/index.d.ts +2 -1
  43. package/dist/manifest/index.d.ts.map +1 -1
  44. package/dist/manifest/index.js +4 -3
  45. package/dist/manifest/kind-modules.d.ts +18 -0
  46. package/dist/manifest/kind-modules.d.ts.map +1 -0
  47. package/dist/manifest/kind-modules.js +58 -0
  48. package/dist/manifest/load-file.d.ts +3 -3
  49. package/dist/manifest/load-file.d.ts.map +1 -1
  50. package/dist/manifest/load-file.js +4 -4
  51. package/dist/manifest/load.d.ts +17 -12
  52. package/dist/manifest/load.d.ts.map +1 -1
  53. package/dist/manifest/load.js +29 -19
  54. package/dist/manifest/runtime-environment.d.ts +11 -0
  55. package/dist/manifest/runtime-environment.d.ts.map +1 -0
  56. package/dist/manifest/runtime-environment.js +44 -0
  57. package/dist/manifest/schema.d.ts +10 -9
  58. package/dist/manifest/schema.d.ts.map +1 -1
  59. package/dist/manifest/schema.js +32 -27
  60. package/dist/react/use-data.d.ts +1 -1
  61. package/dist/react/use-data.js +1 -1
  62. package/dist/render/environment-capture.d.ts +10 -1
  63. package/dist/render/environment-capture.d.ts.map +1 -1
  64. package/dist/render/environment-capture.js +25 -0
  65. package/dist/render/ibl-override-material.d.ts +11 -2
  66. package/dist/render/ibl-override-material.d.ts.map +1 -1
  67. package/dist/render/ibl-override-material.js +16 -2
  68. package/dist/render/matcap-texture.d.ts +5 -0
  69. package/dist/render/matcap-texture.d.ts.map +1 -0
  70. package/dist/render/matcap-texture.js +82 -0
  71. package/dist/render/soft-particle-depth.d.ts +14 -8
  72. package/dist/render/soft-particle-depth.d.ts.map +1 -1
  73. package/dist/render/soft-particle-depth.js +37 -14
  74. package/dist/render/viewport-shading.d.ts +11 -1
  75. package/dist/render/viewport-shading.d.ts.map +1 -1
  76. package/dist/render/viewport-shading.js +25 -0
  77. package/dist/runtime/create-runtime.js +6 -5
  78. package/dist/runtime/debug-bridge.d.ts.map +1 -1
  79. package/dist/runtime/debug-bridge.js +17 -3
  80. package/dist/runtime/mount-manifest.d.ts.map +1 -1
  81. package/dist/runtime/mount-manifest.js +11 -2
  82. package/dist/settings/schema.d.ts +99 -0
  83. package/dist/settings/schema.d.ts.map +1 -0
  84. package/dist/settings/schema.js +110 -0
  85. package/dist/world3d-react/r3f-root-factory.d.ts.map +1 -1
  86. package/dist/world3d-react/r3f-root-factory.js +34 -36
  87. package/dist/world3d-react/rapier-physics-bridge.d.ts.map +1 -1
  88. package/dist/world3d-react/rapier-physics-bridge.js +21 -6
  89. package/dist-config/config.js +1 -1
  90. package/dist-config/config.js.map +2 -2
  91. package/package.json +2 -1
  92. package/schemas/engine-capabilities.json +4 -4
  93. package/schemas/vgai-project.schema.json +41 -36
  94. package/schemas/vgai-settings.schema.json +112 -0
  95. package/src/adapter/adapter-module.ts +33 -51
  96. package/src/adapter/authoring-seam-contract.ts +2 -0
  97. package/src/adapter/authoring.ts +31 -0
  98. package/src/adapter/finders/finder-result.ts +2 -2
  99. package/src/adapter/finders/index.ts +68 -12
  100. package/src/adapter/finders/prefabs-from-stories.ts +2 -2
  101. package/src/adapter/finders/registry.ts +95 -0
  102. package/src/adapter/finders/scenes-from-entrypoint-selection.ts +4 -4
  103. package/src/adapter/ingest/scene-capture.ts +48 -19
  104. package/src/adapter/system-adapter.ts +3 -1
  105. package/src/canvas-react/pixi-react-root-factory.tsx +21 -11
  106. package/src/data/vite-plugin-data.ts +4 -2
  107. package/src/ecs/user-data.ts +6 -0
  108. package/src/index.ts +1 -1
  109. package/src/input/host-pointer.ts +84 -5
  110. package/src/input/input-manager.ts +404 -7
  111. package/src/manifest/configuration-kinds.ts +241 -0
  112. package/src/manifest/index.ts +4 -3
  113. package/src/manifest/kind-modules.ts +58 -0
  114. package/src/manifest/load-file.ts +11 -5
  115. package/src/manifest/load.ts +53 -22
  116. package/src/manifest/runtime-environment.ts +48 -0
  117. package/src/manifest/schema.ts +39 -33
  118. package/src/react/use-data.ts +1 -1
  119. package/src/render/environment-capture.ts +30 -1
  120. package/src/render/ibl-override-material.ts +32 -2
  121. package/src/render/matcap-texture.ts +92 -0
  122. package/src/render/soft-particle-depth.ts +43 -14
  123. package/src/render/viewport-shading.ts +33 -1
  124. package/src/runtime/create-runtime.ts +6 -5
  125. package/src/runtime/debug-bridge.ts +21 -3
  126. package/src/runtime/mount-manifest.ts +13 -2
  127. package/src/settings/schema.ts +127 -0
  128. package/src/world3d-react/r3f-root-factory.tsx +45 -39
  129. package/src/world3d-react/rapier-physics-bridge.tsx +22 -8
@@ -1 +1 @@
1
- {"version":3,"file":"debug-bridge.d.ts","sourceRoot":"","sources":["../../src/runtime/debug-bridge.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"debug-bridge.d.ts","sourceRoot":"","sources":["../../src/runtime/debug-bridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAChF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,EAAc,KAAK,aAAa,EAAE,KAAK,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAGxF;;yEAEyE;AACzE,eAAO,MAAM,sBAAsB,eAAe,CAAC;AAEnD;;;kBAGkB;AAClB,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,KAAK,CAAC,EAAE;QAAE,QAAQ,CAAC,iBAAiB,EAAE,OAAO,CAAA;KAAE,GAAG,SAAS,CAAC;CACtE;AAED;;;;;;;;2EAQ2E;AAC3E,MAAM,WAAW,oBAAoB;IACnC,gBAAgB,CACd,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,EAClD,OAAO,CAAC,EAAE,MAAM,GACf;QAAE,SAAS,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3C,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG;QAAE,SAAS,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5F,mBAAmB,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5C;;;;;;;;;;;;;;;;;;OAkBG;IACH,oBAAoB,CAClB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,EAClD,OAAO,CAAC,EAAE,MAAM,GACf,IAAI,CAAC;IACR;;;+CAG2C;IAC3C,cAAc,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvC,oEAAoE;IACpE,aAAa,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,+CAA+C;IAC/C,WAAW,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IACvC;;;;;mDAK+C;IAC/C,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9F;;;;iFAI6E;IAC7E,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAClG;AAED;;;6BAG6B;AAC7B,MAAM,WAAW,iBAAiB;IAChC;;;;6CAIyC;IACzC,IAAI,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,gBAAgB,GAAG,IAAI,CAAA;KAAE,CAAC;IAClF,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,MAAM,EAAE,gBAAgB,EAAE,CAAC;IAC3B,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAED;;;0EAG0E;AAC1E,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC;IACpB,SAAS,EAAE,YAAY,CAAC,WAAW,CAAC,CAAC;IACrC,KAAK,EAAE,YAAY,CAAC,OAAO,CAAC,CAAC;IAC7B,QAAQ,EAAE,YAAY,CAAC,UAAU,CAAC,CAAC;IACnC,QAAQ,EAAE,YAAY,CAAC,UAAU,CAAC,CAAC;IACnC,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACxD,MAAM,EAAE,YAAY,CAAC,QAAQ,CAAC,CAAC;IAC/B,KAAK,EAAE,oBAAoB,CAAC;IAC5B;;;4BAGwB;IACxB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,iBAAiB,CAAC;IAC/C;;;;;;;;;OASG;IACH,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;IAClD;;;;;;;;;;OAUG;IACH,eAAe,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClE;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACH,OAAO,CACL,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC;QAAE,SAAS,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACpD;;;;;;;OAOG;IACH,SAAS,IAAI,IAAI,CAAC;CACnB;AAED;;8EAE8E;AAC9E,MAAM,WAAW,uBAAuB;IACtC,gBAAgB,CAAC,CACf,IAAI,EAAE,OAAO,GAAG,oBAAoB,EACpC,QAAQ,EAAE,CAAC,KAAK,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,GACjF,IAAI,CAAC;IACR;;;qDAGiD;IACjD,mBAAmB,CAAC,CAClB,IAAI,EAAE,OAAO,GAAG,oBAAoB,EACpC,QAAQ,EAAE,CAAC,KAAK,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,GACjF,IAAI,CAAC;IACR,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,8BAA8B;IAC7C;;yDAEqD;IACrD,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC;IACjC,QAAQ,CAAC,QAAQ,EAAE,mBAAmB,CAAC;IACvC;;yEAEqE;IACrE,QAAQ,CAAC,GAAG,CAAC,EAAE;QAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC;IACvD;;qDAEiD;IACjD,QAAQ,CAAC,MAAM,CAAC,EAAE,uBAAuB,GAAG,SAAS,CAAC;CACvD;AAgCD;;;;;cAKc;AACd,eAAO,MAAM,6BAA6B,QAInB,CAAC;AAaxB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,YAAY,EACrB,UAAU,EAAE,MAAM,EAClB,iBAAiB,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,GACtC,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,oBAAoB,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,CAiD/D;AAiKD;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,8BAA8B,GACnC,eAAe,GAAG,SAAS,CAwB7B"}
@@ -32,10 +32,13 @@ const HOLD_FOR_POLL_MS = 50;
32
32
  * faster in-process interval so the wall-clock grace period (~5s) lands in
33
33
  * the same neighborhood. */
34
34
  const HOLD_FOR_STALL_POLL_LIMIT = 100;
35
- /** Ticks driven per synchronous starved-loop batch. Sized like
35
+ /** Maximum ticks driven per synchronous starved-loop batch. Sized like
36
36
  * `fast-forward.ts`'s own batching rationale: big enough that per-batch
37
37
  * bookkeeping is negligible, small enough that one batch of a complex game's
38
- * phases stays a short synchronous burst. */
38
+ * phases stays a short synchronous burst. The actual batch is capped to the
39
+ * hold's remaining fixed-tick budget below; otherwise a one-tick `tap()` in a
40
+ * hidden tab becomes a 60-tick hold and releases only after short gameplay
41
+ * interactions have already completed. */
39
42
  const STARVED_DRIVE_BATCH_TICKS = 60;
40
43
  /** Hard ceiling on starved-drive batches for ONE hold — `STARVED_DRIVE_BATCH_TICKS
41
44
  * * this` ≈ 33 sim-minutes. A bound, not a timeout: it exists so a
@@ -106,7 +109,18 @@ export async function waitForHoldBudget(adapter, simSeconds, driveStarvedTicks)
106
109
  if (starvedBatches >= STARVED_DRIVE_MAX_BATCHES)
107
110
  return { stalled: true };
108
111
  starvedBatches += 1;
109
- driveStarvedTicks(STARVED_DRIVE_BATCH_TICKS);
112
+ const remaining = simSeconds - (current.simSeconds - start.simSeconds);
113
+ const fixedDt = current.fixedDt;
114
+ // A real Game publishes its fixed timestep, so drive exactly the number of whole ticks
115
+ // still needed (up to the throughput cap). Subtract a tiny ratio tolerance before `ceil`:
116
+ // repeated floating-point additions can leave an integer tick budget a few ulps above its
117
+ // mathematical value, and that must not manufacture one extra held-input frame. A bare
118
+ // adapter that does not publish `fixedDt` takes the conservative path: one tick, re-read,
119
+ // repeat. Exact input duration matters more than batching a non-Game test stand-in.
120
+ const ticksForRemaining = fixedDt !== undefined && Number.isFinite(fixedDt) && fixedDt > 0
121
+ ? Math.max(1, Math.ceil(remaining / fixedDt - 1e-9))
122
+ : 1;
123
+ driveStarvedTicks(Math.min(STARVED_DRIVE_BATCH_TICKS, ticksForRemaining));
110
124
  const after = readTime();
111
125
  // A batch that moved neither the tick counter nor the sim clock means
112
126
  // the drive is a no-op (paused game, torn-down runtime) — the same
@@ -1 +1 @@
1
- {"version":3,"file":"mount-manifest.d.ts","sourceRoot":"","sources":["../../src/runtime/mount-manifest.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"mount-manifest.d.ts","sourceRoot":"","sources":["../../src/runtime/mount-manifest.ts"],"names":[],"mappings":"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"}
@@ -76,6 +76,15 @@ function hasRealWindow() {
76
76
  function looksAlreadyResolved(value) {
77
77
  if (typeof value !== 'object' || value === null)
78
78
  return false;
79
+ // The loader's own output field is the surest mark: a raw manifest never
80
+ // carries it (the schema is strict). Without this, a RESOLVED manifest
81
+ // with `roots: []` — a models project, nothing to play — fell through to
82
+ // `loadGameManifest`, whose strict parse refused THIS key ("Unrecognized
83
+ // key: deferredConfigurationKinds") instead of saying "no roots"
84
+ // (blind lantern round 21, 2026-09-06, sent there by the never-played nag).
85
+ if (Array.isArray(value.deferredConfigurationKinds)) {
86
+ return true;
87
+ }
79
88
  const roots = value.roots;
80
89
  if (!Array.isArray(roots) || roots.length === 0)
81
90
  return false;
@@ -97,7 +106,7 @@ function looksAlreadyResolved(value) {
97
106
  export function resolveManifest(raw) {
98
107
  if (looksAlreadyResolved(raw))
99
108
  return raw;
100
- return loadGameManifest(raw);
109
+ return loadGameManifest(raw, { configurationKinds: 'defer' });
101
110
  }
102
111
  // ---------------------------------------------------------------------------
103
112
  // Per-kind entry -> adapter resolution (mirrors `resolveRootBinding`'s
@@ -265,7 +274,7 @@ export async function mountManifestRoots(opts) {
265
274
  // `manifest/load.ts`) is `{ room, module } | undefined`; its mere presence
266
275
  // is the "this project declares a room" signal, independent of
267
276
  // whether/when the game actually joins it.
268
- if (manifest.server) {
277
+ if (manifest.configurations.some((configuration) => configuration.kind === 'process')) {
269
278
  debugRegistry.setRoomDeclared(true);
270
279
  }
271
280
  // Defect 5 fix: `maybeInstallDebugBridge` adds `window` listeners and
@@ -0,0 +1,99 @@
1
+ /**
2
+ * THE SETTINGS DOCUMENT — the Zod truth for the two shared settings layers
3
+ * (ARCHITECTURE-CORE §Editor chrome, "Settings have four layers with named
4
+ * homes"):
5
+ *
6
+ * ~/.vgai/settings.json the USER layer — one person, every project
7
+ * <project>/.vgai/settings.json the PROJECT layer — one project, committed,
8
+ * every person who opens it
9
+ *
10
+ * Both files carry the same shape; the project layer overrides the user layer
11
+ * key by key (`mergeEditorSettings`). Neither layer holds authored content —
12
+ * an unreadable file is reported by name and falls back to defaults, never
13
+ * migrated. The generated JSON Schema (`npm run generate-schema` →
14
+ * `packages/engine/schemas/vgai-settings.schema.json`) is what an editor
15
+ * autocompletes against when a person edits either file by hand.
16
+ *
17
+ * Every field here has a runtime reader in the editor's settings store
18
+ * consumers (`theme-preference.ts`, `workspace-regions.ts`,
19
+ * `keymap-presets.ts`, `workspace-presets.ts`, `device-preview.ts`); a field
20
+ * with no reader does not get declared (CLAUDE.md, "Do not author schema
21
+ * fields that have no runtime reader").
22
+ */
23
+ import { z } from 'zod';
24
+ export declare const ChromeRegionsSettingsSchema: z.ZodObject<{
25
+ tabs: z.ZodOptional<z.ZodEnum<{
26
+ hidden: "hidden";
27
+ shown: "shown";
28
+ }>>;
29
+ header: z.ZodOptional<z.ZodEnum<{
30
+ hidden: "hidden";
31
+ shown: "shown";
32
+ }>>;
33
+ shelf: z.ZodOptional<z.ZodEnum<{
34
+ hidden: "hidden";
35
+ shown: "shown";
36
+ }>>;
37
+ inspector: z.ZodOptional<z.ZodEnum<{
38
+ properties: "properties";
39
+ column: "column";
40
+ }>>;
41
+ drawer: z.ZodOptional<z.ZodEnum<{
42
+ hidden: "hidden";
43
+ shown: "shown";
44
+ }>>;
45
+ }, z.core.$strict>;
46
+ export declare const EditorSettingsSchema: z.ZodObject<{
47
+ $schema: z.ZodOptional<z.ZodString>;
48
+ appearance: z.ZodOptional<z.ZodObject<{
49
+ palette: z.ZodOptional<z.ZodString>;
50
+ material: z.ZodOptional<z.ZodString>;
51
+ regions: z.ZodOptional<z.ZodObject<{
52
+ tabs: z.ZodOptional<z.ZodEnum<{
53
+ hidden: "hidden";
54
+ shown: "shown";
55
+ }>>;
56
+ header: z.ZodOptional<z.ZodEnum<{
57
+ hidden: "hidden";
58
+ shown: "shown";
59
+ }>>;
60
+ shelf: z.ZodOptional<z.ZodEnum<{
61
+ hidden: "hidden";
62
+ shown: "shown";
63
+ }>>;
64
+ inspector: z.ZodOptional<z.ZodEnum<{
65
+ properties: "properties";
66
+ column: "column";
67
+ }>>;
68
+ drawer: z.ZodOptional<z.ZodEnum<{
69
+ hidden: "hidden";
70
+ shown: "shown";
71
+ }>>;
72
+ }, z.core.$strict>>;
73
+ }, z.core.$strict>>;
74
+ keymap: z.ZodOptional<z.ZodString>;
75
+ workspace: z.ZodOptional<z.ZodObject<{
76
+ default: z.ZodOptional<z.ZodString>;
77
+ }, z.core.$strict>>;
78
+ devicePreview: z.ZodOptional<z.ZodObject<{
79
+ preset: z.ZodOptional<z.ZodString>;
80
+ touch: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
81
+ }, z.core.$strict>>;
82
+ }, z.core.$strict>;
83
+ export type EditorSettings = z.infer<typeof EditorSettingsSchema>;
84
+ export type ChromeRegionsSettings = z.infer<typeof ChromeRegionsSettingsSchema>;
85
+ /** Which layer a file is; the file paths are the server's. */
86
+ export type SettingsLayer = 'user' | 'project';
87
+ /** Deep-merge plain objects; anything else (primitives, arrays, null)
88
+ * replaces. `merge(user, project)` is the effective document. */
89
+ export declare function mergeEditorSettings(base: EditorSettings, over: EditorSettings): EditorSettings;
90
+ /** Validate a raw document. The result carries the parsed settings or the
91
+ * issues, spelled for a person who has the file open. */
92
+ export declare function parseEditorSettings(raw: unknown): {
93
+ settings: EditorSettings;
94
+ issues: [];
95
+ } | {
96
+ settings: null;
97
+ issues: string[];
98
+ };
99
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/settings/schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;;;;;;;;kBAY0B,CAAC;AAEnE,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBA6CsD,CAAC;AAExF,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAClE,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,2BAA2B,CAAC,CAAC;AAEhF,8DAA8D;AAC9D,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,SAAS,CAAC;AAM/C;kEACkE;AAClE,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,cAAc,GAAG,cAAc,CAY9F;AAED;0DAC0D;AAC1D,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,OAAO,GACX;IAAE,QAAQ,EAAE,cAAc,CAAC;IAAC,MAAM,EAAE,EAAE,CAAA;CAAE,GAAG;IAAE,QAAQ,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CASjF"}
@@ -0,0 +1,110 @@
1
+ /**
2
+ * THE SETTINGS DOCUMENT — the Zod truth for the two shared settings layers
3
+ * (ARCHITECTURE-CORE §Editor chrome, "Settings have four layers with named
4
+ * homes"):
5
+ *
6
+ * ~/.vgai/settings.json the USER layer — one person, every project
7
+ * <project>/.vgai/settings.json the PROJECT layer — one project, committed,
8
+ * every person who opens it
9
+ *
10
+ * Both files carry the same shape; the project layer overrides the user layer
11
+ * key by key (`mergeEditorSettings`). Neither layer holds authored content —
12
+ * an unreadable file is reported by name and falls back to defaults, never
13
+ * migrated. The generated JSON Schema (`npm run generate-schema` →
14
+ * `packages/engine/schemas/vgai-settings.schema.json`) is what an editor
15
+ * autocompletes against when a person edits either file by hand.
16
+ *
17
+ * Every field here has a runtime reader in the editor's settings store
18
+ * consumers (`theme-preference.ts`, `workspace-regions.ts`,
19
+ * `keymap-presets.ts`, `workspace-presets.ts`, `device-preview.ts`); a field
20
+ * with no reader does not get declared (CLAUDE.md, "Do not author schema
21
+ * fields that have no runtime reader").
22
+ */
23
+ import { z } from 'zod';
24
+ const RegionVisibility = z.enum(['shown', 'hidden']);
25
+ export const ChromeRegionsSettingsSchema = z
26
+ .object({
27
+ tabs: RegionVisibility.optional().describe('The document tab strip.'),
28
+ header: RegionVisibility.optional().describe('The top header bar.'),
29
+ shelf: RegionVisibility.optional().describe('The utility shelf.'),
30
+ inspector: z
31
+ .enum(['column', 'properties'])
32
+ .optional()
33
+ .describe('Inspector presentation: the narrow docked column or a properties panel.'),
34
+ drawer: RegionVisibility.optional().describe('The bottom drawer.'),
35
+ })
36
+ .strict()
37
+ .describe('Which chrome regions a style bundle shows or hides.');
38
+ export const EditorSettingsSchema = z
39
+ .object({
40
+ $schema: z
41
+ .string()
42
+ .optional()
43
+ .describe('JSON Schema pointer for editor autocomplete; ignored by the editor.'),
44
+ appearance: z
45
+ .object({
46
+ palette: z
47
+ .string()
48
+ .optional()
49
+ .describe('Editor palette id — a built-in or a custom theme document.'),
50
+ material: z.string().optional().describe('Editor material id (`classic` or `glass`).'),
51
+ regions: ChromeRegionsSettingsSchema.optional(),
52
+ })
53
+ .strict()
54
+ .optional()
55
+ .describe('How the editor chrome looks.'),
56
+ keymap: z.string().optional().describe('Active keymap preset id (`vgai`, `blender`, …).'),
57
+ workspace: z
58
+ .object({
59
+ default: z
60
+ .string()
61
+ .optional()
62
+ .describe('The workspace a fresh checkout opens in, when it applies to the project shape.'),
63
+ })
64
+ .strict()
65
+ .optional()
66
+ .describe('Workspace defaults.'),
67
+ devicePreview: z
68
+ .object({
69
+ preset: z.string().optional().describe('Device preview frame preset id.'),
70
+ touch: z
71
+ .boolean()
72
+ .nullable()
73
+ .optional()
74
+ .describe('Touch emulation override; null follows the preset.'),
75
+ })
76
+ .strict()
77
+ .optional()
78
+ .describe('The device frame the Game document previews in.'),
79
+ })
80
+ .strict()
81
+ .describe('Editor settings — the user layer and the project layer share this shape.');
82
+ function isPlainObject(value) {
83
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
84
+ }
85
+ /** Deep-merge plain objects; anything else (primitives, arrays, null)
86
+ * replaces. `merge(user, project)` is the effective document. */
87
+ export function mergeEditorSettings(base, over) {
88
+ const out = { ...base };
89
+ const patch = over;
90
+ for (const key of Object.keys(patch)) {
91
+ const value = patch[key];
92
+ const current = out[key];
93
+ out[key] =
94
+ isPlainObject(current) && isPlainObject(value)
95
+ ? mergeEditorSettings(current, value)
96
+ : value;
97
+ }
98
+ return out;
99
+ }
100
+ /** Validate a raw document. The result carries the parsed settings or the
101
+ * issues, spelled for a person who has the file open. */
102
+ export function parseEditorSettings(raw) {
103
+ const result = EditorSettingsSchema.safeParse(raw);
104
+ if (result.success)
105
+ return { settings: result.data, issues: [] };
106
+ return {
107
+ settings: null,
108
+ issues: result.error.issues.map((issue) => issue.path.length ? `${issue.path.join('.')}: ${issue.message}` : issue.message),
109
+ };
110
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"r3f-root-factory.d.ts","sourceRoot":"","sources":["../../src/world3d-react/r3f-root-factory.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAWH,OAAO,KAAK,EAAoB,WAAW,EAAoB,MAAM,YAAY,CAAC;AAelF,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAmanE;;;;;;;;;;;GAWG;AACH,wBAAgB,sBAAsB,CAAC,WAAW,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAI/F;AAED;;GAEG;AACH,eAAO,MAAM,cAAc,EAAE,qBAO5B,CAAC"}
1
+ {"version":3,"file":"r3f-root-factory.d.ts","sourceRoot":"","sources":["../../src/world3d-react/r3f-root-factory.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAkBH,OAAO,KAAK,EAAoB,WAAW,EAAoB,MAAM,YAAY,CAAC;AAelF,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAkanE;;;;;;;;;;;GAWG;AACH,wBAAgB,sBAAsB,CAAC,WAAW,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAI/F;AAED;;GAEG;AACH,eAAO,MAAM,cAAc,EAAE,qBAO5B,CAAC"}
@@ -35,7 +35,7 @@
35
35
  * `resolve.dedupe: ['three', 'react', 'react-dom']`.
36
36
  */
37
37
  import { advance, createRoot, extend, flushSync, events as pointerEvents, } from '@react-three/fiber';
38
- import { createElement, Fragment, useEffect } from 'react';
38
+ import { Component, createElement, Fragment, useEffect, } from 'react';
39
39
  import { registerRenderVitals } from '../dev/register-render-vitals';
40
40
  import { createRenderDebugAdapter, frameCaptureContextFor, } from '../dev/render-debug-adapter';
41
41
  import { collectRenderMemory } from '../dev/render-memory';
@@ -46,6 +46,20 @@ import { getDebugRegistry } from '../runtime/debug-registry';
46
46
  import { devBuildEnabled } from '../runtime/dev-build';
47
47
  import { DEFAULT_INPUT_MAP_PATH, wireGameInputSeams } from '../runtime/game-input-seams';
48
48
  import { clearHostFrameDelta, setHostFrameDelta } from './frame-delta';
49
+ /** React errors must reject a mount in Node too, where there is no window
50
+ * error event. This boundary changes no authored content on successful mounts. */
51
+ class MountErrorBoundary extends Component {
52
+ state = { failed: false };
53
+ static getDerivedStateFromError() {
54
+ return { failed: true };
55
+ }
56
+ componentDidCatch(error) {
57
+ this.props.onError(error);
58
+ }
59
+ render() {
60
+ return this.state.failed ? null : this.props.children;
61
+ }
62
+ }
49
63
  /**
50
64
  * Build the `RootAdapter` for one default-exported R3F world. Mounts through
51
65
  * react-three-fiber, gated entirely by the host's own loop and rendering
@@ -57,28 +71,9 @@ function threeWorldAdapter(id, component) {
57
71
  return {
58
72
  id,
59
73
  async mount(host) {
60
- // Headless honesty every `mount()` must work headless: the conformance
61
- // kit runs `mount()` in Node no canvas, no WebGL, no fiber
62
- // reconciler. Guard the ENTIRE fiber mount behind `!host.headless` and
63
- // return a bare, real scene + camera instead (still `instanceof
64
- // host.three.Scene` / `.Camera` — the identity rule holds even here,
65
- // since this uses the host's own `three` instance, not a fresh import).
66
- // Residual: the hierarchy is empty under headless conformance —
67
- // recorded as design O2, not hidden; a react-nil-style headless
68
- // reconciler mount is the known fix, out of scope.
69
- if (host.headless) {
70
- const scene = new host.three.Scene();
71
- const camera = new host.three.PerspectiveCamera();
72
- return {
73
- kind: 'three',
74
- scene,
75
- camera,
76
- drivesOwnLoop: false,
77
- dispose() {
78
- /* nothing was ever mounted */
79
- },
80
- };
81
- }
74
+ // Headless mounts use this same Fiber reconciler and authored tree.
75
+ // Their host supplies an inert draw command; absence of a GPU is not
76
+ // permission to return a successful but empty scene.
82
77
  // Fiber v9 made the THREE catalogue tree-shakeable: `<Canvas>` calls
83
78
  // `extend(THREE)` for you, a bare `createRoot` does NOT — without this,
84
79
  // the FIRST three intrinsic in the tree (`<color>`, `<ambientLight>`,
@@ -171,7 +166,7 @@ function threeWorldAdapter(id, component) {
171
166
  // bound to the canvas, no error — and every mesh-level pointer prop
172
167
  // (`onClick`, `onPointerOver`, `onPointerMissed`) is dead. Proven by a
173
168
  // control experiment differing ONLY in this property.
174
- events: pointerEvents,
169
+ ...(host.headless ? {} : { events: pointerEvents }),
175
170
  onCreated: (state) => resolveState(state),
176
171
  });
177
172
  // No `<StrictMode>` — the host mounts once; StrictMode's deliberate
@@ -188,19 +183,20 @@ function threeWorldAdapter(id, component) {
188
183
  const game = host.game;
189
184
  const world = createElement(Fragment, null, content, createElement(MountEffectsReady, { key: 'vgai-mount-effects-ready' }));
190
185
  const provided = game ? createElement(WorldProvider, { game }, world) : world;
191
- root.render(provided);
192
186
  // A reconcile-time crash (e.g. a missing `extend` catalogue entry)
193
187
  // surfaces as an uncaught window error and `onCreated` never fires —
194
188
  // without this guard, `mount()` would await `statePromise` FOREVER and
195
189
  // silently wedge every world declared after this one (roots mount
196
190
  // sequentially). Convert that class of failure into a loud mount error.
197
191
  const state = await new Promise((resolve, reject) => {
198
- const onError = (event) => {
192
+ const fail = (message) => {
199
193
  cleanup();
200
194
  root.unmount();
201
195
  gameDebugRegistry?.strip(id);
202
- reject(new Error(`three world "${id}": fiber crashed before its first commit — ${event.message} ` +
203
- '(mount() fails loudly instead of hanging on onCreated)'));
196
+ reject(new Error(`three world "${id}": fiber crashed before its first commit — ${message}`));
197
+ };
198
+ const onError = (event) => {
199
+ fail(event.message);
204
200
  };
205
201
  const timer = setTimeout(() => {
206
202
  cleanup();
@@ -211,9 +207,12 @@ function threeWorldAdapter(id, component) {
211
207
  }, 10_000);
212
208
  const cleanup = () => {
213
209
  clearTimeout(timer);
214
- window.removeEventListener('error', onError);
210
+ if (typeof window !== 'undefined')
211
+ window.removeEventListener('error', onError);
215
212
  };
216
- window.addEventListener('error', onError);
213
+ if (typeof window !== 'undefined')
214
+ window.addEventListener('error', onError);
215
+ root.render(createElement(MountErrorBoundary, { onError: (error) => fail(error.message) }, provided));
217
216
  void Promise.all([statePromise, effectsReady]).then(([s]) => {
218
217
  cleanup();
219
218
  resolve(s);
@@ -247,10 +246,9 @@ function threeWorldAdapter(id, component) {
247
246
  // to write. Gate: `devBuildEnabled()` (the ONE owner of "is this a dev
248
247
  // context" — a ship build registers nothing and pays nothing) and a
249
248
  // `Game` shell (the readings are folded out of that game's profiler
250
- // frames). "Not headless" needs no term here: a headless mount returned
251
- // above, before fiber was ever configured.
249
+ // frames). A headless host cannot supply GPU readings.
252
250
  let renderVitals = null;
253
- if (host.game && devBuildEnabled()) {
251
+ if (!host.headless && host.game && devBuildEnabled()) {
254
252
  // The readings are folded out of profiler frames, and the profiler is
255
253
  // a flag the editor already sets on play — under the dev gate this is
256
254
  // the same cost arriving a little earlier, not a new one.
@@ -267,10 +265,10 @@ function threeWorldAdapter(id, component) {
267
265
  });
268
266
  }
269
267
  // Engine-owned render introspection, built over the SAME renderer and
270
- // scene Fiber uses. A design-time stand-in has no context and a
271
- // headless mount returned above, so both honestly omit the capability.
268
+ // scene Fiber uses. A design-time stand-in has no context; a headless
269
+ // mount also honestly omits the GPU capture capability.
272
270
  const rendererContext = typeof host.renderer.getContext === 'function' ? host.renderer.getContext() : undefined;
273
- const frameCaptureContext = frameCaptureContextFor(false, rendererContext);
271
+ const frameCaptureContext = frameCaptureContextFor(host.headless ?? false, rendererContext);
274
272
  const frameCapture = frameCaptureContext
275
273
  ? createWebGLFrameCapture(frameCaptureContext)
276
274
  : null;
@@ -1 +1 @@
1
- {"version":3,"file":"rapier-physics-bridge.d.ts","sourceRoot":"","sources":["../../src/world3d-react/rapier-physics-bridge.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8DG;AAUH,OAAO,KAAK,EACV,cAAc,EAKf,MAAM,2BAA2B,CAAC;AAGnC,MAAM,WAAW,wBAAwB;IACvC;;;;;OAKG;IACH,QAAQ,CAAC,aAAa,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;CAClD;AAkCD;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,EAAE,aAAa,EAAE,EAAE,wBAAwB,GAAG,IAAI,CA0QrF;AAkED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,IAAI,cAAc,CAEpD"}
1
+ {"version":3,"file":"rapier-physics-bridge.d.ts","sourceRoot":"","sources":["../../src/world3d-react/rapier-physics-bridge.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8DG;AAUH,OAAO,KAAK,EACV,cAAc,EAKf,MAAM,2BAA2B,CAAC;AAGnC,MAAM,WAAW,wBAAwB;IACvC;;;;;OAKG;IACH,QAAQ,CAAC,aAAa,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;CAClD;AAkCD;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,EAAE,aAAa,EAAE,EAAE,wBAAwB,GAAG,IAAI,CA0QrF;AAgFD;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,IAAI,cAAc,CAEpD"}
@@ -355,16 +355,31 @@ let liveBridgeCount = 0;
355
355
  * silent degrade): a second concurrent bridge mount — a scene that mounted
356
356
  * two, or a second Play instance of a rapier world — is reported the moment
357
357
  * it happens, naming what breaks and until when. */
358
+ /** A contention that resolves within this window is a hand-over, not a state:
359
+ * the editor's design session mounts the NEXT world before it disposes the
360
+ * one on screen (the swap waits for the hand), so every source edit put two
361
+ * bridges on the page for a fraction of a second and printed this warning —
362
+ * which every tester read as instability ("wrap your physics system…",
363
+ * runhuman pass 139). Only a contention that OUTLIVES the hand-over is one. */
364
+ const CONTENTION_GRACE_MS = 2_000;
365
+ let contentionTimer = null;
358
366
  function warnOnContendedMount() {
359
367
  liveBridgeCount += 1;
360
368
  if (liveBridgeCount <= 1)
361
369
  return;
362
- // biome-ignore lint/suspicious/noConsole: the standing-warning channel for a capability the adapter cannot reach — the editor console surfaces it during play
363
- console.warn(`[rapierPhysicsSystem] ${liveBridgeCount} <RapierPhysicsBridge> mounts are live on this ` +
364
- 'page, but the declared physics slot is one per page (engine modules are shared across ' +
365
- "Play instances). Every instance's `systems.physics` now forwards to the LAST bridge " +
366
- 'mounted, so physics gizmo edits and instruments address that world — not necessarily ' +
367
- 'the one selected — until the extra mounts unmount.');
370
+ if (contentionTimer !== null)
371
+ return;
372
+ contentionTimer = setTimeout(() => {
373
+ contentionTimer = null;
374
+ if (liveBridgeCount <= 1)
375
+ return;
376
+ // biome-ignore lint/suspicious/noConsole: the standing-warning channel for a capability the adapter cannot reach — the editor console surfaces it during play
377
+ console.warn(`[rapierPhysicsSystem] ${liveBridgeCount} <RapierPhysicsBridge> mounts are live on this ` +
378
+ 'page, but the declared physics slot is one per page (engine modules are shared across ' +
379
+ "Play instances). Every instance's `systems.physics` now forwards to the LAST bridge " +
380
+ 'mounted, so physics gizmo edits and instruments address that world — not necessarily ' +
381
+ 'the one selected — until the extra mounts unmount.');
382
+ }, CONTENTION_GRACE_MS);
368
383
  }
369
384
  const physicsSlot = createSystemSlot({
370
385
  name: 'rapierPhysicsSystem',
@@ -380,7 +380,7 @@ async function collectDataCheckProblems(options) {
380
380
  }
381
381
  function isToolModuleId(id) {
382
382
  const normalized = id.split("\\").join("/");
383
- return /\/src\/tools\//.test(normalized) || /\.tool\.[tj]sx?(\?|$)/.test(normalized);
383
+ return /\/src\/(?:tools|contributions)\//.test(normalized) || /\.tool\.[tj]sx?(\?|$)/.test(normalized);
384
384
  }
385
385
  function vgaiDataCheck(options) {
386
386
  return {