@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,637 @@
1
+ /**
2
+ * Edit-mode authoring — project open loads `volter.project.json` and
3
+ * installs a {@link CompositeAuthoringAdapter} over EVERY declared world, so a
4
+ * project's composition is disclosed in edit mode. Unlike play mode,
5
+ * roots are NOT running here: a world whose SURFACE has a registered live
6
+ * adapter factory (`active-adapter.ts`'s `setBaseAuthoringFactory`, filled by
7
+ * that surface's integration) gets a live projection over whatever is mounted
8
+ * into the store; every other declared world gets a read-only
9
+ * {@link BoundaryAuthoringAdapter} describing it from the manifest, upgraded
10
+ * to a live adapter only once its design-time layer actually mounts.
11
+ *
12
+ * THIS MODULE NAMES NO SURFACE. It used to pick the project's `three` root by
13
+ * name and build that one adapter itself; the surface key is what replaced
14
+ * that, so a second integration is a registration rather than a branch here.
15
+ *
16
+ * A project with one world and a project with
17
+ * many roots use the SAME game/world authoring tree. Cardinality may affect
18
+ * presentation density, never hierarchy semantics, routing, or persistence.
19
+ * Manifest-less projects still synthesize the conventional `main` world, so
20
+ * every project reaches this one path.
21
+ */
22
+
23
+ import { declaredRoots } from '@volter/project/adapter/manifest-interpreter';
24
+ import { editorConsole } from '@volter/sdk/kit/editor-console';
25
+ import { assertEditorServerAnswered } from '@volter/sdk/kit/editor-server-response';
26
+ import { sourceMutationAttribution } from '@volter/sdk/kit/editor-session-attribution';
27
+ import { hierarchyProjectionFromProjectConfig } from '@volter/sdk/kit/hierarchy-projection';
28
+ import { getProjectFileHistory, type ProjectFileHistory } from '@volter/sdk/kit/history/project-file-history';
29
+ import { getManifestHistoryBackend } from '@volter/sdk/kit/history/project-root-history-backends';
30
+ import { fetchRawGameManifest } from '@volter/sdk/kit/manifest-project';
31
+ import { getCurrentProject } from '../project-manager';
32
+ import { handleProjectMutationFailure } from '@volter/sdk/kit/source-conflict';
33
+ import {
34
+ activeOverrideIsEditMode,
35
+ baseAuthoringFactory,
36
+ getAuthoringOverride,
37
+ hasAuthoringOverride,
38
+ markEditModeOverride,
39
+ setActiveAuthoring,
40
+ } from '@volter/sdk/kit/authoring/active-adapter';
41
+ import { beginAuthoringBootstrap } from './bootstrap-state';
42
+ import { makeNoAuthoringAdapter } from '@volter/sdk/kit/authoring/no-authoring-adapter';
43
+ import { BoundaryAuthoringAdapter, type BoundaryRootInfo } from '@volter/sdk/kit/authoring/boundary-authoring-adapter';
44
+ import { emptyProjectAuthoring, setEmptyProjectAuthoring } from './empty-project-authoring';
45
+ import {
46
+ CompositeAuthoringAdapter,
47
+ type CompositeChild,
48
+ type RootManifestProvider,
49
+ } from '@volter/sdk/kit/authoring/composite-authoring-adapter';
50
+ import type { ShellStore } from '@volter/sdk/kit/shell-store';
51
+
52
+ /**
53
+ * The mounted Scene document's acknowledged edit-mode reinstall owner.
54
+ *
55
+ * A rebuild request can land while Play's dock transition has no Scene
56
+ * document mounted. A one-shot `window` event loses that request forever: Stop
57
+ * restores the already-suspended composite, whose R3F child now points at no
58
+ * scene, and the Hierarchy stays empty even though the Edit viewport still
59
+ * draws. Keeping the request HERE until an owner binds makes the handoff a
60
+ * completion path rather than timing choreography.
61
+ */
62
+ /**
63
+ * The `surface` of the ONE placeholder root installed when `volter.project.json`
64
+ * cannot be parsed. `world-documents.tsx` reads it to keep the Scene document
65
+ * (and with it the edit-mode rebuild OWNER) mounted through that state, so a
66
+ * manifest that becomes valid again can remount without a reload.
67
+ */
68
+ export const INVALID_MANIFEST_SURFACE = '(invalid manifest)';
69
+
70
+ type EditModeRebuildOwner = () => void | Promise<void>;
71
+
72
+ let editModeRebuildRequested = false;
73
+ let editModeRebuildScheduled = false;
74
+ let editModeRebuildRunning = false;
75
+ let editModeRebuildOwner: EditModeRebuildOwner | null = null;
76
+
77
+ function drainEditModeRebuild(): void {
78
+ if (
79
+ editModeRebuildScheduled ||
80
+ editModeRebuildRunning ||
81
+ !editModeRebuildRequested ||
82
+ !editModeRebuildOwner
83
+ )
84
+ return;
85
+ editModeRebuildScheduled = true;
86
+ const owner = editModeRebuildOwner;
87
+ queueMicrotask(() => {
88
+ editModeRebuildScheduled = false;
89
+ if (editModeRebuildOwner !== owner) {
90
+ drainEditModeRebuild();
91
+ return;
92
+ }
93
+ // Coalesce requests received before the install starts. Only a request
94
+ // arriving during the actual install earns another pass.
95
+ editModeRebuildRequested = false;
96
+ editModeRebuildRunning = true;
97
+ void Promise.resolve()
98
+ .then(owner)
99
+ .catch((error: unknown) => {
100
+ editorConsole.error(
101
+ `Edit-mode rebuild failed: ${error instanceof Error ? error.message : String(error)}`,
102
+ 'authoring',
103
+ );
104
+ })
105
+ .finally(() => {
106
+ editModeRebuildRunning = false;
107
+ drainEditModeRebuild();
108
+ });
109
+ });
110
+ }
111
+
112
+ /** Bind the project session that reinstalls edit composition and its attached stages. */
113
+ export function bindEditModeRebuildOwner(owner: EditModeRebuildOwner): () => void {
114
+ editModeRebuildOwner = owner;
115
+ drainEditModeRebuild();
116
+ return () => {
117
+ if (editModeRebuildOwner === owner) editModeRebuildOwner = null;
118
+ };
119
+ }
120
+
121
+ /** Request one acknowledged reinstall after the current transition settles. */
122
+ export function queueEditModeRebuild(): void {
123
+ editModeRebuildRequested = true;
124
+ drainEditModeRebuild();
125
+ }
126
+
127
+ /**
128
+ * The display-relevant slice of a manifest world entry this module needs —
129
+ * deliberately LOOSE (a bare `string` `surface`, not the engine's validated
130
+ * `AdapterRoot['surface']` union) so a world that fails schema validation
131
+ * (an unknown surface) can still be represented and surfaced as an error node
132
+ * (#18). Built by the LENIENT parse below (`parseEditModeManifest`), reachable
133
+ * from the production project-open path — NOT gated on strict Zod, which would
134
+ * reject the whole file for one bad world and make every declared world vanish
135
+ * (defect 2).
136
+ */
137
+ export interface EditModeRootSpec {
138
+ readonly id: string;
139
+ readonly surface: string;
140
+ readonly adapter?: string | undefined;
141
+ readonly scene?: string | undefined;
142
+ readonly entry?: string | undefined;
143
+ readonly zOrder?: number | undefined;
144
+ readonly pausable?: boolean | undefined;
145
+ /**
146
+ * `world` — the component this root's world IS, in the game's own source.
147
+ * When present it is what EDIT mounts (a design-time document,
148
+ * `r3f-design-session.ts`); `entry` stays what PLAY mounts.
149
+ */
150
+ readonly world?: { readonly entry: string; readonly export?: string | undefined } | undefined;
151
+ }
152
+
153
+ export interface EditModeManifest {
154
+ readonly roots: readonly EditModeRootSpec[];
155
+ }
156
+
157
+ const KNOWN_WORLD_KINDS = new Set(['three', 'canvas', 'dom']);
158
+
159
+ function asString(v: unknown): string | undefined {
160
+ return typeof v === 'string' ? v : undefined;
161
+ }
162
+
163
+ /**
164
+ * The raw root-level `world` fact, read as defensively as everything else in
165
+ * this module's lenient parse: anything but an object carrying a string
166
+ * `entry` is simply absent, which puts the root back on its `entry` for both
167
+ * modes rather than failing the whole manifest.
168
+ *
169
+ * It is read off the ROOT, not off any adapter: the split it names — "`entry`
170
+ * mounts the running game, this names the thing an author edits" — belongs to
171
+ * a vendored ingest and a translated first-party port alike.
172
+ */
173
+ function readDesignWorld(root: Record<string, unknown>): EditModeRootSpec['world'] {
174
+ const world = root['world'];
175
+ if (!world || typeof world !== 'object') return undefined;
176
+ const entry = asString((world as Record<string, unknown>)['entry']);
177
+ if (!entry) return undefined;
178
+ return { entry, export: asString((world as Record<string, unknown>)['export']) };
179
+ }
180
+
181
+ /** Display string for a raw `adapter` field — informational only (the Boundary
182
+ * inspector's read-only `adapter` property). Read defensively: the raw JSON
183
+ * may be a string ('default'), a `{ module }`/`{ ingest }` object, or absent. */
184
+ function displayAdapter(adapter: unknown): string | undefined {
185
+ if (adapter === undefined || adapter === null) return undefined;
186
+ if (typeof adapter === 'string') return adapter;
187
+ if (typeof adapter === 'object') {
188
+ const obj = adapter as Record<string, unknown>;
189
+ if (typeof obj['module'] === 'string') return `module:${obj['module']}`;
190
+ const ingest = obj['ingest'];
191
+ if (ingest && typeof ingest === 'object') return 'ingest';
192
+ }
193
+ return undefined;
194
+ }
195
+
196
+ /**
197
+ * LENIENT parse (defect 2): read a raw `volter.project.json` object's `roots[]`
198
+ * defensively into `EditModeRootSpec[]`, so a single bad world (unknown
199
+ * `surface`, missing `scene`+`entry`) becomes an error node (#18) while its VALID
200
+ * siblings still open — never the strict-Zod all-or-nothing of
201
+ * `loadGameManifest`. Returns `null` when there is no usable `roots` array at
202
+ * all (a present-but-unusable manifest, distinct from an ABSENT one) so the
203
+ * caller can fall back to the synthesized single-world floor. A world missing
204
+ * an `id` gets a positional placeholder so it still surfaces rather than
205
+ * vanishing. `surface` is carried through verbatim (even a bogus string) —
206
+ * `resolveRootFailureReason` decides resolvability downstream.
207
+ */
208
+ export function parseEditModeManifest(raw: unknown): EditModeManifest | null {
209
+ if (!raw || typeof raw !== 'object') return null;
210
+ const worldsRaw = (raw as Record<string, unknown>)['roots'];
211
+ if (worldsRaw === undefined) return null;
212
+ // Zero roots is a real shape (ARCHITECTURE-CORE §Roots): nothing mounts,
213
+ // and the editor derives its chrome from what IS declared.
214
+ if (!Array.isArray(worldsRaw)) return null;
215
+ const roots: EditModeRootSpec[] = worldsRaw.map((entry, i) => {
216
+ const w = (entry && typeof entry === 'object' ? entry : {}) as Record<string, unknown>;
217
+ const zOrderRaw = w['zOrder'];
218
+ const pausableRaw = w['pausable'];
219
+ return {
220
+ id: asString(w['id']) ?? `(world ${i})`,
221
+ // Missing/non-string surface is itself unresolvable — carry a sentinel so
222
+ // resolveRootFailureReason names it, rather than crashing on undefined.
223
+ surface:
224
+ (typeof w['adapter'] === 'string' ? asString(w['adapter']) : undefined) ??
225
+ asString(
226
+ w['adapter'] && typeof w['adapter'] === 'object'
227
+ ? (w['adapter'] as Record<string, unknown>)['surface']
228
+ : undefined,
229
+ ) ??
230
+ '(missing adapter surface)',
231
+ adapter: displayAdapter(w['adapter']),
232
+ scene: asString(w['scene']),
233
+ entry: asString(w['entry']),
234
+ zOrder: typeof zOrderRaw === 'number' ? zOrderRaw : undefined,
235
+ pausable: typeof pausableRaw === 'boolean' ? pausableRaw : undefined,
236
+ dev: w['dev'] === true,
237
+ world: readDesignWorld(w),
238
+ };
239
+ });
240
+ return { roots };
241
+ }
242
+
243
+ /**
244
+ * Structural resolvability (#18) — NOT a filesystem check: "missing entry/scene
245
+ * file" here means the world declares NEITHER field (mirrors the manifest
246
+ * schema's own `checkAdapterSceneEntryRules`, `manifest/load.ts`). A live "does
247
+ * the file actually exist on disk" probe is B1 territory (the design-time mount
248
+ * attempt itself degrades to this same error-node floor when a layer throws) —
249
+ * out of scope here, where only the Three world is fetched by this surface.
250
+ */
251
+ export function resolveRootFailureReason(world: EditModeRootSpec): string | null {
252
+ if (!KNOWN_WORLD_KINDS.has(world.surface)) {
253
+ return `Unknown world surface "${world.surface}" — expected one of: three, canvas, react.`;
254
+ }
255
+ if (!world.scene && !world.entry) {
256
+ return `World "${world.id}" declares neither \`scene\` nor \`entry\` — nothing to mount.`;
257
+ }
258
+ return null;
259
+ }
260
+
261
+ // ---------------------------------------------------------------------------
262
+ // A4 (D8) — ManifestAuthoring: read-modify-write root composition properties
263
+ // ---------------------------------------------------------------------------
264
+
265
+ /** A raw `volter.project.json` world entry, read/written defensively — same
266
+ * looseness as {@link EditModeRootSpec}, but this is the RAW (unknown)
267
+ * object, never Zod-parsed, so unrelated fields survive a round trip. */
268
+ type RawAdapterRoot = Record<string, unknown>;
269
+
270
+ function findRawRoot(raw: Record<string, unknown>, worldId: string): RawAdapterRoot | undefined {
271
+ const roots = raw['roots'];
272
+ if (!Array.isArray(roots)) return undefined;
273
+ return roots.find(
274
+ (w): w is RawAdapterRoot =>
275
+ !!w && typeof w === 'object' && (w as RawAdapterRoot)['id'] === worldId,
276
+ );
277
+ }
278
+
279
+ /** Materialize D19's inferred world only when a user edits one of its
280
+ * manifest-backed properties. Until then the raw file remains minimal. */
281
+ function ensureRawRoot(raw: Record<string, unknown>, worldId: string): RawAdapterRoot | undefined {
282
+ return findRawRoot(raw, worldId);
283
+ }
284
+
285
+ /**
286
+ * ManifestAuthoring (A4, D8) — authored roots' manifest-backed
287
+ * {@link RootManifestProvider}: holds the RAW parsed `volter.project.json`
288
+ * object (read-modify-write — NEVER round-tripped through the strict Zod
289
+ * schema, so fields this module doesn't know about survive untouched) and
290
+ * writes it back via `POST /__editor/manifest` (the one manifest-write verb,
291
+ * `editor-server.ts`).
292
+ *
293
+ * Two write modes:
294
+ * - a REAL manifest (`synthesized: false`) writes through on every edit —
295
+ * the acceptance's "round-trips volter.project.json on disk" needs no separate
296
+ * save step.
297
+ * - a SYNTHESIZED manifest (`synthesized: true`, no `volter.project.json` on disk
298
+ * yet) BUFFERS edits in memory only; nothing is written until the
299
+ * explicit `materialize()` call (the generic inspector's "Create
300
+ * volter.project.json" action). D19 makes this branch reachable for a
301
+ * manifest-less conventional project because its inferred root is always
302
+ * present.
303
+ *
304
+ * File-watcher landmine: `chokidar` only watches `public/` (`editor-server.ts`),
305
+ * so a manifest write at the PROJECT ROOT emits no SSE — `notifyIngestEdit()`
306
+ * after every successful write is what keeps the hierarchy panel's badges
307
+ * live instead of stale until reopen.
308
+ */
309
+ export class ManifestAuthoring implements RootManifestProvider {
310
+ private readonly raw: Record<string, unknown>;
311
+ private synthesizedValue: boolean;
312
+ private readonly store: ShellStore;
313
+ private readonly fileHistory: ProjectFileHistory | null;
314
+ private readonly unsubscribeHistory: (() => void) | null;
315
+
316
+ constructor(raw: Record<string, unknown>, synthesized: boolean, store: ShellStore) {
317
+ this.raw = raw;
318
+ this.synthesizedValue = synthesized;
319
+ this.store = store;
320
+ const history = store.projectHistory;
321
+ this.fileHistory = history
322
+ ? getProjectFileHistory(history, getManifestHistoryBackend(), 'project-manifest')
323
+ : null;
324
+ this.unsubscribeHistory = this.fileHistory
325
+ ? this.fileHistory.subscribeAll((path) => {
326
+ if (path !== 'volter.project.json') return;
327
+ void getManifestHistoryBackend()
328
+ .readBytes(path)
329
+ .then((bytes) => JSON.parse(new TextDecoder().decode(bytes)) as Record<string, unknown>)
330
+ .then((next) => {
331
+ for (const key of Object.keys(this.raw)) delete this.raw[key];
332
+ Object.assign(this.raw, next);
333
+ this.store.notifyIngestEdit();
334
+ })
335
+ .catch(() => {});
336
+ })
337
+ : null;
338
+ }
339
+
340
+ getGameName(): string {
341
+ const name = this.raw['name'];
342
+ return typeof name === 'string' ? name : '';
343
+ }
344
+
345
+ get synthesized(): boolean {
346
+ return this.synthesizedValue;
347
+ }
348
+
349
+ setGameName(name: string): void {
350
+ this.raw['name'] = name;
351
+ this.persist('Rename Game');
352
+ }
353
+
354
+ getRootContentSource(worldId: string): string | undefined {
355
+ const world = findRawRoot(this.raw, worldId);
356
+ if (!world) return undefined;
357
+ const scene = world['scene'];
358
+ if (typeof scene === 'string') return `Scene · ${scene}`;
359
+ const entry = world['entry'];
360
+ if (typeof entry === 'string') return `Entry · ${entry}`;
361
+ return 'Adapter-owned runtime content';
362
+ }
363
+
364
+ getRootZOrder(worldId: string): number {
365
+ const z = findRawRoot(this.raw, worldId)?.['zOrder'];
366
+ return typeof z === 'number' ? z : 0;
367
+ }
368
+
369
+ setRootZOrder(worldId: string, value: number): void {
370
+ const world = ensureRawRoot(this.raw, worldId);
371
+ if (!world) return;
372
+ world['zOrder'] = value;
373
+ this.persist('Change World Order');
374
+ }
375
+
376
+ getRootPausable(worldId: string): boolean {
377
+ const p = findRawRoot(this.raw, worldId)?.['pausable'];
378
+ return typeof p === 'boolean' ? p : true;
379
+ }
380
+
381
+ setRootPausable(worldId: string, value: boolean): void {
382
+ const world = ensureRawRoot(this.raw, worldId);
383
+ if (!world) return;
384
+ world['pausable'] = value;
385
+ this.persist('Change World Pausing');
386
+ }
387
+
388
+ /** The "Create volter.project.json" action (generic inspector, while
389
+ * `synthesized`) — materializes the buffered edits to disk. Also safe to
390
+ * call on a non-synthesized instance (equivalent to an explicit re-save). */
391
+ async materialize(): Promise<boolean> {
392
+ const written = await this.write('Create Game Manifest');
393
+ if (written) this.synthesizedValue = false;
394
+ return written;
395
+ }
396
+
397
+ dispose(): void {
398
+ this.unsubscribeHistory?.();
399
+ }
400
+
401
+ private persist(label: string): void {
402
+ if (this.synthesized) return; // buffered only — wait for materialize()
403
+ void this.write(label);
404
+ }
405
+
406
+ private async write(label: string): Promise<boolean> {
407
+ const content = JSON.stringify(this.raw, null, 2);
408
+ try {
409
+ if (this.fileHistory) {
410
+ await this.fileHistory.write('volter.project.json', content, {
411
+ label,
412
+ kind: 'manifest',
413
+ contentType: 'application/json',
414
+ });
415
+ this.store.notifyIngestEdit();
416
+ return true;
417
+ }
418
+ // `volter.project.json` is PROJECT-ROOT-relative, which is why it is
419
+ // written through the session's own manifest route rather than the
420
+ // asset storage backend (that one is rooted at `public/`).
421
+ const write = async () => {
422
+ const res = await fetch('/__editor/manifest', {
423
+ method: 'POST',
424
+ headers: { 'Content-Type': 'application/json' },
425
+ body: JSON.stringify({
426
+ path: 'volter.project.json',
427
+ content,
428
+ ...sourceMutationAttribution(),
429
+ }),
430
+ });
431
+ // `!res.ok` alone read a page fallback as a written manifest.
432
+ assertEditorServerAnswered(res, 'Write volter.project.json failed');
433
+ if (!res.ok) {
434
+ await handleProjectMutationFailure(res, {
435
+ label: 'Write volter.project.json',
436
+ attempted: { 'volter.project.json': content },
437
+ reapply: write,
438
+ });
439
+ }
440
+ };
441
+ await write();
442
+ // No SSE for a project-root write (file-watcher only covers `public/`)
443
+ // — notify directly so the hierarchy panel's badges refresh in place.
444
+ this.store.notifyIngestEdit();
445
+ return true;
446
+ } catch (err) {
447
+ if (this.fileHistory) {
448
+ void getManifestHistoryBackend()
449
+ .readBytes('volter.project.json')
450
+ .then((bytes) => JSON.parse(new TextDecoder().decode(bytes)) as Record<string, unknown>)
451
+ .then((next) => {
452
+ for (const key of Object.keys(this.raw)) delete this.raw[key];
453
+ Object.assign(this.raw, next);
454
+ this.store.notifyIngestEdit();
455
+ })
456
+ .catch(() => {});
457
+ }
458
+ editorConsole.error(`Failed to write volter.project.json: ${err}`, 'project');
459
+ return false;
460
+ }
461
+ }
462
+ }
463
+
464
+ let _manifestAuthoring: ManifestAuthoring | null = null;
465
+
466
+ /**
467
+ * Build the composite over every declared world and install it as the active
468
+ * authoring override for every non-empty composition
469
+ * (D19). Always returns the built composite so callers can inspect it.
470
+ *
471
+ * The project's sole three content root gets the live Three adapter. The
472
+ * manifest rejects a second content root of the same medium, so this function
473
+ * accepts no focus parameter and never arbitrates between competing Three
474
+ * documents.
475
+ *
476
+ * `rawManifestInfo` (A4, D8, optional) — the RAW parsed `volter.project.json` +
477
+ * whether it was synthesized (never written to disk); when given and the
478
+ * composite has a world, a `ManifestAuthoring` is built over it
479
+ * and passed to `CompositeAuthoringAdapter` as its root-property manifest
480
+ * surface. When omitted, composition properties are read-only.
481
+ */
482
+ export function installEditModeAuthoring(
483
+ store: ShellStore,
484
+ manifest: EditModeManifest,
485
+ rawManifestInfo?: { raw: Record<string, unknown>; synthesized: boolean },
486
+ ): CompositeAuthoringAdapter {
487
+ const children: CompositeChild[] = declaredRoots(manifest).map((world) => {
488
+ // D12 (B4) — install-time zOrder for every child, not just the Boundary's
489
+ // own inspector-displayed value: `childAdapters()`'s pick/paint-order
490
+ // consumers (the layered pick walk, the hierarchy zOrder badge) need it
491
+ // off ANY child, including a live world.
492
+ const zOrder = world.zOrder ?? 0;
493
+ // A SURFACE whose integration registered a live adapter gets it; every
494
+ // other declared world gets the manifest-only Boundary disclosure, to be
495
+ // upgraded when its design-time layer actually mounts. This installer
496
+ // names no surface: `active-adapter.ts`'s factory seam is keyed by the
497
+ // world's own `surface`, and the schema allows at most one root per
498
+ // medium, so there is nothing to choose between. An integration that
499
+ // registers AFTER this ran asks for `queueEditModeRebuild()`, the same
500
+ // door a source change uses.
501
+ const live = baseAuthoringFactory(world.surface);
502
+ if (live) {
503
+ return {
504
+ worldId: world.id,
505
+ kind: world.surface,
506
+ adapter: live(store, world.id),
507
+ zOrder,
508
+ };
509
+ }
510
+ const reason = resolveRootFailureReason(world);
511
+ const info: BoundaryRootInfo = {
512
+ id: world.id,
513
+ kind: world.surface,
514
+ adapter: world.adapter,
515
+ entryOrScenePath: world.scene ?? world.entry,
516
+ zOrder,
517
+ pausable: world.pausable ?? true,
518
+ };
519
+ return {
520
+ worldId: world.id,
521
+ kind: world.surface,
522
+ adapter: new BoundaryAuthoringAdapter(store, info, reason ?? undefined),
523
+ zOrder,
524
+ };
525
+ });
526
+
527
+ // D19 — every composition, including one root, uses the same adapter projection.
528
+ // A synthesized manifest uses the same tree; its manifest-backed
529
+ // edits remain buffered until an explicit project change materializes it.
530
+ const manifestAuthoring =
531
+ rawManifestInfo && children.length >= 1
532
+ ? new ManifestAuthoring(rawManifestInfo.raw, rawManifestInfo.synthesized, store)
533
+ : undefined;
534
+ _manifestAuthoring = manifestAuthoring ?? null;
535
+ const projection = hierarchyProjectionFromProjectConfig(getCurrentProject()?.config);
536
+ const composite = new CompositeAuthoringAdapter(children, manifestAuthoring, projection);
537
+
538
+ if (children.length >= 1) {
539
+ // Symmetry with `exitEditModeAuthoring`, which already refuses to clear an
540
+ // override it does not own ("never clobbers a DIFFERENT session, e.g.
541
+ // ingest/play, that took over afterward"). Installing owed the same
542
+ // courtesy and did not give it: a FOREIGN session — an ingested game — was
543
+ // silently overwritten here, which handed the shared Hierarchy/Inspector
544
+ // panels back to the project mid-session. The user saw the project's roots
545
+ // where the ingested game's tree belonged, and, for an opaque bundle, a
546
+ // neighbouring world's fields where the editor owed them the honest
547
+ // no-authoring ceiling. Teardown-aware but install-blind is not a safe
548
+ // asymmetry for a single-slot override.
549
+ if (hasAuthoringOverride() && !activeOverrideIsEditMode()) {
550
+ editorConsole.warn(
551
+ 'Edit-mode authoring not installed: a foreign session (ingest/play) owns the authoring override.',
552
+ 'authoring',
553
+ );
554
+ return composite;
555
+ }
556
+ // Brand BEFORE installing so the store's save guard sees it the instant
557
+ // the override is live (defect 1: the focused first-party child must be
558
+ // able to Ctrl+S/autosave through the store, unlike a foreign override).
559
+ markEditModeOverride(composite);
560
+ setActiveAuthoring(composite);
561
+ store.notifyIngestEdit();
562
+ } else if (!hasAuthoringOverride()) {
563
+ // A project that declares no roots has nothing to author yet, and the panels say
564
+ // what would change that rather than the generic floor's "no authoring adapter".
565
+ const placeholder = makeNoAuthoringAdapter(
566
+ store,
567
+ 'No world yet',
568
+ 'Declare a root in volter.project.json',
569
+ );
570
+ setEmptyProjectAuthoring(placeholder);
571
+ setActiveAuthoring(placeholder);
572
+ store.notifyIngestEdit();
573
+ }
574
+
575
+ return composite;
576
+ }
577
+
578
+ /** Teardown symmetric to `installEditModeAuthoring` — clears the override
579
+ * ONLY if it is still exactly the composite this module last installed
580
+ * (never clobbers a DIFFERENT session, e.g. ingest/play, that took over
581
+ * afterward). */
582
+ export function exitEditModeAuthoring(installed?: CompositeAuthoringAdapter): void {
583
+ if (installed && getAuthoringOverride() === installed) {
584
+ setActiveAuthoring(null);
585
+ }
586
+ const placeholder = emptyProjectAuthoring();
587
+ if (placeholder && getAuthoringOverride() === placeholder) {
588
+ setActiveAuthoring(null);
589
+ }
590
+ setEmptyProjectAuthoring(null);
591
+ _manifestAuthoring?.dispose();
592
+ _manifestAuthoring = null;
593
+ }
594
+
595
+ /**
596
+ * Project-open wiring: fetch the RAW `volter.project.json` and install the edit-mode
597
+ * composite via the LENIENT parse (defect 2) — a manifest with one bad world
598
+ * still opens its valid roots, surfacing the bad one as an error node (#18).
599
+ * ONLY a genuinely ABSENT manifest (the route 404s → `fetchRawGameManifest`
600
+ * returns `null`), or one so malformed it has no usable `roots` array,
601
+ * synthesizes a single `{ id: 'main', surface: 'three', scene: <resolved> }`
602
+ * game IN MEMORY (never written to disk), where `<resolved>` mirrors
603
+ * `loadInitialScene`'s OWN resolution order. This is the only call site that
604
+ * should call `installEditModeAuthoring` at ordinary project open. The shell-owned
605
+ * `project-authoring-session.ts` installs it independently of open viewport tabs.
606
+ */
607
+ export async function installEditModeAuthoringForProject(
608
+ store: ShellStore,
609
+ ): Promise<CompositeAuthoringAdapter> {
610
+ const finishBootstrap = beginAuthoringBootstrap(store);
611
+ let manifest: EditModeManifest;
612
+ // The RAW object backing `ManifestAuthoring` (read-modify-write, never
613
+ // round-tripped through Zod). An omitted roots field is a real manifest
614
+ // using D19's convention, not a synthesized/unsaved manifest.
615
+ let rawManifestInfo: { raw: Record<string, unknown>; synthesized: boolean } | undefined;
616
+ try {
617
+ const raw = await fetchRawGameManifest();
618
+ const parsed = raw !== null && parseEditModeManifest(raw);
619
+ if (parsed) {
620
+ manifest = parsed;
621
+ rawManifestInfo = { raw: raw as Record<string, unknown>, synthesized: false };
622
+ } else {
623
+ throw new Error('manifest has no `roots` array (zero roots is fine; a missing field is not)');
624
+ }
625
+ } catch (err) {
626
+ const detail = err instanceof Error ? err.message : String(err);
627
+ editorConsole.error(`Failed to load volter.project.json: ${detail}`, 'project');
628
+ manifest = {
629
+ roots: [{ id: 'manifest', surface: INVALID_MANIFEST_SURFACE, adapter: detail }],
630
+ };
631
+ }
632
+ try {
633
+ return installEditModeAuthoring(store, manifest, rawManifestInfo);
634
+ } finally {
635
+ finishBootstrap();
636
+ }
637
+ }
@@ -0,0 +1,22 @@
1
+ /**
2
+ * THE PLACEHOLDER A PROJECT WITH NO ROOTS WEARS. `installEditModeAuthoring`
3
+ * installs it so the panels say what would give them something to show
4
+ * ("Declare a root"); `mountedRootSubjects` asks here so the placeholder is
5
+ * never graded as a mounted root. Zero roots is a valid project (a project of
6
+ * documents only, like a music project's pieces): nothing is mounted, so there
7
+ * is no root whose missing providers are a gap.
8
+ *
9
+ * Its own module so the subject derivation does not take the whole edit-mode
10
+ * installer into its import closure.
11
+ */
12
+ import type { AuthoringAdapter } from '@volter/project/adapter';
13
+
14
+ let placeholder: AuthoringAdapter | null = null;
15
+
16
+ export function setEmptyProjectAuthoring(adapter: AuthoringAdapter | null): void {
17
+ placeholder = adapter;
18
+ }
19
+
20
+ export function emptyProjectAuthoring(): AuthoringAdapter | null {
21
+ return placeholder;
22
+ }