@volter/editor-game 0.5.65

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 (302) hide show
  1. package/LICENSE +661 -0
  2. package/NOTICE +23 -0
  3. package/contributions/asset-budget-asset.menu.ts +26 -0
  4. package/contributions/asset-budget.action.ts +18 -0
  5. package/contributions/asset-budget.document.tsx +21 -0
  6. package/contributions/asset-budget.menu.ts +22 -0
  7. package/contributions/audio-unlock.service.ts +17 -0
  8. package/contributions/audio.utility.tsx +15 -0
  9. package/contributions/autoplay.service.ts +48 -0
  10. package/contributions/bridge.command.ts +172 -0
  11. package/contributions/build-profiles.document.tsx +21 -0
  12. package/contributions/build-progress.status.tsx +45 -0
  13. package/contributions/build.action.ts +26 -0
  14. package/contributions/build.command.ts +27 -0
  15. package/contributions/build.header.tsx +37 -0
  16. package/contributions/build.menu.ts +31 -0
  17. package/contributions/build.service.ts +31 -0
  18. package/contributions/connection.status.tsx +43 -0
  19. package/contributions/coverage.service.ts +118 -0
  20. package/contributions/edit-mode-audio.service.ts +23 -0
  21. package/contributions/edit-mode-networking.service.ts +30 -0
  22. package/contributions/game-document.service.ts +25 -0
  23. package/contributions/game-eval.command.ts +210 -0
  24. package/contributions/game.layout.ts +19 -0
  25. package/contributions/gameplay.command.ts +255 -0
  26. package/contributions/generation.service.ts +96 -0
  27. package/contributions/generations.status.tsx +53 -0
  28. package/contributions/ingest.service.ts +80 -0
  29. package/contributions/instances.command.ts +75 -0
  30. package/contributions/navmesh.menu.ts +39 -0
  31. package/contributions/navmesh.service.ts +19 -0
  32. package/contributions/network.utility.tsx +17 -0
  33. package/contributions/play.command.ts +355 -0
  34. package/contributions/profiler.action.ts +16 -0
  35. package/contributions/profiler.menu.ts +22 -0
  36. package/contributions/profiler.utility.tsx +17 -0
  37. package/contributions/react/component-board.service.ts +21 -0
  38. package/contributions/react/design-time-mount.service.ts +60 -0
  39. package/contributions/react/pasteboard.action.ts +41 -0
  40. package/contributions/react/react-inspector.service.ts +85 -0
  41. package/contributions/react/story-documents.service.ts +44 -0
  42. package/contributions/scene-document.service.ts +32 -0
  43. package/contributions/state-watch.action.ts +17 -0
  44. package/contributions/state-watch.menu.ts +23 -0
  45. package/contributions/state-watch.utility.tsx +20 -0
  46. package/contributions/team-playtest.service.ts +124 -0
  47. package/contributions/three/camera-runtime.inspector.tsx +34 -0
  48. package/contributions/three/component-board.service.ts +24 -0
  49. package/contributions/three/component-verbs.command.ts +110 -0
  50. package/contributions/three/component-verbs.service.ts +92 -0
  51. package/contributions/three/constraints.inspector.tsx +34 -0
  52. package/contributions/three/model-asset-sections.service.ts +26 -0
  53. package/contributions/three/reflection-probe-capture.inspector.tsx +32 -0
  54. package/contributions/three/story-documents.service.ts +31 -0
  55. package/contributions/three/three-authoring.service.ts +66 -0
  56. package/contributions/transport.header.tsx +19 -0
  57. package/contributions/xstate-behavior.action.ts +42 -0
  58. package/contributions/xstate-behavior.document.tsx +73 -0
  59. package/contributions/xstate-behavior.inspector.tsx +28 -0
  60. package/contributions/xstate-behavior.menu.ts +23 -0
  61. package/package.json +144 -0
  62. package/src/asset-budget/AssetBudgetPanel.tsx +1172 -0
  63. package/src/asset-budget/asset-budget-model.ts +799 -0
  64. package/src/asset-budget/basis-encoder.ts +165 -0
  65. package/src/asset-budget/gltf-io.ts +154 -0
  66. package/src/asset-budget/gltf-optimize.ts +384 -0
  67. package/src/asset-budget/image-dims.ts +78 -0
  68. package/src/asset-budget/optimize-apply.ts +221 -0
  69. package/src/audio/AudioDebuggerPanel.tsx +457 -0
  70. package/src/audio/audio-debugger-model.ts +87 -0
  71. package/src/bridge/call.ts +60 -0
  72. package/src/bridge/dispatch.ts +459 -0
  73. package/src/bridge/live-frames.ts +25 -0
  74. package/src/bridge/screenshot.ts +316 -0
  75. package/src/build/BuildProfilesPanel.tsx +476 -0
  76. package/src/build/build-session.ts +247 -0
  77. package/src/build/format-bytes.ts +14 -0
  78. package/src/command-results.ts +36 -0
  79. package/src/coverage/live-authoring-surface.ts +30 -0
  80. package/src/coverage/live-project-verbs.ts +162 -0
  81. package/src/coverage/native-system-coverage.ts +143 -0
  82. package/src/coverage/root-coverage.ts +79 -0
  83. package/src/coverage/session-coverage.ts +193 -0
  84. package/src/design-system-stories/ApplicationChrome.stories.tsx +100 -0
  85. package/src/design-system-stories/InspectorNarrowBodies.stories.tsx +406 -0
  86. package/src/edit-mode/edit-mode-audio.ts +56 -0
  87. package/src/edit-mode/edit-mode-networking.ts +112 -0
  88. package/src/game-document/DevicePresetPicker.tsx +84 -0
  89. package/src/game-document/GameCaptureFrameButton.tsx +45 -0
  90. package/src/game-document/GameDocument.tsx +215 -0
  91. package/src/game-document/GamePanel.tsx +662 -0
  92. package/src/game-document/InstanceInspectorPicker.tsx +183 -0
  93. package/src/game-document/crowd-debug.ts +183 -0
  94. package/src/game-document/device-preview.ts +336 -0
  95. package/src/game-document/game-view-store.ts +107 -0
  96. package/src/game-document/physics-debug.ts +187 -0
  97. package/src/generation/GenerationActivity.tsx +421 -0
  98. package/src/generation/GenerationGallery.css +231 -0
  99. package/src/generation/generation-documents.tsx +338 -0
  100. package/src/generation/generation-jobs.ts +128 -0
  101. package/src/generation/generation-presentation.ts +257 -0
  102. package/src/host/adapter-reach.ts +445 -0
  103. package/src/host/adapter-runtime-bindings.ts +303 -0
  104. package/src/host/after-paint.ts +112 -0
  105. package/src/host/api/configurations.ts +66 -0
  106. package/src/host/authoring/babylon-authoring-adapter.ts +703 -0
  107. package/src/host/authoring/canvas-runtime-recognition.ts +50 -0
  108. package/src/host/authoring/contract-hierarchy-authoring.ts +144 -0
  109. package/src/host/authoring/contract-scenes-stories.ts +204 -0
  110. package/src/host/authoring/creation-site-related.ts +55 -0
  111. package/src/host/authoring/ephemeral-persistence.ts +29 -0
  112. package/src/host/authoring/gesture-persist.ts +84 -0
  113. package/src/host/authoring/ingest-data-writer.ts +232 -0
  114. package/src/host/authoring/ingest-source-persistence.ts +826 -0
  115. package/src/host/authoring/mount-isolated-pixi-screen.ts +250 -0
  116. package/src/host/authoring/mounted-authoring.ts +41 -0
  117. package/src/host/authoring/owned-pixi-ticker-listeners.ts +96 -0
  118. package/src/host/authoring/phaser-live-authoring-adapter.ts +265 -0
  119. package/src/host/authoring/pixi-authoring-adapter.ts +1554 -0
  120. package/src/host/authoring/pixi-creation-site-write-target.ts +60 -0
  121. package/src/host/authoring/pixi-isolation-assets.ts +25 -0
  122. package/src/host/authoring/pixi-live-write-target.ts +979 -0
  123. package/src/host/authoring/pixi-source-identity.ts +141 -0
  124. package/src/host/authoring/pixi-still-presentation.ts +71 -0
  125. package/src/host/authoring/pixi-structure-history.ts +237 -0
  126. package/src/host/authoring/pixi-transform-channels.ts +205 -0
  127. package/src/host/authoring/selection-remount-handoff.ts +23 -0
  128. package/src/host/authoring/source-persistence-backend.ts +373 -0
  129. package/src/host/authoring/source-refresh-revisions.ts +81 -0
  130. package/src/host/authoring/struct-write-pipe.ts +143 -0
  131. package/src/host/auto-frame-window.ts +89 -0
  132. package/src/host/binding-resolver.ts +393 -0
  133. package/src/host/browser-transpile.ts +631 -0
  134. package/src/host/canvas-entry-runtime.ts +95 -0
  135. package/src/host/components/CameraAuthoringOverlay.tsx +216 -0
  136. package/src/host/components/HeaderTelemetry.tsx +341 -0
  137. package/src/host/components/PixiIsolationSceneContent.tsx +280 -0
  138. package/src/host/components/ResolutionPicker.tsx +89 -0
  139. package/src/host/components/ThreeIsolationSceneContent.tsx +180 -0
  140. package/src/host/components/frame-debugger-model.ts +579 -0
  141. package/src/host/components/header-telemetry-model.ts +74 -0
  142. package/src/host/components/scene-document.tsx +447 -0
  143. package/src/host/components/utility-view-state.ts +87 -0
  144. package/src/host/components/world-root-stage-binding.tsx +133 -0
  145. package/src/host/components/world-root-stage.ts +1046 -0
  146. package/src/host/coverage/authoring-read-probe.ts +583 -0
  147. package/src/host/coverage/capability-coverage.ts +1587 -0
  148. package/src/host/coverage/coverage-accounting.ts +261 -0
  149. package/src/host/coverage/game-contract-seam-evidence.ts +82 -0
  150. package/src/host/coverage/project-verb-coverage.ts +148 -0
  151. package/src/host/coverage/system-adapter-coverage.ts +373 -0
  152. package/src/host/design-system-stories/StoryLayout.tsx +104 -0
  153. package/src/host/design-system-stories/fixtures/authoring.ts +247 -0
  154. package/src/host/design-system-stories/fixtures/editor-runtime.tsx +115 -0
  155. package/src/host/document-preview-three.ts +110 -0
  156. package/src/host/entry-adjudication.ts +89 -0
  157. package/src/host/game-location-guard.ts +150 -0
  158. package/src/host/game-module-access.ts +196 -0
  159. package/src/host/game-realm-page.ts +358 -0
  160. package/src/host/game-realm-reclaim.ts +55 -0
  161. package/src/host/game-realm-storage.ts +104 -0
  162. package/src/host/gameplay-export.ts +288 -0
  163. package/src/host/gameplay-recording.ts +717 -0
  164. package/src/host/gated-globals.ts +1511 -0
  165. package/src/host/history/json-history-resource.ts +254 -0
  166. package/src/host/ingest/registry.ts +261 -0
  167. package/src/host/instance-extract-actions.ts +120 -0
  168. package/src/host/instance-fork-actions.ts +120 -0
  169. package/src/host/play-control-hook.ts +26 -0
  170. package/src/host/playwright-shim.ts +479 -0
  171. package/src/host/projection/dom.ts +295 -0
  172. package/src/host/projection/pixi.ts +288 -0
  173. package/src/host/r3f-entry-runtime.ts +77 -0
  174. package/src/host/react-mount-runtime.ts +162 -0
  175. package/src/host/realm-services.ts +148 -0
  176. package/src/host/recording-preview.ts +106 -0
  177. package/src/host/roots/module-root.ts +203 -0
  178. package/src/host/roots/react-root.ts +181 -0
  179. package/src/host/same-realm-loop-gate.ts +544 -0
  180. package/src/host/scene-view-drawability.ts +69 -0
  181. package/src/host/sdk/tools.ts +31 -0
  182. package/src/host/served-bundle-runtime-modules.ts +331 -0
  183. package/src/host/server-log-bridge.ts +60 -0
  184. package/src/host/staged-projects.ts +24 -0
  185. package/src/host/stories/mounted-story-viewport-source.ts +64 -0
  186. package/src/host/stories/story-arg-descriptors.ts +50 -0
  187. package/src/host/stories/story-media-presence.ts +152 -0
  188. package/src/host/surface-content.ts +87 -0
  189. package/src/host/take-named-export.ts +23 -0
  190. package/src/host/three-ingest-runtime.ts +76 -0
  191. package/src/host/types-fastnoise-lite.d.ts +7 -0
  192. package/src/host/types-mikktspace.d.ts +20 -0
  193. package/src/host/types-troika-three-text.d.ts +7 -0
  194. package/src/host/use-active-performance-source.ts +53 -0
  195. package/src/host/viewport-pose-memory.ts +48 -0
  196. package/src/host/viewport-root-presentation.ts +40 -0
  197. package/src/ingest/active-ingest.ts +251 -0
  198. package/src/ingest/active-scene-navigation.ts +43 -0
  199. package/src/ingest/authoring/ingest-dom-surface-authoring.ts +191 -0
  200. package/src/ingest/authoring/ingest-root-adapter.ts +897 -0
  201. package/src/ingest/capture-wait-report.ts +122 -0
  202. package/src/ingest/deferred-ingest-play.ts +216 -0
  203. package/src/ingest/deferred-ingest-session.ts +23 -0
  204. package/src/ingest/discovery-public-ingest.ts +242 -0
  205. package/src/ingest/dom-stub-mark.ts +7 -0
  206. package/src/ingest/entry-load.ts +56 -0
  207. package/src/ingest/game-contract-realm.ts +34 -0
  208. package/src/ingest/game-pointer-lock.ts +89 -0
  209. package/src/ingest/held-scene-repaint.ts +73 -0
  210. package/src/ingest/host-surface-box.ts +174 -0
  211. package/src/ingest/ingest-boot-viewport.ts +54 -0
  212. package/src/ingest/ingest-canvas-scene-document.tsx +177 -0
  213. package/src/ingest/ingest-canvas-scene.ts +50 -0
  214. package/src/ingest/ingest-evidence-hook.ts +131 -0
  215. package/src/ingest/ingest-frame-snapshot.ts +183 -0
  216. package/src/ingest/ingest-play-commands.ts +134 -0
  217. package/src/ingest/ingest-play-control.ts +299 -0
  218. package/src/ingest/ingest-render-debug.ts +320 -0
  219. package/src/ingest/ingest-siblings.ts +487 -0
  220. package/src/ingest/ingest-status.ts +62 -0
  221. package/src/ingest/live-ingest-facet.ts +46 -0
  222. package/src/ingest/module-mode.ts +229 -0
  223. package/src/ingest/mount-canvas-ingest-root.ts +899 -0
  224. package/src/ingest/mount-coverage.ts +296 -0
  225. package/src/ingest/mount-dom-ingest-root.ts +282 -0
  226. package/src/ingest/mount-ingest-root.ts +744 -0
  227. package/src/ingest/mount-three-ingest-root.ts +366 -0
  228. package/src/ingest/resolve-canvas.ts +47 -0
  229. package/src/ingest/resolve-three.ts +123 -0
  230. package/src/ingest/served-bundle.ts +109 -0
  231. package/src/ingest/served-html-boot.ts +292 -0
  232. package/src/ingest/surface-canvas.ts +84 -0
  233. package/src/ingest/surface-dom.ts +84 -0
  234. package/src/ingest/surface-three.ts +128 -0
  235. package/src/ingest/types.ts +76 -0
  236. package/src/ingest/unmount-ingest-root.ts +224 -0
  237. package/src/navmesh/navmesh-actions.ts +27 -0
  238. package/src/navmesh/navmesh-handler.ts +237 -0
  239. package/src/navmesh/navmesh-workflow-store.ts +78 -0
  240. package/src/network/NetworkInspectorPanel.tsx +644 -0
  241. package/src/network/network-inspector-model.ts +225 -0
  242. package/src/play/play-boot-stall.ts +118 -0
  243. package/src/play/play-log-events.ts +26 -0
  244. package/src/play/play-mode.ts +2553 -0
  245. package/src/play/play-recording.ts +335 -0
  246. package/src/play/react-play-live-authoring.ts +165 -0
  247. package/src/play-bar/PlayBar.tsx +488 -0
  248. package/src/play-bar/PlayerCountPicker.tsx +100 -0
  249. package/src/profiler/FrameDebuggerPanel.tsx +458 -0
  250. package/src/profiler/PerformancePanel.tsx +1068 -0
  251. package/src/profiler/ProfilerPanel.tsx +53 -0
  252. package/src/profiler/frame-debugger-store.ts +97 -0
  253. package/src/profiler/main-thread-busy.ts +90 -0
  254. package/src/react/design-time-react-mount.ts +782 -0
  255. package/src/react/dom-authoring-adapter.ts +764 -0
  256. package/src/react/pasteboard-materialize.ts +154 -0
  257. package/src/react/react-inspector-section.tsx +2496 -0
  258. package/src/react/react-world-authoring-adapter.ts +3795 -0
  259. package/src/react/story-documents/story-args-section.ts +19 -0
  260. package/src/react/story-documents/story-documents.tsx +1380 -0
  261. package/src/react/story-paint-bounds.ts +94 -0
  262. package/src/react/ui-board-document.tsx +101 -0
  263. package/src/react/ui-board-title.ts +9 -0
  264. package/src/react/ui-component-board.ts +72 -0
  265. package/src/services/audio-pose-guard.ts +81 -0
  266. package/src/services/game-audio-unlock.ts +48 -0
  267. package/src/state-watch/StateWatchPanel.tsx +535 -0
  268. package/src/three/authoring/camera-runtime-inspector-section.tsx +135 -0
  269. package/src/three/authoring/constraint-inspector-section.tsx +189 -0
  270. package/src/three/authoring/design-time-renderer.ts +189 -0
  271. package/src/three/authoring/model-asset-inspector-section.css +41 -0
  272. package/src/three/authoring/model-asset-inspector-section.tsx +869 -0
  273. package/src/three/authoring/oid-source-persistence.ts +557 -0
  274. package/src/three/authoring/r3f-design-session.ts +1174 -0
  275. package/src/three/authoring/r3f-source-authoring-adapter.ts +5949 -0
  276. package/src/three/authoring/reflection-probe-inspector-section.tsx +76 -0
  277. package/src/three/authoring/spatial-audio-handles.ts +215 -0
  278. package/src/three/authoring/spatial-collider-handles.ts +229 -0
  279. package/src/three/authoring/spatial-joint-handles.ts +114 -0
  280. package/src/three/authoring/spatial-light-handles.ts +178 -0
  281. package/src/three/authoring/spatial-lod-handles.ts +93 -0
  282. package/src/three/authoring/spatial-particle-handles.ts +368 -0
  283. package/src/three/authoring/three-authoring-adapter.ts +1953 -0
  284. package/src/three/authoring/three-scene-identity.ts +19 -0
  285. package/src/three/authoring/three-spatial-handles.ts +161 -0
  286. package/src/three/authoring/typed-three-inspector.ts +528 -0
  287. package/src/three/component-verbs/extract-menu.ts +71 -0
  288. package/src/three/component-verbs/fork-menu.ts +78 -0
  289. package/src/three/component-verbs/internals-menu.ts +91 -0
  290. package/src/three/story-documents/three-story-documents.tsx +607 -0
  291. package/src/three/three-board/ThreeBoardDocument.tsx +888 -0
  292. package/src/three/three-board/board-framing.ts +412 -0
  293. package/src/three/three-board/board-layout.ts +401 -0
  294. package/src/three/three-board/board-scene.ts +901 -0
  295. package/src/three/three-board/three-component-board.ts +62 -0
  296. package/src/xstate/XStateBehaviorSection.tsx +130 -0
  297. package/src/xstate/XStateMachineInspector.tsx +566 -0
  298. package/src/xstate/character-animation-machine.fixture.ts +74 -0
  299. package/src/xstate/live-behaviors.ts +106 -0
  300. package/src/xstate/use-live-actor-state.ts +44 -0
  301. package/src/xstate/xstate-graph.ts +235 -0
  302. package/src/xstate/xstate-layout.ts +76 -0
