@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,66 @@
1
+ /**
2
+ * H2, third half — honest gizmo refusal.
3
+ *
4
+ * WHY THE TRIGGER IS TOOL ACTIVATION AND NOT DRAG-START. The design record
5
+ * says "attempting to drag a refused node shows a transient hint". Read
6
+ * against the code, a literal drag-start trigger is unreachable: a fully
7
+ * refused selection never gets a gizmo in the first place —
8
+ * `EditorViewport.syncFromStore` computes `selectedTransformWritable` and
9
+ * calls `this.detach()` (editor-viewport.ts, the `attach`/`detach` branch), so
10
+ * `TransformControls` fires no `dragging-changed`: there is nothing attached
11
+ * to drag. THAT detach is the exact spot where the silence lives.
12
+ *
13
+ * The earliest point at which the user has made a real, unambiguous attempt to
14
+ * transform — as opposed to merely selecting something — is therefore ARMING
15
+ * the move/rotate/scale tool (W/E/R, the toolbar's mode buttons, the command
16
+ * palette's Translate/Rotate/Scale Mode actions) while that refused selection
17
+ * is live. That is the second trigger the brief explicitly allows, and
18
+ * it is what this module implements. Every UI mode-switch call site routes
19
+ * through {@link requestTransformMode} instead of `store.setTransformMode`.
20
+ * (The programmatic `command-listener` path deliberately does not: an
21
+ * automated `set-transform-mode` command is not a user attempt, and a headless
22
+ * caller has no viewport to read a hint in.)
23
+ *
24
+ * The hint text is the adapter's own `reason`, verbatim — the same sentence
25
+ * the hierarchy lock tooltip and the inspector field show (doctrine rule 2).
26
+ * When an adapter refuses without giving a reason we show NOTHING rather than
27
+ * invent a sentence to paraphrase it with.
28
+ */
29
+
30
+ import { resolvePanelAuthoring } from './authoring/panel-authoring';
31
+ import { stageDocument } from './stage-store-registry';
32
+ import { workspaceDocumentSelection } from './workspace-document-registry';
33
+ import type { TransformMode } from '@volter/sdk/kit/shell-store';
34
+ import type { ShellStore } from '@volter/sdk/kit/shell-store';
35
+ import { transformLockSummary } from '@volter/sdk/kit/hierarchy-row-model';
36
+ import { showTransientHint } from '@volter/sdk/kit/transient-hint';
37
+
38
+ /** Set the transform mode, and NAME the refusal if the live selection is one
39
+ * the active adapter will not write. */
40
+ export function requestTransformMode(store: ShellStore, mode: TransformMode): void {
41
+ store.setTransformMode(mode);
42
+ // Arming SELECT is not an attempt to transform anything — it is the tool
43
+ // that transforms nothing (`TransformMode`'s own note) — so the refusal
44
+ // below, whose whole trigger is "a real, unambiguous attempt to transform",
45
+ // has nothing to report about it.
46
+ if (mode === 'select') return;
47
+ const ids = [...store.selectedEntityIds];
48
+ if (ids.length === 0) return;
49
+ // The adapter of the document whose stage asked (a side-by-side document's header asks about
50
+ // its own), else the one the panels drive: a document stage's selection holds its document's
51
+ // ids, which the world's composite does not own.
52
+ const document = stageDocument(store);
53
+ const adapter =
54
+ (document === null ? null : workspaceDocumentSelection(document)?.adapter) ?? resolvePanelAuthoring(store).adapter;
55
+ const editability = adapter.transforms?.editability;
56
+ if (!editability) return;
57
+ let reason: string | undefined;
58
+ for (const id of ids) {
59
+ const summary = transformLockSummary((channel) => editability(id, channel));
60
+ // Anything movable in the selection means the gesture is not refused —
61
+ // the gizmo attaches and moves what it can.
62
+ if (!summary.locked) return;
63
+ reason ??= summary.reason;
64
+ }
65
+ if (reason) showTransientHint(reason);
66
+ }
@@ -0,0 +1,78 @@
1
+ /**
2
+ * The editor's one transient, non-blocking hint channel (H2).
3
+ *
4
+ * There was no toast/notification/status-message mechanism in the editor when
5
+ * this landed (grepped: `toast`, `notification`, `statusMessage`, `hint` —
6
+ * only unrelated hits), so this is the minimal one. Deliberately: one hint at
7
+ * a time (a new one replaces the old), auto-dismissing, carrying nothing but
8
+ * a string it did not write. Blocking dialogs (`window.alert`/`prompt`) are
9
+ * banned in editor UI.
10
+ *
11
+ * Publisher lives here (plain module state, no React) so non-React callers —
12
+ * hotkeys, the action registry — can raise a hint without importing the
13
+ * component. `components/TransientHint.tsx` renders it.
14
+ */
15
+
16
+ export const TRANSIENT_HINT_MS = 3000;
17
+
18
+ export interface TransientHint {
19
+ /** Monotonic — lets the renderer restart its animation on a repeat message. */
20
+ readonly id: number;
21
+ readonly message: string;
22
+ }
23
+
24
+ let current: TransientHint | null = null;
25
+ let timer: ReturnType<typeof setTimeout> | null = null;
26
+ let nextId = 1;
27
+ const listeners = new Set<() => void>();
28
+
29
+ function emit(): void {
30
+ for (const listener of listeners) listener();
31
+ }
32
+
33
+ /** Show `message` for {@link TRANSIENT_HINT_MS}, replacing any live hint. */
34
+ export function showTransientHint(message: string): void {
35
+ current = { id: nextId++, message };
36
+ if (timer) clearTimeout(timer);
37
+ timer = setTimeout(() => {
38
+ current = null;
39
+ timer = null;
40
+ emit();
41
+ }, TRANSIENT_HINT_MS);
42
+ emit();
43
+ }
44
+
45
+ export function dismissTransientHint(): void {
46
+ if (timer) clearTimeout(timer);
47
+ timer = null;
48
+ current = null;
49
+ emit();
50
+ }
51
+
52
+ export const subscribeTransientHint = (listener: () => void): (() => void) => {
53
+ listeners.add(listener);
54
+ return () => {
55
+ listeners.delete(listener);
56
+ };
57
+ };
58
+
59
+ export const transientHint = (): TransientHint | null => current;
60
+
61
+ /**
62
+ * A drag that ended with NOTHING accepting it says so.
63
+ *
64
+ * `dropEffect === 'none'` at `dragend` is the browser's own word that no drop
65
+ * target took the payload: the card was released over editor chrome (a tab
66
+ * strip, the toolbar, a console row) instead of the viewport or a hierarchy
67
+ * row. That used to be perfectly silent — no hint, no console line, nothing
68
+ * changed — and a verifier lost a whole round to it before checking
69
+ * `elementFromPoint` (2026-09-02). A human just sees "the drop did nothing".
70
+ */
71
+ export function reportUnacceptedAssetDrop(event: { dataTransfer: DataTransfer | null }): void {
72
+ if (event.dataTransfer?.dropEffect !== 'none') return;
73
+ // Surface-neutral on purpose: the source cannot know whether the scene is
74
+ // three or canvas, and a 2D tester told 'the 3D view' would be misled.
75
+ showTransientHint(
76
+ 'Nothing accepted that drop — release it over the scene view or a hierarchy row.',
77
+ );
78
+ }
@@ -0,0 +1,174 @@
1
+ /**
2
+ * THE TRANSPORT, DRAWN — the one look every stage gets over its own transport
3
+ * (WORK.md §The stage transport and the animation door, Step 5).
4
+ *
5
+ * It draws nothing until a subject is attached, so a stage with nothing to
6
+ * show at a time costs an empty render and no chrome. Blender's Timeline is a
7
+ * SECOND look over the same handle, not a replacement for this one: an origin
8
+ * decides which subjects attach, never which transport drives them.
9
+ *
10
+ * IT HOLDS NO TIME OF ITS OWN. Every value here is read from the snapshot on
11
+ * each notification — there is no local playhead state to drift, and no clock
12
+ * in this file. `validate-import-bans.mjs`'s `private-clocks` row scans this
13
+ * path for `requestAnimationFrame`/`performance.now` for exactly that reason.
14
+ *
15
+ * WHILE THE WORLD DRIVES (Play), it goes read-only and SAYS SO. A disabled
16
+ * button with no reason is the failure this avoids: the refusal the transport
17
+ * would throw is the sentence shown instead.
18
+ */
19
+
20
+ import {
21
+ EditorIcon,
22
+ editorIcons,
23
+ IconButton,
24
+ Text,
25
+ TextInput,
26
+ themeVars,
27
+ } from '@volter/sdk/widgets';
28
+ import { useCallback, useSyncExternalStore } from 'react';
29
+ import type { StageTransportHandle } from '../transport';
30
+
31
+ /** The speeds the strip offers. Not a free number field: a speed is a viewing
32
+ * choice with a few useful values, and a text box invites 0.37. */
33
+ const SPEEDS = [0.25, 0.5, 1, 2] as const;
34
+
35
+ function formatSeconds(seconds: number, fps: number): string {
36
+ const frame = Math.round(seconds * fps);
37
+ return `${seconds.toFixed(2)}s · f${frame}`;
38
+ }
39
+
40
+ export function TransportStrip({ transport }: { transport: StageTransportHandle | null }) {
41
+ const snapshot = useSyncExternalStore(
42
+ useCallback(
43
+ (listener: () => void) => (transport ? transport.subscribe(listener) : () => {}),
44
+ [transport],
45
+ ),
46
+ useCallback(() => transport?.snapshot() ?? null, [transport]),
47
+ );
48
+
49
+ if (!transport || !snapshot || snapshot.activeSubject === null) return null;
50
+
51
+ const driven = snapshot.driver === 'world';
52
+ const playing = snapshot.playbackState === 'playing';
53
+ const { start, end, fps, loop } = snapshot.range;
54
+ const active = snapshot.subjects.find((s) => s.id === snapshot.activeSubject);
55
+ // Two different pickers, and they are not the same question: SUBJECTS are
56
+ // the several things this stage can show at a time, CLIPS are the several
57
+ // animations one subject has. A Blender action is a subject with no clips.
58
+ const subjects = snapshot.subjects.length > 1 ? snapshot.subjects : null;
59
+ const clips = transport.activeClips();
60
+
61
+ return (
62
+ <section
63
+ aria-label="Transport"
64
+ data-testid="stage-transport-strip"
65
+ style={{
66
+ display: 'flex',
67
+ alignItems: 'center',
68
+ gap: 'var(--volter-space-2)',
69
+ padding: 'var(--volter-space-1) var(--volter-space-3)',
70
+ borderTop: `var(--volter-stroke-resting) solid ${themeVars.boundary.default}`,
71
+ background: themeVars.surface.raised,
72
+ }}
73
+ >
74
+ <IconButton
75
+ size="compact"
76
+ aria-label={playing ? 'Pause' : 'Play'}
77
+ disabled={driven}
78
+ onClick={() => (playing ? transport.pause() : transport.play())}
79
+ >
80
+ <EditorIcon icon={playing ? editorIcons.transport.pause : editorIcons.transport.play} />
81
+ </IconButton>
82
+ <IconButton
83
+ size="compact"
84
+ aria-label="Stop"
85
+ disabled={driven}
86
+ onClick={() => transport.stop()}
87
+ >
88
+ <EditorIcon icon={editorIcons.transport.stop} />
89
+ </IconButton>
90
+
91
+ <TextInput
92
+ aria-label="Playhead"
93
+ type="range"
94
+ min={start}
95
+ max={end}
96
+ step={1 / fps}
97
+ value={snapshot.time}
98
+ disabled={driven}
99
+ onChange={(event) => transport.seek(Number(event.target.value))}
100
+ style={{ flex: 1 }}
101
+ />
102
+
103
+ <Text as="span" variant="caption">
104
+ {formatSeconds(snapshot.time, fps)}
105
+ </Text>
106
+
107
+ {subjects ? (
108
+ <select
109
+ aria-label="Subject"
110
+ value={snapshot.activeSubject}
111
+ disabled={driven}
112
+ onChange={(event) => transport.setActiveSubject(event.target.value)}
113
+ >
114
+ {subjects.map((subject) => (
115
+ <option key={subject.id} value={subject.id}>
116
+ {subject.label}
117
+ </option>
118
+ ))}
119
+ </select>
120
+ ) : null}
121
+
122
+ {clips ? (
123
+ <select
124
+ aria-label="Clip"
125
+ disabled={driven}
126
+ onChange={(event) => transport.setActiveClip(event.target.value)}
127
+ >
128
+ {clips.map((clip) => (
129
+ <option key={clip.id} value={clip.id}>
130
+ {clip.label}
131
+ </option>
132
+ ))}
133
+ </select>
134
+ ) : null}
135
+
136
+ <label style={{ display: 'flex', alignItems: 'center', gap: 'var(--volter-space-1)' }}>
137
+ <input
138
+ type="checkbox"
139
+ checked={loop}
140
+ disabled={driven}
141
+ onChange={(event) => transport.setLoop(event.target.checked)}
142
+ />
143
+ <Text as="span" variant="caption">
144
+ Loop
145
+ </Text>
146
+ </label>
147
+
148
+ <select
149
+ aria-label="Speed"
150
+ value={String(snapshot.timeScale)}
151
+ disabled={driven}
152
+ onChange={(event) => transport.setTimeScale(Number(event.target.value))}
153
+ >
154
+ {SPEEDS.map((speed) => (
155
+ <option key={speed} value={String(speed)}>
156
+ {speed}×
157
+ </option>
158
+ ))}
159
+ </select>
160
+
161
+ {driven ? (
162
+ // The refusal the write verbs would throw, shown instead of a disabled
163
+ // control with no reason.
164
+ <Text as="span" variant="caption">
165
+ The world is driving time (Play); pause the game to scrub
166
+ </Text>
167
+ ) : active ? (
168
+ <Text as="span" variant="caption">
169
+ {active.label}
170
+ </Text>
171
+ ) : null}
172
+ </section>
173
+ );
174
+ }
@@ -0,0 +1,238 @@
1
+ import ts from 'typescript';
2
+
3
+ /**
4
+ * A SYNCHRONOUS, source-only read of what a project's `editor/volter.adapter.ts`
5
+ * declares about which files belong to which SURFACE: each region's `include`
6
+ * globs, and the additional surfaces it `mounts` — stated either as parameters
7
+ * layered onto the `'manifest-roots'` rule (`regionIncludes`, what every
8
+ * first-party project uses) or inside an explicit `regions` list (the
9
+ * full-replacement form). Pure — the dev server adds
10
+ * the filesystem and a cache (`server/adapter-region-includes.ts`); the
11
+ * browser-hosted Content index reads the same file through its storage backend.
12
+ *
13
+ * WHY A STATIC READ AND NOT AN IMPORT. The adapter module's contract
14
+ * (`@volter/project/adapter/adapter-module`, ARCHITECTURE-CORE §The editor protocol) is
15
+ * that its TOP LEVEL is "a STATICALLY EVALUABLE BINDING TABLE, readable without
16
+ * booting the game" — plain data, closures only inside `observation[].answer`.
17
+ * This module takes the contract at its word for the one consumer that cannot
18
+ * take any other route: the OID stamping transform runs in a Vite `transform`
19
+ * hook, synchronously, per project `.tsx`, long before any browser-tier adapter
20
+ * load has happened (and in `vite build`, where none ever will). The same
21
+ * placement test ARCHITECTURE-CORE applies to manifest-vs-adapter fields —
22
+ * "readable WITHOUT EVALUATING ANY MODULE … e.g. Vite config time" — is what
23
+ * makes a static read of a statically-evaluable table the right instrument here
24
+ * rather than a second declaration home.
25
+ *
26
+ * It reads those properties and reads them literally. Anything it cannot read
27
+ * literally is reported as {@link AdapterRegionIncludes.unreadable} — never
28
+ * silently treated as "no includes", because a silently dropped declaration is
29
+ * indistinguishable from a declaration that worked, which is the whole failure
30
+ * class this rung exists to end. `packages/sdk/src/kit/project-adapter.ts` (the
31
+ * real loader, which IMPORTS the module) stays the validation authority: this
32
+ * read never accepts anything that loader would reject, it only declines to
33
+ * answer.
34
+ */
35
+
36
+ /** One ADDITIONAL mounted surface a region declares — see
37
+ * `@volter/project/adapter/adapter-module`'s `AdapterRegion.mounts`. */
38
+ export interface AdapterRegionMountDeclaration {
39
+ readonly surface: 'three' | 'canvas' | 'dom';
40
+ readonly include: readonly string[];
41
+ }
42
+
43
+ /** Region id -> the `include` globs it declares, and the additional surfaces it
44
+ * mounts. */
45
+ export interface AdapterRegionIncludes {
46
+ readonly byRegionId: ReadonlyMap<string, readonly string[]>;
47
+ /** Region id -> the surfaces it mounts BESIDE its manifest root's own
48
+ * adapter, each with the files that render on it. Read here for the same
49
+ * reason `include` is: it is the one place a root's second surface can be
50
+ * stated, and every OID/HMR/Content reader answers from the same table. */
51
+ readonly mountsByRegionId: ReadonlyMap<string, readonly AdapterRegionMountDeclaration[]>;
52
+ /**
53
+ * `true` when the file HAS a `regions` binding this static read could not
54
+ * evaluate (a spread, an imported constant, a computed value). The caller
55
+ * reports it; it never reads as "declares nothing".
56
+ */
57
+ readonly unreadable: boolean;
58
+ }
59
+
60
+ export const EMPTY_REGION_INCLUDES: AdapterRegionIncludes = {
61
+ byRegionId: new Map(),
62
+ mountsByRegionId: new Map(),
63
+ unreadable: false,
64
+ };
65
+
66
+ const UNREADABLE_REGION_INCLUDES: AdapterRegionIncludes = {
67
+ byRegionId: new Map(),
68
+ mountsByRegionId: new Map(),
69
+ unreadable: true,
70
+ };
71
+
72
+ function stringLiteralOf(node: ts.Node | undefined): string | undefined {
73
+ return node && ts.isStringLiteralLike(node) ? node.text : undefined;
74
+ }
75
+
76
+ function stringArrayOf(node: ts.Node | undefined): string[] | undefined {
77
+ if (!node || !ts.isArrayLiteralExpression(node)) return undefined;
78
+ const out: string[] = [];
79
+ for (const element of node.elements) {
80
+ const value = stringLiteralOf(element);
81
+ if (value === undefined) return undefined;
82
+ out.push(value);
83
+ }
84
+ return out;
85
+ }
86
+
87
+ function propertyOf(object: ts.ObjectLiteralExpression, name: string): ts.Expression | undefined {
88
+ for (const member of object.properties) {
89
+ if (!ts.isPropertyAssignment(member)) continue;
90
+ const key = ts.isIdentifier(member.name)
91
+ ? member.name.text
92
+ : (stringLiteralOf(member.name) ?? null);
93
+ if (key === name) return member.initializer;
94
+ }
95
+ return undefined;
96
+ }
97
+
98
+ /**
99
+ * What the module's default export gives this reader.
100
+ *
101
+ * The three outcomes are deliberately distinct, because two of them used to
102
+ * collapse into one and that collapse WAS a silent hole: `export default def`
103
+ * (a hoisted `const def = defineAdapter({…})`) and `defineAdapter(config)`
104
+ * both evaluate fine in `project-adapter.ts` — which validates the exported
105
+ * VALUE — while this reader saw "not a readable literal" and answered "no
106
+ * includes, nothing to report". The loader would honor an `include` this tier
107
+ * had silently dropped, which is exactly the disagreement the module docblock
108
+ * promises cannot happen. Both are now `'unreadable'`.
109
+ */
110
+ type DefinitionRead =
111
+ /** A statically readable argument object (possibly with no `regions`). */
112
+ | { readonly kind: 'literal'; readonly literal: ts.ObjectLiteralExpression }
113
+ /** A zero-argument call — `nativeAdapter()`. The legitimate empty. */
114
+ | { readonly kind: 'empty' }
115
+ /** No default export at all: nothing here worth flagging; the loader is the
116
+ * validation authority and an absent adapter is the native default. */
117
+ | { readonly kind: 'absent' }
118
+ /** A default export this reader cannot evaluate but the loader can. */
119
+ | { readonly kind: 'unreadable' };
120
+
121
+ function readDefinition(source: ts.SourceFile): DefinitionRead {
122
+ for (const statement of source.statements) {
123
+ if (!ts.isExportAssignment(statement) || statement.isExportEquals) continue;
124
+ const call = statement.expression;
125
+ if (!ts.isCallExpression(call)) return { kind: 'unreadable' };
126
+ const arg = call.arguments[0];
127
+ if (arg === undefined) return { kind: 'empty' };
128
+ return ts.isObjectLiteralExpression(arg)
129
+ ? { kind: 'literal', literal: arg }
130
+ : { kind: 'unreadable' };
131
+ }
132
+ return { kind: 'absent' };
133
+ }
134
+
135
+ /** Read `regions[].include` out of one adapter source. Pure — the fs half is
136
+ * `server/adapter-region-includes.ts`, so this is directly testable, and
137
+ * `adapter-region-includes-conformance.test.ts` pins it against what
138
+ * `parseAdapterDefinition` yields from EVALUATING the same source. */
139
+ export function parseAdapterRegionIncludes(code: string): AdapterRegionIncludes {
140
+ const source = ts.createSourceFile('editor/volter.adapter.ts', code, ts.ScriptTarget.Latest, true);
141
+ const definition = readDefinition(source);
142
+ if (definition.kind === 'unreadable') return UNREADABLE_REGION_INCLUDES;
143
+ if (definition.kind !== 'literal') return EMPTY_REGION_INCLUDES;
144
+ const regions = propertyOf(definition.literal, 'regions');
145
+ const overlay = propertyOf(definition.literal, 'regionIncludes');
146
+ const listed = regions !== undefined && !ts.isStringLiteralLike(regions);
147
+ // The two forms may not be combined — `defineAdapter` rejects that pairing by
148
+ // name, so the module never loads. This tier declines to answer rather than
149
+ // reporting half of an invalid table.
150
+ if (listed && overlay !== undefined) return UNREADABLE_REGION_INCLUDES;
151
+ // Absent, or the `'manifest-roots'` RULE: the derivation runs, and the
152
+ // declared PARAMETERS beside it are what a native project states (decision,
153
+ // 2026-08-17). Neither present is a real answer — pure reach — not a gap.
154
+ if (!listed) return overlay ? layeredIncludes(overlay) : EMPTY_REGION_INCLUDES;
155
+ if (!ts.isArrayLiteralExpression(regions)) return UNREADABLE_REGION_INCLUDES;
156
+
157
+ const byRegionId = new Map<string, readonly string[]>();
158
+ const mountsByRegionId = new Map<string, readonly AdapterRegionMountDeclaration[]>();
159
+ for (const element of regions.elements) {
160
+ if (!ts.isObjectLiteralExpression(element)) return UNREADABLE_REGION_INCLUDES;
161
+ const id = stringLiteralOf(propertyOf(element, 'id'));
162
+ if (id === undefined) return UNREADABLE_REGION_INCLUDES;
163
+ const include = propertyOf(element, 'include');
164
+ if (include !== undefined) {
165
+ const globs = stringArrayOf(include);
166
+ if (globs === undefined) return UNREADABLE_REGION_INCLUDES;
167
+ byRegionId.set(id, globs);
168
+ }
169
+ const mounts = propertyOf(element, 'mounts');
170
+ if (mounts === undefined) continue;
171
+ const declared = mountArrayOf(mounts);
172
+ if (declared === undefined) return UNREADABLE_REGION_INCLUDES;
173
+ mountsByRegionId.set(id, declared);
174
+ }
175
+ return { byRegionId, mountsByRegionId, unreadable: false };
176
+ }
177
+
178
+ /**
179
+ * Read the LAYERED form: `regionIncludes`, the per-region parameters the
180
+ * `'manifest-roots'` rule takes (`@volter/project/adapter/adapter-module`'s
181
+ * {@link AdapterDefinition.regionIncludes}, decision 2026-08-17).
182
+ *
183
+ * Statically readable BY CONSTRUCTION — it is an object literal of object
184
+ * literals of string arrays, sitting beside the `regions` string in the same
185
+ * argument object — which is exactly why the decision put the parameters here
186
+ * rather than behind a builder call. Anything that is NOT that literal shape
187
+ * (a spread, an imported table, a computed key) is `unreadable`, on the same
188
+ * terms as every other shape this reader declines: the loader would honor it,
189
+ * so silence about it would be the drift this module exists to prevent.
190
+ */
191
+ function layeredIncludes(node: ts.Expression): AdapterRegionIncludes {
192
+ if (!ts.isObjectLiteralExpression(node)) return UNREADABLE_REGION_INCLUDES;
193
+ const byRegionId = new Map<string, readonly string[]>();
194
+ const mountsByRegionId = new Map<string, readonly AdapterRegionMountDeclaration[]>();
195
+ for (const member of node.properties) {
196
+ if (!ts.isPropertyAssignment(member)) return UNREADABLE_REGION_INCLUDES;
197
+ const id = ts.isIdentifier(member.name) ? member.name.text : stringLiteralOf(member.name);
198
+ const overlay = overlayOf(member.initializer);
199
+ if (id === undefined || overlay === undefined) return UNREADABLE_REGION_INCLUDES;
200
+ if (overlay.include) byRegionId.set(id, overlay.include);
201
+ if (overlay.mounts) mountsByRegionId.set(id, overlay.mounts);
202
+ }
203
+ return { byRegionId, mountsByRegionId, unreadable: false };
204
+ }
205
+
206
+ /** One `regionIncludes` entry, read literally. `undefined` for anything this
207
+ * reader cannot evaluate — never a partial answer. */
208
+ function overlayOf(
209
+ node: ts.Expression,
210
+ ): { include?: string[]; mounts?: AdapterRegionMountDeclaration[] } | undefined {
211
+ if (!ts.isObjectLiteralExpression(node)) return undefined;
212
+ const includeNode = propertyOf(node, 'include');
213
+ const include = includeNode === undefined ? undefined : stringArrayOf(includeNode);
214
+ if (includeNode !== undefined && include === undefined) return undefined;
215
+ const mountsNode = propertyOf(node, 'mounts');
216
+ const mounts = mountsNode === undefined ? undefined : mountArrayOf(mountsNode);
217
+ if (mountsNode !== undefined && mounts === undefined) return undefined;
218
+ return { ...(include ? { include } : {}), ...(mounts ? { mounts } : {}) };
219
+ }
220
+
221
+ /** Read a region's `mounts` array literally. `undefined` — not an empty list —
222
+ * for anything this reader cannot evaluate, so the caller reports it rather
223
+ * than silently dropping a surface the real loader will honor. */
224
+ function mountArrayOf(node: ts.Expression): AdapterRegionMountDeclaration[] | undefined {
225
+ if (!ts.isArrayLiteralExpression(node)) return undefined;
226
+ const out: AdapterRegionMountDeclaration[] = [];
227
+ for (const element of node.elements) {
228
+ if (!ts.isObjectLiteralExpression(element)) return undefined;
229
+ const surface = stringLiteralOf(propertyOf(element, 'surface'));
230
+ if (surface !== 'three' && surface !== 'canvas' && surface !== 'dom') return undefined;
231
+ const include = propertyOf(element, 'include');
232
+ if (include === undefined) return undefined;
233
+ const globs = stringArrayOf(include);
234
+ if (globs === undefined || globs.length === 0) return undefined;
235
+ out.push({ surface, include: globs });
236
+ }
237
+ return out;
238
+ }