@volter/editor-core 0.5.57

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 (719) hide show
  1. package/BUNDLED_NOTICES +1527 -0
  2. package/LICENSE +686 -0
  3. package/LICENSE-APACHE +202 -0
  4. package/NOTICE +18 -0
  5. package/README.md +24 -0
  6. package/dist/build/chunk-JS4D4XZ3.js +175 -0
  7. package/dist/build/chunk-JS4D4XZ3.js.map +7 -0
  8. package/dist/build/vite-plugin-product-contributions.js +100 -0
  9. package/dist/build/vite-plugin-product-contributions.js.map +7 -0
  10. package/dist/build/vite-plugin-shared-react.js +25 -0
  11. package/dist/build/vite-plugin-shared-react.js.map +7 -0
  12. package/dist/build/vite-plugin-shared-three.js +86 -0
  13. package/dist/build/vite-plugin-shared-three.js.map +7 -0
  14. package/dist/server/chunk-KMJC7AGO.js +98 -0
  15. package/dist/server/chunk-KMJC7AGO.js.map +7 -0
  16. package/dist/server/chunk-PSILUMGS.js +46 -0
  17. package/dist/server/chunk-PSILUMGS.js.map +7 -0
  18. package/dist/server/frame-proxy.js +255 -0
  19. package/dist/server/frame-proxy.js.map +7 -0
  20. package/dist/server/open-browser.js +53 -0
  21. package/dist/server/open-browser.js.map +7 -0
  22. package/dist/server/process-shutdown.js +127 -0
  23. package/dist/server/process-shutdown.js.map +7 -0
  24. package/dist/server/session-registry.js +141 -0
  25. package/dist/server/session-registry.js.map +7 -0
  26. package/dist/server/spawn-opener.js +11 -0
  27. package/dist/server/spawn-opener.js.map +7 -0
  28. package/dist/server/worktree-identity.js +11 -0
  29. package/dist/server/worktree-identity.js.map +7 -0
  30. package/dist-server/packaged.mjs +88816 -0
  31. package/package.json +118 -0
  32. package/scripts/build-plugins.mjs +14 -0
  33. package/scripts/build-server.mjs +26 -0
  34. package/scripts/build-session.mjs +9 -0
  35. package/server/account-credentials.ts +60 -0
  36. package/server/account-service.ts +1434 -0
  37. package/server/adapter-region-includes.ts +47 -0
  38. package/server/asset-catalog-v2.ts +175 -0
  39. package/server/asset-history-snapshots.ts +196 -0
  40. package/server/asset-ledger-store.ts +195 -0
  41. package/server/asset-library-routes.ts +1595 -0
  42. package/server/blender-wasm-artifact.ts +430 -0
  43. package/server/boot-timings.ts +106 -0
  44. package/server/canonical-path.ts +50 -0
  45. package/server/checkout-workspace-preflight.ts +349 -0
  46. package/server/cloud-asset-catalog.ts +158 -0
  47. package/server/coding-inference-launch.ts +237 -0
  48. package/server/collaboration-account-client.ts +202 -0
  49. package/server/collaboration-attribution.ts +122 -0
  50. package/server/collaboration-session.ts +934 -0
  51. package/server/comfyui-bridge.ts +248 -0
  52. package/server/console-ledger.ts +499 -0
  53. package/server/creation-site-transform.ts +304 -0
  54. package/server/creation-site-write.ts +648 -0
  55. package/server/data-file-serialize.ts +158 -0
  56. package/server/editor-brand-html.ts +72 -0
  57. package/server/editor-control-socket.ts +366 -0
  58. package/server/editor-server-options.ts +190 -0
  59. package/server/editor-server.ts +1483 -0
  60. package/server/editor-sse.ts +352 -0
  61. package/server/engine-provenance.ts +169 -0
  62. package/server/engine-source-restart.ts +117 -0
  63. package/server/frame-bridge.ts +115 -0
  64. package/server/frame-proxy.ts +490 -0
  65. package/server/frame-workbench.ts +259 -0
  66. package/server/frontend-handoff.ts +229 -0
  67. package/server/game-globals-shadow.ts +113 -0
  68. package/server/gameplay-session-retention.ts +149 -0
  69. package/server/gameplay-sessions.ts +123 -0
  70. package/server/generation-jobs.ts +201 -0
  71. package/server/generation-reconciler.ts +137 -0
  72. package/server/generative-execution-context.ts +59 -0
  73. package/server/git-workflow.ts +612 -0
  74. package/server/harness-chat-caller.ts +36 -0
  75. package/server/harness-chat-service.ts +1681 -0
  76. package/server/idle-shutdown.ts +170 -0
  77. package/server/js-profiling-policy.ts +52 -0
  78. package/server/launcher-settings.ts +84 -0
  79. package/server/local-asset-catalog.ts +410 -0
  80. package/server/managed-account-defaults.ts +22 -0
  81. package/server/mock-control-plane.ts +540 -0
  82. package/server/model-import-conversion.ts +345 -0
  83. package/server/native-credential-store.ts +162 -0
  84. package/server/open-browser.ts +118 -0
  85. package/server/packaged.ts +1192 -0
  86. package/server/play-stall.ts +126 -0
  87. package/server/process-shutdown.ts +218 -0
  88. package/server/product-presets.ts +55 -0
  89. package/server/project-build-artifact.ts +95 -0
  90. package/server/project-components.ts +100 -0
  91. package/server/project-dependency-invalidation.ts +114 -0
  92. package/server/project-file-scan.ts +235 -0
  93. package/server/project-hmr-files.ts +215 -0
  94. package/server/project-install-roots.ts +210 -0
  95. package/server/project-kinds.ts +71 -0
  96. package/server/project-mcp-servers.ts +82 -0
  97. package/server/project-module-freshness.ts +109 -0
  98. package/server/project-module-instance.ts +375 -0
  99. package/server/project-optimize-deps-entries.ts +827 -0
  100. package/server/project-output-writer.ts +679 -0
  101. package/server/project-package-origin.ts +63 -0
  102. package/server/project-root-surface.ts +831 -0
  103. package/server/project-scratch-path.ts +47 -0
  104. package/server/project-script-hmr.ts +619 -0
  105. package/server/project-serving-plugins.ts +236 -0
  106. package/server/project-tools.ts +653 -0
  107. package/server/project-validation.ts +250 -0
  108. package/server/project-verbs.ts +127 -0
  109. package/server/project-view.ts +52 -0
  110. package/server/project-watch.ts +1134 -0
  111. package/server/project-work-coordinator.ts +288 -0
  112. package/server/provider-credentials.ts +331 -0
  113. package/server/recent-projects-store.ts +98 -0
  114. package/server/redact-secrets.ts +71 -0
  115. package/server/repository-presence.ts +267 -0
  116. package/server/routes/account.ts +357 -0
  117. package/server/routes/agents.ts +60 -0
  118. package/server/routes/assets.ts +154 -0
  119. package/server/routes/build.ts +13 -0
  120. package/server/routes/collaboration.ts +595 -0
  121. package/server/routes/configurations.ts +419 -0
  122. package/server/routes/context.ts +264 -0
  123. package/server/routes/control-plane.ts +1811 -0
  124. package/server/routes/logs.ts +272 -0
  125. package/server/routes/project-identity.ts +302 -0
  126. package/server/routes/project-open.ts +429 -0
  127. package/server/routes/project-source.ts +686 -0
  128. package/server/routes/project-state.ts +383 -0
  129. package/server/routes/relay.ts +1029 -0
  130. package/server/routes/route-helpers.ts +29 -0
  131. package/server/routes/served-modules.ts +138 -0
  132. package/server/routes/session-tabs.ts +196 -0
  133. package/server/routes/settings.ts +121 -0
  134. package/server/routes/share-control.ts +486 -0
  135. package/server/routes/themes.ts +116 -0
  136. package/server/routes/tools.ts +230 -0
  137. package/server/routes/worktrees.ts +595 -0
  138. package/server/scoped-game-css.ts +461 -0
  139. package/server/server-utils.ts +1194 -0
  140. package/server/session-product.ts +112 -0
  141. package/server/session-registry.ts +230 -0
  142. package/server/share-claims.ts +138 -0
  143. package/server/share-host.ts +526 -0
  144. package/server/share-session-gateway.ts +1362 -0
  145. package/server/share-tunnel.ts +123 -0
  146. package/server/spawn-opener.ts +74 -0
  147. package/server/support/play/log-format.ts +76 -0
  148. package/server/support/play/session-record.ts +199 -0
  149. package/server/support/project/build-discipline.ts +718 -0
  150. package/server/support/project/inspection-node.ts +119 -0
  151. package/server/support/project/log-naming.ts +54 -0
  152. package/server/support/project/provenance.ts +290 -0
  153. package/server/support/project/run-name.ts +18 -0
  154. package/server/support/project/session-journal.ts +830 -0
  155. package/server/support/project/shared.ts +327 -0
  156. package/server/tab-bootstrap.ts +62 -0
  157. package/server/tab-heartbeat.ts +477 -0
  158. package/server/tab-lifecycle.ts +550 -0
  159. package/server/tab-presence.ts +1508 -0
  160. package/server/team-agent-mirror.ts +95 -0
  161. package/server/twin-auth.ts +138 -0
  162. package/server/vendored-lock-recorder.ts +968 -0
  163. package/server/worktree-identity.ts +121 -0
  164. package/server/worktree-management.ts +398 -0
  165. package/server/worktree-retention.d.mts +13 -0
  166. package/server/worktree-retention.mjs +205 -0
  167. package/src/EditorContext.tsx +169 -0
  168. package/src/account.ts +333 -0
  169. package/src/action-registry.ts +532 -0
  170. package/src/active-product.ts +74 -0
  171. package/src/active-project.ts +155 -0
  172. package/src/adapter-editor-config.ts +25 -0
  173. package/src/adapter-observation.ts +49 -0
  174. package/src/animation/stage-transport.ts +379 -0
  175. package/src/animation/three-clips-subject.ts +172 -0
  176. package/src/api/asset-library-wire.ts +45 -0
  177. package/src/api/assets.ts +365 -0
  178. package/src/api/base.ts +10 -0
  179. package/src/api/build.ts +99 -0
  180. package/src/api/git-wire.ts +56 -0
  181. package/src/api/logs.ts +92 -0
  182. package/src/api/project-identity.ts +74 -0
  183. package/src/api/project-open.ts +355 -0
  184. package/src/api/project-source.ts +162 -0
  185. package/src/api/project-state.ts +107 -0
  186. package/src/api/relay.ts +268 -0
  187. package/src/api/settings.ts +36 -0
  188. package/src/api/themes.ts +45 -0
  189. package/src/api/worktrees.ts +257 -0
  190. package/src/asset-compare-core.ts +171 -0
  191. package/src/asset-compare.ts +294 -0
  192. package/src/asset-editor-context.tsx +100 -0
  193. package/src/asset-events.ts +97 -0
  194. package/src/asset-inspector-actions.ts +87 -0
  195. package/src/asset-preview-framing.ts +357 -0
  196. package/src/asset-preview.ts +2802 -0
  197. package/src/asset-selection-viewer-registry.ts +113 -0
  198. package/src/asset-selection.ts +133 -0
  199. package/src/asset-workflow/asset-capabilities.ts +344 -0
  200. package/src/asset-workflow/asset-import-jobs.ts +106 -0
  201. package/src/asset-workflow/asset-ledger-backend.ts +126 -0
  202. package/src/asset-workflow/asset-ledger.ts +156 -0
  203. package/src/asset-workflow/asset-materialization-report.ts +140 -0
  204. package/src/asset-workflow/asset-pack-manifest.ts +320 -0
  205. package/src/asset-workflow/asset-types.ts +142 -0
  206. package/src/asset-workflow/asset-workflow-quality.ts +61 -0
  207. package/src/asset-workflow/audio-preview-player.ts +193 -0
  208. package/src/asset-workflow/audio-waveform.ts +22 -0
  209. package/src/asset-workflow/cloud-asset-client.ts +263 -0
  210. package/src/asset-workflow/folder-preview.ts +345 -0
  211. package/src/asset-workflow/hosted-asset-materialization.ts +236 -0
  212. package/src/asset-workflow/image-view-scale.ts +32 -0
  213. package/src/asset-workflow/import-contract.ts +124 -0
  214. package/src/asset-workflow/ledger-write-lock.ts +244 -0
  215. package/src/asset-workflow/model-inspection.ts +818 -0
  216. package/src/asset-workflow/pixi-spritesheet.ts +197 -0
  217. package/src/asset-workflow/preview-resource-lifetime.ts +44 -0
  218. package/src/asset-workflow/project-asset-commands.ts +23 -0
  219. package/src/asset-workflow/project-asset-health.ts +139 -0
  220. package/src/asset-workflow/project-asset-operations.ts +154 -0
  221. package/src/asset-workflow/project-asset-roots.ts +68 -0
  222. package/src/asset-workflow/project-content.ts +288 -0
  223. package/src/asset-workflow/project-source-index.ts +550 -0
  224. package/src/asset-workflow/thumbnail-system.ts +256 -0
  225. package/src/authoring/active-adapter.ts +199 -0
  226. package/src/authoring/active-systems.ts +422 -0
  227. package/src/authoring/adapter-key.ts +18 -0
  228. package/src/authoring/authoring-asset-url.ts +27 -0
  229. package/src/authoring/bootstrap-state.ts +49 -0
  230. package/src/authoring/boundary-authoring-adapter.ts +184 -0
  231. package/src/authoring/breakpoint-state.ts +43 -0
  232. package/src/authoring/canvas-scene-guides.ts +76 -0
  233. package/src/authoring/component-instance-root.ts +171 -0
  234. package/src/authoring/composite-authoring-adapter.ts +2110 -0
  235. package/src/authoring/consumer-actions.ts +520 -0
  236. package/src/authoring/css-numeric-style.ts +97 -0
  237. package/src/authoring/design-time-layers.ts +849 -0
  238. package/src/authoring/design-time-mount-registry.ts +235 -0
  239. package/src/authoring/design-time-settle.ts +343 -0
  240. package/src/authoring/edit-mode-authoring.ts +619 -0
  241. package/src/authoring/eyedropper-session.ts +60 -0
  242. package/src/authoring/instance-source-menu-register.ts +13 -0
  243. package/src/authoring/instance-source-menu.ts +135 -0
  244. package/src/authoring/layered-pick.ts +183 -0
  245. package/src/authoring/live-gesture-lock.ts +50 -0
  246. package/src/authoring/live-object-transform.ts +62 -0
  247. package/src/authoring/mount-failure-report.ts +154 -0
  248. package/src/authoring/mounted-root-subjects.ts +144 -0
  249. package/src/authoring/no-authoring-adapter.ts +55 -0
  250. package/src/authoring/null-inspection-subjects.tsx +75 -0
  251. package/src/authoring/object3d-document-persistence.ts +106 -0
  252. package/src/authoring/object3d-document-session-registry.ts +120 -0
  253. package/src/authoring/object3d-document-session.ts +1326 -0
  254. package/src/authoring/object3d-gesture-controller.ts +113 -0
  255. package/src/authoring/panel-authoring.ts +121 -0
  256. package/src/authoring/prefab-instance-inspector-section.tsx +237 -0
  257. package/src/authoring/prefab-instance-section-model.ts +55 -0
  258. package/src/authoring/project-authoring-session.ts +105 -0
  259. package/src/authoring/provenance.ts +99 -0
  260. package/src/authoring/quarks-particle-systems.ts +19 -0
  261. package/src/authoring/react-canvas-navigation.ts +255 -0
  262. package/src/authoring/react-design-canvas-style.ts +20 -0
  263. package/src/authoring/react-story-board.ts +937 -0
  264. package/src/authoring/selection-scope.ts +195 -0
  265. package/src/authoring/shell-document-ops.ts +169 -0
  266. package/src/authoring/shell-object3d-document-write-policy.ts +108 -0
  267. package/src/authoring/shell-viewport-policy.ts +48 -0
  268. package/src/authoring/source-object3d-authoring-adapter.ts +526 -0
  269. package/src/authoring/stories-scope.ts +35 -0
  270. package/src/authoring/story-board-chrome-fit.ts +107 -0
  271. package/src/authoring/story-board-presentation.ts +111 -0
  272. package/src/authoring/three-projection-core.ts +226 -0
  273. package/src/authoring/viewport-pick-context.ts +40 -0
  274. package/src/authoring/viewport-raycast.ts +240 -0
  275. package/src/authoring/viewport-tool-context.ts +73 -0
  276. package/src/authoring/world-canvas-viewport-state.ts +35 -0
  277. package/src/authoring/world-hidden-viewport.ts +152 -0
  278. package/src/authoring/world-pan-state.ts +198 -0
  279. package/src/authoring/world-session-state.ts +101 -0
  280. package/src/authoring/write-pipe.ts +173 -0
  281. package/src/availability-tick.ts +66 -0
  282. package/src/bitmap-label.ts +120 -0
  283. package/src/blender-tab-metrics.ts +161 -0
  284. package/src/board-open-actions.ts +20 -0
  285. package/src/boot-routing.ts +391 -0
  286. package/src/build-identity.ts +15 -0
  287. package/src/bytes-codec.ts +62 -0
  288. package/src/camera-authoring.ts +175 -0
  289. package/src/cancellation-reason.ts +58 -0
  290. package/src/canvas-preview-frames.ts +482 -0
  291. package/src/capture-camera-pose.ts +77 -0
  292. package/src/chrome-registry.ts +159 -0
  293. package/src/chrome-slot-registry.ts +91 -0
  294. package/src/collaboration-client.ts +264 -0
  295. package/src/collaboration-presence.ts +41 -0
  296. package/src/command-dispatch.ts +19 -0
  297. package/src/command-listener.ts +2743 -0
  298. package/src/command-registry.ts +70 -0
  299. package/src/component-board-registry.ts +205 -0
  300. package/src/component-states-registry.ts +200 -0
  301. package/src/components/AgentPresentationNotice.tsx +75 -0
  302. package/src/components/AlignToolbar.tsx +204 -0
  303. package/src/components/AppRoot.tsx +394 -0
  304. package/src/components/ApplicationMenus.tsx +415 -0
  305. package/src/components/AssetBrowser.tsx +2843 -0
  306. package/src/components/AssetEditorShell.tsx +216 -0
  307. package/src/components/AssetInspectorToolSection.tsx +124 -0
  308. package/src/components/BoardRulers.tsx +354 -0
  309. package/src/components/CameraInfo.tsx +81 -0
  310. package/src/components/CanvasSceneViewport.tsx +556 -0
  311. package/src/components/CapabilityCoverageSection.tsx +185 -0
  312. package/src/components/CenterDocuments.tsx +22 -0
  313. package/src/components/ChromeSlot.tsx +20 -0
  314. package/src/components/CodeView.tsx +470 -0
  315. package/src/components/CollaborationHeaderControl.css +74 -0
  316. package/src/components/CompactInspectorCard.tsx +190 -0
  317. package/src/components/CompactInspectorShell.tsx +39 -0
  318. package/src/components/ConsolePanel.css +55 -0
  319. package/src/components/ConsolePanel.tsx +270 -0
  320. package/src/components/DefaultEditorLayout.tsx +106 -0
  321. package/src/components/DocumentHeaderStrip.tsx +96 -0
  322. package/src/components/DocumentShelfRail.tsx +45 -0
  323. package/src/components/DocumentThumbnail.tsx +345 -0
  324. package/src/components/EditorLeaseGuard.tsx +372 -0
  325. package/src/components/ErrorBanner.tsx +123 -0
  326. package/src/components/FolderPreviewTile.tsx +159 -0
  327. package/src/components/GameHierarchy.tsx +3842 -0
  328. package/src/components/GameplaySessionTimeline.tsx +295 -0
  329. package/src/components/InspectionProjection.tsx +968 -0
  330. package/src/components/Inspector.tsx +233 -0
  331. package/src/components/InspectorCanvasPreview.tsx +35 -0
  332. package/src/components/InspectorFieldsSection.tsx +290 -0
  333. package/src/components/InspectorObjectPreview.tsx +57 -0
  334. package/src/components/InspectorStoriesSection.tsx +92 -0
  335. package/src/components/InspectorToolSection.tsx +96 -0
  336. package/src/components/InspectorTransformSection.tsx +245 -0
  337. package/src/components/LightExplorerPanel.tsx +433 -0
  338. package/src/components/MediaProperties.tsx +145 -0
  339. package/src/components/NonThreeAuthoringBootstrap.tsx +19 -0
  340. package/src/components/Object3DDocumentToolbar.css +100 -0
  341. package/src/components/Object3DDocumentToolbar.tsx +454 -0
  342. package/src/components/Object3DDocumentViewport.tsx +58 -0
  343. package/src/components/ProjectHeader.css +617 -0
  344. package/src/components/ProjectHeader.tsx +328 -0
  345. package/src/components/ProjectLayout.tsx +249 -0
  346. package/src/components/ReactCanvasControls.tsx +284 -0
  347. package/src/components/RootSelectionOverlay.tsx +3162 -0
  348. package/src/components/RootTextEditor.tsx +79 -0
  349. package/src/components/SaveStatus.tsx +70 -0
  350. package/src/components/StageHost.tsx +1954 -0
  351. package/src/components/StageOverlays.tsx +21 -0
  352. package/src/components/StartupErrorScreen.tsx +76 -0
  353. package/src/components/StartupLoadingScreen.tsx +65 -0
  354. package/src/components/StatsOverlay.tsx +78 -0
  355. package/src/components/SurfaceStateOverlay.tsx +24 -0
  356. package/src/components/ToolContributionSurfaces.tsx +65 -0
  357. package/src/components/ToolHost.tsx +370 -0
  358. package/src/components/ToolObject3DPreview.tsx +39 -0
  359. package/src/components/Toolbar.tsx +595 -0
  360. package/src/components/TransientHint.tsx +44 -0
  361. package/src/components/TransportStrip.tsx +174 -0
  362. package/src/components/VersionControlSection.tsx +470 -0
  363. package/src/components/VgaiLogo.css +83 -0
  364. package/src/components/VgaiLogo.tsx +35 -0
  365. package/src/components/ViewportControlsHint.tsx +60 -0
  366. package/src/components/ViewportFurniture.tsx +401 -0
  367. package/src/components/ViewportOverlay.tsx +145 -0
  368. package/src/components/ViewportOverlaysMenu.tsx +153 -0
  369. package/src/components/ViewportShadingMenu.tsx +300 -0
  370. package/src/components/ViewportViewMenu.tsx +101 -0
  371. package/src/components/WorkspaceDocumentSurface.tsx +204 -0
  372. package/src/components/WorkspaceUtilitySurface.tsx +22 -0
  373. package/src/components/WorktreeSwitcher.css +239 -0
  374. package/src/components/WorktreeSwitcher.tsx +890 -0
  375. package/src/components/account-documents.tsx +1162 -0
  376. package/src/components/asset-documents.tsx +812 -0
  377. package/src/components/asset-editor-persistence.ts +216 -0
  378. package/src/components/asset-selection-section.tsx +535 -0
  379. package/src/components/asset-thumbnails.tsx +312 -0
  380. package/src/components/asset-viewers/AudioViewer.tsx +201 -0
  381. package/src/components/asset-viewers/EntityModelDocument.tsx +122 -0
  382. package/src/components/asset-viewers/EnvironmentAssetDocument.tsx +440 -0
  383. package/src/components/asset-viewers/GenericJsonViewer.tsx +102 -0
  384. package/src/components/asset-viewers/ImageViewer.tsx +300 -0
  385. package/src/components/asset-viewers/JsonAssetDocument.tsx +93 -0
  386. package/src/components/asset-viewers/LiveModuleDocument.tsx +417 -0
  387. package/src/components/asset-viewers/LutAssetDocument.tsx +444 -0
  388. package/src/components/asset-viewers/ModelAssetDocument.tsx +105 -0
  389. package/src/components/asset-viewers/Object3DPreview.tsx +359 -0
  390. package/src/components/asset-viewers/OnlineAssetDetail.tsx +421 -0
  391. package/src/components/asset-viewers/PasteboardModuleDocument.tsx +67 -0
  392. package/src/components/asset-viewers/QuarksAssetDocument.tsx +526 -0
  393. package/src/components/asset-viewers/ShaderAssetDocument.tsx +743 -0
  394. package/src/components/asset-viewers/SourceAssetViewer.tsx +281 -0
  395. package/src/components/asset-viewers/SpritesheetSpriteView.tsx +102 -0
  396. package/src/components/asset-viewers/VideoViewer.tsx +101 -0
  397. package/src/components/asset-viewers/shader-source.ts +144 -0
  398. package/src/components/asset-workflow.css +731 -0
  399. package/src/components/board-guides.ts +150 -0
  400. package/src/components/compact-inspector.css +539 -0
  401. package/src/components/core-utilities.tsx +90 -0
  402. package/src/components/editor-notifications.css +40 -0
  403. package/src/components/engine-workspace.css +274 -0
  404. package/src/components/inspector-preview-section.tsx +238 -0
  405. package/src/components/inspector-property-grouping.ts +64 -0
  406. package/src/components/inspector-revert-label.ts +20 -0
  407. package/src/components/inspector-selection.ts +42 -0
  408. package/src/components/inspector-stories-gating.ts +171 -0
  409. package/src/components/inspector-transform-subject.ts +11 -0
  410. package/src/components/inspector-transform.ts +75 -0
  411. package/src/components/kind-documents.tsx +500 -0
  412. package/src/components/palette-action-publisher.tsx +140 -0
  413. package/src/components/primitives/DraftColorInput.tsx +74 -0
  414. package/src/components/product-shell.css +1829 -0
  415. package/src/components/project-tool-documents.tsx +410 -0
  416. package/src/components/scene-documents.tsx +223 -0
  417. package/src/components/stage-keyboard.tsx +37 -0
  418. package/src/components/stage-overlay-set.tsx +107 -0
  419. package/src/components/stage-presence-markers.ts +478 -0
  420. package/src/components/standard-viewport-dressing.ts +417 -0
  421. package/src/components/status-contributions.tsx +403 -0
  422. package/src/components/tool-documents.tsx +309 -0
  423. package/src/components/tool-schema-form.tsx +262 -0
  424. package/src/components/use-after-paint.ts +41 -0
  425. package/src/components/use-project-image-assets.ts +86 -0
  426. package/src/components/viewport-header-controls.css +90 -0
  427. package/src/components/viewport-surface-status.tsx +55 -0
  428. package/src/components/workspace-history.ts +32 -0
  429. package/src/components/workspace-static-panel-registry.tsx +152 -0
  430. package/src/components/workspace-surfaces.css +621 -0
  431. package/src/components/world-documents.tsx +586 -0
  432. package/src/components/world-overlay-gestures.ts +1694 -0
  433. package/src/composite-screenshot.ts +1641 -0
  434. package/src/console-sync.ts +131 -0
  435. package/src/constraint-helper.ts +338 -0
  436. package/src/content-entry-source-registry.ts +184 -0
  437. package/src/coverage/authoring-seam-evidence.ts +300 -0
  438. package/src/coverage/canvas-reveal.ts +192 -0
  439. package/src/coverage/design-time-surfaces.ts +101 -0
  440. package/src/coverage/live-seam-evidence.ts +11 -0
  441. package/src/coverage/ontology-invariants.ts +466 -0
  442. package/src/coverage/session-vitals.ts +501 -0
  443. package/src/coverage/system-seam-evidence.ts +72 -0
  444. package/src/crash-null-boundary.ts +36 -0
  445. package/src/creation-site-edit.ts +1479 -0
  446. package/src/creation-site-registry.ts +160 -0
  447. package/src/delegate-harness-registry.ts +143 -0
  448. package/src/document-context-registry.ts +177 -0
  449. package/src/document-open-registry.ts +200 -0
  450. package/src/document-preview-source.ts +20 -0
  451. package/src/document-renderer-session.ts +138 -0
  452. package/src/editor-api.ts +46 -0
  453. package/src/editor-chrome-capture.ts +139 -0
  454. package/src/editor-commands.ts +164 -0
  455. package/src/editor-console.ts +563 -0
  456. package/src/editor-current-view.ts +82 -0
  457. package/src/editor-document-probe.ts +881 -0
  458. package/src/editor-git-client.ts +115 -0
  459. package/src/editor-host-door.ts +462 -0
  460. package/src/editor-hotkeys.ts +842 -0
  461. package/src/editor-lease-view.ts +39 -0
  462. package/src/editor-lease.ts +415 -0
  463. package/src/editor-mode.ts +19 -0
  464. package/src/editor-notifications.ts +140 -0
  465. package/src/editor-presence.ts +563 -0
  466. package/src/editor-presentation-activity.ts +50 -0
  467. package/src/editor-presentation-notice.ts +42 -0
  468. package/src/editor-runtime.tsx +145 -0
  469. package/src/editor-server-response.ts +86 -0
  470. package/src/editor-session-attribution.ts +75 -0
  471. package/src/editor-session-mode.ts +54 -0
  472. package/src/editor-shell-store.ts +1304 -0
  473. package/src/editor-state-facets.ts +74 -0
  474. package/src/editor-styles.css +33 -0
  475. package/src/editor-view-presentation.ts +810 -0
  476. package/src/editor-viewport.ts +5302 -0
  477. package/src/entity-lod.ts +31 -0
  478. package/src/entity-object.ts +91 -0
  479. package/src/files/file-provider.ts +62 -0
  480. package/src/files/project-files.ts +264 -0
  481. package/src/finders/index.ts +136 -0
  482. package/src/finders/scenes-from-entrypoint-selection.ts +387 -0
  483. package/src/frame/bridge.tsx +1408 -0
  484. package/src/frame/product.ts +77 -0
  485. package/src/gameplay-dom-recording.ts +319 -0
  486. package/src/gameplay-export-state.ts +14 -0
  487. package/src/gameplay-replay.ts +417 -0
  488. package/src/gameplay-session-time.ts +9 -0
  489. package/src/gameplay-sessions.ts +204 -0
  490. package/src/harness-chat-types.ts +253 -0
  491. package/src/hierarchy-component-marks.ts +298 -0
  492. package/src/hierarchy-drop.ts +91 -0
  493. package/src/hierarchy-expansion-state.ts +80 -0
  494. package/src/hierarchy-header-slot.ts +52 -0
  495. package/src/hierarchy-internals.ts +197 -0
  496. package/src/hierarchy-kind-icon.ts +217 -0
  497. package/src/hierarchy-mark-reader.ts +73 -0
  498. package/src/hierarchy-menu-registry.ts +67 -0
  499. package/src/hierarchy-node-rows.ts +307 -0
  500. package/src/hierarchy-panel-view.ts +280 -0
  501. package/src/hierarchy-projection.ts +76 -0
  502. package/src/hierarchy-row-cache.ts +243 -0
  503. package/src/hierarchy-row-model.ts +308 -0
  504. package/src/hierarchy-rows.ts +11 -0
  505. package/src/hierarchy-walk.ts +86 -0
  506. package/src/history/editor-session.ts +25 -0
  507. package/src/history/history-commands.ts +147 -0
  508. package/src/history/history-delegate.ts +163 -0
  509. package/src/history/history-limit-notices.ts +43 -0
  510. package/src/history/history-service.ts +1173 -0
  511. package/src/history/persistence-coordinator.ts +35 -0
  512. package/src/history/project-file-history.ts +386 -0
  513. package/src/history/project-root-history-backends.ts +139 -0
  514. package/src/history/resource-registry.ts +209 -0
  515. package/src/history/snapshot-store.ts +103 -0
  516. package/src/history/source-history-backend.ts +546 -0
  517. package/src/history/types.ts +124 -0
  518. package/src/hmr-registration-group.ts +67 -0
  519. package/src/hmr-stable-react-context.ts +23 -0
  520. package/src/hotkeys.ts +188 -0
  521. package/src/inference-diagnostics.ts +69 -0
  522. package/src/initial-project.ts +80 -0
  523. package/src/inspection/active-subject.ts +578 -0
  524. package/src/inspection/active-surface.ts +142 -0
  525. package/src/inspection/compose.ts +1064 -0
  526. package/src/inspection/display.ts +170 -0
  527. package/src/inspection/document-subject.ts +109 -0
  528. package/src/inspection/game-subject.ts +85 -0
  529. package/src/inspection/model.ts +542 -0
  530. package/src/inspection/null-subject.ts +115 -0
  531. package/src/inspection/serialize.ts +357 -0
  532. package/src/inspection/use-active-inspection.ts +180 -0
  533. package/src/inspector-presentation.ts +201 -0
  534. package/src/inspector-section-registry.ts +221 -0
  535. package/src/instance-source-actions.ts +163 -0
  536. package/src/instanced-presentation.ts +164 -0
  537. package/src/js-heap.ts +71 -0
  538. package/src/key-actions.ts +91 -0
  539. package/src/keymap-presets.ts +401 -0
  540. package/src/layout-policy.ts +31 -0
  541. package/src/learn-links.ts +73 -0
  542. package/src/light-explorer-model.ts +134 -0
  543. package/src/live-canvas-frame.ts +55 -0
  544. package/src/live-document.ts +279 -0
  545. package/src/live-module-source.ts +230 -0
  546. package/src/live-session-registry.ts +220 -0
  547. package/src/live-transition.ts +633 -0
  548. package/src/manifest-project.ts +107 -0
  549. package/src/model-thumbnail.ts +523 -0
  550. package/src/native-selection-style.ts +202 -0
  551. package/src/object3d-document-write-policy.ts +137 -0
  552. package/src/packaged-runtime.ts +108 -0
  553. package/src/palettes/maya.palette.json +57 -0
  554. package/src/palettes/substance.palette.json +57 -0
  555. package/src/pasteboard-module.ts +81 -0
  556. package/src/performance-profiler.ts +367 -0
  557. package/src/performance-sources.ts +69 -0
  558. package/src/play-boot-phase.ts +145 -0
  559. package/src/presentation-surface.ts +248 -0
  560. package/src/project-adapter.ts +1143 -0
  561. package/src/project-asset-refresh.ts +26 -0
  562. package/src/project-declaration-refresh.ts +31 -0
  563. package/src/project-local-state.ts +118 -0
  564. package/src/project-manager.ts +243 -0
  565. package/src/project-module-changes.ts +163 -0
  566. package/src/project-module-split.ts +266 -0
  567. package/src/project-provenance.ts +115 -0
  568. package/src/project-ready.ts +42 -0
  569. package/src/project-session-reset.ts +67 -0
  570. package/src/project-shape.ts +68 -0
  571. package/src/project-tool-discovery.ts +66 -0
  572. package/src/project-tools.ts +107 -0
  573. package/src/project-work-types.ts +149 -0
  574. package/src/projection/three.ts +898 -0
  575. package/src/projection/types.ts +44 -0
  576. package/src/readiness.ts +113 -0
  577. package/src/reflection-probe-helper.ts +142 -0
  578. package/src/reported-play-state.ts +90 -0
  579. package/src/resolve-relative-specifier.ts +33 -0
  580. package/src/scene-document-plan.ts +315 -0
  581. package/src/scene-framing.ts +315 -0
  582. package/src/scene-live-open.ts +210 -0
  583. package/src/scene-view-fog.ts +89 -0
  584. package/src/scoped-game-css.ts +152 -0
  585. package/src/session-orphan-record.ts +193 -0
  586. package/src/session-tombstone.ts +126 -0
  587. package/src/settings/settings-provider.ts +82 -0
  588. package/src/settings-store.ts +345 -0
  589. package/src/shared-view-restore.ts +42 -0
  590. package/src/shell-store-door.ts +45 -0
  591. package/src/source-conflict.ts +122 -0
  592. package/src/spatial-handle-visuals.ts +332 -0
  593. package/src/stage-context.ts +341 -0
  594. package/src/stage-store-registry.ts +63 -0
  595. package/src/stale-chunk-recovery.ts +34 -0
  596. package/src/state-report-deferral.ts +73 -0
  597. package/src/storage/host-files-storage.ts +97 -0
  598. package/src/storage/http-storage.ts +174 -0
  599. package/src/storage/index.ts +75 -0
  600. package/src/storage/mem-storage.ts +149 -0
  601. package/src/storage/path-lock.ts +44 -0
  602. package/src/storage/paths.ts +26 -0
  603. package/src/storage/types.ts +116 -0
  604. package/src/stories/StoryComponentThumbnail.tsx +184 -0
  605. package/src/stories/StoryPreviewMount.tsx +306 -0
  606. package/src/stories/component-content-source.tsx +106 -0
  607. package/src/stories/component-states-source.ts +78 -0
  608. package/src/stories/compose-project-stories.ts +255 -0
  609. package/src/stories/pixi-story-model.ts +30 -0
  610. package/src/stories/prefabs-finder.ts +54 -0
  611. package/src/stories/prefabs-from-stories.ts +182 -0
  612. package/src/stories/project-story-discovery.ts +78 -0
  613. package/src/stories/project-story-regions.ts +24 -0
  614. package/src/stories/story-actions.ts +54 -0
  615. package/src/stories/story-capture-command.ts +124 -0
  616. package/src/stories/story-capture.ts +584 -0
  617. package/src/stories/story-declared-medium.ts +126 -0
  618. package/src/stories/story-discovery.ts +176 -0
  619. package/src/stories/story-document-openers.ts +36 -0
  620. package/src/stories/story-dom-runtime.ts +78 -0
  621. package/src/stories/story-grouping.ts +111 -0
  622. package/src/stories/story-lane.ts +88 -0
  623. package/src/stories/story-mount-turn.ts +27 -0
  624. package/src/stories/story-opener.ts +260 -0
  625. package/src/stories/story-pixi-preview.ts +408 -0
  626. package/src/stories/story-presentation.ts +215 -0
  627. package/src/stories/story-registry.ts +517 -0
  628. package/src/stories/story-three-preview.ts +807 -0
  629. package/src/stories/three-story-model.ts +96 -0
  630. package/src/story-three-preview-runtime.ts +56 -0
  631. package/src/surface-keyboard.ts +112 -0
  632. package/src/surface-state.ts +124 -0
  633. package/src/tab-bootstrap.js +628 -0
  634. package/src/tab-census.ts +198 -0
  635. package/src/tab-lifecycle-client.ts +196 -0
  636. package/src/theme-library.ts +844 -0
  637. package/src/theme-preference.ts +378 -0
  638. package/src/theme.css +3437 -0
  639. package/src/three-viewport/bone-selection-highlight.ts +119 -0
  640. package/src/three-viewport/camera-fit.ts +41 -0
  641. package/src/three-viewport/interactive-renderer.ts +132 -0
  642. package/src/three-viewport/selection-brackets.ts +310 -0
  643. package/src/three-viewport/selection-outline.ts +183 -0
  644. package/src/three-viewport/skeleton-helper.ts +61 -0
  645. package/src/three-viewport/source-color.ts +167 -0
  646. package/src/three-viewport/studio-environment.ts +96 -0
  647. package/src/three-viewport-presentation.ts +23 -0
  648. package/src/tool-contribution-play.ts +74 -0
  649. package/src/tool-loader.ts +1798 -0
  650. package/src/transform-mode-request.ts +57 -0
  651. package/src/transient-hint.ts +78 -0
  652. package/src/trigger-volume-helper.ts +116 -0
  653. package/src/ui-source/adapter-region-includes.ts +241 -0
  654. package/src/ui-source/ensure-import.ts +132 -0
  655. package/src/ui-source/file-region-resolver.ts +302 -0
  656. package/src/ui-source/inspect.ts +775 -0
  657. package/src/ui-source/oid-transform.ts +1845 -0
  658. package/src/ui-source/plan-csf-story.ts +196 -0
  659. package/src/ui-source/plan-extract-component.ts +421 -0
  660. package/src/ui-source/plan-fork-component.ts +621 -0
  661. package/src/ui-source/plan-named-style.ts +95 -0
  662. package/src/ui-source/plan-source-edit.ts +353 -0
  663. package/src/ui-source/r3f-contract-resolver.ts +327 -0
  664. package/src/ui-source/r3f-diagnostic-index.ts +165 -0
  665. package/src/ui-source/r3f-environment-binding.ts +133 -0
  666. package/src/ui-source/r3f-joint-binding.ts +251 -0
  667. package/src/ui-source/r3f-lod-binding.ts +91 -0
  668. package/src/ui-source/r3f-particle-binding.ts +235 -0
  669. package/src/ui-source/r3f-physics-binding.ts +483 -0
  670. package/src/ui-source/r3f-project-contracts.ts +444 -0
  671. package/src/ui-source/relative-import-specifier.ts +34 -0
  672. package/src/ui-source/reparent-guard.ts +544 -0
  673. package/src/ui-source/source-edit-request.ts +97 -0
  674. package/src/ui-source/source-write-backend.ts +618 -0
  675. package/src/ui-source/syntactic-prop-specs.ts +296 -0
  676. package/src/ui-source/tier-source-write-backend.ts +279 -0
  677. package/src/ui-source/ts-ast.ts +171 -0
  678. package/src/ui-source/utility-class-support.ts +169 -0
  679. package/src/ui-source/write-component-default.ts +133 -0
  680. package/src/ui-source/writer.ts +1989 -0
  681. package/src/viewport-activation-timings.ts +840 -0
  682. package/src/viewport-authoring-policy.ts +186 -0
  683. package/src/viewport-controls-hint.ts +57 -0
  684. package/src/viewport-door.ts +237 -0
  685. package/src/viewport-shading-boundary.ts +12 -0
  686. package/src/vite-error-surface.ts +141 -0
  687. package/src/wait-until.ts +37 -0
  688. package/src/workspace-areas.ts +156 -0
  689. package/src/workspace-aux-commands.ts +11 -0
  690. package/src/workspace-available-documents.ts +127 -0
  691. package/src/workspace-core-utilities.ts +31 -0
  692. package/src/workspace-document-ids.ts +59 -0
  693. package/src/workspace-document-registry.ts +612 -0
  694. package/src/workspace-document-restore.ts +145 -0
  695. package/src/workspace-host-commands.ts +141 -0
  696. package/src/workspace-persistence-gate.ts +40 -0
  697. package/src/workspace-play-utilities.ts +44 -0
  698. package/src/workspace-presets.ts +425 -0
  699. package/src/workspace-regions.ts +294 -0
  700. package/src/workspace-state-persistence.ts +536 -0
  701. package/src/workspace-static-panels.ts +73 -0
  702. package/src/workspace-status-registry.ts +121 -0
  703. package/src/workspace-style.ts +239 -0
  704. package/src/workspace-utility-commands.ts +74 -0
  705. package/src/workspace-utility-registry.ts +263 -0
  706. package/src/workspace-viewport-rect.ts +97 -0
  707. package/src/world-adoption.ts +115 -0
  708. package/src/world-document-routing.ts +104 -0
  709. package/vite-plugin-creation-site-write.ts +184 -0
  710. package/vite-plugin-creation-site.ts +80 -0
  711. package/vite-plugin-game-static.ts +303 -0
  712. package/vite-plugin-module-doorways.ts +336 -0
  713. package/vite-plugin-product-contributions.ts +197 -0
  714. package/vite-plugin-project-game-static.ts +125 -0
  715. package/vite-plugin-project-jsx-js.ts +65 -0
  716. package/vite-plugin-project-root-absolute-assets.ts +359 -0
  717. package/vite-plugin-shared-react.ts +420 -0
  718. package/vite-plugin-shared-three.ts +203 -0
  719. package/vite-plugin-ui-oid.ts +2106 -0
