@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,259 @@
1
+ /**
2
+ * THE SESSION OWNS THE FRAME. This module is where it does.
3
+ *
4
+ * `vgai edit` IS the Code-OSS workbench, and the workbench is two things: the
5
+ * remote extension host (a child process, serving the VS Code page) and the
6
+ * one-origin proxy (a listener in THIS process, `frame-proxy.ts`). Both belong
7
+ * to the session, which is the only owner that can be right: they exist to
8
+ * serve this project's session, they must die when it does, and a `vgai edit`
9
+ * that merely REUSES a live session must not have to adopt somebody else's
10
+ * children.
11
+ *
12
+ * RESOURCE OWNERSHIP, stated once (the rule that cost a game-scoped clock).
13
+ * - OWNER: this session process. It spawns the REH into its own process group
14
+ * and listens for the proxy itself.
15
+ * - SHARERS: none. The CLI allocates the two reserved ports and hands them
16
+ * over; after that it owns nothing of the frame. A second `vgai edit` on
17
+ * this project reuses the session and therefore reuses the frame.
18
+ * - THE ONE TEARDOWN: the host's shutdown task list (`dev.ts`/`packaged.ts`'s
19
+ * `createProcessShutdown`), which is the same path `vgai close`, SIGTERM and
20
+ * the idle timer all take — the path that already ends run configurations.
21
+ * Nothing else may stop it.
22
+ *
23
+ * WHERE THE WORKBENCH IS comes from the project's own declaration
24
+ * (`.vgai/workbench.json`) or `vgai edit --workbench <dir>`; the CLI resolves it
25
+ * once to refuse early and passes the directory here. `@volter/editor-sdk/session/
26
+ * workbench-locator` is the one resolver and the one set of refusal texts.
27
+ */
28
+
29
+ import { type ChildProcess, spawn } from 'node:child_process';
30
+ import { createConnection } from 'node:net';
31
+ import { workbenchProductId } from '@volter/editor-sdk/session/product-locator';
32
+ import {
33
+ resolveWorkbench,
34
+ type WorkbenchIdentity,
35
+ workbenchUrl,
36
+ } from '@volter/editor-sdk/session/workbench-locator';
37
+ import { startFrameProxy } from './frame-proxy';
38
+ import { stopProcess } from './process-shutdown';
39
+ import { sessionProduct } from './session-product';
40
+
41
+ /** The workbench directory the CLI resolved and handed over. */
42
+ const WORKBENCH_DIR_ENV = 'VGAI_WORKBENCH_DIR';
43
+ /** The reserved port for the Code-OSS server. */
44
+ const FRAME_PORT_ENV = 'VGAI_FRAME_PORT';
45
+ /** The reserved port for the one-origin proxy — the url a person opens. */
46
+ const FRAME_PROXY_PORT_ENV = 'VGAI_FRAME_PROXY_PORT';
47
+
48
+ export interface FrameLaunch {
49
+ readonly workbenchDir: string;
50
+ readonly rehPort: number;
51
+ readonly proxyPort: number;
52
+ }
53
+
54
+ /**
55
+ * What this session was told to frame, or `null` when it was told nothing.
56
+ * Reading the three together is deliberate: a launch with a workbench and no
57
+ * ports, or ports and no workbench, is a caller bug and reads as "not framed"
58
+ * rather than as half a frame.
59
+ */
60
+ export function frameLaunchFromEnv(): FrameLaunch | null {
61
+ const workbenchDir = process.env[WORKBENCH_DIR_ENV];
62
+ const rehPort = Number(process.env[FRAME_PORT_ENV]);
63
+ const proxyPort = Number(process.env[FRAME_PROXY_PORT_ENV]);
64
+ if (!workbenchDir || !Number.isInteger(rehPort) || !Number.isInteger(proxyPort)) return null;
65
+ return { workbenchDir, rehPort, proxyPort };
66
+ }
67
+
68
+ /**
69
+ * The url the workbench will answer on, known before anything starts.
70
+ *
71
+ * The tab bijection needs it at `createEditorServer` time — under the frame the
72
+ * session's ONE tab is the workbench page, not this server's own — and it is
73
+ * pure arithmetic over the reserved port, so nothing has to have booted yet.
74
+ */
75
+ export function frameWorkbenchUrl(launch: FrameLaunch, projectRoot: string): string {
76
+ return workbenchUrl(launch.proxyPort, projectRoot);
77
+ }
78
+
79
+ export interface FrameWorkbench {
80
+ /** What this session is running, for `EditorState.workbench` and `vgai status`. */
81
+ readonly identity: WorkbenchIdentity;
82
+ readonly url: string;
83
+ /**
84
+ * STOP THE CODE-OSS SERVER — the detached CHILD, and the one thing here that
85
+ * can outlive this process. Unconditional in the shutdown list: it waits on
86
+ * nothing, least of all a tab (`dev.ts`'s task list).
87
+ */
88
+ stopServer(): Promise<void>;
89
+ /**
90
+ * CLOSE THE ONE-ORIGIN PROXY — a listener in THIS process, and the tab's only
91
+ * route to this session: the page's origin is the proxy's, so every
92
+ * `/__editor/*` call it makes, the tab-close ACK BEACON included, arrives
93
+ * here first. So it closes with the HTTP server, AFTER the tab-close notice,
94
+ * and not with the child above. Measured 2026-09-21: closing it beside the
95
+ * child turned every `vgai close` from `session-end-acked … ms 26` into
96
+ * `session-end-unacked … ms 2002` — the page was told, closed itself, and
97
+ * its beacon had nowhere to land.
98
+ */
99
+ closeProxy(): Promise<void>;
100
+ /** Both, in one call — for the boot error path and the source-restart exit,
101
+ * where there is no tab to preserve a route for. */
102
+ stop(): Promise<void>;
103
+ }
104
+
105
+ /** True while something is listening on `port` of loopback. */
106
+ function portTaken(port: number): Promise<boolean> {
107
+ return new Promise((done) => {
108
+ const socket = createConnection({ host: '127.0.0.1', port });
109
+ const settle = (taken: boolean) => {
110
+ socket.destroy();
111
+ done(taken);
112
+ };
113
+ socket.once('connect', () => settle(true));
114
+ socket.once('error', () => settle(false));
115
+ socket.setTimeout(750, () => settle(false));
116
+ });
117
+ }
118
+
119
+ async function waitForPort(
120
+ port: number,
121
+ what: string,
122
+ child: ChildProcess,
123
+ timeoutMs: number,
124
+ ): Promise<void> {
125
+ const deadline = Date.now() + timeoutMs;
126
+ for (;;) {
127
+ if (await portTaken(port)) return;
128
+ if (child.exitCode !== null) {
129
+ throw new Error(`${what} exited (code ${child.exitCode}) before it listened on ${port}.`);
130
+ }
131
+ if (Date.now() > deadline) {
132
+ throw new Error(`${what} never listened on ${port} within ${Math.round(timeoutMs / 1000)}s.`);
133
+ }
134
+ await new Promise((settle) => setTimeout(settle, 500));
135
+ }
136
+ }
137
+
138
+ /**
139
+ * Start the workbench for this session: the REH, then the proxy in front of it
140
+ * and of this process.
141
+ *
142
+ * The argv is the same string whichever kind the workbench is — a release is
143
+ * meant to be measured against the sources, and a boot that differed in a flag
144
+ * would be measuring the flag.
145
+ */
146
+ export async function startFrameWorkbench(options: {
147
+ launch: FrameLaunch;
148
+ projectRoot: string;
149
+ sessionPort: number;
150
+ /**
151
+ * EXTRA ENVIRONMENT FOR THE REH, and through it for its extension host.
152
+ * Today that is the Chat view's runtime handoff (`frontend-handoff.ts`): the
153
+ * bundled supercode frontend reads `SUPERCODE_FRONTEND_*` at activation. It is
154
+ * a SPAWN argument and not a later call because a child's environment cannot
155
+ * be changed after it starts — which is why the session starts its harness
156
+ * runtime before it gets here, and why there is deliberately no
157
+ * restart-the-REH path when one arrives late.
158
+ */
159
+ env?: Readonly<Record<string, string>>;
160
+ log: (line: string) => void;
161
+ }): Promise<FrameWorkbench> {
162
+ const { launch, projectRoot, sessionPort, log } = options;
163
+ // A WORKBENCH IS ONE PRODUCT'S (P3): the editor kit and one product's
164
+ // workbench half are overlaid on the fork together, so a release or checkout
165
+ // built for the other product is refused here BY NAME. The session is the
166
+ // right place for it — the CLI checks the same pair before a server exists,
167
+ // and this is the read that spawns. A project whose product cannot be
168
+ // resolved is not judged: `/__editor/served-modules` is the door that says
169
+ // why, in its own words.
170
+ const product = sessionProduct(projectRoot);
171
+ const workbench = resolveWorkbench(
172
+ launch.workbenchDir,
173
+ product === null ? undefined : workbenchProductId(product.name),
174
+ );
175
+
176
+ for (const [port, what] of [
177
+ [launch.rehPort, 'the Code-OSS server'],
178
+ [launch.proxyPort, 'the one-origin proxy'],
179
+ ] as const) {
180
+ if (await portTaken(port)) {
181
+ throw new Error(
182
+ `This project reserves port ${port} for ${what}, and something is already listening there. ` +
183
+ `Free it (\`lsof -nP -iTCP:${port} -sTCP:LISTEN\`) — the frame never drifts to another port.`,
184
+ );
185
+ }
186
+ }
187
+
188
+ log(
189
+ `frame: Code-OSS ${workbench.kind} ${workbench.commit.slice(0, 12)} (${workbench.dir}) on ${launch.rehPort}`,
190
+ );
191
+ const reh = spawn(
192
+ workbench.serverBin,
193
+ [
194
+ '--host',
195
+ '127.0.0.1',
196
+ '--port',
197
+ String(launch.rehPort),
198
+ '--without-connection-token',
199
+ projectRoot,
200
+ ],
201
+ {
202
+ cwd: workbench.cwd,
203
+ stdio: 'ignore',
204
+ detached: true,
205
+ env: { ...process.env, ...options.env },
206
+ },
207
+ );
208
+ let proxy: { close(): Promise<void> } | null = null;
209
+ const closeProxy = async (): Promise<void> => {
210
+ const closing = proxy?.close() ?? Promise.resolve();
211
+ proxy = null;
212
+ await closing;
213
+ };
214
+ // 2 s between SIGTERM and SIGKILL, not `stopProcess`'s 5 s default: this
215
+ // runs as ONE TASK of the session's shutdown list, which bounds each task at
216
+ // 4 s so the whole shutdown fits inside `vgai close`'s 5.5 s grace. The
217
+ // escalation must COMPLETE inside that window — the REH is detached into its
218
+ // own process group, so the group SIGKILL `vgai close` sends at 5.5 s never
219
+ // reaches it, and a REH that outlives this process is an orphan on the
220
+ // reserved `frame` port that refuses the next `vgai edit` by name (measured
221
+ // 2026-09-21 under load average ~30).
222
+ const stopServer = (): Promise<void> => stopProcess(reh, 2_000);
223
+ const stop = async (): Promise<void> => {
224
+ await Promise.all([closeProxy(), stopServer()]);
225
+ };
226
+ try {
227
+ await waitForPort(launch.rehPort, 'the Code-OSS server', reh, 300_000);
228
+ log(
229
+ `frame: one-origin proxy on ${launch.proxyPort} → workbench ${launch.rehPort} + session ${sessionPort}`,
230
+ );
231
+ const started = await startFrameProxy({
232
+ port: launch.proxyPort,
233
+ upstreamPort: launch.rehPort,
234
+ sessionPort,
235
+ projectRoot,
236
+ // WHICH WAY ROUND THE PAGE PAINTS, from the product resolved above —
237
+ // the same read that decides which workbench may spawn decides the
238
+ // workbench's first frame, so there is one resolution and not two.
239
+ colorTheme: product?.colorTheme ?? null,
240
+ log,
241
+ });
242
+ proxy = started;
243
+ return {
244
+ identity: {
245
+ kind: workbench.kind,
246
+ dir: workbench.dir,
247
+ commit: workbench.commit,
248
+ product: workbench.product,
249
+ },
250
+ url: started.url,
251
+ stopServer,
252
+ closeProxy,
253
+ stop,
254
+ };
255
+ } catch (error) {
256
+ await stop();
257
+ throw error;
258
+ }
259
+ }
@@ -0,0 +1,229 @@
1
+ /**
2
+ * THE AI IN THE TAB GETS ITS RUNTIME FROM THE SESSION, AT SPAWN.
3
+ *
4
+ * ARCHITECTURE-CORE §The core is Code-OSS, rule 7: the agent's front end is the
5
+ * workbench's own Chat view, filled by `sdk/frontend-vscode`, and its back end is
6
+ * the harness runtime this session already runs. This module is the wire between
7
+ * them, and it is four environment variables.
8
+ *
9
+ * WHY ENV, AND WHY AT SPAWN. The extension's second connection path (its README,
10
+ * "The runtime's environment handover") reads `SUPERCODE_FRONTEND_URL`,
11
+ * `_CLIENT_ID`, `_CREDENTIAL_FILE` and `_PERMISSIONS` from the EXTENSION HOST's
12
+ * environment at activation — the same shape supercode's own CLI uses to launch
13
+ * the pi frontend, without the `PI` infix. A Code-OSS server passes its
14
+ * environment to its extension host, and `frame-workbench.ts` spawns that server,
15
+ * so the handover costs no pasted token and no route of ours. The price is that
16
+ * env is FIXED AT SPAWN: whatever the runtime is when the REH starts is what the
17
+ * panel gets, which is why the session starts the runtime first.
18
+ *
19
+ * WHY THE SESSION MINTS RATHER THAN FORWARDS. The runtime's receipt carries a
20
+ * BOOTSTRAP bearer (`crates/harness/src/live_runtime.rs`), and handing that to a
21
+ * frontend would give it the runtime's own authority. Every supercode frontend
22
+ * instead asks the runtime's loopback mint door for a credential scoped to its
23
+ * own client id and grant, and gives it back on the way out. That door's reader
24
+ * and caller are supercode's, not ours —
25
+ * `@volter-ai-dev/supercode-harness-sdk/live-runtime`, extracted there from
26
+ * `sdk/teams`'s HTTP door when this became its second consumer.
27
+ *
28
+ * WHAT THE SESSION NEVER DOES is read the credential file back. It receives 64
29
+ * hex bytes from the mint door, writes them 0600 where only this user can read
30
+ * them, and hands over the PATH; the extension re-checks the file's identity
31
+ * across the open (`sdk/frontend-vscode`'s `credential.ts`).
32
+ *
33
+ * RESOURCE OWNERSHIP, stated once:
34
+ * - OWNER: the `HarnessChatService` that minted it. It holds exactly one
35
+ * handoff at a time and replaces it only by disposing the previous one.
36
+ * - SHARERS: the REH child, which received the path in its environment and may
37
+ * re-read it across an extension-host reload for as long as the session lives.
38
+ * - THE ONE TEARDOWN: `dispose()`, called from the service's `close()` — the
39
+ * same shutdown list that stops the REH. Nothing else may revoke it, because
40
+ * a revoked grant with a live panel is a chat that has silently gone deaf.
41
+ */
42
+
43
+ import { randomUUID } from 'node:crypto';
44
+ import { chmodSync, mkdirSync, rmSync, writeFileSync } from 'node:fs';
45
+ import { dirname, join, resolve } from 'node:path';
46
+ import { pathToFileURL } from 'node:url';
47
+
48
+ /** `observe` watches, `interact` sends, `approve` answers a permission request.
49
+ * `terminate` is deliberately NOT here: the panel may drive the agent and answer
50
+ * for it, and may not kill the session the terminal and the CLI also hold. */
51
+ export const FRONTEND_PERMISSIONS = 'observe,interact,approve';
52
+
53
+ /**
54
+ * THE OTHER HALF OF THE HANDOVER: why there is no runtime, when there is none.
55
+ *
56
+ * The four `SUPERCODE_FRONTEND_*` variables above hand the extension a runtime. This one hands
57
+ * it the SENTENCE instead — B9c's refusal, which names the harness and its own login command —
58
+ * and `sdk/frontend-vscode` 0.1.3 reads it at activation and shows it as the session's first
59
+ * turn. Without it the Chat view was indistinguishable from a working one: "Build with Agent"
60
+ * and a live input over an agent that would never answer (measured on the 0.1.1 bytes, gate 6).
61
+ *
62
+ * It is never set beside the four: a handoff either carries a runtime or carries the reason it
63
+ * does not.
64
+ */
65
+ export const FRONTEND_UNAVAILABLE_ENV = 'SUPERCODE_FRONTEND_UNAVAILABLE';
66
+
67
+ /** The four variables, and the one call that ends the grant they carry. */
68
+ export interface FrontendHandoff {
69
+ /** Spread into the REH spawn's environment. Empty means there is nothing to hand over. */
70
+ readonly env: Readonly<Record<string, string>>;
71
+ /** The client id the runtime's lease coordinator will see. */
72
+ readonly clientId: string;
73
+ /** True when the runtime's mint door answered; false when it 404'd and the receipt's own
74
+ * bearer was handed over instead (see the measurement in `mintFrontendHandoff`). */
75
+ readonly minted: boolean;
76
+ /** Revoke the grant and delete the credential file. Idempotent. */
77
+ dispose(): Promise<void>;
78
+ }
79
+
80
+ interface LiveRuntimeReceipt {
81
+ readonly base_url: string;
82
+ readonly token: string;
83
+ }
84
+
85
+ interface LiveRuntimeDoor {
86
+ findLiveReceipt(runtimeId: string, env?: NodeJS.ProcessEnv): LiveRuntimeReceipt | null;
87
+ mintFrontendCredential(
88
+ receipt: LiveRuntimeReceipt,
89
+ options: { clientId: string; grant: 'interactive' | 'observer' },
90
+ ): Promise<string>;
91
+ revokeFrontendCredential(
92
+ receipt: LiveRuntimeReceipt,
93
+ options: { clientId: string },
94
+ ): Promise<number | undefined>;
95
+ }
96
+
97
+ function moduleCandidate(root: string | undefined, file: string): string[] {
98
+ if (!root) return [];
99
+ return [root.endsWith('.mjs') ? root : join(root, file)];
100
+ }
101
+
102
+ /**
103
+ * The supercode door, resolved the way every other optional supercode import in
104
+ * this server is: the published package first, a sibling checkout after, and a
105
+ * refusal that names every location tried rather than an opaque `ERR_MODULE_NOT_FOUND`.
106
+ */
107
+ async function importLiveRuntimeDoor(engineRoot: string): Promise<LiveRuntimeDoor> {
108
+ const sibling = join(dirname(engineRoot), 'supercode', 'sdk', 'typescript', 'live-runtime.mjs');
109
+ const cwdSibling = join(
110
+ dirname(resolve(process.cwd())),
111
+ 'supercode',
112
+ 'sdk',
113
+ 'typescript',
114
+ 'live-runtime.mjs',
115
+ );
116
+ const failures: string[] = [];
117
+ for (const candidate of [
118
+ ...moduleCandidate(process.env['SUPERCODE_SDK_PATH'], 'live-runtime.mjs'),
119
+ '@volter-ai-dev/supercode-harness-sdk/live-runtime',
120
+ sibling,
121
+ cwdSibling,
122
+ ]) {
123
+ try {
124
+ const specifier = candidate.startsWith('/') ? pathToFileURL(candidate).href : candidate;
125
+ const module = (await import(specifier)) as Partial<LiveRuntimeDoor>;
126
+ if (module.findLiveReceipt && module.mintFrontendCredential && module.revokeFrontendCredential) {
127
+ return module as LiveRuntimeDoor;
128
+ }
129
+ failures.push(`${candidate}: missing findLiveReceipt/mintFrontendCredential/revokeFrontendCredential`);
130
+ } catch (error) {
131
+ failures.push(`${candidate}: ${error instanceof Error ? error.message : String(error)}`);
132
+ }
133
+ }
134
+ throw new Error(
135
+ `The supercode live-runtime door could not be loaded, so the Chat view has no runtime to attach to. Tried:\n ${failures.join('\n ')}`,
136
+ );
137
+ }
138
+
139
+ /**
140
+ * Mint one scoped credential for a runtime this session started, and return the
141
+ * environment the extension host reads at activation.
142
+ *
143
+ * `runtimeSessionId` is `ManagedRuntime.handle.runtime_id` — the same string the
144
+ * runtime wrote into its receipt as `runtime_session_id`.
145
+ */
146
+ export async function mintFrontendHandoff(options: {
147
+ readonly engineRoot: string;
148
+ readonly runtimeSessionId: string;
149
+ /** Where the 0600 credential goes. One directory per session, removed with it. */
150
+ readonly directory: string;
151
+ }): Promise<FrontendHandoff> {
152
+ const door = await importLiveRuntimeDoor(options.engineRoot);
153
+ const receipt = door.findLiveReceipt(options.runtimeSessionId);
154
+ if (!receipt) {
155
+ throw new Error(
156
+ `Supercode registered no live receipt for runtime ${options.runtimeSessionId}, so there is nothing for the Chat view to attach to.`,
157
+ );
158
+ }
159
+ const clientId = `vgai-editor-${process.pid}-${randomUUID().slice(0, 8)}`;
160
+ // THERE ARE TWO HTTP SERVERS IN A SUPERCODE RUNTIME, and a MANAGED runtime's receipt
161
+ // points at the one WITHOUT the mint door. Measured against supercode 0.4.36 on
162
+ // 2026-09-21, on a runtime started through `startManagedRuntime`:
163
+ //
164
+ // POST /rpc 200 (frontend.v2.describe answered)
165
+ // POST /_supercode/frontend-credentials/mint 404 {"error":"not found"}
166
+ // …the same path with no bearer 401 — so it IS supercode's server
167
+ //
168
+ // `crates/harness/src/server.rs`: `handle_http_conn` (~:2611) serves the mint door and is
169
+ // what `supercode serve` runs; `handle_frontend_http_conn` (~:2962) is what
170
+ // `insert_hosted_runtime` starts and registers in the receipt, and it serves `POST /rpc`,
171
+ // `GET /frontend/events` and the observer assets — everything else is that 404.
172
+ //
173
+ // So the credential is minted WHEN THE DOOR EXISTS and is the receipt's own bearer when it
174
+ // does not. That is not an invention: it is supercode's own fallback, transcribed from
175
+ // `sdk/teams`'s HTTP door (`if (!/^mint 404/.test(error.message)) throw error;`), and it is
176
+ // still SCOPED — the generated frontend client sends `x-supercode-client-id` and
177
+ // `x-supercode-permissions` on every request (`sdk/frontend/client.mjs` :104-105), and
178
+ // `coordinated_http_client` (~:2491) takes the supplied id for an unbound credential and
179
+ // RESTRICTS the authorization to the header's permissions. What the fallback loses is the
180
+ // server-side BINDING: a client that stripped those headers would keep the bootstrap's
181
+ // authorization. Serving the mint door on the frontend server is supercode's to add.
182
+ let token: string;
183
+ let minted: boolean;
184
+ try {
185
+ token = await door.mintFrontendCredential(receipt, { clientId, grant: 'interactive' });
186
+ minted = true;
187
+ } catch (error) {
188
+ const message = error instanceof Error ? error.message : String(error);
189
+ if (!/^mint 404/.test(message)) throw error;
190
+ token = receipt.token;
191
+ minted = false;
192
+ }
193
+ // The reader's own rules (`sdk/frontend-vscode`'s `credential.ts`): a regular,
194
+ // private, single-linked file of exactly 64 lowercase hex bytes. Checked HERE too,
195
+ // because a malformed secret should name the door it came from rather than surface later
196
+ // as "the credential is malformed" from inside an extension host with no logs a person reads.
197
+ if (!/^[0-9a-f]{64}$/.test(token)) {
198
+ throw new Error(
199
+ `The runtime's ${minted ? 'mint door' : 'receipt'} carried ${token.length} bytes that are not 64 hex characters; the Chat view's credential reader would refuse them.`,
200
+ );
201
+ }
202
+ mkdirSync(options.directory, { recursive: true, mode: 0o700 });
203
+ chmodSync(options.directory, 0o700);
204
+ const credentialFile = join(options.directory, 'frontend-credential');
205
+ // `mode` on `writeFileSync` is masked by the umask, so the chmod is not redundant:
206
+ // a 0022 umask would leave 0644 and the extension refuses a world-readable credential.
207
+ writeFileSync(credentialFile, token, { mode: 0o600 });
208
+ chmodSync(credentialFile, 0o600);
209
+ let disposed = false;
210
+ return {
211
+ env: {
212
+ SUPERCODE_FRONTEND_URL: receipt.base_url,
213
+ SUPERCODE_FRONTEND_CLIENT_ID: clientId,
214
+ SUPERCODE_FRONTEND_CREDENTIAL_FILE: credentialFile,
215
+ SUPERCODE_FRONTEND_PERMISSIONS: FRONTEND_PERMISSIONS,
216
+ },
217
+ clientId,
218
+ minted,
219
+ async dispose() {
220
+ if (disposed) return;
221
+ disposed = true;
222
+ rmSync(options.directory, { recursive: true, force: true });
223
+ // Only a MINTED grant is ours to give back; the receipt's own bearer is the runtime's
224
+ // and dies with it. A runtime that has already exited cannot take anything back either,
225
+ // and saying so would be reporting the shutdown we are already performing.
226
+ if (minted) await door.revokeFrontendCredential(receipt, { clientId }).catch(() => undefined);
227
+ },
228
+ };
229
+ }
@@ -0,0 +1,113 @@
1
+ /**
2
+ * Pure predicate for the `vgai-game-globals` Vite plugin in `dev.ts` — split
3
+ * out into its own side-effect-free module so it's unit-testable without
4
+ * booting Vite/Express (`dev.ts`'s module top-level calls `main()`, which
5
+ * starts real servers — importing it directly in a test would do that).
6
+ *
7
+ * The prelude used to be scoped to `projectRoots` alone (an opened project's
8
+ * own `/src/`), which covers first-party project code and play-mode's game
9
+ * examples but NOT the in-tree ingest fixtures' same-realm
10
+ * ingest-fixture entry modules — those live under this EDITOR
11
+ * PACKAGE's own `packages/editor/src/ingest/games/**` tree (every surface —
12
+ * holds the former `games-2d`/`games-react` siblings),
13
+ * which `ingest/registry.ts` pulls into the SAME Vite module graph via
14
+ * `import.meta.glob` (they are ordinary `/src/` modules Vite already knows
15
+ * about statically — not an external project folder), so they were served
16
+ * UNSHADOWED: a vendored game's raw `window`/`document` input listeners ran
17
+ * for its entire mount regardless of editor focus.
18
+ */
19
+ import path from 'node:path';
20
+ import { isEditorLanePath } from '@volter/editor-sdk/session/tool-contribution-convention';
21
+ import { isPathInside } from './server-utils';
22
+
23
+ /**
24
+ * The same-realm ingest-fixture root, given this editor package's own `src/`
25
+ * directory. Fixed (not runtime-discovered) — this folder is part of THIS
26
+ * package's source tree, not a project a user opens. It was a LIST of two
27
+ * once the per-library fixture directories merged into one; the
28
+ * signature stays plural because the caller wires an array of roots and
29
+ * nothing is gained by narrowing it.
30
+ */
31
+ export function ingestGameShadowRoots(editorSrcRoot: string): string[] {
32
+ return [
33
+ path.resolve(editorSrcRoot, 'ingest/games'),
34
+ // THE GAME'S OWN SOURCE, which until now was the half that got missed.
35
+ // The root above covers only the host-authored manifest folder — the
36
+ // entry shim, a contract shim — while every line of the game itself lives
37
+ // under `vendor/games/<id>/src/`, outside it. A source-vendored game
38
+ // therefore ran its raw `window`/`document` listeners and its own rAF
39
+ // loop UNSHADOWED for its entire mount, so play-mode's input gate and
40
+ // pause reached nothing in it. Measured on the racing-game ingest, whose
41
+ // `controls/Keyboard.ts` binds `window.addEventListener('keydown')`
42
+ // directly and whose Vehicle drives a `useFrame` loop: with only the
43
+ // manifest folder shadowed, `editor.pause()` left the coverage `loop` row
44
+ // at `loop: null` — the host held no gate over it.
45
+ //
46
+ // Bundle-vendored games are deliberately NOT covered: they are BUILT
47
+ // output under `public/ingest/<id>/`, which `isShadowableModulePath`
48
+ // already declines (no `/src/` segment) and which the prelude's lexical
49
+ // shadow is not safe to prepend to anyway.
50
+ path.resolve(editorSrcRoot, '../../../vendor/games'),
51
+ ];
52
+ }
53
+
54
+ /**
55
+ * True if `file` is a `/src/` TS/JS module — the shape the prelude assumes
56
+ * (a lexically-scoped `const window=…,document=…;` prepended to the top of
57
+ * the module body; see `gated-globals.ts`'s doc comment for why that's safe
58
+ * even ahead of the module's own `import` statements).
59
+ *
60
+ * DEPENDENCY CODE IS NEVER THE PROJECT'S OWN, and the `/src/` test alone does
61
+ * not say so: a project whose own path contains a `src` segment makes every
62
+ * file under its `node_modules/` match — including Vite's project-local
63
+ * optimized-deps cache (`<project>/node_modules/.vite-editor/deps/three.js`,
64
+ * `editorViteCacheDir`). Measured on an ingest whose manifest folder lives
65
+ * under `packages/editor/src/ingest/games/`: the prebundled
66
+ * `three.js` was instrumented by `vite-plugin-creation-site`, so
67
+ * `DRACOLoader`'s worker — which it builds by `DRACOWorker.toString()` and
68
+ * hands to a Blob URL — carried the recorder identifier into a realm that has
69
+ * no such binding. `__vgaiCS$ is not defined` in a `blob:` URL, every Draco
70
+ * mesh failed to decode, `useGLTF` suspended forever, and the scene mounted
71
+ * EMPTY with no error naming any of it. Ordinary projects were safe only by
72
+ * accident of their path.
73
+ */
74
+ export function isShadowableModulePath(file: string): boolean {
75
+ if (file.includes('/node_modules/') || isEditorLanePath(file)) return false;
76
+ return /\.(ts|tsx|js|jsx)$/.test(file) && file.includes('/src/');
77
+ }
78
+
79
+ /**
80
+ * True if `file` should get the `GAME_GLOBALS_PRELUDE` shadow prepended:
81
+ * a shadowable module path under any of `roots` (an opened project's root,
82
+ * or one of {@link ingestGameShadowRoots}).
83
+ */
84
+ export function shouldShadowGameGlobals(file: string, roots: Iterable<string>): boolean {
85
+ if (!isShadowableModulePath(file)) return false;
86
+ // Containment, not a string prefix: a bare `startsWith` shadows every module
87
+ // of the SIBLING project `<root>-old/src/…` as if it belonged to `<root>`.
88
+ for (const root of roots) {
89
+ if (isPathInside(root, file)) return true;
90
+ }
91
+ return false;
92
+ }
93
+
94
+ /** A project (or ingest-fixture) stylesheet, not a dependency. */
95
+ export function isGameCssPath(file: string): boolean {
96
+ return file.endsWith('.css') && !file.includes('/node_modules/') && !isEditorLanePath(file);
97
+ }
98
+
99
+ /**
100
+ * True if Vite-imported game CSS must be rewritten into `@scope` so
101
+ * `html`/`body`/`*` rules cannot restyle the editor document. The sibling
102
+ * of {@link shouldShadowGameGlobals} for stylesheets: first-party worlds
103
+ * `import './style.css'`, which Vite injects as a page sheet unless this
104
+ * transform contains it the same way `server/scoped-game-css.ts` contains
105
+ * a declared ingest stylesheet.
106
+ */
107
+ export function shouldScopeGameCss(file: string, roots: Iterable<string>): boolean {
108
+ if (!isGameCssPath(file)) return false;
109
+ for (const root of roots) {
110
+ if (isPathInside(root, file)) return true;
111
+ }
112
+ return false;
113
+ }