@volter/sdk 0.0.0-stage → 0.5.203

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 (523) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +20 -0
  3. package/README.md +38 -3
  4. package/package.json +510 -4
  5. package/src/account.ts +210 -0
  6. package/src/chrome.ts +88 -0
  7. package/src/client.ts +1646 -0
  8. package/src/commands.ts +66 -0
  9. package/src/contributions.ts +619 -0
  10. package/src/css-numeric-style.ts +97 -0
  11. package/src/document-probe.ts +282 -0
  12. package/src/editor-view.ts +225 -0
  13. package/src/extension.ts +40 -0
  14. package/src/generations.ts +178 -0
  15. package/src/host.ts +1157 -0
  16. package/src/http-transport.browser.ts +14 -0
  17. package/src/http-transport.node.ts +19 -0
  18. package/src/index.ts +131 -0
  19. package/src/kit/CapabilityCoverageSection.tsx +185 -0
  20. package/src/kit/account-client.ts +333 -0
  21. package/src/kit/action-registry.ts +317 -0
  22. package/src/kit/active-product.ts +76 -0
  23. package/src/kit/active-project.ts +155 -0
  24. package/src/kit/adapter-editor-config.ts +25 -0
  25. package/src/kit/adapter-module.ts +7 -0
  26. package/src/kit/adapter-observation.ts +49 -0
  27. package/src/kit/animation/animation-clock.ts +479 -0
  28. package/src/kit/animation/stage-transport.ts +385 -0
  29. package/src/kit/api/assets.ts +365 -0
  30. package/src/kit/api/project-open.ts +355 -0
  31. package/src/kit/api/project-source.ts +180 -0
  32. package/src/kit/api/project-state.ts +110 -0
  33. package/src/kit/api/relay.ts +270 -0
  34. package/src/kit/api/themes.ts +45 -0
  35. package/src/kit/api-asset-library-wire.ts +45 -0
  36. package/src/kit/api-base.ts +10 -0
  37. package/src/kit/api-build.ts +99 -0
  38. package/src/kit/api-git-wire.ts +56 -0
  39. package/src/kit/api-logs.ts +92 -0
  40. package/src/kit/api-project-identity.ts +74 -0
  41. package/src/kit/api-settings.ts +36 -0
  42. package/src/kit/api-worktrees.ts +205 -0
  43. package/src/kit/asset-capabilities.ts +344 -0
  44. package/src/kit/asset-compare-core.ts +171 -0
  45. package/src/kit/asset-editor-context.tsx +101 -0
  46. package/src/kit/asset-events.ts +96 -0
  47. package/src/kit/asset-inspector-actions.ts +87 -0
  48. package/src/kit/asset-selection-viewer-registry.ts +113 -0
  49. package/src/kit/asset-selection.ts +146 -0
  50. package/src/kit/asset-thumbnails.ts +25 -0
  51. package/src/kit/asset-viewers.ts +115 -0
  52. package/src/kit/asset-workflow/asset-import-jobs.ts +106 -0
  53. package/src/kit/asset-workflow/asset-ledger-backend.ts +126 -0
  54. package/src/kit/asset-workflow/asset-ledger.ts +156 -0
  55. package/src/kit/asset-workflow/asset-materialization-report.ts +140 -0
  56. package/src/kit/asset-workflow/asset-pack-manifest.ts +320 -0
  57. package/src/kit/asset-workflow/asset-types.ts +142 -0
  58. package/src/kit/asset-workflow/audio-preview-player.ts +193 -0
  59. package/src/kit/asset-workflow/audio-waveform.ts +22 -0
  60. package/src/kit/asset-workflow/cloud-asset-client.ts +263 -0
  61. package/src/kit/asset-workflow/hosted-asset-materialization.ts +236 -0
  62. package/src/kit/asset-workflow/image-view-scale.ts +31 -0
  63. package/src/kit/asset-workflow/import-contract.ts +124 -0
  64. package/src/kit/asset-workflow/ledger-write-lock.ts +244 -0
  65. package/src/kit/asset-workflow/pixi-spritesheet.ts +197 -0
  66. package/src/kit/asset-workflow/preview-resource-lifetime.ts +44 -0
  67. package/src/kit/asset-workflow/project-asset-commands.ts +20 -0
  68. package/src/kit/asset-workflow/project-content.ts +288 -0
  69. package/src/kit/asset-workflow/project-source-index.ts +545 -0
  70. package/src/kit/asset-workflow/thumbnail-system.ts +256 -0
  71. package/src/kit/authoring/active-adapter.ts +200 -0
  72. package/src/kit/authoring/active-systems.ts +422 -0
  73. package/src/kit/authoring/adapter-key.ts +18 -0
  74. package/src/kit/authoring/authoring-asset-url.ts +27 -0
  75. package/src/kit/authoring/bootstrap-state.ts +49 -0
  76. package/src/kit/authoring/boundary-authoring-adapter.ts +189 -0
  77. package/src/kit/authoring/canvas-scene-guides.ts +84 -0
  78. package/src/kit/authoring/composite-authoring-adapter.ts +2109 -0
  79. package/src/kit/authoring/consumer-actions.ts +531 -0
  80. package/src/kit/authoring/design-time-layers.ts +852 -0
  81. package/src/kit/authoring/design-time-mount-registry.ts +244 -0
  82. package/src/kit/authoring/edit-mode-authoring.ts +637 -0
  83. package/src/kit/authoring/empty-project-authoring.ts +22 -0
  84. package/src/kit/authoring/instance-source-menu.ts +135 -0
  85. package/src/kit/authoring/layered-pick.ts +185 -0
  86. package/src/kit/authoring/mounted-root-subjects.ts +146 -0
  87. package/src/kit/authoring/no-authoring-adapter.ts +59 -0
  88. package/src/kit/authoring/object3d-document-persistence.ts +122 -0
  89. package/src/kit/authoring/panel-authoring.ts +121 -0
  90. package/src/kit/authoring/project-authoring-session.ts +105 -0
  91. package/src/kit/authoring/provenance.ts +99 -0
  92. package/src/kit/authoring/react-canvas-navigation.ts +259 -0
  93. package/src/kit/authoring/react-design-canvas-style.ts +20 -0
  94. package/src/kit/authoring/react-story-board.ts +917 -0
  95. package/src/kit/authoring/selection-scope.ts +195 -0
  96. package/src/kit/authoring/shell-document-ops.ts +169 -0
  97. package/src/kit/authoring/story-board-chrome-fit.ts +107 -0
  98. package/src/kit/authoring/story-board-presentation.ts +111 -0
  99. package/src/kit/authoring/three-root.ts +67 -0
  100. package/src/kit/authoring/viewport-tool-context.ts +73 -0
  101. package/src/kit/authoring/viewport-tool-owner.ts +38 -0
  102. package/src/kit/authoring/world-session-state.ts +101 -0
  103. package/src/kit/authoring-seam-evidence.ts +300 -0
  104. package/src/kit/availability-tick.ts +66 -0
  105. package/src/kit/bitmap-label.ts +120 -0
  106. package/src/kit/boot-routing.ts +392 -0
  107. package/src/kit/breakpoint-state.ts +43 -0
  108. package/src/kit/build-identity.ts +16 -0
  109. package/src/kit/bytes-codec.ts +62 -0
  110. package/src/kit/cancellation-reason.ts +58 -0
  111. package/src/kit/canvas-frames.ts +88 -0
  112. package/src/kit/capture-camera-pose.ts +77 -0
  113. package/src/kit/capture-size.ts +88 -0
  114. package/src/kit/chrome-registry.ts +159 -0
  115. package/src/kit/chrome-slot-registry.ts +91 -0
  116. package/src/kit/collaboration-client.ts +264 -0
  117. package/src/kit/collaboration-presence.ts +41 -0
  118. package/src/kit/command-dispatch.ts +19 -0
  119. package/src/kit/command-listener.ts +2182 -0
  120. package/src/kit/command-registry.ts +71 -0
  121. package/src/kit/component-board-registry.ts +205 -0
  122. package/src/kit/component-states-registry.ts +199 -0
  123. package/src/kit/components/AlignToolbar.tsx +204 -0
  124. package/src/kit/components/ApplicationMenus.tsx +372 -0
  125. package/src/kit/components/AssetEditorShell.tsx +216 -0
  126. package/src/kit/components/AssetInspectorToolSection.tsx +124 -0
  127. package/src/kit/components/BoardRulers.tsx +354 -0
  128. package/src/kit/components/CanvasAddNodeDialogs.tsx +529 -0
  129. package/src/kit/components/CanvasSceneViewport.tsx +1195 -0
  130. package/src/kit/components/ChromeSlot.tsx +20 -0
  131. package/src/kit/components/CodeView.tsx +470 -0
  132. package/src/kit/components/CompactInspectorShell.tsx +39 -0
  133. package/src/kit/components/ConsolePanel.tsx +273 -0
  134. package/src/kit/components/GameplaySessionTimeline.tsx +295 -0
  135. package/src/kit/components/InspectionProjection.tsx +932 -0
  136. package/src/kit/components/Inspector.tsx +270 -0
  137. package/src/kit/components/InspectorCanvasPreview.tsx +35 -0
  138. package/src/kit/components/InspectorFieldsSection.tsx +290 -0
  139. package/src/kit/components/InspectorStoriesSection.tsx +92 -0
  140. package/src/kit/components/InspectorToolSection.tsx +96 -0
  141. package/src/kit/components/InspectorTransformSection.tsx +245 -0
  142. package/src/kit/components/LightExplorerPanel.tsx +433 -0
  143. package/src/kit/components/MediaProperties.tsx +145 -0
  144. package/src/kit/components/ProjectHeader.tsx +328 -0
  145. package/src/kit/components/ReactCanvasControls.tsx +358 -0
  146. package/src/kit/components/RootSelectionOverlay.tsx +3688 -0
  147. package/src/kit/components/RootTextEditor.tsx +79 -0
  148. package/src/kit/components/SaveStatus.tsx +70 -0
  149. package/src/kit/components/SurfaceCrashBoundary.tsx +105 -0
  150. package/src/kit/components/SurfaceStateOverlay.tsx +24 -0
  151. package/src/kit/components/ToolContributionSurfaces.tsx +49 -0
  152. package/src/kit/components/ToolHost.tsx +380 -0
  153. package/src/kit/components/Toolbar.tsx +811 -0
  154. package/src/kit/components/TransientHint.tsx +44 -0
  155. package/src/kit/components/VersionControlSection.tsx +470 -0
  156. package/src/kit/components/ViewportOverlaysMenu.tsx +177 -0
  157. package/src/kit/components/VolterLogo.tsx +18 -0
  158. package/src/kit/components/WorktreeSwitcher.tsx +712 -0
  159. package/src/kit/components/account-documents.tsx +1162 -0
  160. package/src/kit/components/asset-documents.tsx +794 -0
  161. package/src/kit/components/asset-editor-persistence.ts +216 -0
  162. package/src/kit/components/asset-selection-section.tsx +545 -0
  163. package/src/kit/components/asset-thumbnails.tsx +307 -0
  164. package/src/kit/components/asset-viewers/AudioViewer.tsx +201 -0
  165. package/src/kit/components/asset-viewers/GenericJsonViewer.tsx +102 -0
  166. package/src/kit/components/asset-viewers/ImageViewer.tsx +300 -0
  167. package/src/kit/components/asset-viewers/JsonAssetDocument.tsx +98 -0
  168. package/src/kit/components/asset-viewers/OnlineAssetDetail.tsx +426 -0
  169. package/src/kit/components/asset-viewers/SourceAssetViewer.tsx +356 -0
  170. package/src/kit/components/asset-viewers/SpritesheetSpriteView.tsx +102 -0
  171. package/src/kit/components/asset-viewers/VideoViewer.tsx +101 -0
  172. package/src/kit/components/asset-viewers/shader-source.ts +144 -0
  173. package/src/kit/components/board-guides.ts +150 -0
  174. package/src/kit/components/canvas-scene-hotkeys.ts +37 -0
  175. package/src/kit/components/canvas-temporary-pivot.ts +34 -0
  176. package/src/kit/components/core-utilities.tsx +94 -0
  177. package/src/kit/components/inspector-preview-section.tsx +223 -0
  178. package/src/kit/components/inspector-revert-label.ts +20 -0
  179. package/src/kit/components/inspector-selection.ts +42 -0
  180. package/src/kit/components/inspector-stories-gating.ts +171 -0
  181. package/src/kit/components/inspector-transform-subject.ts +11 -0
  182. package/src/kit/components/inspector-transform.ts +88 -0
  183. package/src/kit/components/kind-documents.tsx +544 -0
  184. package/src/kit/components/primitives/DraftColorInput.tsx +74 -0
  185. package/src/kit/components/project-tool-documents.tsx +402 -0
  186. package/src/kit/components/scene-documents.tsx +221 -0
  187. package/src/kit/components/status-contributions.tsx +407 -0
  188. package/src/kit/components/tool-documents.tsx +302 -0
  189. package/src/kit/components/tool-schema-form.tsx +262 -0
  190. package/src/kit/components/use-after-paint.ts +41 -0
  191. package/src/kit/components/use-project-image-assets.ts +86 -0
  192. package/src/kit/components/workspace-history.ts +32 -0
  193. package/src/kit/components/world-documents.tsx +570 -0
  194. package/src/kit/components/world-overlay-gestures.ts +1939 -0
  195. package/src/kit/composite-screenshot.ts +2238 -0
  196. package/src/kit/content-entry-source-registry.ts +184 -0
  197. package/src/kit/contribution-surfaces.ts +48 -0
  198. package/src/kit/coverage/canvas-reveal.ts +192 -0
  199. package/src/kit/coverage/design-time-surfaces.ts +101 -0
  200. package/src/kit/coverage/ontology-invariants.ts +466 -0
  201. package/src/kit/coverage/session-vitals.ts +503 -0
  202. package/src/kit/crash-null-boundary.ts +36 -0
  203. package/src/kit/creation-site-edit.ts +1491 -0
  204. package/src/kit/creation-site-registry.ts +160 -0
  205. package/src/kit/delegate-harness-registry.ts +134 -0
  206. package/src/kit/document-areas.ts +70 -0
  207. package/src/kit/document-context-registry.ts +193 -0
  208. package/src/kit/document-open-registry.ts +200 -0
  209. package/src/kit/document-play-extension.ts +221 -0
  210. package/src/kit/document-preview-source.ts +20 -0
  211. package/src/kit/document-renderer-session.ts +138 -0
  212. package/src/kit/document-stage-sessions.ts +26 -0
  213. package/src/kit/document-viewports.ts +120 -0
  214. package/src/kit/editor-api.ts +46 -0
  215. package/src/kit/editor-chrome-capture.ts +136 -0
  216. package/src/kit/editor-commands.ts +176 -0
  217. package/src/kit/editor-console.ts +580 -0
  218. package/src/kit/editor-current-view.ts +56 -0
  219. package/src/kit/editor-document-probe.ts +1166 -0
  220. package/src/kit/editor-git-client.ts +115 -0
  221. package/src/kit/editor-hotkeys.ts +728 -0
  222. package/src/kit/editor-lease-view.ts +39 -0
  223. package/src/kit/editor-lease.ts +415 -0
  224. package/src/kit/editor-mode.ts +19 -0
  225. package/src/kit/editor-notifications.ts +140 -0
  226. package/src/kit/editor-presence.ts +563 -0
  227. package/src/kit/editor-presentation-activity.ts +58 -0
  228. package/src/kit/editor-presentation-notice.ts +42 -0
  229. package/src/kit/editor-runtime.tsx +147 -0
  230. package/src/kit/editor-server-response.ts +86 -0
  231. package/src/kit/editor-session-attribution.ts +85 -0
  232. package/src/kit/editor-session-mode.ts +54 -0
  233. package/src/kit/editor-state-facets.ts +74 -0
  234. package/src/kit/editor-view-presentation.ts +777 -0
  235. package/src/kit/environment-images.ts +58 -0
  236. package/src/kit/eyedropper-session.ts +60 -0
  237. package/src/kit/files/file-provider.ts +62 -0
  238. package/src/kit/files/project-files.ts +270 -0
  239. package/src/kit/finders/index.ts +137 -0
  240. package/src/kit/finders/scenes-from-entrypoint-selection.ts +387 -0
  241. package/src/kit/frame/frame-parts.ts +30 -0
  242. package/src/kit/framed-document-capture.ts +34 -0
  243. package/src/kit/game-globals-prelude.ts +143 -0
  244. package/src/kit/game-surface-defaults.ts +33 -0
  245. package/src/kit/gameplay-dom-recording.ts +318 -0
  246. package/src/kit/gameplay-export-state.ts +14 -0
  247. package/src/kit/gameplay-replay.ts +417 -0
  248. package/src/kit/gameplay-session-time.ts +9 -0
  249. package/src/kit/gameplay-sessions.ts +204 -0
  250. package/src/kit/hierarchy-component-marks.ts +298 -0
  251. package/src/kit/hierarchy-internals.ts +197 -0
  252. package/src/kit/hierarchy-kind-icon.ts +217 -0
  253. package/src/kit/hierarchy-menu-registry.ts +67 -0
  254. package/src/kit/hierarchy-node-rows.ts +307 -0
  255. package/src/kit/hierarchy-panel-view.ts +280 -0
  256. package/src/kit/hierarchy-projection.ts +76 -0
  257. package/src/kit/hierarchy-row-media.ts +45 -0
  258. package/src/kit/hierarchy-row-model.ts +308 -0
  259. package/src/kit/hierarchy-rows.ts +11 -0
  260. package/src/kit/hierarchy-walk.ts +86 -0
  261. package/src/kit/history/editor-session.ts +25 -0
  262. package/src/kit/history/history-commands.ts +147 -0
  263. package/src/kit/history/history-delegate.ts +187 -0
  264. package/src/kit/history/history-limit-notices.ts +43 -0
  265. package/src/kit/history/history-service.ts +1189 -0
  266. package/src/kit/history/persistence-coordinator.ts +35 -0
  267. package/src/kit/history/project-file-history.ts +386 -0
  268. package/src/kit/history/project-root-history-backends.ts +139 -0
  269. package/src/kit/history/resource-registry.ts +209 -0
  270. package/src/kit/history/snapshot-store.ts +103 -0
  271. package/src/kit/history/source-history-backend.ts +546 -0
  272. package/src/kit/history-types.ts +124 -0
  273. package/src/kit/hmr-registration-group.ts +67 -0
  274. package/src/kit/hmr-stable-react-context.ts +23 -0
  275. package/src/kit/hotkeys.ts +190 -0
  276. package/src/kit/inference-diagnostics.ts +69 -0
  277. package/src/kit/initial-project.ts +80 -0
  278. package/src/kit/inspection/active-subject.ts +571 -0
  279. package/src/kit/inspection/active-surface.ts +142 -0
  280. package/src/kit/inspection/compose-subject.ts +1055 -0
  281. package/src/kit/inspection/compose.ts +7 -0
  282. package/src/kit/inspection/display.ts +171 -0
  283. package/src/kit/inspection/document-subject.ts +109 -0
  284. package/src/kit/inspection/game-subject.ts +85 -0
  285. package/src/kit/inspection/null-subject.ts +119 -0
  286. package/src/kit/inspection/serialize.ts +357 -0
  287. package/src/kit/inspection/use-active-inspection.ts +180 -0
  288. package/src/kit/inspection-model.ts +542 -0
  289. package/src/kit/inspection-node-media.ts +58 -0
  290. package/src/kit/inspector-presentation.ts +203 -0
  291. package/src/kit/inspector-property-grouping.ts +64 -0
  292. package/src/kit/inspector-section-registry.ts +221 -0
  293. package/src/kit/instance-source-actions.ts +163 -0
  294. package/src/kit/js-heap.ts +71 -0
  295. package/src/kit/key-actions.ts +91 -0
  296. package/src/kit/keymap-presets.ts +428 -0
  297. package/src/kit/layout-policy.ts +31 -0
  298. package/src/kit/light-explorer-model.ts +134 -0
  299. package/src/kit/live-canvas-frame.ts +55 -0
  300. package/src/kit/live-document.ts +296 -0
  301. package/src/kit/live-gesture-lock.ts +50 -0
  302. package/src/kit/live-seam-evidence.ts +11 -0
  303. package/src/kit/live-session-registry.ts +220 -0
  304. package/src/kit/live-transition.ts +391 -0
  305. package/src/kit/manifest-project.ts +107 -0
  306. package/src/kit/module-fetch-diagnosis.ts +192 -0
  307. package/src/kit/mount-failure-report.ts +154 -0
  308. package/src/kit/native-selection-style.ts +497 -0
  309. package/src/kit/object3d-document-write-policy.ts +137 -0
  310. package/src/kit/packaged-runtime.ts +108 -0
  311. package/src/kit/palettes/maya.palette.json +57 -0
  312. package/src/kit/palettes/substance.palette.json +57 -0
  313. package/src/kit/performance-profiler.ts +367 -0
  314. package/src/kit/performance-sources.ts +69 -0
  315. package/src/kit/photograph-notice.ts +141 -0
  316. package/src/kit/play-boot-phase.ts +166 -0
  317. package/src/kit/play-camera-flight.ts +35 -0
  318. package/src/kit/png-encode.worker.ts +26 -0
  319. package/src/kit/presentation-surface.ts +248 -0
  320. package/src/kit/product-command.ts +90 -0
  321. package/src/kit/project-adapter.ts +1140 -0
  322. package/src/kit/project-asset-refresh.ts +23 -0
  323. package/src/kit/project-asset-roots.ts +68 -0
  324. package/src/kit/project-local-state.ts +151 -0
  325. package/src/kit/project-manager.ts +243 -0
  326. package/src/kit/project-module-changes.ts +201 -0
  327. package/src/kit/project-module-split.ts +270 -0
  328. package/src/kit/project-play-layers.ts +25 -0
  329. package/src/kit/project-provenance.ts +115 -0
  330. package/src/kit/project-ready.ts +42 -0
  331. package/src/kit/project-shape.ts +68 -0
  332. package/src/kit/project-tools.ts +107 -0
  333. package/src/kit/projection-types.ts +44 -0
  334. package/src/kit/readiness.ts +113 -0
  335. package/src/kit/renderer-resource-counts.ts +27 -0
  336. package/src/kit/reported-play-state.ts +90 -0
  337. package/src/kit/resolve-contributed-command.ts +14 -0
  338. package/src/kit/resolve-relative-specifier.ts +33 -0
  339. package/src/kit/retained-document-states.ts +91 -0
  340. package/src/kit/scene-document-plan.ts +320 -0
  341. package/src/kit/scene-live-open.ts +210 -0
  342. package/src/kit/scoped-game-css.ts +152 -0
  343. package/src/kit/served-url.ts +5 -0
  344. package/src/kit/session-close.ts +17 -0
  345. package/src/kit/session-tombstone.ts +127 -0
  346. package/src/kit/settings/settings-provider.ts +82 -0
  347. package/src/kit/settings-store.ts +348 -0
  348. package/src/kit/shell-document-state.ts +27 -0
  349. package/src/kit/shell-store-door.ts +45 -0
  350. package/src/kit/shell-store.ts +722 -0
  351. package/src/kit/source-conflict.ts +122 -0
  352. package/src/kit/stage-context.ts +377 -0
  353. package/src/kit/stage-invalidation.ts +25 -0
  354. package/src/kit/stage-store-registry.ts +69 -0
  355. package/src/kit/startup-failure.ts +80 -0
  356. package/src/kit/state-report-deferral.ts +73 -0
  357. package/src/kit/storage/host-files-storage.ts +97 -0
  358. package/src/kit/storage/http-storage.ts +174 -0
  359. package/src/kit/storage/index.ts +75 -0
  360. package/src/kit/storage/mem-storage.ts +158 -0
  361. package/src/kit/storage/path-lock.ts +44 -0
  362. package/src/kit/storage/paths.ts +26 -0
  363. package/src/kit/storage-types.ts +127 -0
  364. package/src/kit/stories/StoryPreviewMount.tsx +306 -0
  365. package/src/kit/stories/compose-project-stories.ts +255 -0
  366. package/src/kit/stories/prefabs-finder.ts +54 -0
  367. package/src/kit/stories/prefabs-from-stories.ts +182 -0
  368. package/src/kit/stories/project-story-regions.ts +24 -0
  369. package/src/kit/stories/story-capture.ts +579 -0
  370. package/src/kit/stories/story-declared-medium.ts +126 -0
  371. package/src/kit/stories/story-discovery.ts +176 -0
  372. package/src/kit/stories/story-dom-runtime.ts +78 -0
  373. package/src/kit/stories/story-grouping.ts +111 -0
  374. package/src/kit/stories/story-mount-turn.ts +27 -0
  375. package/src/kit/stories/story-presentation.ts +215 -0
  376. package/src/kit/stories/story-preview-component.ts +7 -0
  377. package/src/kit/stories/story-registry.ts +530 -0
  378. package/src/kit/stories-scope.ts +35 -0
  379. package/src/kit/story-document-openers.ts +36 -0
  380. package/src/kit/story-thumbnails.ts +47 -0
  381. package/src/kit/surface-keyboard.ts +101 -0
  382. package/src/kit/surface-state.ts +135 -0
  383. package/src/kit/system-seam-evidence.ts +72 -0
  384. package/src/kit/tab-census.ts +202 -0
  385. package/src/kit/tab-lifecycle-client.ts +227 -0
  386. package/src/kit/theme-library.ts +897 -0
  387. package/src/kit/theme-preference.ts +429 -0
  388. package/src/kit/three-viewport-presentation.ts +23 -0
  389. package/src/kit/tool-contribution-play.ts +74 -0
  390. package/src/kit/tool-loader.ts +1918 -0
  391. package/src/kit/transform-mode-request.ts +66 -0
  392. package/src/kit/transient-hint.ts +78 -0
  393. package/src/kit/transport-strip.tsx +174 -0
  394. package/src/kit/ui-source/adapter-region-includes.ts +238 -0
  395. package/src/kit/ui-source/file-region-resolver.ts +302 -0
  396. package/src/kit/ui-source/inspect.ts +775 -0
  397. package/src/kit/ui-source/source-write-backend.ts +605 -0
  398. package/src/kit/ui-source/tier-source-write-backend.ts +279 -0
  399. package/src/kit/user-local-state.ts +105 -0
  400. package/src/kit/viewport-activation-timings.ts +840 -0
  401. package/src/kit/viewport-editor-controls.ts +22 -0
  402. package/src/kit/viewport-presentation.ts +668 -0
  403. package/src/kit/viewport-surface-status.tsx +55 -0
  404. package/src/kit/wait-until.ts +37 -0
  405. package/src/kit/worker-call-metrics.ts +166 -0
  406. package/src/kit/workspace-areas.ts +191 -0
  407. package/src/kit/workspace-aux-commands.ts +11 -0
  408. package/src/kit/workspace-available-documents.ts +142 -0
  409. package/src/kit/workspace-core-utilities.ts +31 -0
  410. package/src/kit/workspace-document-ids.ts +59 -0
  411. package/src/kit/workspace-document-registry.ts +624 -0
  412. package/src/kit/workspace-document-restore.ts +146 -0
  413. package/src/kit/workspace-host-commands.ts +141 -0
  414. package/src/kit/workspace-persistence-gate.ts +40 -0
  415. package/src/kit/workspace-play-utilities.ts +44 -0
  416. package/src/kit/workspace-presets.ts +446 -0
  417. package/src/kit/workspace-regions.ts +276 -0
  418. package/src/kit/workspace-static-panels.ts +73 -0
  419. package/src/kit/workspace-status-registry.ts +121 -0
  420. package/src/kit/workspace-storage.ts +35 -0
  421. package/src/kit/workspace-style.ts +226 -0
  422. package/src/kit/workspace-utility-commands.ts +74 -0
  423. package/src/kit/workspace-utility-registry.ts +263 -0
  424. package/src/kit/world-adoption-event.ts +23 -0
  425. package/src/kit/world-adoption.ts +115 -0
  426. package/src/kit/world-canvas-viewport-state.ts +35 -0
  427. package/src/kit/world-document-routing.ts +104 -0
  428. package/src/kit/world-pan-state.ts +198 -0
  429. package/src/kit/write-pipe.ts +173 -0
  430. package/src/layout-arrangements.ts +5 -0
  431. package/src/layouts.tsx +108 -0
  432. package/src/looks.ts +16 -0
  433. package/src/project/output-roots.ts +73 -0
  434. package/src/project/tab-census.ts +155 -0
  435. package/src/project-tool-catalog.ts +104 -0
  436. package/src/selection.tsx +107 -0
  437. package/src/services.ts +18 -0
  438. package/src/session/build-report.ts +22 -0
  439. package/src/session/collaboration-types.ts +262 -0
  440. package/src/session/command-table.ts +327 -0
  441. package/src/session/discovery.ts +100 -0
  442. package/src/session/editor-brand.ts +48 -0
  443. package/src/session/editor-compatibility.ts +317 -0
  444. package/src/session/editor-control-lifecycle.ts +68 -0
  445. package/src/session/editor-control-protocol.ts +5 -0
  446. package/src/session/entrypoint-selection-readers.ts +66 -0
  447. package/src/session/entrypoint-selection-source.ts +120 -0
  448. package/src/session/game-css-scope.ts +30 -0
  449. package/src/session/hosted-attachment.ts +225 -0
  450. package/src/session/limited-view.ts +82 -0
  451. package/src/session/product-create.ts +24 -0
  452. package/src/session/product-locator.ts +478 -0
  453. package/src/session/project-module-url.ts +242 -0
  454. package/src/session/project-serving.ts +164 -0
  455. package/src/session/project-upgrade.ts +403 -0
  456. package/src/session/registry-format.ts +210 -0
  457. package/src/session/relative-path-guard.ts +56 -0
  458. package/src/session/scoped-game-css.ts +461 -0
  459. package/src/session/source-glob.ts +15 -0
  460. package/src/session/tool-contribution-convention.ts +123 -0
  461. package/src/session/workbench-locator.ts +712 -0
  462. package/src/session.ts +41 -0
  463. package/src/share.ts +160 -0
  464. package/src/source-analysis.ts +28 -0
  465. package/src/source-authoring.ts +439 -0
  466. package/src/tools/errors.ts +91 -0
  467. package/src/tools/provider-execution.ts +70 -0
  468. package/src/tools/registry.ts +341 -0
  469. package/src/tools/types.ts +159 -0
  470. package/src/transport.ts +100 -0
  471. package/src/types.ts +1693 -0
  472. package/src/views.ts +164 -0
  473. package/src/widgets/design-system.ts +93 -0
  474. package/src/widgets/editor-appearance.ts +151 -0
  475. package/src/widgets/editor-material.ts +83 -0
  476. package/src/widgets/icon-set-registry.ts +105 -0
  477. package/src/widgets/index.ts +71 -0
  478. package/src/widgets/inspector-widgets/AlignmentGrid.tsx +182 -0
  479. package/src/widgets/inspector-widgets/AssetSlotPicker.tsx +123 -0
  480. package/src/widgets/inspector-widgets/BorderEditor.tsx +309 -0
  481. package/src/widgets/inspector-widgets/ColorPicker.tsx +549 -0
  482. package/src/widgets/inspector-widgets/CurveEditor.tsx +359 -0
  483. package/src/widgets/inspector-widgets/FilterEditor.tsx +108 -0
  484. package/src/widgets/inspector-widgets/FontPicker.tsx +191 -0
  485. package/src/widgets/inspector-widgets/GradientEditor.tsx +623 -0
  486. package/src/widgets/inspector-widgets/ScrubbableInput.tsx +180 -0
  487. package/src/widgets/inspector-widgets/ShadowEditor.tsx +319 -0
  488. package/src/widgets/inspector-widgets/color-utils.ts +201 -0
  489. package/src/widgets/inspector-widgets/curve-utils.ts +212 -0
  490. package/src/widgets/inspector-widgets/index.ts +25 -0
  491. package/src/widgets/inspector-widgets/shared.tsx +140 -0
  492. package/src/widgets/interactive-edit-scope.ts +33 -0
  493. package/src/widgets/patterns/Dialog.tsx +140 -0
  494. package/src/widgets/patterns/Fields.tsx +44 -0
  495. package/src/widgets/patterns/List.tsx +25 -0
  496. package/src/widgets/patterns/StateSurface.tsx +40 -0
  497. package/src/widgets/patterns/Surfaces.tsx +122 -0
  498. package/src/widgets/patterns/Tabs.tsx +80 -0
  499. package/src/widgets/patterns/Toolbar.tsx +72 -0
  500. package/src/widgets/patterns/Tree.tsx +72 -0
  501. package/src/widgets/primitives/AnchoredMenu.tsx +260 -0
  502. package/src/widgets/primitives/Button.tsx +62 -0
  503. package/src/widgets/primitives/ColorInput.tsx +78 -0
  504. package/src/widgets/primitives/DraftTextInput.tsx +63 -0
  505. package/src/widgets/primitives/EditorIcon.tsx +157 -0
  506. package/src/widgets/primitives/FormControls.tsx +88 -0
  507. package/src/widgets/primitives/HoverPreview.tsx +96 -0
  508. package/src/widgets/primitives/JsonInput.tsx +113 -0
  509. package/src/widgets/primitives/Layout.tsx +100 -0
  510. package/src/widgets/primitives/Menu.tsx +161 -0
  511. package/src/widgets/primitives/NumberInput.tsx +169 -0
  512. package/src/widgets/primitives/Panel.tsx +80 -0
  513. package/src/widgets/primitives/SectionHeader.tsx +77 -0
  514. package/src/widgets/primitives/Text.tsx +54 -0
  515. package/src/widgets/primitives/ThemeRootPortal.tsx +52 -0
  516. package/src/widgets/primitives/Tooltip.tsx +204 -0
  517. package/src/widgets/primitives/Vec3Input.tsx +70 -0
  518. package/src/widgets/primitives/banner-tones.ts +32 -0
  519. package/src/widgets/primitives/clamp-to-viewport.ts +44 -0
  520. package/src/widgets/primitives/editor-icons.ts +254 -0
  521. package/src/widgets/primitives/panel-header-styles.ts +42 -0
  522. package/src/widgets/theme.ts +2841 -0
  523. package/src/widgets/z-index.ts +25 -0