@@ -0,0 +1,827 @@
1
+ // C3 (phase-b/c3-r3f-packaged) — the adaptive `optimizeDeps.entries` source
2
+ // for `packaged.ts`'s project-rooted Vite instance. See that file's header
3
+ // doc comment, "optimizeDeps" section, for the full crawl-vs-crash story;
4
+ // this module only computes WHICH files to scope the crawl to.
5
+
6
+ import { type Dirent, existsSync, readdirSync, readFileSync, statSync } from 'node:fs';
7
+ import { createRequire } from 'node:module';
8
+ import { dirname, isAbsolute, join, relative, sep } from 'node:path';
9
+ import { EDITOR_LANE_DIRS } from '@volter/editor-sdk/session/tool-contribution-convention';
10
+ import { isDynamicPattern } from 'tinyglobby';
11
+ import { loadGameManifestDir } from '@volter/editor-project/manifest/load-file';
12
+ import { doorwayModuleSource, PACKAGED_MODULE_DOORWAYS } from '../vite-plugin-module-doorways';
13
+ import { isToolContributionModule, projectStorySourceDirs } from './server-utils';
14
+ import { ADAPTER_MODULE_FILENAME } from '../src/ui-source/adapter-region-includes';
15
+
16
+ /**
17
+ * SERVER-ONLY packages that must never be crawled INTO during the client
18
+ * dep-prebundle — passed to `optimizeDeps.exclude` in `packaged.ts` (C3
19
+ * hardening follow-on). Belt to the entries-scoping suspenders.
20
+ *
21
+ * ## The pathological case this closes
22
+ *
23
+ * The entries-scoping fix (`computeProjectOptimizeDepsEntries` below) makes
24
+ * the crawl start ONLY from a project's declared world entries — which
25
+ * NORMALLY never reach `server/` code, so the colyseus server stack
26
+ * (`colyseus` -> `@colyseus/core` -> `@pm2/io`) is never crawled and the
27
+ * esbuild-scanner crash that `noDiscovery: true` used to guard against never
28
+ * fires. But if a project VIOLATES the repo's D2 rule (CLAUDE.md
29
+ * "Networking": client code calls Colyseus via the CLIENT SDK
30
+ * `@colyseus/sdk`, dynamic-imported, and NEVER value-imports the `server/`
31
+ * room classes) by having a WORLD ENTRY statically `import` from `server/`,
32
+ * the crawl reaches `@colyseus/core`'s `Stats.mjs`, whose `import("@pm2/io")`
33
+ * has no resolvable browser entry, and esbuild's prebundle step THROWS from
34
+ * inside the async optimizer — which, unhandled, HARD-KILLS the whole
35
+ * packaged node process (the only authoring surface). That is a strictly
36
+ * harsher degrade than the old `noDiscovery: true`, which at least still
37
+ * booted an editor.
38
+ *
39
+ * `exclude`-ing these three names keeps esbuild from crawling into them
40
+ * during prebundle: even a world entry that (wrongly) reaches them no longer
41
+ * crashes the scanner — the offending world degrades to a benign browser-
42
+ * side runtime import failure for that ONE world, and the editor process
43
+ * survives and serves everything else. Verified live (a real, checkout-
44
+ * absent packaged boot against a project whose world entry value-imports
45
+ * `server/rooms`): without this list the server process dies at boot; with
46
+ * it, the server boots and serves.
47
+ *
48
+ * CRITICAL: this list must NOT contain `@colyseus/sdk` — that is the
49
+ * legitimate CLIENT SDK a real multiplayer project's own game code imports
50
+ * (dynamic-imported per D2; e.g. `examples/third-person-arena/src/
51
+ * network.ts`). It is a SEPARATE package from `@colyseus/core` — its own
52
+ * published `build/index.mjs` is a self-contained client bundle — and MUST
53
+ * still prebundle so those projects work. Excluding only the server-side
54
+ * names leaves the client SDK's prebundle path untouched (proven: a world
55
+ * entry importing `@colyseus/sdk` still prebundles it cleanly with this
56
+ * exclude list active).
57
+ */
58
+ export const SERVER_ONLY_PREBUNDLE_EXCLUDE: readonly string[] = [
59
+ 'colyseus',
60
+ '@colyseus/core',
61
+ '@pm2/io',
62
+ ];
63
+
64
+ /**
65
+ * The project-relative runtime WORLD entries shared by dependency discovery
66
+ * and source warmup, for the project rooted at
67
+ * `projectRoot` — every `roots[].entry` its OWN `vgai.project.json` declares
68
+ * (default-adapter, code-authored roots; scene-only roots have no `entry`
69
+ * and contribute nothing here — their gameplay code is registered
70
+ * elsewhere, reached transitively from whichever world DOES declare an
71
+ * `entry`, e.g. the template's single world), deduped, and filtered to paths
72
+ * that exist on disk.
73
+ *
74
+ * ## Why THESE files, not `index.html` or the project's own bootstrap `main.ts`
75
+ *
76
+ * A project's `index.html` -> `src/main.ts` bootstrap ties every declared
77
+ * world together for the STANDALONE (`npm run game`) build, and — critically
78
+ * — the scaffolded template's own `main.ts` also carries the P2P-Colyseus
79
+ * URL-param branch that dynamically imports the project's OWN `server/rooms`
80
+ * (`await import('../server/rooms')`, gated behind `?net=p2p-host`, but
81
+ * esbuild's dependency scanner follows a string-literal dynamic `import()`
82
+ * as an unconditional graph edge regardless of the runtime guard around it).
83
+ * `server/rooms.ts` re-exports real Colyseus `Room` classes, whose `colyseus`
84
+ * (SERVER package) import chain reaches `@colyseus/core` -> `@pm2/io`, a
85
+ * package esbuild's prebundle step cannot resolve an entry for (confirmed
86
+ * empirically, not theoretically: a direct `vite.optimizeDeps` run scoped to
87
+ * `index.html`-style discovery against `packages/editor/template` throws
88
+ * `Failed to resolve entry for package "@pm2/io"` from inside
89
+ * `@colyseus/core/build/Stats.mjs`'s own `import("@pm2/io")` — this is
90
+ * `packaged.ts`'s ORIGINAL reason for `noDiscovery: true`, verified still
91
+ * true on this Vite version at the time of the C3 fix).
92
+ *
93
+ * A manifest's `roots[].entry` files never reach that chain: they are the
94
+ * PER-WORLD mount code the editor's own binding-resolver dynamically imports
95
+ * directly for Play mode / world mounting (never `src/main.ts` — that
96
+ * bootstrap is the STANDALONE build's concern, unrelated to how the editor
97
+ * itself mounts a world; see `packaged.ts`'s header doc comment). Scoping the
98
+ * crawl to exactly these files means: (a) it never touches `server/`, so the
99
+ * `@pm2/io` class of crash cannot occur no matter what a project's server
100
+ * room code imports, and (b) any CJS-needing-prebundle client dependency a
101
+ * world's own code reaches — `react`, `@react-three/fiber`, `@react-three/
102
+ * drei`, or some future ecosystem this repo has never heard of — gets
103
+ * auto-discovered and prebundled for free, with no per-package allowlist to
104
+ * maintain (this is what actually fixes the R3F class of bug this file's own
105
+ * feature exists for: `@react-three/fiber`'s CJS transitive deps like
106
+ * `use-sync-external-store` are reached from `examples/r3f-first-party`'s
107
+ * `src/net-entry.tsx`, never from anything server-shaped).
108
+ *
109
+ * The client SDK case (`@colyseus/sdk`, the package a world's own game code
110
+ * legitimately imports for real multiplayer — e.g.
111
+ * `examples/third-person-arena/src/network.ts`) is DIFFERENT from the
112
+ * server-package case above and does NOT crash: `@colyseus/sdk`'s own
113
+ * published build (`build/index.mjs`) is a self-contained client bundle that
114
+ * does not pull in `@colyseus/core`'s server-only `Stats.mjs` (confirmed
115
+ * empirically the same way: a full prebundle scoped to
116
+ * `examples/third-person-arena`'s own `src/index.tsx` world entry succeeds
117
+ * and prebundles `@colyseus/sdk` cleanly).
118
+ *
119
+ * ## Discovery and warmup lifetimes
120
+ *
121
+ * Dependency discovery computes this ONCE from the boot-time `VGAI_PROJECT`,
122
+ * exactly like `engineSrc`/`resolve.alias` in `packaged.ts`; those settings
123
+ * are baked into Vite's `createServer` call. Checkout-dev source warmup also
124
+ * calls this helper after `onProjectOpened`, so a switched-to project warms
125
+ * its own current entries even though it keeps the boot project's dependency
126
+ * discovery configuration.
127
+ *
128
+ * Never throws: an absent/unparseable manifest (no project open yet, a
129
+ * pre-Phase-B project, a broken `vgai.project.json`) degrades to `[]` — the
130
+ * SAFEST fallback, not a guess. Per Vite's own `optimizeDeps.entries`
131
+ * resolution (`computeEntries` in vite's dep-scanner), a truthy-but-empty
132
+ * array short-circuits the `**\/*.html` crawl fallback WITHOUT crawling
133
+ * anything itself, so an unreadable manifest degrades to "no auto-discovery
134
+ * beyond the static `include` list" — the same conservative posture
135
+ * `noDiscovery: true` had, rather than falling back to a full crawl that
136
+ * could reach server code we know nothing about.
137
+ */
138
+ export function computeProjectWorldEntries(projectRoot: string): string[] {
139
+ let manifest: ReturnType<typeof loadGameManifestDir>;
140
+ try {
141
+ manifest = loadGameManifestDir(projectRoot);
142
+ } catch {
143
+ return [];
144
+ }
145
+
146
+ const entries = new Set<string>();
147
+ const add = (relative: string | undefined): void => {
148
+ if (!relative) return;
149
+ if (!existsSync(join(projectRoot, relative))) return;
150
+ entries.add(relative);
151
+ };
152
+ for (const world of manifest.roots) {
153
+ add(world.entry);
154
+ // THE ROOT'S OWN WORLD COMPONENT, when it declares one
155
+ // (`world.entry`). It is a SECOND discovery root for the
156
+ // same reason `browserToolEntries` below is: the editor's design session
157
+ // (`authoring/r3f-design-session.ts`) dynamic-imports that file directly,
158
+ // and nothing reachable from `entry` leads to it — an ingest `entry` is a
159
+ // host shim whose reference to the game is deliberately a VARIABLE
160
+ // specifier under `@vite-ignore` (so the vendored source is never
161
+ // typechecked against this checkout's React/fiber/three), which esbuild's
162
+ // scanner cannot follow by construction.
163
+ //
164
+ // Measured cold on racing-game: without this, `@react-three/cannon` is
165
+ // never prebundled, the design mount's `import()` fails with "Failed to
166
+ // fetch dynamically imported module", and the Scene view is a Boundary —
167
+ // i.e. the entire design-time lane is dark on a cold dep cache.
168
+ add(world.world?.entry);
169
+ }
170
+ return [...entries];
171
+ }
172
+
173
+ /**
174
+ * Dependency discovery includes every browser-loaded project module that is
175
+ * not reachable from a world entry: the adapter, tool contributions and portable stories.
176
+ *
177
+ * Stories are load-time entry points in their own right. A Pixi prefab may be
178
+ * the project's only import of `@pixi/react`; leaving its CSF module out of
179
+ * the initial scan lets Vite discover that renderer after the editor has
180
+ * already loaded React, invalidating the optimized graph and producing an
181
+ * invalid-hook-call split across optimizer generations.
182
+ */
183
+ export function computeProjectOptimizeDepsEntries(projectRoot: string): string[] {
184
+ const entries = new Set(computeProjectWorldEntries(projectRoot));
185
+ // Modeling projects can have no runtime roots. Their adapter still imports
186
+ // browser-facing layouts and looks; discover those before the first page load.
187
+ if (existsSync(join(projectRoot, ADAPTER_MODULE_FILENAME)))
188
+ entries.add(ADAPTER_MODULE_FILENAME);
189
+ for (const tool of browserToolEntries(projectRoot)) entries.add(tool);
190
+ for (const story of browserStoryEntries(projectRoot)) entries.add(story);
191
+ return [...entries];
192
+ }
193
+
194
+ function browserStoryEntries(projectRoot: string): string[] {
195
+ let manifest: ReturnType<typeof loadGameManifestDir>;
196
+ try {
197
+ manifest = loadGameManifestDir(projectRoot);
198
+ } catch {
199
+ return [];
200
+ }
201
+
202
+ const found: string[] = [];
203
+ const walk = (directory: string): void => {
204
+ let entries: Dirent[];
205
+ try {
206
+ entries = readdirSync(directory, { withFileTypes: true });
207
+ } catch {
208
+ return;
209
+ }
210
+ for (const entry of entries) {
211
+ if (entry.name.startsWith('.') || entry.name === 'node_modules') continue;
212
+ const absolute = join(directory, entry.name);
213
+ if (entry.isDirectory()) {
214
+ walk(absolute);
215
+ } else if (
216
+ entry.isFile() &&
217
+ (entry.name.endsWith('.stories.tsx') || entry.name.endsWith('.stories.ts'))
218
+ ) {
219
+ found.push(relative(projectRoot, absolute).split('\\').join('/'));
220
+ }
221
+ }
222
+ };
223
+
224
+ for (const directory of projectStorySourceDirs(projectRoot, manifest)) walk(directory);
225
+ for (const preview of ['.storybook/preview.tsx', '.storybook/preview.ts']) {
226
+ if (existsSync(join(projectRoot, preview))) found.push(preview);
227
+ }
228
+ return found.sort();
229
+ }
230
+
231
+ /**
232
+ * The project's BROWSER-LOADED tool contribution modules — the second
233
+ * discovery root the world-entry crawl cannot reach.
234
+ *
235
+ * The editor dynamic-imports a project's tool CONTRIBUTIONS (`src/contributions/
236
+ * *.utility.tsx` cockpit cells, `*.document.tsx`, `*.inspector.tsx`, …) into
237
+ * the browser, and those pull ordinary siblings (`src/tools/
238
+ * dev-cockpit.utility.tsx` → `./tuning` → `@vgai/sdk/tools`). None of that
239
+ * hangs off any `roots[].entry`, so scoping the crawl to world entries alone
240
+ * left `@vgai/sdk/tools` undiscovered until the first cockpit mount —
241
+ * measured 2026-08-09 on a live session: "✨ new dependencies optimized:
242
+ * @vgai/sdk/tools" → "optimized dependencies changed. reloading", a full
243
+ * editor reload minutes into authoring, which dropped the in-flight play
244
+ * command (the exact class the C3 entries-scoping exists to prevent).
245
+ *
246
+ * The membership test is `isToolContributionModule` — the SAME predicate
247
+ * `project-tools.ts`'s scan feeds `tool-loader.ts`'s browser dynamic-import
248
+ * list, so "what the browser loads" stays one fact rather than a filename
249
+ * rule kept in lockstep by hand. A negation (everything except `*.tool.ts`)
250
+ * was measured wrong in the opposite direction: it swept each example's
251
+ * `src/contributions/module-source.ts` — a NODE module importing `node:fs`, and
252
+ * reachable only from a server-executed tool definition — into the browser
253
+ * crawl, which is exactly the server-only import chain this file's scoping
254
+ * exists to keep out. Walked recursively for the same reason
255
+ * the loader's own scan is: a project may organise its contributions into
256
+ * subdirectories.
257
+ */
258
+ function browserToolEntries(projectRoot: string): string[] {
259
+ const found: string[] = [];
260
+ let laneDir = '';
261
+ const walk = (directory: string, relative: string): void => {
262
+ let entries: Dirent[];
263
+ try {
264
+ entries = readdirSync(directory, { withFileTypes: true });
265
+ } catch {
266
+ return;
267
+ }
268
+ for (const entry of entries) {
269
+ if (entry.name.startsWith('.') || entry.name === 'node_modules') continue;
270
+ const childRelative = relative === '' ? entry.name : `${relative}/${entry.name}`;
271
+ if (entry.isDirectory()) {
272
+ walk(join(directory, entry.name), childRelative);
273
+ } else if (entry.isFile() && isToolContributionModule(entry.name)) {
274
+ found.push(`${laneDir}/${childRelative}`);
275
+ }
276
+ }
277
+ };
278
+ for (const dir of EDITOR_LANE_DIRS) {
279
+ laneDir = dir;
280
+ walk(join(projectRoot, ...dir.split('/')), '');
281
+ }
282
+ return found;
283
+ }
284
+
285
+ /**
286
+ * The list handed to `optimizeDeps.entries`, spelled so Vite takes the LITERAL
287
+ * fast path through it.
288
+ *
289
+ * ## The silent degrade this closes
290
+ *
291
+ * Vite's `globEntries` (dep-scanner) reads the whole list as ONE decision:
292
+ *
293
+ * ```js
294
+ * if (resolvedPatterns.every((str) => !isDynamicPattern(str))) {
295
+ * return resolvedPatterns.map((p) => normalizePath(path.resolve(root, p)));
296
+ * }
297
+ * return glob(pattern, { cwd: root, ignore: ['**\/node_modules/**', …] });
298
+ * ```
299
+ *
300
+ * Every entry this module produces is a real file path, never a pattern — but
301
+ * a path is a pattern's syntax too. One entry containing `(`, `[` or a leading
302
+ * `!` makes `isDynamicPattern` true and routes ALL of them through `glob()`,
303
+ * whose unconditional `**\/node_modules/**` ignore then drops the engine-source
304
+ * crawl entries (`computeRuntimeSourceCrawlEntries` — they live in the project's
305
+ * own `node_modules/@vgai/<runtime package>/src`). Nothing reports it: the boot succeeds,
306
+ * `exclude` still holds, and cold-start discovery just quietly stops reaching
307
+ * the engine's graph — one optimizer wave and tab reload at a time, the exact
308
+ * class those entries exist to prevent. Measured with the real predicate
309
+ * (tinyglobby 0.2.x, the package Vite scans with): a project at
310
+ * `~/my (game)` or `~/my [wip]` makes every absolute entry dynamic; `{x}`,
311
+ * `+` and spaces do not.
312
+ *
313
+ * ## Why relative, and NOT escaped
314
+ *
315
+ * Escaping the specials (`escapePath`) is the obvious fix and is WRONG here,
316
+ * measurably: an escaped path is no longer a dynamic pattern, so Vite takes the
317
+ * fast path and `path.resolve`s the escaped STRING — a path with literal
318
+ * backslashes in it, which exists nowhere. That turns a dropped engine entry
319
+ * into a dropped everything.
320
+ *
321
+ * The specials come from the ROOT segment of the path, not from the parts this
322
+ * module builds, so spelling every under-root entry root-RELATIVE removes them
323
+ * from the string Vite tests: `resolve(root, 'node_modules/@vgai/project/src/
324
+ * loader.ts')` is the same file with no pattern syntax in the entry at all.
325
+ * Entries outside the Vite root (the dev server's project entries) keep their
326
+ * absolute spelling — Vite accepts absolute non-glob entries — because a
327
+ * `../../my (game)/…` relative path would carry the same specials.
328
+ *
329
+ * An entry that is STILL dynamic after that (a project whose own `src` folder
330
+ * is named `assets (new)`) has no correct spelling left, so it warns by name
331
+ * rather than degrading silently.
332
+ */
333
+ export function viteOptimizeDepsEntries(viteRoot: string, files: readonly string[]): string[] {
334
+ const rootPrefix = viteRoot.endsWith(sep) ? viteRoot : `${viteRoot}${sep}`;
335
+ const entries = files.map((file) =>
336
+ isAbsolute(file) && file.startsWith(rootPrefix)
337
+ ? relative(viteRoot, file).split(sep).join('/')
338
+ : file,
339
+ );
340
+
341
+ const dynamic = entries.filter((entry) => isDynamicPattern(entry));
342
+ if (dynamic.length > 0) {
343
+ console.warn(
344
+ `\n \x1b[33mWarning:\x1b[0m ${dynamic.length} dependency-scan ` +
345
+ `entr${dynamic.length === 1 ? 'y reads' : 'ies read'} as a glob pattern ` +
346
+ `(${dynamic.join(', ')}). Vite scans the whole list with glob() when any entry ` +
347
+ 'does, and that path ignores **/node_modules/**, so the engine-source crawl entries ' +
348
+ 'are dropped and their dependencies are discovered mid-session (an optimizer wave and ' +
349
+ 'a tab reload each) instead of at boot. Renaming the path segment containing ' +
350
+ '( ) [ ] or a leading ! restores the fast path.\n',
351
+ );
352
+ }
353
+ return entries;
354
+ }
355
+
356
+ /**
357
+ * Dependency-scan entries for the checkout-backed editor dev server.
358
+ *
359
+ * That Vite instance is rooted at the engine checkout, so it must keep the
360
+ * editor's own HTML entry while also scanning the opened project's
361
+ * manifest-declared roots. A project opened from OUTSIDE the checkout stays
362
+ * absolute (Vite accepts absolute non-glob entries and preserves them);
363
+ * anything under the root is spelled root-relative — see
364
+ * {@link viteOptimizeDepsEntries} for why that spelling is load-bearing.
365
+ */
366
+ export function computeDevOptimizeDepsEntries(
367
+ engineRoot: string,
368
+ projectRoot: string | undefined,
369
+ productEntry: string | null,
370
+ productContributions: readonly string[] = [],
371
+ ): string[] {
372
+ // THE EDITOR'S OWN ENTRY is the PRODUCT's entry: the module the Code-OSS
373
+ // contribution imports, and the root of every editor import there is. It used
374
+ // to be `index.html`, which crawled to the same graph through a page that no
375
+ // longer exists. `null` when this session serves no product — then the crawl
376
+ // is the project's alone, which is the honest answer for a session with no
377
+ // editor to boot.
378
+ //
379
+ // ...AND ITS COMPOSED PACKAGES' CONTRIBUTIONS, HANDED OVER, because the crawl
380
+ // cannot walk to them: the product names each package as a SYNTHESIZED module
381
+ // (`vgai:contributions/<name>`), which hangs off no file, so the esbuild
382
+ // scanner never sees the `import()` rows inside it. That is the same blindness
383
+ // `vite-plugin-module-doorways.ts`'s header records for the other synthesized
384
+ // module, cured the same way — from the same declaration the browser is
385
+ // served (`server/session-product.ts`'s `productContributionFiles`). Measured
386
+ // without it, 2026-09-21: a `--template game` boot discovered storybook's
387
+ // preview API, three `@gltf-transform` packages and `axe-core` mid-session and
388
+ // Vite hard-reloaded the one tab out from under the session.
389
+ const entries = productEntry === null ? [] : [productEntry, ...productContributions];
390
+ if (projectRoot) {
391
+ for (const entry of computeProjectOptimizeDepsEntries(projectRoot)) {
392
+ entries.push(join(projectRoot, entry));
393
+ }
394
+ }
395
+ return viteOptimizeDepsEntries(engineRoot, entries);
396
+ }
397
+
398
+ // ---------------------------------------------------------------------------
399
+ // The EDITOR's own browser-side modules (C3 follow-on, 2026-08-19)
400
+ // ---------------------------------------------------------------------------
401
+
402
+ /**
403
+ * The bare (package) specifiers written in a literal module body.
404
+ *
405
+ * Deliberately lexical: the bodies these are read from are hand-written
406
+ * constant strings of static `import`/`export … from` lines, so a lexical
407
+ * read is exact for them, and it cannot execute or resolve anything.
408
+ */
409
+ function bareSpecifiersOf(moduleSource: string): string[] {
410
+ const found = new Set<string>();
411
+ const pattern =
412
+ /(?:^|\s)(?:import|export)[^'"\n]*?from\s*['"]([^'"]+)['"]|import\s*['"]([^'"]+)['"]/g;
413
+ for (const match of moduleSource.matchAll(pattern)) {
414
+ const specifier = match[1] ?? match[2];
415
+ if (!specifier) continue;
416
+ if (specifier.startsWith('.') || specifier.startsWith('/') || specifier.startsWith('node:')) {
417
+ continue;
418
+ }
419
+ found.add(specifier);
420
+ }
421
+ return [...found];
422
+ }
423
+
424
+ /**
425
+ * Every package specifier the editor's OWN synthesized browser modules import.
426
+ *
427
+ * ## The gap this closes
428
+ *
429
+ * `packaged.ts` serves five MODULE DOORWAYS that exist only in memory —
430
+ * `/__vgai-react-world-runtime`, `/__vgai-r3f-runtime`,
431
+ * `/__vgai-canvas-runtime`, `/__vgai-three-ingest-runtime`,
432
+ * `/__vgai-story-runtime`
433
+ * (see `vite-plugin-module-doorways.ts` for why the editor must reach react /
434
+ * fiber / `@pixi/react` / `@storybook/react` through the PROJECT's Vite graph
435
+ * rather than its own prebuilt SPA copy). Being synthesized, they hang off NO file on disk, so no
436
+ * `optimizeDeps.entries` value can ever crawl them: the boot scan starts at the
437
+ * project's world entries, tool contributions and stories, none of which import
438
+ * a `/__vgai-*` URL. The editor requests them at the FIRST Play mount / story
439
+ * preview instead — mid-session — and Vite answers a newly-seen bare specifier
440
+ * by re-running the optimizer and hard-reloading the controlling tab
441
+ * ("optimized dependencies changed. reloading"), which drops the in-flight
442
+ * command and, when the reload lands between two module generations, splits the
443
+ * React identity (`Invalid hook call`, `Cannot read properties of null (reading
444
+ * 'useContext')`).
445
+ *
446
+ * Measured on a real canonical-Pixi project (`packaged.ts` against a game whose
447
+ * only renderer is Pixi), cold `node_modules/.vite`: the boot pass prebundled
448
+ * 19 deps; a single request for the three synthetic modules took it to 21,
449
+ * adding `three` and `@react-three/fiber` — two optimizer waves, two reloads.
450
+ * The project had grown a workaround file importing `@pixi/react`,
451
+ * `@react-three/fiber` and `three` from a world entry purely to keep the crawl
452
+ * complete; closing the gap here is what makes that unnecessary.
453
+ *
454
+ * Read from each doorway's own module BODY — the same string the browser is
455
+ * served — so this list cannot drift from what the modules actually import.
456
+ */
457
+ export const EDITOR_RUNTIME_MODULE_SPECIFIERS: readonly string[] = [
458
+ ...new Set(
459
+ PACKAGED_MODULE_DOORWAYS.flatMap((doorway) => bareSpecifiersOf(doorwayModuleSource(doorway))),
460
+ ),
461
+ ].sort();
462
+
463
+ /**
464
+ * The vgai RUNTIME packages a project installs — the contract and the two
465
+ * shipped twins. All three are source-served whole (never prebundled), for the
466
+ * one-singleton reason the crawl-entry doc below states.
467
+ */
468
+ export const RUNTIME_PACKAGE_NAMES = ['@volter/editor-project', '@volter/editor-threejs'] as const;
469
+
470
+ /** name -> that package's installed `src` directory, for the ones that resolve. */
471
+ export type RuntimePackageSources = ReadonlyMap<string, string>;
472
+
473
+ /** The runtime package a specifier names, or undefined. */
474
+ function runtimePackageOf(specifier: string): string | undefined {
475
+ return RUNTIME_PACKAGE_NAMES.find(
476
+ (name) => specifier === name || specifier.startsWith(`${name}/`),
477
+ );
478
+ }
479
+
480
+ function isRuntimePackageSpecifier(specifier: string): boolean {
481
+ return runtimePackageOf(specifier) !== undefined;
482
+ }
483
+
484
+ /** The package name a specifier belongs to (`three/addons/x.js` -> `three`). */
485
+ function packageNameOf(specifier: string): string {
486
+ const segments = specifier.split('/');
487
+ return specifier.startsWith('@') ? segments.slice(0, 2).join('/') : (segments[0] ?? specifier);
488
+ }
489
+
490
+ /**
491
+ * Whether `specifier` resolves from `fromDir` — Node's own resolution, rooted
492
+ * where the import is actually written, so a nested install is found the same
493
+ * way Vite would find it.
494
+ *
495
+ * The `require.resolve` fallback matters: a package published with an
496
+ * `exports` map that has no `require` condition throws `ERR_PACKAGE_PATH_NOT_
497
+ * EXPORTED` even though it is installed and perfectly resolvable by Vite. A
498
+ * false "not installed" there would push an INSTALLED package into
499
+ * `optimizeDeps.exclude` below and un-prebundle it, so fall back to the
500
+ * question actually being asked — is the package directory on disk? — by
501
+ * resolving its `package.json`, which every package exposes.
502
+ */
503
+ export function specifierResolvesFrom(fromDir: string, specifier: string): boolean {
504
+ const require = createRequire(join(fromDir, '__vgai-resolve__.js'));
505
+ try {
506
+ require.resolve(specifier);
507
+ return true;
508
+ } catch {
509
+ // fall through to the package-directory question
510
+ }
511
+ try {
512
+ require.resolve(`${packageNameOf(specifier)}/package.json`);
513
+ return true;
514
+ } catch {
515
+ return false;
516
+ }
517
+ }
518
+
519
+ /**
520
+ * The synthesized-module specifiers to add to `optimizeDeps.include` for the
521
+ * project rooted at `projectRoot`.
522
+ *
523
+ * Conditional on the package actually being installed for the same reason the
524
+ * existing `@storybook/react` entry in `packaged.ts` is: Vite ERRORS on
525
+ * `include`-ing a dependency it cannot resolve, and this server opens arbitrary
526
+ * projects — a canonical Pixi game must not be required to install the 3D
527
+ * renderer stack just to boot its editor. A project WITHOUT `three` simply
528
+ * never mounts an R3F root, so the specifier it lacks is one it never requests.
529
+ *
530
+ * Engine specifiers are excluded here on purpose: `packaged.ts` puts
531
+ * every runtime package in `optimizeDeps.exclude` so every one of their subpaths stays
532
+ * source-served (one WorldProvider identity), and an `include`
533
+ * entry for an excluded package is a contradiction Vite warns about. They are
534
+ * handled by `computeRuntimeSourceCrawlEntries` instead — as crawl ENTRIES,
535
+ * which reach the engine's own source graph without prebundling it.
536
+ */
537
+
538
+ export function computeEditorRuntimeIncludes(projectRoot: string): string[] {
539
+ return EDITOR_RUNTIME_MODULE_SPECIFIERS.filter(
540
+ (specifier) =>
541
+ !isRuntimePackageSpecifier(specifier) && specifierResolvesFrom(projectRoot, specifier),
542
+ );
543
+ }
544
+
545
+ const SOURCE_EXTENSIONS = ['.ts', '.tsx', '.mts', '.js', '.jsx', '.mjs'] as const;
546
+
547
+ /** The file an aliased `<runtime package>/<subpath>` import lands on, or null. */
548
+ function packageSubpathFile(srcDir: string, subpath: string): string | null {
549
+ const base = join(srcDir, subpath);
550
+ const candidates = [
551
+ base,
552
+ ...SOURCE_EXTENSIONS.map((extension) => `${base}${extension}`),
553
+ ...SOURCE_EXTENSIONS.map((extension) => join(base, `index${extension}`)),
554
+ ];
555
+ for (const candidate of candidates) {
556
+ try {
557
+ if (statSync(candidate).isFile()) return candidate;
558
+ } catch {
559
+ // next candidate
560
+ }
561
+ }
562
+ return null;
563
+ }
564
+
565
+ /**
566
+ * Engine subpaths the browser loads LAZILY — a scaffolded project's own client
567
+ * modules (`@vgai/game-runtime/runtime/mount-game`, `react/use-data`, the loader,
568
+ * the input/scene/asset readers), reached only after the editor shell is up
569
+ * and therefore outside the world-entry/tool/story crawl.
570
+ *
571
+ * They are crawl ENTRIES, never `optimizeDeps.include` entries, and the
572
+ * difference is a correctness one, not a tuning one. `include` PREBUNDLES the
573
+ * named module: esbuild bundles that engine file and everything it reaches by
574
+ * relative import into one dep chunk, so the chunk carries its own copy of
575
+ * `react/world-state`'s `GameContext` while the canonical
576
+ * `@vgai/game-runtime/react/world-state` import is served as source — two providers,
577
+ * one of which silently answers `null` to `useDebugProvider`/`useWorldState`.
578
+ * (`exclude: ['@vgai/game-runtime']` does not stop it: the scanner tests the
579
+ * RAW specifier, and this list used to be written in an alias spelling that
580
+ * check never sees. Measured on a live packaged session:
581
+ * eight prebundled engine modules in `.vite/deps/_metadata.json`, none of them
582
+ * `react/world-state`.)
583
+ *
584
+ * As entries they buy exactly what the include list was for — the third-party
585
+ * packages these modules import (three, zod, `three/addons/*`, fiber) are
586
+ * discovered in the BOOT pass instead of one mid-session optimizer wave and
587
+ * tab reload at a time — while the engine itself stays source-served.
588
+ */
589
+ const LAZY_RUNTIME_CRAWL_SPECIFIERS: readonly string[] = ['@volter/editor-threejs/asset-parse-error', '@volter/editor-threejs/loader'];
590
+
591
+ /**
592
+ * Crawl entries for the engine source the browser reaches: the document-side
593
+ * modules the editor's synthesized runtime modules import, plus the lazily
594
+ * loaded subpaths above.
595
+ *
596
+ * `packaged.ts` `exclude`s each runtime package, and Vite's dep SCANNER checks
597
+ * `exclude` against the raw specifier BEFORE it resolves anything — so an
598
+ * `import … from '@vgai/game-runtime/world3d-react'` is externalized on sight and the
599
+ * engine's own source graph is never crawled at all. That graph is then served
600
+ * as source and its bare imports are discovered one browser request at a time,
601
+ * each a fresh optimizer wave. Naming the engine FILES as entries walks that
602
+ * graph at boot instead: entries are absolute paths, so the scanner's
603
+ * bare-specifier `exclude` check never sees them, while the modules they reach
604
+ * are the very ones the browser will ask for.
605
+ *
606
+ * Measured on the same cold Pixi project as above, scoped to
607
+ * `react/world-state` + `world3d-react`: four `three/addons/*` entry points
608
+ * (`DRACOLoader`, `GLTFLoader`, `KTX2Loader`, `meshopt_decoder`) that the
609
+ * include list alone never reaches are discovered at boot — four waves that
610
+ * would otherwise fire the first time the asset lane loads a glTF.
611
+ *
612
+ * Paths are built the way `packaged.ts`'s own alias resolves them
613
+ * (`@vgai/game-runtime/x` -> `<that package's src>/x`), not through its
614
+ * `exports` map, because that alias is what Vite actually applies. A subpath
615
+ * that does not exist in the installed engine contributes nothing.
616
+ */
617
+ export function computeRuntimeSourceCrawlEntries(sources: RuntimePackageSources): string[] {
618
+ const specifiers = new Set<string>();
619
+ for (const specifier of EDITOR_RUNTIME_MODULE_SPECIFIERS)
620
+ if (isRuntimePackageSpecifier(specifier)) specifiers.add(specifier);
621
+ for (const specifier of LAZY_RUNTIME_CRAWL_SPECIFIERS) specifiers.add(specifier);
622
+
623
+ const entries: string[] = [];
624
+ for (const specifier of specifiers) {
625
+ const name = runtimePackageOf(specifier);
626
+ const srcDir = name === undefined ? undefined : sources.get(name);
627
+ if (name === undefined || srcDir === undefined) continue;
628
+ const subpath = specifier.slice(name.length + 1);
629
+ if (!subpath) continue;
630
+ const file = packageSubpathFile(srcDir, subpath);
631
+ if (file) entries.push(file);
632
+ }
633
+ return entries;
634
+ }
635
+
636
+ /**
637
+ * The packages imported ANYWHERE in the installed engine's source that the
638
+ * OPENED PROJECT cannot resolve — to be added to `optimizeDeps.exclude`.
639
+ *
640
+ * This is the safety net that makes `computeRuntimeSourceCrawlEntries` safe to
641
+ * hand to Vite. Crawling engine source can reach a package the engine does not
642
+ * DECLARE and a given project therefore does not have: measured on this repo's
643
+ * engine, `src/world3d-react/r3f-adapter.tsx` imports `@react-three/fiber`
644
+ * and `src/world3d-react/rapier-physics-bridge.tsx` imports
645
+ * `@react-three/rapier` — neither of them in the engine's `dependencies`. An unresolvable bare import during the scan is not a
646
+ * warning: Vite collects it and `discoverProjectDependencies` THROWS "The
647
+ * following dependencies are imported but could not be resolved", which in
648
+ * `packaged.ts` rejects the boot-time `optimizeDeps()` barrier and kills the
649
+ * only authoring surface the user has. Vite's scanner tests `exclude` against
650
+ * the raw specifier before resolving, so an excluded name is externalized and
651
+ * never recorded as missing — the same mechanism, and the same benign degrade
652
+ * (that ONE feature fails in the browser; the editor boots and serves), as
653
+ * `SERVER_ONLY_PREBUNDLE_EXCLUDE` above.
654
+ *
655
+ * Scanning the whole `src` tree rather than only the reachable subgraph is
656
+ * deliberate: it is a strict superset, it costs one lexical pass over ~180
657
+ * files, and it stays correct when the engine grows a new optional peer without
658
+ * anyone remembering this file. Excluding a name nothing imports is a no-op, so
659
+ * the lexical scan's occasional false positive (a package-name-shaped word in a
660
+ * string literal) is harmless by construction — which is why a parser is not
661
+ * worth its cost here.
662
+ *
663
+ * ## Resolve from the PROJECT ROOT, not from the engine's own directory
664
+ *
665
+ * The first version of this asked Node whether the name resolved from
666
+ * the package's own src dir, which reads like the more accurate question — that is where
667
+ * the import is written. It is wrong, and the failure is silent until boot:
668
+ * every name in `packaged.ts`'s `resolve.dedupe` (`three`,
669
+ * `@react-three/fiber`, `pixi.js`, react, the runtime packages themselves) is resolved by
670
+ * Vite from `root` — the PROJECT — precisely so one copy wins. Measured on a
671
+ * synthetic Pixi-only project whose runtime packages link into a tree that
672
+ * DOES have `three`: resolving from their own src dirs judged `three` installed and
673
+ * left it out of this list, and the boot died on exactly the error this
674
+ * function exists to prevent, naming `three`, four `three/addons/*` entries and
675
+ * `@react-three/fiber`. Asking the project is also the conservative direction:
676
+ * npm hoists a dependency of the engine to the project's own `node_modules`, so
677
+ * "not resolvable from the project" means "not installed anywhere Vite will
678
+ * look", while the reverse error un-prebundles a package that works.
679
+ */
680
+ export function computeUnresolvableRuntimeImports(
681
+ sources: RuntimePackageSources,
682
+ projectRoot: string,
683
+ ): string[] {
684
+ if (sources.size === 0) return [];
685
+
686
+ const specifiers = new Set<string>();
687
+ const walk = (directory: string): void => {
688
+ let entries: Dirent[];
689
+ try {
690
+ entries = readdirSync(directory, { withFileTypes: true });
691
+ } catch {
692
+ return;
693
+ }
694
+ for (const entry of entries) {
695
+ if (entry.name.startsWith('.') || entry.name === 'node_modules') continue;
696
+ const absolute = join(directory, entry.name);
697
+ if (entry.isDirectory()) {
698
+ walk(absolute);
699
+ } else if (entry.isFile() && SOURCE_FILE_PATTERN.test(entry.name)) {
700
+ for (const name of importedPackageNames(absolute)) specifiers.add(name);
701
+ }
702
+ }
703
+ };
704
+ for (const srcDir of sources.values()) walk(srcDir);
705
+
706
+ return [...specifiers].filter((name) => !specifierResolvesFrom(projectRoot, name)).sort();
707
+ }
708
+
709
+ /**
710
+ * A PACKAGE's contributions, as crawl entries (WORKBENCH.md §Package or copy;
711
+ * ARCHITECTURE-CORE §The universal editor). On a real install a skew package
712
+ * (`@volter/editor-blender`, `@vgai/game`) sits under the project's `node_modules`, and
713
+ * the editor imports its `package.json#vgai.contributions` modules by
714
+ * absolute path. Vite's scanner never walks a graph that starts under
715
+ * `node_modules`, so every bare import those modules reach — the mesh kit's
716
+ * `@react-three/drei`, and through it the CommonJS `stats.js` — is served
717
+ * raw, one optimizer wave per request, or not at all: measured 2026-09-17 on
718
+ * a registry 0.5.56 install, `SyntaxError: The requested module
719
+ * '/node_modules/stats.js/build/stats.min.js' does not provide an export
720
+ * named 'default'` on every mesh contribution. Naming the contribution FILES
721
+ * as entries walks their graphs at boot, exactly as the engine's source
722
+ * entries do above.
723
+ *
724
+ * `unresolvable` is the same safety net as {@link computeUnresolvableRuntimeImports}
725
+ * over the package's own tree: a peer the project does not have is excluded
726
+ * by name rather than allowed to reject the boot-time optimizer.
727
+ */
728
+ export interface PackageContributionCrawl {
729
+ readonly entries: string[];
730
+ readonly unresolvable: string[];
731
+ }
732
+
733
+ export function computePackageContributionCrawlEntries(
734
+ projectRoot: string,
735
+ ): PackageContributionCrawl {
736
+ const entries: string[] = [];
737
+ const specifiers = new Set<string>();
738
+ let declared: string[] = [];
739
+ try {
740
+ const pkg = JSON.parse(readFileSync(join(projectRoot, 'package.json'), 'utf-8')) as {
741
+ dependencies?: Record<string, string>;
742
+ devDependencies?: Record<string, string>;
743
+ };
744
+ declared = [...Object.keys(pkg.dependencies ?? {}), ...Object.keys(pkg.devDependencies ?? {})];
745
+ } catch {
746
+ return { entries, unresolvable: [] };
747
+ }
748
+ const req = createRequire(join(projectRoot, 'package.json'));
749
+ for (const name of declared) {
750
+ let manifestPath: string;
751
+ try {
752
+ manifestPath = req.resolve(`${name}/package.json`);
753
+ } catch {
754
+ continue;
755
+ }
756
+ let contributions: unknown;
757
+ try {
758
+ contributions = (
759
+ JSON.parse(readFileSync(manifestPath, 'utf-8')) as { vgai?: { contributions?: unknown } }
760
+ ).vgai?.contributions;
761
+ } catch {
762
+ continue;
763
+ }
764
+ if (!Array.isArray(contributions)) continue;
765
+ const dir = dirname(manifestPath);
766
+ for (const entry of contributions) {
767
+ if (typeof entry !== 'string') continue;
768
+ const file = join(dir, entry);
769
+ if (existsSync(file)) entries.push(file);
770
+ }
771
+ const walk = (directory: string): void => {
772
+ let found: Dirent[];
773
+ try {
774
+ found = readdirSync(directory, { withFileTypes: true });
775
+ } catch {
776
+ return;
777
+ }
778
+ for (const item of found) {
779
+ if (item.name.startsWith('.') || item.name === 'node_modules') continue;
780
+ const absolute = join(directory, item.name);
781
+ if (item.isDirectory()) walk(absolute);
782
+ else if (item.isFile() && SOURCE_FILE_PATTERN.test(item.name))
783
+ for (const imported of importedPackageNames(absolute)) specifiers.add(imported);
784
+ }
785
+ };
786
+ walk(join(dir, 'contributions'));
787
+ walk(join(dir, 'src'));
788
+ }
789
+ const unresolvable = [...specifiers]
790
+ .filter((name) => !specifierResolvesFrom(projectRoot, name))
791
+ .sort();
792
+ return { entries, unresolvable };
793
+ }
794
+
795
+ const SOURCE_FILE_PATTERN = /\.(?:ts|tsx|mts|js|jsx|mjs)$/;
796
+ const IMPORT_PATTERN = /(?:from|import|require)\s*\(?\s*['"]([^'"\n]+)['"]/g;
797
+ /** npm's own name grammar — anything else the lexical scan caught is prose. */
798
+ const PACKAGE_NAME_PATTERN = /^(?:@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/;
799
+
800
+ /** The package names a source file's bare imports name; `[]` if unreadable. */
801
+ function importedPackageNames(file: string): string[] {
802
+ let source: string;
803
+ try {
804
+ source = readFileSync(file, 'utf-8');
805
+ } catch {
806
+ return [];
807
+ }
808
+ const names: string[] = [];
809
+ for (const match of source.matchAll(IMPORT_PATTERN)) {
810
+ const specifier = match[1];
811
+ if (!specifier || isLocalSpecifier(specifier)) continue;
812
+ const name = packageNameOf(specifier);
813
+ if (PACKAGE_NAME_PATTERN.test(name)) names.push(name);
814
+ }
815
+ return names;
816
+ }
817
+
818
+ /** Resolved by path or by this repo's own aliases — never by node_modules. */
819
+ function isLocalSpecifier(specifier: string): boolean {
820
+ return (
821
+ specifier.startsWith('.') ||
822
+ specifier.startsWith('/') ||
823
+ specifier.startsWith('node:') ||
824
+ specifier.startsWith('virtual:') ||
825
+ isRuntimePackageSpecifier(specifier)
826
+ );
827
+ }