@@ -0,0 +1,445 @@
1
+ /**
2
+ * WHAT THE EDITOR ACTUALLY REACHES on a mounted world, measured off the
3
+ * `AuthoringAdapter` the mount returned — and the WORDS for every capability it
4
+ * did not reach.
5
+ *
6
+ * There is ONE end state for any world the editor opens: editor capability
7
+ * identical to a native root. Anything short of that is a gap, and a gap is a
8
+ * standing warning that keeps firing until the capability works — never a
9
+ * grade, a rung, or a name for a place it is acceptable to stop. Nothing here
10
+ * consults the manifest, the mount route, or the game's id: a game this module
11
+ * has never heard of gets the same answer as one it has.
12
+ *
13
+ * ## The vocabulary is GENERATED, never written
14
+ *
15
+ * The row vocabulary used to be four hand-picked names (`capture`,
16
+ * `transforms`, `inspector`, `persistence`), which is exactly how "all warnings
17
+ * closed" went quiet while `stories`, `assetDrop`, `related`, `structure`,
18
+ * `text` and a dozen more were missing on every mounted root and warned about
19
+ * nowhere. The set is now `AUTHORING_PROVIDER_KEYS`
20
+ * (`@volter/editor-project/adapter/authoring`), which the compiler pins to the
21
+ * `AuthoringAdapter` interface itself — so a capability nobody remembered to
22
+ * enumerate still warns, and adding a provider to the contract without giving
23
+ * it words here does not compile.
24
+ *
25
+ * `capture` survives as its own fact, not a provider: it is the answer to "did
26
+ * the editor reach this game's runtime AT ALL", and it is the thing every
27
+ * provider stands on.
28
+ *
29
+ * ## N-A is a per-surface answer, and it is also a table the compiler pins
30
+ *
31
+ * A DOM root has no 3D `transforms` provider and never will; a three root has
32
+ * no CSS box model. Reporting those as gaps would be noise that teaches readers
33
+ * to ignore the report. {@link SURFACE_NOT_APPLICABLE} states the exceptions per
34
+ * surface kind, with the REASON, and the map is a `Record` over `AdapterSurface`
35
+ * so a fourth surface kind cannot be added without answering the question.
36
+ * Everything not listed is a gap — under-claiming N-A costs a standing row,
37
+ * over-claiming it hides a real one, so the table stays deliberately small.
38
+ *
39
+ * Pure computation + message formatting. Deliberately NO import of
40
+ * `./editor-console`: that module touches `window` unconditionally at its top
41
+ * level, and this module's callers (`binding-resolver.ts`) are imported by
42
+ * headless Node/vitest suites with no `window` stub. Callers that already own
43
+ * an `editorConsole` import do the actual logging.
44
+ */
45
+
46
+ import type {
47
+ AuthoringAdapter,
48
+ AuthoringProviderKey,
49
+ MountedThreeRoot,
50
+ SeamEvidenceVerdict,
51
+ } from '@volter/editor-project/adapter';
52
+ import { AUTHORING_PROVIDER_KEYS, measureAuthoringProviders } from '@volter/editor-project/adapter';
53
+ import type { AdapterSurface } from '@volter/editor-project/adapter/adapter-surface';
54
+ import { probeAuthoringReads } from './coverage/authoring-read-probe';
55
+ import {
56
+ authoringAdapterEpoch,
57
+ inspectAuthoringAdapterSeams,
58
+ } from '@volter/editor-core/coverage/authoring-seam-evidence';
59
+
60
+ /** Re-exported so consumers of a coverage row need one import, not two. */
61
+ export type { AuthoringProviderKey };
62
+ export { AUTHORING_PROVIDER_KEYS };
63
+
64
+ /**
65
+ * What this mount reached. `captured` is the runtime-reach fact; `providers` is
66
+ * the measured presence of every member of the authoring contract.
67
+ *
68
+ * Every field is a measurement of the live `AuthoringAdapter`, never a
69
+ * declaration — `capabilities` is not consulted, because a flag and a provider
70
+ * can disagree and only one of them is what the editor's panels will call.
71
+ */
72
+ export interface AdapterReach {
73
+ readonly captured: boolean;
74
+ readonly providers: Readonly<Record<AuthoringProviderKey, boolean>>;
75
+ /** Current-epoch proof, separate from provider presence. Older injected
76
+ * fixtures may omit it; omission is unverified, never an implicit pass. */
77
+ readonly providerEvidence?:
78
+ | Readonly<Record<AuthoringProviderKey, SeamEvidenceVerdict>>
79
+ | undefined;
80
+ /** The hierarchy operation is the minimum evidence that capture reached the
81
+ * adapter's projected runtime rather than merely obtaining an object. */
82
+ readonly captureEvidence?: SeamEvidenceVerdict | undefined;
83
+ }
84
+
85
+ /** What the editor cannot do while something is missing, and the named
86
+ * mechanism that would close it. */
87
+ export interface CapabilityGap {
88
+ readonly missing: string;
89
+ readonly fix: string;
90
+ }
91
+
92
+ /**
93
+ * The capture fact's words. Separate from the provider table because it is a
94
+ * different KIND of statement: not "this adapter omits a provider" but "no
95
+ * adapter exists, because the editor never reached the game".
96
+ */
97
+ export const CAPTURE_GAP: CapabilityGap = {
98
+ missing:
99
+ 'the editor never reached this game’s scene, so hierarchy, inspector and gizmo have ' +
100
+ 'nothing to work on — not one object in it can be listed, selected, inspected or moved',
101
+ fix:
102
+ 'make the game’s own runtime instance reachable to the host: a bare, un-rewritten ' +
103
+ "`import 'three'` / `import 'pixi.js'` in the game's own source, so it resolves in the " +
104
+ 'editor’s realm to the very instance the capture trap is installed on',
105
+ };
106
+
107
+ /**
108
+ * THE OTHER capture failure, and it needed its own words.
109
+ *
110
+ * `captured` and the HIERARCHY seam are two different facts, and the report
111
+ * used to spend {@link CAPTURE_GAP}'s sentences on both. So a root the editor
112
+ * had reached — an adapter in hand, a tree in the Hierarchy panel, a gizmo
113
+ * moving things — printed *"the editor never reached this game's scene … not
114
+ * one object in it can be listed"* and told the reader to add a bare
115
+ * `import 'three'` to a game that already has one. A reader who checks reads
116
+ * it as a false alarm and stops trusting the instrument, which is the exact
117
+ * failure this module's header forbids.
118
+ *
119
+ * MEASURED 2026-09-19 on a `--template game` scaffold, standalone `vgai edit`
120
+ * (it is NOT frame-specific): `hierarchy.roots()` passed, ten `hierarchy
121
+ * .node()` calls passed, and the walk still failed — three of the default
122
+ * scene's nodes report a `parentId` their listed parent does not claim. What
123
+ * the reader needs is THAT, not a capture story.
124
+ */
125
+ export const HIERARCHY_RECIPROCITY_GAP: CapabilityGap = {
126
+ missing:
127
+ 'this root’s hierarchy does not agree with itself: the editor reached the world and can ' +
128
+ 'list it, but `hierarchy.node(id).parentId` and the parent’s own `childIds` name different ' +
129
+ 'nodes, so anything that walks UPWARD — reparent targets, paste anchors, ancestor ' +
130
+ 'selection — resolves against a tree the panel is not showing',
131
+ fix:
132
+ 'make the adapter’s `hierarchy` reciprocal: for every id in a node’s `childIds`, ' +
133
+ '`hierarchy.node(childId).parentId` must be that node’s own id. The report’s `detail` ' +
134
+ 'names which direction disagreed',
135
+ };
136
+
137
+ /**
138
+ * ONE sentence pair per provider in the contract — the SAME words wherever a
139
+ * root is short of it, because the missing thing is the provider, not the game.
140
+ *
141
+ * The `Record` type is the tripwire: a provider added to `AuthoringAdapter`
142
+ * lands here as a compile error rather than as silence in every report.
143
+ */
144
+ export const PROVIDER_GAP: Readonly<Record<AuthoringProviderKey, CapabilityGap>> = {
145
+ provenance: {
146
+ missing:
147
+ 'the shell shows no provenance badge for this root, so nothing tells the author what the ' +
148
+ 'rows they are editing are backed by or how writable it is',
149
+ fix: 'the adapter must declare `provenance` (`AuthoringAdapter.provenance`)',
150
+ },
151
+ selection: {
152
+ missing:
153
+ 'this root owns no selection, so a viewport hit cannot be resolved to the node the author ' +
154
+ 'actually means — a click lands on whatever raw id the substrate reports',
155
+ fix: 'the adapter must expose a `selection` provider (`AuthoringAdapter.selection`)',
156
+ },
157
+ transforms: {
158
+ missing: 'the gizmo cannot move, rotate or scale anything in this world',
159
+ fix: 'the adapter must expose a `transforms` provider (`AuthoringAdapter.transforms`) over the captured tree',
160
+ },
161
+ inspector: {
162
+ missing: 'the inspector shows no properties for a selected object in this world',
163
+ fix: 'the adapter must expose an `inspector` provider (`AuthoringAdapter.inspector`)',
164
+ },
165
+ assetSubject: {
166
+ missing:
167
+ 'an authored node that IS an asset (inline SVG, an embedded image) cannot be opened in the ' +
168
+ 'Asset Editor from this root — it stays an opaque row',
169
+ fix: 'the adapter must expose an `assetSubject` provider (`AuthoringAdapter.assetSubject`)',
170
+ },
171
+ related: {
172
+ missing:
173
+ 'the inspector offers no jump from a selected subject to the document that defines it ' +
174
+ '(a component to its source, an instance to its story) — navigation stops at the row',
175
+ fix: 'the adapter must expose a `related` provider (`AuthoringAdapter.related`)',
176
+ },
177
+ instances: {
178
+ missing:
179
+ 'the inspector cannot distinguish a prefab instance override from its component default, ' +
180
+ 'so authors cannot revert the instance or deliberately apply its value to the component',
181
+ fix: 'the adapter must expose an `instances` provider (`AuthoringAdapter.instances`) derived from native component source',
182
+ },
183
+ structure: {
184
+ missing:
185
+ 'nothing in this world can be created, deleted, duplicated or reparented: the creation ' +
186
+ 'palette is empty and the hierarchy’s drag-drop and context-menu structure ops do nothing',
187
+ fix: 'the adapter must expose a `structure` provider (`AuthoringAdapter.structure`)',
188
+ },
189
+ persistence: {
190
+ missing:
191
+ 'edits to this world are live-only — the mount carries no write-back route to the ' +
192
+ 'game’s own source, so nothing you change survives the session',
193
+ fix: 'the adapter must expose a `persistence` provider (`AuthoringAdapter.persistence`)',
194
+ },
195
+ pickable: {
196
+ missing:
197
+ 'this root is not pickable in the viewport: clicking its content selects nothing, so it ' +
198
+ 'can only be reached from the hierarchy list',
199
+ fix: 'the adapter must expose a `pickable` provider (`AuthoringAdapter.pickable`)',
200
+ },
201
+ rects: {
202
+ missing:
203
+ 'the editor has no screen geometry for this root’s nodes, so the selection overlay, the ' +
204
+ 'measure/snap guides and the empty-container hints cannot be drawn',
205
+ fix: 'the adapter must expose a `rects` provider (`AuthoringAdapter.rects`)',
206
+ },
207
+ boxEdit: {
208
+ missing:
209
+ 'nothing in this root can be moved or resized by dragging it — its spatial values are ' +
210
+ 'reachable only by typing numbers into the inspector',
211
+ fix: 'the adapter must expose a `boxEdit` provider (`AuthoringAdapter.boxEdit`)',
212
+ },
213
+ text: {
214
+ missing: 'text in this root cannot be edited in place — double-click does nothing',
215
+ fix: 'the adapter must expose a `text` provider (`AuthoringAdapter.text`)',
216
+ },
217
+ colorSample: {
218
+ missing:
219
+ 'the eyedropper has no fallback path on this root, so colour picking is dead wherever the ' +
220
+ 'browser has no native `EyeDropper`',
221
+ fix: 'the adapter must expose a `colorSample` provider (`AuthoringAdapter.colorSample`)',
222
+ },
223
+ stories: {
224
+ missing:
225
+ 'no component of this root can be opened against a story: its prefabs never appear on the ' +
226
+ 'component board, and a designer cannot open, apply or isolate a design-time state',
227
+ fix: 'the adapter must expose a `stories` provider (`AuthoringAdapter.stories`) reading the root’s colocated portable CSF',
228
+ },
229
+ truth: {
230
+ missing:
231
+ 'the editor cannot say where any object in this world came from, so an inspector edit has ' +
232
+ 'no source address to be written back to',
233
+ fix: 'the adapter must expose a `truth` provider (`AuthoringAdapter.truth`)',
234
+ },
235
+ spatialHandles: {
236
+ missing:
237
+ 'component-owned spatial values in this world (an audio attenuation radius, a light cone, ' +
238
+ 'a collider extent) are invisible in the viewport and cannot be dragged',
239
+ fix: 'the adapter must expose a `spatialHandles` provider (`AuthoringAdapter.spatialHandles`)',
240
+ },
241
+ assetDrop: {
242
+ missing:
243
+ 'nothing can be dropped into this world: a model, image or material dragged from the asset ' +
244
+ 'browser onto the viewport or the hierarchy is refused',
245
+ fix: 'the adapter must expose an `assetDrop` provider (`AuthoringAdapter.assetDrop`)',
246
+ },
247
+ subscribe: {
248
+ missing:
249
+ 'this root never tells the editor its tree changed, so the hierarchy and inspector show a ' +
250
+ 'stale projection until something else happens to re-render them',
251
+ fix: 'the adapter must implement `subscribe` (`AuthoringAdapter.subscribe`)',
252
+ },
253
+ };
254
+
255
+ /**
256
+ * The providers that are absent BY DESIGN for a surface kind, each with the
257
+ * reason a reader needs. A `Record` over `AdapterSurface`, so a new surface kind
258
+ * cannot skip the question.
259
+ *
260
+ * Kept deliberately small. An N-A entry is a promise that no editor capability
261
+ * is lost, and a wrong one HIDES a real gap — the exact failure this whole
262
+ * derivation exists to end. Everything not listed here reports as a gap, which
263
+ * is the cheap direction to be wrong in.
264
+ */
265
+ export const SURFACE_NOT_APPLICABLE: Readonly<
266
+ Record<AdapterSurface, Partial<Record<AuthoringProviderKey, string>>>
267
+ > = {
268
+ three: {
269
+ assetSubject:
270
+ 'the current asset-subject contract is an inline SVG embedded in a DOM source document; ' +
271
+ 'a Three scene-graph node has no such representation',
272
+ rects:
273
+ 'screen rects are the DOM visual editor’s coordinate system; a three root is manipulated ' +
274
+ 'in world space through the gizmo',
275
+ boxEdit:
276
+ 'the CSS box model has no three analogue — spatial editing here is the `transforms` ' +
277
+ 'provider plus the gizmo',
278
+ text: 'a three world has no editable element text body',
279
+ colorSample: 'the eyedropper’s CSS background-chain walk has no three analogue',
280
+ },
281
+ canvas: {
282
+ assetSubject:
283
+ 'the current asset-subject contract is an inline SVG embedded in a DOM source document; ' +
284
+ 'a canvas display node has no such representation',
285
+ // `boxEdit` is deliberately NOT excused here: `PixiAuthoringAdapter` ships
286
+ // a real one (the overlay's drag-to-move/resize bridged onto the 2D
287
+ // transforms), so on the Pixi surface the row measures `ok` — and a canvas
288
+ // adapter without one (a structural Phaser/Babylon capture) is honestly
289
+ // short of a capability the surface has, which is a gap, not an N-A.
290
+ text: 'a canvas world has no editable element text body',
291
+ colorSample: 'the eyedropper’s CSS background-chain walk has no canvas analogue',
292
+ },
293
+ dom: {
294
+ transforms:
295
+ 'a DOM root has no 3D transform; its spatial editing is the `boxEdit` provider, which is ' +
296
+ 'reported on its own row',
297
+ spatialHandles:
298
+ 'world-space component guides have no DOM analogue — a DOM root’s geometry is its box, ' +
299
+ 'reported by `rects`/`boxEdit`',
300
+ },
301
+ };
302
+
303
+ /**
304
+ * MEASURE the reach of a mounted world from the authoring surface it returned.
305
+ *
306
+ * No authoring surface at all means nothing was captured, and every provider
307
+ * that stands on the captured tree is missing with it — reported per provider
308
+ * rather than collapsed into one word, because each one is a separate thing the
309
+ * user cannot do.
310
+ */
311
+ /** Every provider absent — what an uncaptured mount reaches. Derived from the
312
+ * same vocabulary as a real measurement, never spelled out. */
313
+ const NO_PROVIDERS: Readonly<Record<AuthoringProviderKey, boolean>> = Object.freeze(
314
+ Object.fromEntries(AUTHORING_PROVIDER_KEYS.map((key) => [key, false])) as Record<
315
+ AuthoringProviderKey,
316
+ boolean
317
+ >,
318
+ );
319
+
320
+ /** A mount that reached nothing: no capture, no provider. Named because the
321
+ * no-authoring floor, the coverage stories and the tests all need to say the
322
+ * same thing, and each spelling it out would re-create the hand list. */
323
+ export const UNCAPTURED_REACH: AdapterReach = Object.freeze({
324
+ captured: false,
325
+ providers: NO_PROVIDERS,
326
+ });
327
+
328
+ export function measureAdapterReach(
329
+ mounted: Pick<MountedThreeRoot, 'authoring'>,
330
+ subject = 'root',
331
+ ): AdapterReach {
332
+ const { authoring } = mounted;
333
+ if (!authoring) return UNCAPTURED_REACH;
334
+ return measureAdapter(authoring as AuthoringAdapter, subject);
335
+ }
336
+
337
+ /**
338
+ * The composite's PUBLIC child-walk door (`CompositeAuthoringAdapter
339
+ * .childAdapters()`, T0), duck-typed rather than `instanceof`-checked: this
340
+ * module must stay importable by headless Node suites (see the header), and
341
+ * the composite's own import graph touches `window` via `editor-console`.
342
+ * Only the composite defines this member, and only the fields this signature
343
+ * names are read.
344
+ */
345
+ interface CompositeChildWalk {
346
+ childAdapters?: () => ReadonlyArray<{ readonly adapter: AuthoringAdapter }>;
347
+ }
348
+
349
+ /** Measure an adapter directly, for callers that hold one rather than a mount. */
350
+ export function measureAdapter(adapter: AuthoringAdapter, subject = 'root'): AdapterReach {
351
+ const epoch = authoringAdapterEpoch(adapter);
352
+ const evidence = inspectAuthoringAdapterSeams({
353
+ adapter,
354
+ subject,
355
+ epoch,
356
+ receipts: probeAuthoringReads({ adapter, subject, epoch }),
357
+ });
358
+ const providers = { ...measureAuthoringProviders(adapter) };
359
+ const children = (adapter as CompositeChildWalk).childAdapters?.();
360
+ if (children) {
361
+ // A composite deliberately implements neither `pickable` nor `provenance`
362
+ // (`authoring/composite-authoring-adapter.ts`'s own notes): the shell's
363
+ // delivering doors are composite-aware — viewport picking walks
364
+ // `childAdapters()` in `authoring/layered-pick.ts`, and provenance
365
+ // resolves per node through `authoring/provenance.ts`'s governing-adapter
366
+ // hop (the hierarchy's world rows read each child's own badge). Reading
367
+ // the composite's absent fields would report a capability the editor in
368
+ // fact delivers — the exact instrument failure this module's header
369
+ // forbids — so these two rows measure the door the panels actually call:
370
+ // any child that answers it. Everything else the composite either routes
371
+ // itself (measured directly above) or genuinely lacks.
372
+ providers.pickable ||= children.some((child) => child.adapter.pickable !== undefined);
373
+ providers.provenance ||= children.some((child) => child.adapter.provenance !== undefined);
374
+ }
375
+ return {
376
+ captured: true,
377
+ providers,
378
+ providerEvidence: evidence.providers,
379
+ // The WALK, not the carrier — see `AuthoringSeamEvidence.hierarchyWalk`.
380
+ // `captureEvidence`'s documented meaning (above) is "a current-epoch
381
+ // hierarchy OPERATION proves capture reached the projected runtime", and
382
+ // the carrier grade answers a strictly stronger question that no three
383
+ // adapter can pass, so reading it here made the capture row's `ok` branch
384
+ // unreachable.
385
+ captureEvidence: evidence.hierarchyWalk,
386
+ };
387
+ }
388
+
389
+ /**
390
+ * Is this provider absent BY DESIGN on this surface? The reason, or `null` when
391
+ * its absence is a real gap. An unknown surface kind gets `null` — never a
392
+ * fabricated exemption.
393
+ */
394
+ export function notApplicableReason(
395
+ surface: AdapterSurface | null,
396
+ provider: AuthoringProviderKey,
397
+ ): string | null {
398
+ if (surface === null) return null;
399
+ return SURFACE_NOT_APPLICABLE[surface]?.[provider] ?? null;
400
+ }
401
+
402
+ /** The providers this mount has not reached and that its surface does not excuse,
403
+ * in report order. */
404
+ export function reachGaps(
405
+ reach: AdapterReach,
406
+ surface: AdapterSurface | null = null,
407
+ ): readonly AuthoringProviderKey[] {
408
+ return AUTHORING_PROVIDER_KEYS.filter(
409
+ (key) => !reach.providers[key] && notApplicableReason(surface, key) === null,
410
+ );
411
+ }
412
+
413
+ /** Greppable prefix shared by every capability warning this module produces. */
414
+ export const CAPABILITY_GAP_PREFIX = 'capability-gap';
415
+
416
+ /**
417
+ * The ONE warning shape for a world the editor cannot fully author, or `null`
418
+ * when it reaches everything its surface can have (a complete mount says
419
+ * nothing — silence is what "identical to native" sounds like).
420
+ *
421
+ * `mechanism` is the mount's own description of how it reached the game
422
+ * (the capture route, a failure reason) — diagnosis the reader needs to act on
423
+ * the fix, never a verdict.
424
+ */
425
+ export function formatCapabilityWarning(
426
+ worldId: string,
427
+ reach: AdapterReach,
428
+ mechanism: string,
429
+ surface: AdapterSurface | null = null,
430
+ ): string | null {
431
+ const lines: string[] = [];
432
+ if (!reach.captured) {
433
+ lines.push(` ✗ capture — ${CAPTURE_GAP.missing}\n fix: ${CAPTURE_GAP.fix}`);
434
+ }
435
+ for (const key of reachGaps(reach, surface)) {
436
+ lines.push(` ✗ ${key} — ${PROVIDER_GAP[key].missing}\n fix: ${PROVIDER_GAP[key].fix}`);
437
+ }
438
+ if (lines.length === 0) return null;
439
+ return [
440
+ `${CAPABILITY_GAP_PREFIX} world "${worldId}" — ${lines.length} editor capabilit${
441
+ lines.length === 1 ? 'y is' : 'ies are'
442
+ } missing (${mechanism}). This world is not authorable the way a native one is:`,
443
+ ...lines,
444
+ ].join('\n');
445
+ }