@@ -0,0 +1,122 @@
1
+ import { assertEditorServerAnswered } from '@volter/sdk/kit/editor-server-response';
2
+
3
+ export interface SourceConflictResource {
4
+ path: string;
5
+ revision: number;
6
+ sha: string | null;
7
+ }
8
+
9
+ export interface SourceConflictNotice {
10
+ id: string;
11
+ conflictId: string;
12
+ label: string;
13
+ expectedRevision: number;
14
+ currentRevision: number;
15
+ conflicts: SourceConflictResource[];
16
+ attempted: Record<string, string | null>;
17
+ base: Record<string, string | null>;
18
+ reapply?: (() => Promise<void>) | undefined;
19
+ }
20
+
21
+ const listeners = new Set<(notice: SourceConflictNotice | null) => void>();
22
+ let current: SourceConflictNotice | null = null;
23
+
24
+ export function sourceConflictNotice(): SourceConflictNotice | null {
25
+ return current;
26
+ }
27
+
28
+ export function subscribeSourceConflict(
29
+ listener: (notice: SourceConflictNotice | null) => void,
30
+ ): () => void {
31
+ listeners.add(listener);
32
+ return () => listeners.delete(listener);
33
+ }
34
+
35
+ export function clearSourceConflict(): void {
36
+ current = null;
37
+ for (const listener of listeners) listener(null);
38
+ }
39
+
40
+ export async function handleProjectMutationFailure(
41
+ response: Response,
42
+ input: {
43
+ label: string;
44
+ attempted?: Record<string, string | null>;
45
+ reapply?: () => Promise<void>;
46
+ },
47
+ ): Promise<never> {
48
+ const payload = (await response.json().catch(() => null)) as {
49
+ code?: unknown;
50
+ conflictId?: unknown;
51
+ error?: unknown;
52
+ expectedRevision?: unknown;
53
+ currentRevision?: unknown;
54
+ conflicts?: unknown;
55
+ bases?: unknown;
56
+ } | null;
57
+ if (
58
+ response.status === 409 &&
59
+ payload?.code === 'SOURCE_REVISION_CONFLICT' &&
60
+ typeof payload.conflictId === 'string' &&
61
+ Number.isInteger(payload.expectedRevision) &&
62
+ Number.isInteger(payload.currentRevision) &&
63
+ Array.isArray(payload.conflicts)
64
+ ) {
65
+ current = {
66
+ id: globalThis.crypto?.randomUUID?.() ?? `conflict-${Date.now()}`,
67
+ conflictId: payload.conflictId,
68
+ label: input.label,
69
+ expectedRevision: payload.expectedRevision as number,
70
+ currentRevision: payload.currentRevision as number,
71
+ conflicts: payload.conflicts as SourceConflictResource[],
72
+ attempted: { ...(input.attempted ?? {}) },
73
+ base:
74
+ payload.bases && typeof payload.bases === 'object' && !Array.isArray(payload.bases)
75
+ ? { ...(payload.bases as Record<string, string | null>) }
76
+ : {},
77
+ ...(input.reapply ? { reapply: input.reapply } : {}),
78
+ };
79
+ for (const listener of listeners) listener(current);
80
+ throw new Error(
81
+ `${input.label} conflicts with source revision ${current.currentRevision}; inspect it before reapplying.`,
82
+ );
83
+ }
84
+ throw new Error(
85
+ typeof payload?.error === 'string'
86
+ ? payload.error
87
+ : `${input.label} failed with HTTP ${response.status}.`,
88
+ );
89
+ }
90
+
91
+ export async function resolveSourceConflict(
92
+ notice: SourceConflictNotice,
93
+ resources: Record<string, string | null>,
94
+ ): Promise<void> {
95
+ const { sourceMutationAttribution } = await import('@volter/sdk/kit/editor-session-attribution');
96
+ const response = await fetch('/__editor/source-conflict/resolve', {
97
+ method: 'POST',
98
+ headers: { 'Content-Type': 'application/json' },
99
+ body: JSON.stringify({
100
+ conflictId: notice.conflictId,
101
+ resources: Object.entries(resources).map(([path, content]) => ({ path, content })),
102
+ ...sourceMutationAttribution(),
103
+ }),
104
+ });
105
+ // This function REPORTS BY RETURNING, so a page fallback (which is `ok`)
106
+ // used to close the conflict banner over a resolution nobody applied.
107
+ assertEditorServerAnswered(response, 'Conflict resolution failed');
108
+ if (!response.ok) {
109
+ if (response.status === 409) {
110
+ await handleProjectMutationFailure(response, {
111
+ label: 'Resolve source conflict',
112
+ attempted: resources,
113
+ });
114
+ }
115
+ const body = (await response.json().catch(() => null)) as { error?: unknown } | null;
116
+ throw new Error(
117
+ typeof body?.error === 'string'
118
+ ? body.error
119
+ : `Conflict resolution failed (${response.status}).`,
120
+ );
121
+ }
122
+ }
@@ -0,0 +1,377 @@
1
+ /**
2
+ * WHAT A STAGE IS SHOWING — the ONE derived answer every stage capability asks.
3
+ *
4
+ * ARCHITECTURE-CORE §One stage: there is one 3D stage host, and a capability is
5
+ * present on a stage wherever its CONDITION holds — never by the origin or kind
6
+ * of the document that happens to have opened it. Before this, four gates spelled
7
+ * that question four ways in three places (`threeSurfaceToolsApply` for the shelf
8
+ * rail, `showThreejsTools` in the scene panel, `studioStage`/`hasShell` in the
9
+ * document host), which is why a prefab's stage and the world root's stage could
10
+ * not be the same code.
11
+ *
12
+ * It is a FUNCTION over the stores the panels already subscribe to, not a store
13
+ * of its own — the method transcribed from `inspection/active-surface.ts`, whose
14
+ * docblock states the rule: the surface is derived, never held. Callers keep
15
+ * their existing `useSyncExternalStore` subscriptions (shell store, active
16
+ * authoring, the session registry); this module only reads.
17
+ */
18
+
19
+ import { stageTransformDoor } from '@volter/sdk/contributions';
20
+ import { getActiveAuthoring } from './authoring/active-adapter';
21
+ import { CompositeAuthoringAdapter } from '@volter/sdk/kit/authoring/composite-authoring-adapter';
22
+ import { documentStageSession } from '@volter/sdk/kit/document-stage-sessions';
23
+ import {
24
+ isViewportToolContextVisible,
25
+ resolveViewportToolContext,
26
+ } from './authoring/viewport-tool-context';
27
+ import { isThreejsSurfaceVisible } from './authoring/three-root';
28
+ import { stageStore } from './stage-store-registry';
29
+ import { activeWorkspaceDocumentId, openWorkspaceDocuments } from '@volter/sdk/kit/workspace-document-registry';
30
+ import type { ShellStore } from '@volter/sdk/kit/shell-store';
31
+
32
+ export type StageSurface = 'three' | 'canvas' | 'dom';
33
+
34
+ /** The documents painting a 2D canvas stage right now, as each says while it is mounted. */
35
+ const canvasStageDocuments = new Map<string, number>();
36
+
37
+ /** A document's canvas stage is mounted: its stage context reports the `canvas` surface (what a
38
+ * 2D view's keys key on) until the returned release runs. */
39
+ export function markCanvasStageDocument(documentId: string): () => void {
40
+ canvasStageDocuments.set(documentId, (canvasStageDocuments.get(documentId) ?? 0) + 1);
41
+ return () => {
42
+ const left = (canvasStageDocuments.get(documentId) ?? 1) - 1;
43
+ if (left > 0) canvasStageDocuments.set(documentId, left);
44
+ else canvasStageDocuments.delete(documentId);
45
+ };
46
+ }
47
+
48
+ /** What the stage's document IS — the document's own `presentation()` kind
49
+ * (`WorkspaceDocumentDescriptor.presentation`), folded to the subjects a
50
+ * stage distinguishes. `unknown` when the descriptor declares none. */
51
+ export type StageSubject =
52
+ | { readonly kind: 'composition' } // presentation 'scene' | 'world' (a scene, a manifest root)
53
+ | { readonly kind: 'story' } // 'story' — a piece in isolation with its parameters
54
+ | { readonly kind: 'artifact' } // 'asset' — an ecosystem artifact (glTF, particles, a model)
55
+ | { readonly kind: 'data' } // 'document' — an adapter-table document (a model, a page)
56
+ | { readonly kind: 'unknown' };
57
+
58
+ export interface StageSelection {
59
+ readonly count: number;
60
+ /** The surface that owns the whole selection; null when empty or mixed. */
61
+ readonly surface: StageSurface | null;
62
+ /** Whether that owner is painted on this stage (hidden roots are not). */
63
+ readonly visible: boolean;
64
+ }
65
+
66
+ /**
67
+ * Whether the stage has chrome of its own, or is EMBEDDED in another surface
68
+ * with none (the inspector's object preview). It is a genuine condition OF THE
69
+ * STAGE — the same kind of fact as `surface`, `selection` and `play` — never
70
+ * the origin or kind of a document; and the HOST is the only thing that knows
71
+ * it, because an embedded preview has no workspace document at all (which is
72
+ * exactly why `subjectOf` answers `unknown` for one). So the host supplies it
73
+ * and nothing is inferred (decided 2026-09-18, an application of
74
+ * ARCHITECTURE-CORE §One stage's own rule).
75
+ */
76
+ export type StageChrome = 'document' | 'embedded';
77
+
78
+ export interface StageContext {
79
+ readonly documentId: string | null;
80
+ readonly chrome: StageChrome;
81
+ readonly subject: StageSubject;
82
+ /** The surface the stage paints; null when nothing is showing. */
83
+ readonly surface: StageSurface | null;
84
+ readonly selection: StageSelection;
85
+ readonly play: 'stopped' | 'playing' | 'paused';
86
+ }
87
+
88
+ const EMPTY_SELECTION: StageSelection = { count: 0, surface: null, visible: false };
89
+
90
+ function stageSurfaceOf(kind: string | undefined): StageSurface | null {
91
+ return kind === 'three' || kind === 'canvas' || kind === 'dom' ? kind : null;
92
+ }
93
+
94
+ function subjectFromKind(kind: string | undefined): StageSubject {
95
+ switch (kind) {
96
+ case 'scene':
97
+ case 'world':
98
+ return { kind: 'composition' };
99
+ case 'story':
100
+ return { kind: 'story' };
101
+ case 'asset':
102
+ return { kind: 'artifact' };
103
+ case 'document':
104
+ return { kind: 'data' };
105
+ default:
106
+ return { kind: 'unknown' };
107
+ }
108
+ }
109
+
110
+ function subjectOf(documentId: string | null): StageSubject {
111
+ if (documentId === null) return { kind: 'unknown' };
112
+ const open = openWorkspaceDocuments().find((doc) => doc.descriptor.id === documentId);
113
+ if (!open) return { kind: 'unknown' };
114
+ const presentation = open.descriptor.presentation?.() ?? null;
115
+ const projected = subjectFromKind(presentation?.kind);
116
+ if (projected.kind !== 'unknown') return projected;
117
+ // The document's own declared KIND is the fallback, and it is a real answer
118
+ // rather than a guess: `presentation()` is the ADDRESSABLE projection of a
119
+ // document, and a document can legitimately have none while still being an
120
+ // artifact — `asset-documents.tsx:258` returns null for an ONLINE asset and
121
+ // for one with no project path, and reading only the projection took the
122
+ // studio stage off exactly those (measured 2026-09-18, which is why the
123
+ // `documentKind` prop could not simply be deleted without this).
124
+ return subjectFromKind(open.descriptor.kind);
125
+ }
126
+
127
+ /**
128
+ * Whether this adapter PAINTS a three surface at all, selection or not — the
129
+ * no-selection branch of what `threeSurfaceToolsApply` asked before this module
130
+ * existed, transcribed verbatim. A composite paints three when some child does;
131
+ * a single adapter paints three when it is not rect-capable and can hand back an
132
+ * `Object3D` for a node.
133
+ */
134
+ function adapterPaintsThree(adapter: ReturnType<typeof getActiveAuthoring>): boolean {
135
+ if (adapter instanceof CompositeAuthoringAdapter)
136
+ return adapter.childAdapters().some((child) => child.kind === 'three');
137
+ return !adapter.rects && typeof adapter.hierarchy.object3D === 'function';
138
+ }
139
+
140
+ function worldStageContext(
141
+ store: ShellStore,
142
+ documentId: string | null,
143
+ subject: StageSubject,
144
+ chrome: StageChrome,
145
+ ): StageContext {
146
+ const adapter = getActiveAuthoring(store);
147
+ const surface: StageSurface | null =
148
+ isThreejsSurfaceVisible(store) && adapterPaintsThree(adapter) ? 'three' : null;
149
+ const play = store.playState;
150
+ const count = store.selectedEntityIds.size;
151
+ if (count === 0)
152
+ return { documentId, chrome, subject, surface, selection: EMPTY_SELECTION, play };
153
+ const context = resolveViewportToolContext(adapter, store.selectedEntityIds);
154
+ return {
155
+ documentId,
156
+ chrome,
157
+ subject,
158
+ surface,
159
+ selection: {
160
+ count,
161
+ surface: stageSurfaceOf(context?.kind),
162
+ visible: isViewportToolContextVisible(store, context),
163
+ },
164
+ play,
165
+ };
166
+ }
167
+
168
+ /**
169
+ * The stage a given document is showing.
170
+ *
171
+ * Two shapes answer this, and which one applies is a FACT about the document —
172
+ * not a kind it declares: a DOCUMENT stage has registered an
173
+ * `Object3DDocumentSession` (a model, a prefab story, an isolation scene) and
174
+ * its selection is its session's own; everything else is the WORLD stage — the
175
+ * manifest's roots under the shell store, whose selection is the shell's and
176
+ * whose surface is subject to the world-hidden eye.
177
+ */
178
+ export function documentStageContext(
179
+ store: ShellStore,
180
+ documentId: string,
181
+ chrome: StageChrome = 'document',
182
+ ): StageContext {
183
+ const subject = subjectOf(documentId);
184
+ // A canvas document paints the 2D stage whatever else the world holds (a 3D game with a 2D
185
+ // root included); its keys follow this.
186
+ if (canvasStageDocuments.has(documentId)) {
187
+ const world = worldStageContext(store, documentId, subject, chrome);
188
+ return { ...world, surface: 'canvas' };
189
+ }
190
+ const session = documentStageSession(documentId);
191
+ if (session === null) {
192
+ // A RESOURCE document with no stage session of its own (a table, a
193
+ // report, a text document) shows no stage at all; only the world's own
194
+ // documents answer with the world stage.
195
+ const kind = openWorkspaceDocuments().find((doc) => doc.descriptor.id === documentId)
196
+ ?.descriptor.kind;
197
+ if (kind !== undefined && kind !== 'game' && kind !== 'scene' && kind !== 'world')
198
+ return {
199
+ documentId,
200
+ chrome,
201
+ subject,
202
+ surface: null,
203
+ selection: EMPTY_SELECTION,
204
+ play: store.playState,
205
+ };
206
+ return worldStageContext(store, documentId, subject, chrome);
207
+ }
208
+ // A document stage's own selection: the session reads it straight off its
209
+ // authoring adapter, and its stage is the only thing painting it, so an owner
210
+ // it reports is by construction three-owned and visible here.
211
+ const count = session.selection().length;
212
+ return {
213
+ documentId,
214
+ chrome,
215
+ subject,
216
+ surface: 'three',
217
+ selection: { count, surface: count > 0 ? 'three' : null, visible: true },
218
+ play: store.playState,
219
+ };
220
+ }
221
+
222
+ /** The stage the FOCUSED document is showing; the world stage when no document
223
+ * is active (the shell with nothing focused still paints the world root). */
224
+ export function focusedStageContext(store: ShellStore): StageContext {
225
+ const documentId = activeWorkspaceDocumentId();
226
+ if (documentId !== null) return documentStageContext(store, documentId);
227
+ return worldStageContext(store, null, { kind: 'unknown' }, 'document');
228
+ }
229
+
230
+ /**
231
+ * THE STORE THE FOCUSED STAGE RUNS ON — where a shared panel reads per-stage
232
+ * state (selection, scene/objectMap, camera pose, orbit target, tool state,
233
+ * view options like `showStats`/shading).
234
+ *
235
+ * `shell` is the answer for a focused document with no stage of its own — a
236
+ * tool tab, a text document, the Game tab. That is not a fallback in name
237
+ * only: the world root's stage runs on the session store (see
238
+ * `StageHost.tsx`'s world-root install), so a panel asked while focus sits
239
+ * off every stage keeps reporting the world, exactly as it did before §One
240
+ * stage unit 4.
241
+ *
242
+ * It is a FUNCTION, like the rest of this module: the caller keeps its own
243
+ * subscriptions, and a panel that reads this subscribes to
244
+ * `subscribeStageStores` and `subscribeWorkspaceDocuments` so a mount or a
245
+ * tab switch re-renders it against the new answer.
246
+ */
247
+ export function focusedStageStore(shell: ShellStore): ShellStore {
248
+ return stageStore(activeWorkspaceDocumentId()) ?? shell;
249
+ }
250
+
251
+ /** The host transform strip on a stage's shelf (Blender's persistent rail),
252
+ * where the editor viewport's own gizmo is what it drives. This is the
253
+ * `gizmo` arm of {@link stageTransformDriver} and nothing else asks it. */
254
+ export function transformToolsApply(ctx: StageContext): boolean {
255
+ if (ctx.surface !== 'three') return false;
256
+ if (ctx.selection.count === 0) return true;
257
+ return ctx.selection.surface === 'three' && ctx.selection.visible;
258
+ }
259
+
260
+ /**
261
+ * WHAT THE HOST'S TRANSFORM TOOLS DRIVE ON THIS STAGE — one answer the shelf's
262
+ * strip and the header's transform wells both ask.
263
+ *
264
+ * `gizmo` `EditorViewport`'s `TransformControls`, through the stage's own
265
+ * `EditorShellStore.transformMode` (`stage-store-registry.ts` — NOT
266
+ * the shell's; see `ToolStrip`'s note for the measurement that
267
+ * separates them). The header's four wells configure that same gizmo,
268
+ * so they are drawn with it.
269
+ * `modal` the stage transforms MODALLY instead and declared how
270
+ * (`registerStageTransform`): a mesh module's `G`/`R`/`S`. The three
271
+ * single-channel tools arm it; the all-handles tool and the header
272
+ * wells are NOT DRAWN, because a modal transform is no gizmo and has
273
+ * nothing for a well to configure.
274
+ * `none` not a three stage, or the selection belongs to another surface —
275
+ * `transformToolsApply`'s own condition, unchanged.
276
+ *
277
+ * A DOCUMENT STAGE IS NOT AUTOMATICALLY THE MODAL CASE, and assuming it was is
278
+ * the error this docblock replaces: measured 2026-09-19 on a prefab story, a
279
+ * session-painted stage DOES draw the host's gizmo on its selection. Only a
280
+ * stage that declares a door takes the modal arm.
281
+ */
282
+ export type StageTransformDriver = 'gizmo' | 'modal' | 'none';
283
+
284
+ export function stageTransformDriver(ctx: StageContext): StageTransformDriver {
285
+ if (!transformToolsApply(ctx)) return 'none';
286
+ return stageTransformDoor(ctx.documentId) === null ? 'gizmo' : 'modal';
287
+ }
288
+
289
+ /** The three tools that need a selection (ViewportOverlay, CameraInfo). */
290
+ export function threeSelectionToolsApply(ctx: StageContext): boolean {
291
+ return (
292
+ ctx.surface === 'three' &&
293
+ ctx.selection.count > 0 &&
294
+ ctx.selection.surface === 'three' &&
295
+ ctx.selection.visible
296
+ );
297
+ }
298
+
299
+ /**
300
+ * THE ARTIFACT-FLAVOURED SUBJECT — a piece shown IN ISOLATION that is not the
301
+ * project's own live composition: an artifact (a glTF, a particle system, a
302
+ * model asset), a story (a prefab mounted with its parameters), or a stage
303
+ * EMBEDDED in another surface with no workspace document at all (the
304
+ * inspector's object preview, which is why nothing can infer this one and the
305
+ * host supplies `chrome`).
306
+ *
307
+ * This is the question `documentKind: 'source' | 'asset'` asked as a PROP the
308
+ * caller chose, and it is the base the two conditions below are written
309
+ * against, so they cannot drift apart: it drives the source adapter's
310
+ * `documentKind` (its "derived asset" provenance line and its `model-asset`
311
+ * hierarchy kind) and the `asset` performance-source kind.
312
+ *
313
+ * DATA is deliberately not here. A mesh module is the project's own CODE — it
314
+ * opens in an isolation scene (§A model is data) but nothing about it is a
315
+ * derived asset, and saying so is what the `documentKind` prop did by
316
+ * accident once the studio grew a data arm.
317
+ */
318
+ export function assetSubjectApplies(ctx: StageContext): boolean {
319
+ return (
320
+ ctx.chrome === 'embedded' || ctx.subject.kind === 'story' || ctx.subject.kind === 'artifact'
321
+ );
322
+ }
323
+
324
+ /**
325
+ * THE STUDIO PRESENTATION — the alpha clear and the editor's own backdrop
326
+ * behind a piece in isolation.
327
+ *
328
+ * ARCHITECTURE-CORE §A model is data: "opening data opens an ISOLATION SCENE
329
+ * around it … whose story is the STUDIO". So the studio is every
330
+ * artifact-flavoured subject PLUS data — a mesh module, a page, anything the
331
+ * adapter's table calls a document.
332
+ *
333
+ * The one condition on the data arm is the LOOK, and it is a condition rather
334
+ * than a kind: the studio's backdrop is the EDITOR'S (the alpha canvas over the
335
+ * `.volter-object3d-studio-stage` bloom), and a look that declares its own
336
+ * `color.viewport` group has already said what the 3D viewport is painted —
337
+ * Blender's flat #3f3f3f — so painting the studio over it would be the editor
338
+ * overruling the skew.
339
+ *
340
+ * `lookPaintsViewport` is that group's presence, and it is a PARAMETER rather
341
+ * than a read inside here for two reasons: this module is derived-never-held
342
+ * and the look is not one of the stores its callers already subscribe to (the
343
+ * host subscribes to the theme root itself, `StageHost.tsx`); and importing
344
+ * the renderer's token reader here put `native-selection-style.ts` into
345
+ * `main.tsx`'s pinned closure for a layout predicate, which is the erosion the
346
+ * closure gate exists to stop (measured 2026-09-18: +1 file on `main.tsx` and
347
+ * on both builds). `native-selection-style.ts`'s `lookDeclaresViewportColors`
348
+ * is the one reader of that token, so the stage and the renderer cannot
349
+ * disagree about what is on screen.
350
+ */
351
+ export function studioStageApplies(ctx: StageContext, lookPaintsViewport: boolean): boolean {
352
+ if (assetSubjectApplies(ctx)) return true;
353
+ return ctx.subject.kind === 'data' && !lookPaintsViewport;
354
+ }
355
+
356
+ /**
357
+ * THE IDENTITY-ROW FRAME — the Asset Lab shell around the stage: the row that
358
+ * names the thing, its type and its path, and the one registrar of the
359
+ * document's own workspace selection (the host registers it wherever this
360
+ * shell is absent, and exactly one of the two must).
361
+ *
362
+ * ARCHITECTURE-CORE §One stage: "the identity row when the subject is an
363
+ * ARTIFACT rather than source". It was the studio presentation's own answer
364
+ * until the studio gained a data arm, and it must not follow it there: a mesh
365
+ * module is the project's CODE, so an Asset-Lab row naming it a type and a
366
+ * file path, wrapped around the mesh editor's own header, would say the
367
+ * opposite of what the document is.
368
+ *
369
+ * An EMBEDDED stage never takes it — it has no chrome of its own by
370
+ * definition. Whether a STORY should keep it is the ruling's own open reading
371
+ * (a prefab's truth is source too); no frame of a story document has been
372
+ * read against that sentence, so this stays exactly what
373
+ * `assetSubjectApplies` says and nothing is re-decided blind.
374
+ */
375
+ export function identityRowApplies(ctx: StageContext): boolean {
376
+ return ctx.chrome === 'document' && assetSubjectApplies(ctx);
377
+ }
@@ -0,0 +1,25 @@
1
+ /**
2
+ * THE EDITOR'S OWN CHANGES TO A STAGE'S PICTURE, announced.
3
+ *
4
+ * A stage whose content announces its changes (`ToolObject3DPreviewSource.
5
+ * onChange`) draws only when something changed (`StageHost`'s frame). The
6
+ * content's own changes, the camera, input on the stage, the stage store and
7
+ * playback are each watched there. What remains is the editor acting on a
8
+ * stage from outside all of those -- a view-menu toggle reaching the document
9
+ * session, a helper handed in, a postprocessing chunk that finished loading --
10
+ * and each of those calls {@link invalidateStages}.
11
+ *
12
+ * One counter for every stage rather than a flag per stage: such changes are
13
+ * rare, and a stage that draws one frame it did not strictly need costs
14
+ * nothing, while one that misses a change shows a stale picture.
15
+ */
16
+ let generation = 0;
17
+
18
+ export function invalidateStages(): void {
19
+ generation++;
20
+ }
21
+
22
+ /** Compared by each stage against the value it last drew at. */
23
+ export function stageGeneration(): number {
24
+ return generation;
25
+ }
@@ -0,0 +1,69 @@
1
+ import type { ShellStore } from '@volter/sdk/kit/shell-store';
2
+ /**
3
+ * WHICH STORE A STAGE RUNS ON — the live identities behind
4
+ * `focusedStageStore()` (`stage-context.ts`).
5
+ *
6
+ * ARCHITECTURE-CORE §One stage: no stage is on "the" store by birthright.
7
+ * Every mounted stage owns an `EditorShellStore` holding its own per-stage
8
+ * state — selection, scene/objectMap, camera pose, orbit target, tool state
9
+ * and view options — and the shared panels read whichever one the FOCUSED
10
+ * document's stage runs on. Before this, only one stage's store was reachable
11
+ * (the shell's), so a control mounted over a model or a prefab drove a
12
+ * different stage's state: the grid button toggled the world's grid, and the
13
+ * camera readout reported a camera nobody was looking through.
14
+ *
15
+ * A registry of live identities, deliberately shaped like
16
+ * `authoring/object3d-document-session-registry.ts` — the same job for the
17
+ * same objects, and the reason it is not merged into that module is that a
18
+ * stage has a store BEFORE it has a session (the world root's stage has no
19
+ * `Object3DDocumentSession` at all, measured 2026-09-18). A leaf module with
20
+ * no imports beyond the store's type, so any lane may read it without an
21
+ * import cycle.
22
+ */
23
+
24
+ const stores = new Map<string, { store: ShellStore }>();
25
+ let registryVersion = 0;
26
+ const listeners = new Set<() => void>();
27
+
28
+ function notify(): void {
29
+ registryVersion++;
30
+ for (const listener of [...listeners]) listener();
31
+ }
32
+
33
+ /** A mounted stage declares the store it runs on. Re-registering the same
34
+ * document replaces it; the returned unregister drops it. */
35
+ export function registerStageStore(documentId: string, store: ShellStore): () => void {
36
+ const registration = { store };
37
+ stores.set(documentId, registration);
38
+ notify();
39
+ return () => {
40
+ if (stores.get(documentId) !== registration) return;
41
+ stores.delete(documentId);
42
+ notify();
43
+ };
44
+ }
45
+
46
+ /** The store that document's stage runs on, or `null` for a document with no
47
+ * stage of its own (a tool tab, a text document, the Game tab). */
48
+ export function stageStore(documentId: string | null): ShellStore | null {
49
+ return documentId === null ? null : (stores.get(documentId)?.store ?? null);
50
+ }
51
+
52
+ /** The document whose stage runs on `store`, or null for a store no stage registered. */
53
+ export function stageDocument(store: ShellStore): string | null {
54
+ for (const [documentId, registration] of stores) if (registration.store === store) return documentId;
55
+ return null;
56
+ }
57
+
58
+ /** `useSyncExternalStore` shape — a stage mounting or unmounting changes what
59
+ * `focusedStageStore()` answers, so a panel that reads it subscribes here. */
60
+ export function subscribeStageStores(listener: () => void): () => void {
61
+ listeners.add(listener);
62
+ return () => {
63
+ listeners.delete(listener);
64
+ };
65
+ }
66
+
67
+ export function stageStoresVersion(): number {
68
+ return registryVersion;
69
+ }
@@ -0,0 +1,80 @@
1
+ /**
2
+ * A TERMINAL STARTUP FAILURE, as the FRAME needs it: the product's loading
3
+ * cover (`volterCover.ts`, z-index above every part) sits over the whole
4
+ * editor while it opens, so an error screen drawn beneath it is seen by
5
+ * nobody. Measured on the owner's stream 2026-10-06: a pinned-engine refusal
6
+ * rendered under the cover while it said "Starting Blender…" with a moving bar
7
+ * forever. So whoever decides that startup failed publishes it here, and the
8
+ * bridge hands it to the cover (`mountEditor`'s `startup` door), which replaces
9
+ * its splash with the message and its fix.
10
+ *
11
+ * ANY PART OF THE BOOT PUBLISHES, not only AppRoot: a project that cannot be
12
+ * detected, a page with no project, an editor surface that crashed, a Blender
13
+ * worker that could not open the model. The newest failure is the one shown;
14
+ * `clearStartupFailure(source)` withdraws only that source's, so a Retry that
15
+ * cures one cause does not hide another.
16
+ *
17
+ * ONE REGISTRY PER PAGE, whichever copy of this module a contribution loaded
18
+ * it through (the packaged shell inlines the SDK while a package's
19
+ * contribution is served from the project's own copy), hence the
20
+ * `Symbol.for` key, as `document-play-extension.ts` does.
21
+ */
22
+ export interface StartupFailureNotice {
23
+ readonly message: string;
24
+ readonly guidance: string | null;
25
+ /** The recovery as one pasteable line (`commandSequence`), when it has one. */
26
+ readonly command: string | null;
27
+ /**
28
+ * STILL TRYING, not refused: a slow start that may yet succeed (detection that keeps being
29
+ * re-asked). The cover shows it as progress under its splash, never as a refusal — a
30
+ * refusal is one-way, and a healthy slow start called failed is the reverse of the silent
31
+ * hang this door exists for (#147 review).
32
+ */
33
+ readonly transient?: boolean;
34
+ }
35
+
36
+ interface Registry {
37
+ /** Live failures by source, oldest first; the last is the one shown. */
38
+ readonly failures: Map<string, StartupFailureNotice>;
39
+ readonly listeners: Set<(notice: StartupFailureNotice | null) => void>;
40
+ }
41
+
42
+ const key = Symbol.for('volter.startup-failure');
43
+ const page = globalThis as typeof globalThis & { [key]?: Registry };
44
+ const registry: Registry = page[key] ??= { failures: new Map(), listeners: new Set() };
45
+
46
+ /** The newest refusal, else the newest still-trying notice: a refusal is the stronger fact. */
47
+ function current(): StartupFailureNotice | null {
48
+ const all = [...registry.failures.values()];
49
+ return all.filter((notice) => !notice.transient).at(-1) ?? all.at(-1) ?? null;
50
+ }
51
+
52
+ function publish(): void {
53
+ const notice = current();
54
+ for (const listener of [...registry.listeners]) {
55
+ try { listener(notice); } catch { /* A reader's failure is not the boot's. */ }
56
+ }
57
+ }
58
+
59
+ /** This page's boot failed for `source`'s reason; the cover shows it at once. */
60
+ export function reportStartupFailure(source: string, notice: StartupFailureNotice): void {
61
+ registry.failures.delete(source);
62
+ registry.failures.set(source, notice);
63
+ publish();
64
+ }
65
+
66
+ /** `source`'s failure is over (a Retry got past it). Other sources' stand. */
67
+ export function clearStartupFailure(source: string): void {
68
+ if (registry.failures.delete(source)) publish();
69
+ }
70
+
71
+ /** Hear this page's startup failure — at once if one is standing — and `null`
72
+ * when the last one clears. */
73
+ export function subscribeStartupFailure(
74
+ listener: (notice: StartupFailureNotice | null) => void,
75
+ ): () => void {
76
+ registry.listeners.add(listener);
77
+ const notice = current();
78
+ if (notice) listener(notice);
79
+ return () => { registry.listeners.delete(listener); };
80
+ }