@volter/editor-core 0.5.57

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (719) hide show
  1. package/BUNDLED_NOTICES +1527 -0
  2. package/LICENSE +686 -0
  3. package/LICENSE-APACHE +202 -0
  4. package/NOTICE +18 -0
  5. package/README.md +24 -0
  6. package/dist/build/chunk-JS4D4XZ3.js +175 -0
  7. package/dist/build/chunk-JS4D4XZ3.js.map +7 -0
  8. package/dist/build/vite-plugin-product-contributions.js +100 -0
  9. package/dist/build/vite-plugin-product-contributions.js.map +7 -0
  10. package/dist/build/vite-plugin-shared-react.js +25 -0
  11. package/dist/build/vite-plugin-shared-react.js.map +7 -0
  12. package/dist/build/vite-plugin-shared-three.js +86 -0
  13. package/dist/build/vite-plugin-shared-three.js.map +7 -0
  14. package/dist/server/chunk-KMJC7AGO.js +98 -0
  15. package/dist/server/chunk-KMJC7AGO.js.map +7 -0
  16. package/dist/server/chunk-PSILUMGS.js +46 -0
  17. package/dist/server/chunk-PSILUMGS.js.map +7 -0
  18. package/dist/server/frame-proxy.js +255 -0
  19. package/dist/server/frame-proxy.js.map +7 -0
  20. package/dist/server/open-browser.js +53 -0
  21. package/dist/server/open-browser.js.map +7 -0
  22. package/dist/server/process-shutdown.js +127 -0
  23. package/dist/server/process-shutdown.js.map +7 -0
  24. package/dist/server/session-registry.js +141 -0
  25. package/dist/server/session-registry.js.map +7 -0
  26. package/dist/server/spawn-opener.js +11 -0
  27. package/dist/server/spawn-opener.js.map +7 -0
  28. package/dist/server/worktree-identity.js +11 -0
  29. package/dist/server/worktree-identity.js.map +7 -0
  30. package/dist-server/packaged.mjs +88816 -0
  31. package/package.json +118 -0
  32. package/scripts/build-plugins.mjs +14 -0
  33. package/scripts/build-server.mjs +26 -0
  34. package/scripts/build-session.mjs +9 -0
  35. package/server/account-credentials.ts +60 -0
  36. package/server/account-service.ts +1434 -0
  37. package/server/adapter-region-includes.ts +47 -0
  38. package/server/asset-catalog-v2.ts +175 -0
  39. package/server/asset-history-snapshots.ts +196 -0
  40. package/server/asset-ledger-store.ts +195 -0
  41. package/server/asset-library-routes.ts +1595 -0
  42. package/server/blender-wasm-artifact.ts +430 -0
  43. package/server/boot-timings.ts +106 -0
  44. package/server/canonical-path.ts +50 -0
  45. package/server/checkout-workspace-preflight.ts +349 -0
  46. package/server/cloud-asset-catalog.ts +158 -0
  47. package/server/coding-inference-launch.ts +237 -0
  48. package/server/collaboration-account-client.ts +202 -0
  49. package/server/collaboration-attribution.ts +122 -0
  50. package/server/collaboration-session.ts +934 -0
  51. package/server/comfyui-bridge.ts +248 -0
  52. package/server/console-ledger.ts +499 -0
  53. package/server/creation-site-transform.ts +304 -0
  54. package/server/creation-site-write.ts +648 -0
  55. package/server/data-file-serialize.ts +158 -0
  56. package/server/editor-brand-html.ts +72 -0
  57. package/server/editor-control-socket.ts +366 -0
  58. package/server/editor-server-options.ts +190 -0
  59. package/server/editor-server.ts +1483 -0
  60. package/server/editor-sse.ts +352 -0
  61. package/server/engine-provenance.ts +169 -0
  62. package/server/engine-source-restart.ts +117 -0
  63. package/server/frame-bridge.ts +115 -0
  64. package/server/frame-proxy.ts +490 -0
  65. package/server/frame-workbench.ts +259 -0
  66. package/server/frontend-handoff.ts +229 -0
  67. package/server/game-globals-shadow.ts +113 -0
  68. package/server/gameplay-session-retention.ts +149 -0
  69. package/server/gameplay-sessions.ts +123 -0
  70. package/server/generation-jobs.ts +201 -0
  71. package/server/generation-reconciler.ts +137 -0
  72. package/server/generative-execution-context.ts +59 -0
  73. package/server/git-workflow.ts +612 -0
  74. package/server/harness-chat-caller.ts +36 -0
  75. package/server/harness-chat-service.ts +1681 -0
  76. package/server/idle-shutdown.ts +170 -0
  77. package/server/js-profiling-policy.ts +52 -0
  78. package/server/launcher-settings.ts +84 -0
  79. package/server/local-asset-catalog.ts +410 -0
  80. package/server/managed-account-defaults.ts +22 -0
  81. package/server/mock-control-plane.ts +540 -0
  82. package/server/model-import-conversion.ts +345 -0
  83. package/server/native-credential-store.ts +162 -0
  84. package/server/open-browser.ts +118 -0
  85. package/server/packaged.ts +1192 -0
  86. package/server/play-stall.ts +126 -0
  87. package/server/process-shutdown.ts +218 -0
  88. package/server/product-presets.ts +55 -0
  89. package/server/project-build-artifact.ts +95 -0
  90. package/server/project-components.ts +100 -0
  91. package/server/project-dependency-invalidation.ts +114 -0
  92. package/server/project-file-scan.ts +235 -0
  93. package/server/project-hmr-files.ts +215 -0
  94. package/server/project-install-roots.ts +210 -0
  95. package/server/project-kinds.ts +71 -0
  96. package/server/project-mcp-servers.ts +82 -0
  97. package/server/project-module-freshness.ts +109 -0
  98. package/server/project-module-instance.ts +375 -0
  99. package/server/project-optimize-deps-entries.ts +827 -0
  100. package/server/project-output-writer.ts +679 -0
  101. package/server/project-package-origin.ts +63 -0
  102. package/server/project-root-surface.ts +831 -0
  103. package/server/project-scratch-path.ts +47 -0
  104. package/server/project-script-hmr.ts +619 -0
  105. package/server/project-serving-plugins.ts +236 -0
  106. package/server/project-tools.ts +653 -0
  107. package/server/project-validation.ts +250 -0
  108. package/server/project-verbs.ts +127 -0
  109. package/server/project-view.ts +52 -0
  110. package/server/project-watch.ts +1134 -0
  111. package/server/project-work-coordinator.ts +288 -0
  112. package/server/provider-credentials.ts +331 -0
  113. package/server/recent-projects-store.ts +98 -0
  114. package/server/redact-secrets.ts +71 -0
  115. package/server/repository-presence.ts +267 -0
  116. package/server/routes/account.ts +357 -0
  117. package/server/routes/agents.ts +60 -0
  118. package/server/routes/assets.ts +154 -0
  119. package/server/routes/build.ts +13 -0
  120. package/server/routes/collaboration.ts +595 -0
  121. package/server/routes/configurations.ts +419 -0
  122. package/server/routes/context.ts +264 -0
  123. package/server/routes/control-plane.ts +1811 -0
  124. package/server/routes/logs.ts +272 -0
  125. package/server/routes/project-identity.ts +302 -0
  126. package/server/routes/project-open.ts +429 -0
  127. package/server/routes/project-source.ts +686 -0
  128. package/server/routes/project-state.ts +383 -0
  129. package/server/routes/relay.ts +1029 -0
  130. package/server/routes/route-helpers.ts +29 -0
  131. package/server/routes/served-modules.ts +138 -0
  132. package/server/routes/session-tabs.ts +196 -0
  133. package/server/routes/settings.ts +121 -0
  134. package/server/routes/share-control.ts +486 -0
  135. package/server/routes/themes.ts +116 -0
  136. package/server/routes/tools.ts +230 -0
  137. package/server/routes/worktrees.ts +595 -0
  138. package/server/scoped-game-css.ts +461 -0
  139. package/server/server-utils.ts +1194 -0
  140. package/server/session-product.ts +112 -0
  141. package/server/session-registry.ts +230 -0
  142. package/server/share-claims.ts +138 -0
  143. package/server/share-host.ts +526 -0
  144. package/server/share-session-gateway.ts +1362 -0
  145. package/server/share-tunnel.ts +123 -0
  146. package/server/spawn-opener.ts +74 -0
  147. package/server/support/play/log-format.ts +76 -0
  148. package/server/support/play/session-record.ts +199 -0
  149. package/server/support/project/build-discipline.ts +718 -0
  150. package/server/support/project/inspection-node.ts +119 -0
  151. package/server/support/project/log-naming.ts +54 -0
  152. package/server/support/project/provenance.ts +290 -0
  153. package/server/support/project/run-name.ts +18 -0
  154. package/server/support/project/session-journal.ts +830 -0
  155. package/server/support/project/shared.ts +327 -0
  156. package/server/tab-bootstrap.ts +62 -0
  157. package/server/tab-heartbeat.ts +477 -0
  158. package/server/tab-lifecycle.ts +550 -0
  159. package/server/tab-presence.ts +1508 -0
  160. package/server/team-agent-mirror.ts +95 -0
  161. package/server/twin-auth.ts +138 -0
  162. package/server/vendored-lock-recorder.ts +968 -0
  163. package/server/worktree-identity.ts +121 -0
  164. package/server/worktree-management.ts +398 -0
  165. package/server/worktree-retention.d.mts +13 -0
  166. package/server/worktree-retention.mjs +205 -0
  167. package/src/EditorContext.tsx +169 -0
  168. package/src/account.ts +333 -0
  169. package/src/action-registry.ts +532 -0
  170. package/src/active-product.ts +74 -0
  171. package/src/active-project.ts +155 -0
  172. package/src/adapter-editor-config.ts +25 -0
  173. package/src/adapter-observation.ts +49 -0
  174. package/src/animation/stage-transport.ts +379 -0
  175. package/src/animation/three-clips-subject.ts +172 -0
  176. package/src/api/asset-library-wire.ts +45 -0
  177. package/src/api/assets.ts +365 -0
  178. package/src/api/base.ts +10 -0
  179. package/src/api/build.ts +99 -0
  180. package/src/api/git-wire.ts +56 -0
  181. package/src/api/logs.ts +92 -0
  182. package/src/api/project-identity.ts +74 -0
  183. package/src/api/project-open.ts +355 -0
  184. package/src/api/project-source.ts +162 -0
  185. package/src/api/project-state.ts +107 -0
  186. package/src/api/relay.ts +268 -0
  187. package/src/api/settings.ts +36 -0
  188. package/src/api/themes.ts +45 -0
  189. package/src/api/worktrees.ts +257 -0
  190. package/src/asset-compare-core.ts +171 -0
  191. package/src/asset-compare.ts +294 -0
  192. package/src/asset-editor-context.tsx +100 -0
  193. package/src/asset-events.ts +97 -0
  194. package/src/asset-inspector-actions.ts +87 -0
  195. package/src/asset-preview-framing.ts +357 -0
  196. package/src/asset-preview.ts +2802 -0
  197. package/src/asset-selection-viewer-registry.ts +113 -0
  198. package/src/asset-selection.ts +133 -0
  199. package/src/asset-workflow/asset-capabilities.ts +344 -0
  200. package/src/asset-workflow/asset-import-jobs.ts +106 -0
  201. package/src/asset-workflow/asset-ledger-backend.ts +126 -0
  202. package/src/asset-workflow/asset-ledger.ts +156 -0
  203. package/src/asset-workflow/asset-materialization-report.ts +140 -0
  204. package/src/asset-workflow/asset-pack-manifest.ts +320 -0
  205. package/src/asset-workflow/asset-types.ts +142 -0
  206. package/src/asset-workflow/asset-workflow-quality.ts +61 -0
  207. package/src/asset-workflow/audio-preview-player.ts +193 -0
  208. package/src/asset-workflow/audio-waveform.ts +22 -0
  209. package/src/asset-workflow/cloud-asset-client.ts +263 -0
  210. package/src/asset-workflow/folder-preview.ts +345 -0
  211. package/src/asset-workflow/hosted-asset-materialization.ts +236 -0
  212. package/src/asset-workflow/image-view-scale.ts +32 -0
  213. package/src/asset-workflow/import-contract.ts +124 -0
  214. package/src/asset-workflow/ledger-write-lock.ts +244 -0
  215. package/src/asset-workflow/model-inspection.ts +818 -0
  216. package/src/asset-workflow/pixi-spritesheet.ts +197 -0
  217. package/src/asset-workflow/preview-resource-lifetime.ts +44 -0
  218. package/src/asset-workflow/project-asset-commands.ts +23 -0
  219. package/src/asset-workflow/project-asset-health.ts +139 -0
  220. package/src/asset-workflow/project-asset-operations.ts +154 -0
  221. package/src/asset-workflow/project-asset-roots.ts +68 -0
  222. package/src/asset-workflow/project-content.ts +288 -0
  223. package/src/asset-workflow/project-source-index.ts +550 -0
  224. package/src/asset-workflow/thumbnail-system.ts +256 -0
  225. package/src/authoring/active-adapter.ts +199 -0
  226. package/src/authoring/active-systems.ts +422 -0
  227. package/src/authoring/adapter-key.ts +18 -0
  228. package/src/authoring/authoring-asset-url.ts +27 -0
  229. package/src/authoring/bootstrap-state.ts +49 -0
  230. package/src/authoring/boundary-authoring-adapter.ts +184 -0
  231. package/src/authoring/breakpoint-state.ts +43 -0
  232. package/src/authoring/canvas-scene-guides.ts +76 -0
  233. package/src/authoring/component-instance-root.ts +171 -0
  234. package/src/authoring/composite-authoring-adapter.ts +2110 -0
  235. package/src/authoring/consumer-actions.ts +520 -0
  236. package/src/authoring/css-numeric-style.ts +97 -0
  237. package/src/authoring/design-time-layers.ts +849 -0
  238. package/src/authoring/design-time-mount-registry.ts +235 -0
  239. package/src/authoring/design-time-settle.ts +343 -0
  240. package/src/authoring/edit-mode-authoring.ts +619 -0
  241. package/src/authoring/eyedropper-session.ts +60 -0
  242. package/src/authoring/instance-source-menu-register.ts +13 -0
  243. package/src/authoring/instance-source-menu.ts +135 -0
  244. package/src/authoring/layered-pick.ts +183 -0
  245. package/src/authoring/live-gesture-lock.ts +50 -0
  246. package/src/authoring/live-object-transform.ts +62 -0
  247. package/src/authoring/mount-failure-report.ts +154 -0
  248. package/src/authoring/mounted-root-subjects.ts +144 -0
  249. package/src/authoring/no-authoring-adapter.ts +55 -0
  250. package/src/authoring/null-inspection-subjects.tsx +75 -0
  251. package/src/authoring/object3d-document-persistence.ts +106 -0
  252. package/src/authoring/object3d-document-session-registry.ts +120 -0
  253. package/src/authoring/object3d-document-session.ts +1326 -0
  254. package/src/authoring/object3d-gesture-controller.ts +113 -0
  255. package/src/authoring/panel-authoring.ts +121 -0
  256. package/src/authoring/prefab-instance-inspector-section.tsx +237 -0
  257. package/src/authoring/prefab-instance-section-model.ts +55 -0
  258. package/src/authoring/project-authoring-session.ts +105 -0
  259. package/src/authoring/provenance.ts +99 -0
  260. package/src/authoring/quarks-particle-systems.ts +19 -0
  261. package/src/authoring/react-canvas-navigation.ts +255 -0
  262. package/src/authoring/react-design-canvas-style.ts +20 -0
  263. package/src/authoring/react-story-board.ts +937 -0
  264. package/src/authoring/selection-scope.ts +195 -0
  265. package/src/authoring/shell-document-ops.ts +169 -0
  266. package/src/authoring/shell-object3d-document-write-policy.ts +108 -0
  267. package/src/authoring/shell-viewport-policy.ts +48 -0
  268. package/src/authoring/source-object3d-authoring-adapter.ts +526 -0
  269. package/src/authoring/stories-scope.ts +35 -0
  270. package/src/authoring/story-board-chrome-fit.ts +107 -0
  271. package/src/authoring/story-board-presentation.ts +111 -0
  272. package/src/authoring/three-projection-core.ts +226 -0
  273. package/src/authoring/viewport-pick-context.ts +40 -0
  274. package/src/authoring/viewport-raycast.ts +240 -0
  275. package/src/authoring/viewport-tool-context.ts +73 -0
  276. package/src/authoring/world-canvas-viewport-state.ts +35 -0
  277. package/src/authoring/world-hidden-viewport.ts +152 -0
  278. package/src/authoring/world-pan-state.ts +198 -0
  279. package/src/authoring/world-session-state.ts +101 -0
  280. package/src/authoring/write-pipe.ts +173 -0
  281. package/src/availability-tick.ts +66 -0
  282. package/src/bitmap-label.ts +120 -0
  283. package/src/blender-tab-metrics.ts +161 -0
  284. package/src/board-open-actions.ts +20 -0
  285. package/src/boot-routing.ts +391 -0
  286. package/src/build-identity.ts +15 -0
  287. package/src/bytes-codec.ts +62 -0
  288. package/src/camera-authoring.ts +175 -0
  289. package/src/cancellation-reason.ts +58 -0
  290. package/src/canvas-preview-frames.ts +482 -0
  291. package/src/capture-camera-pose.ts +77 -0
  292. package/src/chrome-registry.ts +159 -0
  293. package/src/chrome-slot-registry.ts +91 -0
  294. package/src/collaboration-client.ts +264 -0
  295. package/src/collaboration-presence.ts +41 -0
  296. package/src/command-dispatch.ts +19 -0
  297. package/src/command-listener.ts +2743 -0
  298. package/src/command-registry.ts +70 -0
  299. package/src/component-board-registry.ts +205 -0
  300. package/src/component-states-registry.ts +200 -0
  301. package/src/components/AgentPresentationNotice.tsx +75 -0
  302. package/src/components/AlignToolbar.tsx +204 -0
  303. package/src/components/AppRoot.tsx +394 -0
  304. package/src/components/ApplicationMenus.tsx +415 -0
  305. package/src/components/AssetBrowser.tsx +2843 -0
  306. package/src/components/AssetEditorShell.tsx +216 -0
  307. package/src/components/AssetInspectorToolSection.tsx +124 -0
  308. package/src/components/BoardRulers.tsx +354 -0
  309. package/src/components/CameraInfo.tsx +81 -0
  310. package/src/components/CanvasSceneViewport.tsx +556 -0
  311. package/src/components/CapabilityCoverageSection.tsx +185 -0
  312. package/src/components/CenterDocuments.tsx +22 -0
  313. package/src/components/ChromeSlot.tsx +20 -0
  314. package/src/components/CodeView.tsx +470 -0
  315. package/src/components/CollaborationHeaderControl.css +74 -0
  316. package/src/components/CompactInspectorCard.tsx +190 -0
  317. package/src/components/CompactInspectorShell.tsx +39 -0
  318. package/src/components/ConsolePanel.css +55 -0
  319. package/src/components/ConsolePanel.tsx +270 -0
  320. package/src/components/DefaultEditorLayout.tsx +106 -0
  321. package/src/components/DocumentHeaderStrip.tsx +96 -0
  322. package/src/components/DocumentShelfRail.tsx +45 -0
  323. package/src/components/DocumentThumbnail.tsx +345 -0
  324. package/src/components/EditorLeaseGuard.tsx +372 -0
  325. package/src/components/ErrorBanner.tsx +123 -0
  326. package/src/components/FolderPreviewTile.tsx +159 -0
  327. package/src/components/GameHierarchy.tsx +3842 -0
  328. package/src/components/GameplaySessionTimeline.tsx +295 -0
  329. package/src/components/InspectionProjection.tsx +968 -0
  330. package/src/components/Inspector.tsx +233 -0
  331. package/src/components/InspectorCanvasPreview.tsx +35 -0
  332. package/src/components/InspectorFieldsSection.tsx +290 -0
  333. package/src/components/InspectorObjectPreview.tsx +57 -0
  334. package/src/components/InspectorStoriesSection.tsx +92 -0
  335. package/src/components/InspectorToolSection.tsx +96 -0
  336. package/src/components/InspectorTransformSection.tsx +245 -0
  337. package/src/components/LightExplorerPanel.tsx +433 -0
  338. package/src/components/MediaProperties.tsx +145 -0
  339. package/src/components/NonThreeAuthoringBootstrap.tsx +19 -0
  340. package/src/components/Object3DDocumentToolbar.css +100 -0
  341. package/src/components/Object3DDocumentToolbar.tsx +454 -0
  342. package/src/components/Object3DDocumentViewport.tsx +58 -0
  343. package/src/components/ProjectHeader.css +617 -0
  344. package/src/components/ProjectHeader.tsx +328 -0
  345. package/src/components/ProjectLayout.tsx +249 -0
  346. package/src/components/ReactCanvasControls.tsx +284 -0
  347. package/src/components/RootSelectionOverlay.tsx +3162 -0
  348. package/src/components/RootTextEditor.tsx +79 -0
  349. package/src/components/SaveStatus.tsx +70 -0
  350. package/src/components/StageHost.tsx +1954 -0
  351. package/src/components/StageOverlays.tsx +21 -0
  352. package/src/components/StartupErrorScreen.tsx +76 -0
  353. package/src/components/StartupLoadingScreen.tsx +65 -0
  354. package/src/components/StatsOverlay.tsx +78 -0
  355. package/src/components/SurfaceStateOverlay.tsx +24 -0
  356. package/src/components/ToolContributionSurfaces.tsx +65 -0
  357. package/src/components/ToolHost.tsx +370 -0
  358. package/src/components/ToolObject3DPreview.tsx +39 -0
  359. package/src/components/Toolbar.tsx +595 -0
  360. package/src/components/TransientHint.tsx +44 -0
  361. package/src/components/TransportStrip.tsx +174 -0
  362. package/src/components/VersionControlSection.tsx +470 -0
  363. package/src/components/VgaiLogo.css +83 -0
  364. package/src/components/VgaiLogo.tsx +35 -0
  365. package/src/components/ViewportControlsHint.tsx +60 -0
  366. package/src/components/ViewportFurniture.tsx +401 -0
  367. package/src/components/ViewportOverlay.tsx +145 -0
  368. package/src/components/ViewportOverlaysMenu.tsx +153 -0
  369. package/src/components/ViewportShadingMenu.tsx +300 -0
  370. package/src/components/ViewportViewMenu.tsx +101 -0
  371. package/src/components/WorkspaceDocumentSurface.tsx +204 -0
  372. package/src/components/WorkspaceUtilitySurface.tsx +22 -0
  373. package/src/components/WorktreeSwitcher.css +239 -0
  374. package/src/components/WorktreeSwitcher.tsx +890 -0
  375. package/src/components/account-documents.tsx +1162 -0
  376. package/src/components/asset-documents.tsx +812 -0
  377. package/src/components/asset-editor-persistence.ts +216 -0
  378. package/src/components/asset-selection-section.tsx +535 -0
  379. package/src/components/asset-thumbnails.tsx +312 -0
  380. package/src/components/asset-viewers/AudioViewer.tsx +201 -0
  381. package/src/components/asset-viewers/EntityModelDocument.tsx +122 -0
  382. package/src/components/asset-viewers/EnvironmentAssetDocument.tsx +440 -0
  383. package/src/components/asset-viewers/GenericJsonViewer.tsx +102 -0
  384. package/src/components/asset-viewers/ImageViewer.tsx +300 -0
  385. package/src/components/asset-viewers/JsonAssetDocument.tsx +93 -0
  386. package/src/components/asset-viewers/LiveModuleDocument.tsx +417 -0
  387. package/src/components/asset-viewers/LutAssetDocument.tsx +444 -0
  388. package/src/components/asset-viewers/ModelAssetDocument.tsx +105 -0
  389. package/src/components/asset-viewers/Object3DPreview.tsx +359 -0
  390. package/src/components/asset-viewers/OnlineAssetDetail.tsx +421 -0
  391. package/src/components/asset-viewers/PasteboardModuleDocument.tsx +67 -0
  392. package/src/components/asset-viewers/QuarksAssetDocument.tsx +526 -0
  393. package/src/components/asset-viewers/ShaderAssetDocument.tsx +743 -0
  394. package/src/components/asset-viewers/SourceAssetViewer.tsx +281 -0
  395. package/src/components/asset-viewers/SpritesheetSpriteView.tsx +102 -0
  396. package/src/components/asset-viewers/VideoViewer.tsx +101 -0
  397. package/src/components/asset-viewers/shader-source.ts +144 -0
  398. package/src/components/asset-workflow.css +731 -0
  399. package/src/components/board-guides.ts +150 -0
  400. package/src/components/compact-inspector.css +539 -0
  401. package/src/components/core-utilities.tsx +90 -0
  402. package/src/components/editor-notifications.css +40 -0
  403. package/src/components/engine-workspace.css +274 -0
  404. package/src/components/inspector-preview-section.tsx +238 -0
  405. package/src/components/inspector-property-grouping.ts +64 -0
  406. package/src/components/inspector-revert-label.ts +20 -0
  407. package/src/components/inspector-selection.ts +42 -0
  408. package/src/components/inspector-stories-gating.ts +171 -0
  409. package/src/components/inspector-transform-subject.ts +11 -0
  410. package/src/components/inspector-transform.ts +75 -0
  411. package/src/components/kind-documents.tsx +500 -0
  412. package/src/components/palette-action-publisher.tsx +140 -0
  413. package/src/components/primitives/DraftColorInput.tsx +74 -0
  414. package/src/components/product-shell.css +1829 -0
  415. package/src/components/project-tool-documents.tsx +410 -0
  416. package/src/components/scene-documents.tsx +223 -0
  417. package/src/components/stage-keyboard.tsx +37 -0
  418. package/src/components/stage-overlay-set.tsx +107 -0
  419. package/src/components/stage-presence-markers.ts +478 -0
  420. package/src/components/standard-viewport-dressing.ts +417 -0
  421. package/src/components/status-contributions.tsx +403 -0
  422. package/src/components/tool-documents.tsx +309 -0
  423. package/src/components/tool-schema-form.tsx +262 -0
  424. package/src/components/use-after-paint.ts +41 -0
  425. package/src/components/use-project-image-assets.ts +86 -0
  426. package/src/components/viewport-header-controls.css +90 -0
  427. package/src/components/viewport-surface-status.tsx +55 -0
  428. package/src/components/workspace-history.ts +32 -0
  429. package/src/components/workspace-static-panel-registry.tsx +152 -0
  430. package/src/components/workspace-surfaces.css +621 -0
  431. package/src/components/world-documents.tsx +586 -0
  432. package/src/components/world-overlay-gestures.ts +1694 -0
  433. package/src/composite-screenshot.ts +1641 -0
  434. package/src/console-sync.ts +131 -0
  435. package/src/constraint-helper.ts +338 -0
  436. package/src/content-entry-source-registry.ts +184 -0
  437. package/src/coverage/authoring-seam-evidence.ts +300 -0
  438. package/src/coverage/canvas-reveal.ts +192 -0
  439. package/src/coverage/design-time-surfaces.ts +101 -0
  440. package/src/coverage/live-seam-evidence.ts +11 -0
  441. package/src/coverage/ontology-invariants.ts +466 -0
  442. package/src/coverage/session-vitals.ts +501 -0
  443. package/src/coverage/system-seam-evidence.ts +72 -0
  444. package/src/crash-null-boundary.ts +36 -0
  445. package/src/creation-site-edit.ts +1479 -0
  446. package/src/creation-site-registry.ts +160 -0
  447. package/src/delegate-harness-registry.ts +143 -0
  448. package/src/document-context-registry.ts +177 -0
  449. package/src/document-open-registry.ts +200 -0
  450. package/src/document-preview-source.ts +20 -0
  451. package/src/document-renderer-session.ts +138 -0
  452. package/src/editor-api.ts +46 -0
  453. package/src/editor-chrome-capture.ts +139 -0
  454. package/src/editor-commands.ts +164 -0
  455. package/src/editor-console.ts +563 -0
  456. package/src/editor-current-view.ts +82 -0
  457. package/src/editor-document-probe.ts +881 -0
  458. package/src/editor-git-client.ts +115 -0
  459. package/src/editor-host-door.ts +462 -0
  460. package/src/editor-hotkeys.ts +842 -0
  461. package/src/editor-lease-view.ts +39 -0
  462. package/src/editor-lease.ts +415 -0
  463. package/src/editor-mode.ts +19 -0
  464. package/src/editor-notifications.ts +140 -0
  465. package/src/editor-presence.ts +563 -0
  466. package/src/editor-presentation-activity.ts +50 -0
  467. package/src/editor-presentation-notice.ts +42 -0
  468. package/src/editor-runtime.tsx +145 -0
  469. package/src/editor-server-response.ts +86 -0
  470. package/src/editor-session-attribution.ts +75 -0
  471. package/src/editor-session-mode.ts +54 -0
  472. package/src/editor-shell-store.ts +1304 -0
  473. package/src/editor-state-facets.ts +74 -0
  474. package/src/editor-styles.css +33 -0
  475. package/src/editor-view-presentation.ts +810 -0
  476. package/src/editor-viewport.ts +5302 -0
  477. package/src/entity-lod.ts +31 -0
  478. package/src/entity-object.ts +91 -0
  479. package/src/files/file-provider.ts +62 -0
  480. package/src/files/project-files.ts +264 -0
  481. package/src/finders/index.ts +136 -0
  482. package/src/finders/scenes-from-entrypoint-selection.ts +387 -0
  483. package/src/frame/bridge.tsx +1408 -0
  484. package/src/frame/product.ts +77 -0
  485. package/src/gameplay-dom-recording.ts +319 -0
  486. package/src/gameplay-export-state.ts +14 -0
  487. package/src/gameplay-replay.ts +417 -0
  488. package/src/gameplay-session-time.ts +9 -0
  489. package/src/gameplay-sessions.ts +204 -0
  490. package/src/harness-chat-types.ts +253 -0
  491. package/src/hierarchy-component-marks.ts +298 -0
  492. package/src/hierarchy-drop.ts +91 -0
  493. package/src/hierarchy-expansion-state.ts +80 -0
  494. package/src/hierarchy-header-slot.ts +52 -0
  495. package/src/hierarchy-internals.ts +197 -0
  496. package/src/hierarchy-kind-icon.ts +217 -0
  497. package/src/hierarchy-mark-reader.ts +73 -0
  498. package/src/hierarchy-menu-registry.ts +67 -0
  499. package/src/hierarchy-node-rows.ts +307 -0
  500. package/src/hierarchy-panel-view.ts +280 -0
  501. package/src/hierarchy-projection.ts +76 -0
  502. package/src/hierarchy-row-cache.ts +243 -0
  503. package/src/hierarchy-row-model.ts +308 -0
  504. package/src/hierarchy-rows.ts +11 -0
  505. package/src/hierarchy-walk.ts +86 -0
  506. package/src/history/editor-session.ts +25 -0
  507. package/src/history/history-commands.ts +147 -0
  508. package/src/history/history-delegate.ts +163 -0
  509. package/src/history/history-limit-notices.ts +43 -0
  510. package/src/history/history-service.ts +1173 -0
  511. package/src/history/persistence-coordinator.ts +35 -0
  512. package/src/history/project-file-history.ts +386 -0
  513. package/src/history/project-root-history-backends.ts +139 -0
  514. package/src/history/resource-registry.ts +209 -0
  515. package/src/history/snapshot-store.ts +103 -0
  516. package/src/history/source-history-backend.ts +546 -0
  517. package/src/history/types.ts +124 -0
  518. package/src/hmr-registration-group.ts +67 -0
  519. package/src/hmr-stable-react-context.ts +23 -0
  520. package/src/hotkeys.ts +188 -0
  521. package/src/inference-diagnostics.ts +69 -0
  522. package/src/initial-project.ts +80 -0
  523. package/src/inspection/active-subject.ts +578 -0
  524. package/src/inspection/active-surface.ts +142 -0
  525. package/src/inspection/compose.ts +1064 -0
  526. package/src/inspection/display.ts +170 -0
  527. package/src/inspection/document-subject.ts +109 -0
  528. package/src/inspection/game-subject.ts +85 -0
  529. package/src/inspection/model.ts +542 -0
  530. package/src/inspection/null-subject.ts +115 -0
  531. package/src/inspection/serialize.ts +357 -0
  532. package/src/inspection/use-active-inspection.ts +180 -0
  533. package/src/inspector-presentation.ts +201 -0
  534. package/src/inspector-section-registry.ts +221 -0
  535. package/src/instance-source-actions.ts +163 -0
  536. package/src/instanced-presentation.ts +164 -0
  537. package/src/js-heap.ts +71 -0
  538. package/src/key-actions.ts +91 -0
  539. package/src/keymap-presets.ts +401 -0
  540. package/src/layout-policy.ts +31 -0
  541. package/src/learn-links.ts +73 -0
  542. package/src/light-explorer-model.ts +134 -0
  543. package/src/live-canvas-frame.ts +55 -0
  544. package/src/live-document.ts +279 -0
  545. package/src/live-module-source.ts +230 -0
  546. package/src/live-session-registry.ts +220 -0
  547. package/src/live-transition.ts +633 -0
  548. package/src/manifest-project.ts +107 -0
  549. package/src/model-thumbnail.ts +523 -0
  550. package/src/native-selection-style.ts +202 -0
  551. package/src/object3d-document-write-policy.ts +137 -0
  552. package/src/packaged-runtime.ts +108 -0
  553. package/src/palettes/maya.palette.json +57 -0
  554. package/src/palettes/substance.palette.json +57 -0
  555. package/src/pasteboard-module.ts +81 -0
  556. package/src/performance-profiler.ts +367 -0
  557. package/src/performance-sources.ts +69 -0
  558. package/src/play-boot-phase.ts +145 -0
  559. package/src/presentation-surface.ts +248 -0
  560. package/src/project-adapter.ts +1143 -0
  561. package/src/project-asset-refresh.ts +26 -0
  562. package/src/project-declaration-refresh.ts +31 -0
  563. package/src/project-local-state.ts +118 -0
  564. package/src/project-manager.ts +243 -0
  565. package/src/project-module-changes.ts +163 -0
  566. package/src/project-module-split.ts +266 -0
  567. package/src/project-provenance.ts +115 -0
  568. package/src/project-ready.ts +42 -0
  569. package/src/project-session-reset.ts +67 -0
  570. package/src/project-shape.ts +68 -0
  571. package/src/project-tool-discovery.ts +66 -0
  572. package/src/project-tools.ts +107 -0
  573. package/src/project-work-types.ts +149 -0
  574. package/src/projection/three.ts +898 -0
  575. package/src/projection/types.ts +44 -0
  576. package/src/readiness.ts +113 -0
  577. package/src/reflection-probe-helper.ts +142 -0
  578. package/src/reported-play-state.ts +90 -0
  579. package/src/resolve-relative-specifier.ts +33 -0
  580. package/src/scene-document-plan.ts +315 -0
  581. package/src/scene-framing.ts +315 -0
  582. package/src/scene-live-open.ts +210 -0
  583. package/src/scene-view-fog.ts +89 -0
  584. package/src/scoped-game-css.ts +152 -0
  585. package/src/session-orphan-record.ts +193 -0
  586. package/src/session-tombstone.ts +126 -0
  587. package/src/settings/settings-provider.ts +82 -0
  588. package/src/settings-store.ts +345 -0
  589. package/src/shared-view-restore.ts +42 -0
  590. package/src/shell-store-door.ts +45 -0
  591. package/src/source-conflict.ts +122 -0
  592. package/src/spatial-handle-visuals.ts +332 -0
  593. package/src/stage-context.ts +341 -0
  594. package/src/stage-store-registry.ts +63 -0
  595. package/src/stale-chunk-recovery.ts +34 -0
  596. package/src/state-report-deferral.ts +73 -0
  597. package/src/storage/host-files-storage.ts +97 -0
  598. package/src/storage/http-storage.ts +174 -0
  599. package/src/storage/index.ts +75 -0
  600. package/src/storage/mem-storage.ts +149 -0
  601. package/src/storage/path-lock.ts +44 -0
  602. package/src/storage/paths.ts +26 -0
  603. package/src/storage/types.ts +116 -0
  604. package/src/stories/StoryComponentThumbnail.tsx +184 -0
  605. package/src/stories/StoryPreviewMount.tsx +306 -0
  606. package/src/stories/component-content-source.tsx +106 -0
  607. package/src/stories/component-states-source.ts +78 -0
  608. package/src/stories/compose-project-stories.ts +255 -0
  609. package/src/stories/pixi-story-model.ts +30 -0
  610. package/src/stories/prefabs-finder.ts +54 -0
  611. package/src/stories/prefabs-from-stories.ts +182 -0
  612. package/src/stories/project-story-discovery.ts +78 -0
  613. package/src/stories/project-story-regions.ts +24 -0
  614. package/src/stories/story-actions.ts +54 -0
  615. package/src/stories/story-capture-command.ts +124 -0
  616. package/src/stories/story-capture.ts +584 -0
  617. package/src/stories/story-declared-medium.ts +126 -0
  618. package/src/stories/story-discovery.ts +176 -0
  619. package/src/stories/story-document-openers.ts +36 -0
  620. package/src/stories/story-dom-runtime.ts +78 -0
  621. package/src/stories/story-grouping.ts +111 -0
  622. package/src/stories/story-lane.ts +88 -0
  623. package/src/stories/story-mount-turn.ts +27 -0
  624. package/src/stories/story-opener.ts +260 -0
  625. package/src/stories/story-pixi-preview.ts +408 -0
  626. package/src/stories/story-presentation.ts +215 -0
  627. package/src/stories/story-registry.ts +517 -0
  628. package/src/stories/story-three-preview.ts +807 -0
  629. package/src/stories/three-story-model.ts +96 -0
  630. package/src/story-three-preview-runtime.ts +56 -0
  631. package/src/surface-keyboard.ts +112 -0
  632. package/src/surface-state.ts +124 -0
  633. package/src/tab-bootstrap.js +628 -0
  634. package/src/tab-census.ts +198 -0
  635. package/src/tab-lifecycle-client.ts +196 -0
  636. package/src/theme-library.ts +844 -0
  637. package/src/theme-preference.ts +378 -0
  638. package/src/theme.css +3437 -0
  639. package/src/three-viewport/bone-selection-highlight.ts +119 -0
  640. package/src/three-viewport/camera-fit.ts +41 -0
  641. package/src/three-viewport/interactive-renderer.ts +132 -0
  642. package/src/three-viewport/selection-brackets.ts +310 -0
  643. package/src/three-viewport/selection-outline.ts +183 -0
  644. package/src/three-viewport/skeleton-helper.ts +61 -0
  645. package/src/three-viewport/source-color.ts +167 -0
  646. package/src/three-viewport/studio-environment.ts +96 -0
  647. package/src/three-viewport-presentation.ts +23 -0
  648. package/src/tool-contribution-play.ts +74 -0
  649. package/src/tool-loader.ts +1798 -0
  650. package/src/transform-mode-request.ts +57 -0
  651. package/src/transient-hint.ts +78 -0
  652. package/src/trigger-volume-helper.ts +116 -0
  653. package/src/ui-source/adapter-region-includes.ts +241 -0
  654. package/src/ui-source/ensure-import.ts +132 -0
  655. package/src/ui-source/file-region-resolver.ts +302 -0
  656. package/src/ui-source/inspect.ts +775 -0
  657. package/src/ui-source/oid-transform.ts +1845 -0
  658. package/src/ui-source/plan-csf-story.ts +196 -0
  659. package/src/ui-source/plan-extract-component.ts +421 -0
  660. package/src/ui-source/plan-fork-component.ts +621 -0
  661. package/src/ui-source/plan-named-style.ts +95 -0
  662. package/src/ui-source/plan-source-edit.ts +353 -0
  663. package/src/ui-source/r3f-contract-resolver.ts +327 -0
  664. package/src/ui-source/r3f-diagnostic-index.ts +165 -0
  665. package/src/ui-source/r3f-environment-binding.ts +133 -0
  666. package/src/ui-source/r3f-joint-binding.ts +251 -0
  667. package/src/ui-source/r3f-lod-binding.ts +91 -0
  668. package/src/ui-source/r3f-particle-binding.ts +235 -0
  669. package/src/ui-source/r3f-physics-binding.ts +483 -0
  670. package/src/ui-source/r3f-project-contracts.ts +444 -0
  671. package/src/ui-source/relative-import-specifier.ts +34 -0
  672. package/src/ui-source/reparent-guard.ts +544 -0
  673. package/src/ui-source/source-edit-request.ts +97 -0
  674. package/src/ui-source/source-write-backend.ts +618 -0
  675. package/src/ui-source/syntactic-prop-specs.ts +296 -0
  676. package/src/ui-source/tier-source-write-backend.ts +279 -0
  677. package/src/ui-source/ts-ast.ts +171 -0
  678. package/src/ui-source/utility-class-support.ts +169 -0
  679. package/src/ui-source/write-component-default.ts +133 -0
  680. package/src/ui-source/writer.ts +1989 -0
  681. package/src/viewport-activation-timings.ts +840 -0
  682. package/src/viewport-authoring-policy.ts +186 -0
  683. package/src/viewport-controls-hint.ts +57 -0
  684. package/src/viewport-door.ts +237 -0
  685. package/src/viewport-shading-boundary.ts +12 -0
  686. package/src/vite-error-surface.ts +141 -0
  687. package/src/wait-until.ts +37 -0
  688. package/src/workspace-areas.ts +156 -0
  689. package/src/workspace-aux-commands.ts +11 -0
  690. package/src/workspace-available-documents.ts +127 -0
  691. package/src/workspace-core-utilities.ts +31 -0
  692. package/src/workspace-document-ids.ts +59 -0
  693. package/src/workspace-document-registry.ts +612 -0
  694. package/src/workspace-document-restore.ts +145 -0
  695. package/src/workspace-host-commands.ts +141 -0
  696. package/src/workspace-persistence-gate.ts +40 -0
  697. package/src/workspace-play-utilities.ts +44 -0
  698. package/src/workspace-presets.ts +425 -0
  699. package/src/workspace-regions.ts +294 -0
  700. package/src/workspace-state-persistence.ts +536 -0
  701. package/src/workspace-static-panels.ts +73 -0
  702. package/src/workspace-status-registry.ts +121 -0
  703. package/src/workspace-style.ts +239 -0
  704. package/src/workspace-utility-commands.ts +74 -0
  705. package/src/workspace-utility-registry.ts +263 -0
  706. package/src/workspace-viewport-rect.ts +97 -0
  707. package/src/world-adoption.ts +115 -0
  708. package/src/world-document-routing.ts +104 -0
  709. package/vite-plugin-creation-site-write.ts +184 -0
  710. package/vite-plugin-creation-site.ts +80 -0
  711. package/vite-plugin-game-static.ts +303 -0
  712. package/vite-plugin-module-doorways.ts +336 -0
  713. package/vite-plugin-product-contributions.ts +197 -0
  714. package/vite-plugin-project-game-static.ts +125 -0
  715. package/vite-plugin-project-jsx-js.ts +65 -0
  716. package/vite-plugin-project-root-absolute-assets.ts +359 -0
  717. package/vite-plugin-shared-react.ts +420 -0
  718. package/vite-plugin-shared-three.ts +203 -0
  719. package/vite-plugin-ui-oid.ts +2106 -0
@@ -0,0 +1,542 @@
1
+ /**
2
+ * The INSPECTION MODEL — the data the inspector is a view of (design:
3
+ * `docs/ARCHITECTURE-CORE.md` §Editor chrome, "The Inspection Model"; build
4
+ * ledger: `docs/WORK.md` §Inspection Model program).
5
+ *
6
+ * Layer 0 is the typed field vocabulary ({@link FieldDescriptor}, a superset
7
+ * of the engine's `PropertyDescriptor`, plus the {@link MIXED} sentinel so
8
+ * multi-select is in the value model from day one). Layer 1 is
9
+ * {@link InspectionSubject} — identity, quick actions, related links,
10
+ * sections. Layer 2 is {@link InspectionSection} — an IDENTIFIED block whose
11
+ * `body` is a field list, an opaque custom render, or the subject's live
12
+ * preview.
13
+ *
14
+ * EVERYTHING a projection shows is here. What you click on decides the
15
+ * subject; the subject decides the sections; the box is a pure view of that —
16
+ * the section-icon strip IS `subject.sections`, each stacked section's body IS
17
+ * its own render, the header IS its title and icon. There is deliberately no
18
+ * channel beside the section list, not even for the live preview
19
+ * ({@link PREVIEW_SECTION_ID} is an ordinary section): a subject part that
20
+ * only one projection knew where to put is how two projections stop being the
21
+ * same box.
22
+ *
23
+ * Layer 3 — the projections — is NOT here: `components/Inspector.tsx` renders
24
+ * this model as the narrow column or the mini card, and
25
+ * `inspector-presentation.ts` maps the same sections onto the section-icon
26
+ * strip. A projection reads identity/order/title/icon off the model; it never
27
+ * re-derives what a section IS.
28
+ *
29
+ * This module is deliberately close to React-free: only the opaque section
30
+ * bodies (a contributed custom block, the live preview) name `ReactNode`.
31
+ */
32
+
33
+ import type { IconDefinition } from '@fortawesome/free-solid-svg-icons';
34
+ import type { PropertyDescriptor, WriteAck } from '@volter/editor-project/adapter';
35
+ import type { ReactNode } from 'react';
36
+
37
+ // ---- Layer 0: fields -----------------------------------------------------
38
+
39
+ /**
40
+ * "These subjects disagree about this field." Reserved by the design so that
41
+ * multi-select is expressible in the value model before multi-select EDITING
42
+ * is built: an io that spans more than one subject returns this instead of
43
+ * inventing one of the values. Single-subject inspection (all of W1) never
44
+ * produces it; the field renderer normalizes it to "no single value" (blank +
45
+ * placeholder), which is the correct reading, not a special case.
46
+ */
47
+ export const MIXED: unique symbol = Symbol('vgai.inspection.mixed');
48
+ export type Mixed = typeof MIXED;
49
+
50
+ /** A value read from an inspection subject: a real value, or {@link MIXED}. */
51
+ export type FieldValue<T> = T | Mixed;
52
+
53
+ export function isMixed(value: unknown): value is Mixed {
54
+ return value === MIXED;
55
+ }
56
+
57
+ /**
58
+ * The inspection layer's field vocabulary — structurally the engine adapter
59
+ * seam's `PropertyDescriptor` (stable scriptable `path`, `type`, `label`,
60
+ * `group`, `defaulted`, `readonly`, `resettable`, `revertsTo`), named here so
61
+ * the model has one address space of its own. Additive kinds
62
+ * (`color`/`vec3`/`asset-ref` beyond what the seam already carries) land in a
63
+ * later wave by widening the seam, never by forking a second descriptor
64
+ * shape here.
65
+ */
66
+ export interface FieldDescriptor extends PropertyDescriptor {}
67
+
68
+ /** The one explanation every projection and write door uses for a read-only
69
+ * field. An adapter can name its actual gate; the fallback remains honest for
70
+ * inherently informational fields that have no more specific refusal. */
71
+ export function fieldReadonlyReason(field: FieldDescriptor): string {
72
+ return field.readonlyReason ?? 'This field is read-only.';
73
+ }
74
+
75
+ /** Read/write access to one subject's fields, addressed by `path`. */
76
+ export interface InspectionFieldIo {
77
+ get(path: string): FieldValue<unknown>;
78
+ /**
79
+ * Write one field — and answer for THAT write with the persistence pipe's
80
+ * own {@link WriteAck} (`authoring/write-pipe.ts`), passed straight through
81
+ * from whichever provider performed it. `void` is the honest report of an io
82
+ * that performed no persisted write; the caller then reports the live-only
83
+ * floor rather than reading a destination off the surface, which is what
84
+ * made a three-root edit ack the DOM root's file with `persisted: true`.
85
+ */
86
+ set(path: string, value: unknown): void | WriteAck | Promise<void | WriteAck>;
87
+ /**
88
+ * Optional — SHOW a value without writing it, for a control the user drags
89
+ * (seam: `InspectorProvider.preview`). Never persists; the control calls
90
+ * {@link set} once when its gesture ends. Absent ⇒ the control's preview is
91
+ * a no-op and the value still lands on commit.
92
+ */
93
+ preview?(path: string, value: unknown): void;
94
+ /**
95
+ * Drop the document's override (Unity's revert arrow) — the ONE door that can
96
+ * express byte-ABSENCE, because {@link set} can only write a value.
97
+ *
98
+ * Same ack contract as `set`: the persistence pipe's own {@link WriteAck} for
99
+ * THIS removal, passed straight through, awaited. Absent ⇒ no field in this
100
+ * section can lose its override, and `remove-inspection-field` refuses by name
101
+ * instead of silently degrading to a value write that would leave the prop in
102
+ * the file.
103
+ */
104
+ remove?(path: string): void | WriteAck | Promise<void | WriteAck>;
105
+ }
106
+
107
+ // ---- Layer 1: subjects ---------------------------------------------------
108
+
109
+ /**
110
+ * The SURFACE a subject belongs to — the axis presentation affinity and the
111
+ * user's presentation preference are keyed by. `three`/`canvas`/`dom` are the
112
+ * engine's own `AdapterSurface` values; `asset-lab` is an open asset document,
113
+ * which is the three paradigm scoped to a SUBTREE (Unity's prefab-isolation
114
+ * mode: same view, same hierarchy, same inspector — only the root changes).
115
+ *
116
+ * A surface decides two things and NOTHING else: which producer composes the
117
+ * subject, and which key the presentation preference is stored under. It never
118
+ * decides what a projection renders — that is subject data, all of it.
119
+ */
120
+ export type InspectionSurfaceKind = 'three' | 'canvas' | 'dom' | 'asset-lab';
121
+
122
+ /**
123
+ * Layer 3's three projections, named in the model so a subject can say which
124
+ * one FITS it (never which one is showing — that is the resolver's answer):
125
+ * - `column` — the DEFAULT: the subject's full inspector as a slim vertical
126
+ * column — identity row, a section-icon strip that signposts what the
127
+ * subject has and jumps to a section, then every section stacked and
128
+ * collapsible;
129
+ * - `properties` — the same docked column with the sections TABBED instead
130
+ * of stacked: a vertical icon rail down the left edge, one section body at
131
+ * a time (Blender's Properties editor, Substance's too). A workspace
132
+ * chooses it as data (`EditorWorkspaceRegions.inspector`); the user's
133
+ * per-surface preference still wins;
134
+ * - `card` — the space-tight fallback: a MINI card (preview, name, the same
135
+ * icon strip) collapsing at the floor to a single-line PILL. Clicking any
136
+ * collapsed form restores the column.
137
+ *
138
+ * They differ in LAYOUT only. All three read the same subject, render the
139
+ * same identity and section data; the icon strip, the rail and the column's
140
+ * collapse triangles are the layout's own affordances.
141
+ */
142
+ export type InspectionPresentation = 'card' | 'column' | 'properties';
143
+
144
+ /**
145
+ * The subject's presentation AFFINITY — what fits this surface when the user
146
+ * has expressed no preference for it. The default is the narrow `column` on
147
+ * every surface (owner, 2026-08-19): with agents doing most editing the
148
+ * inspector's daily job is looking, and an always-present slim column reads
149
+ * details with no discovery-dependent expand gesture. The mini card is a
150
+ * space-tight fallback the user opts into, not a per-surface default.
151
+ */
152
+ export interface InspectionPresentationAffinity {
153
+ readonly preferred: InspectionPresentation;
154
+ }
155
+
156
+ /**
157
+ * The affinity for a surface — the ONE place the default lives, shared by the
158
+ * composer (which stamps it onto the subject) and the workspace (which must
159
+ * resolve the same answer without composing).
160
+ *
161
+ * The narrow `column` is the default for EVERY surface (owner, 2026-08-19):
162
+ * the card demoted from default to a space-tight fallback the user opts into
163
+ * per surface. The `kind` still selects which producer composed the subject
164
+ * and which key a preference is stored under; it no longer picks the layout.
165
+ */
166
+ export function inspectionAffinityFor(
167
+ _kind: InspectionSurfaceKind | undefined,
168
+ ): InspectionPresentation {
169
+ return 'column';
170
+ }
171
+
172
+ /**
173
+ * Where a projection puts a verb. `identity` verbs sit on the subject's name
174
+ * row (today: the visibility eye); `preview` verbs are rendered over the
175
+ * preview SECTION's body, in the box, identically in both projections (today:
176
+ * the Asset Editor jump). A projection places by this, never by action id — a
177
+ * renderer that branches on "is this the asset-editor button" would be exactly
178
+ * the content knowledge this model exists to remove.
179
+ */
180
+ export type InspectionActionPlacement = 'identity' | 'preview';
181
+
182
+ /** A verb on the subject itself. */
183
+ export interface InspectionAction {
184
+ /** Stable id; also the projection's `data-testid`. */
185
+ readonly id: string;
186
+ /** Accessible name + tooltip — ONE string, both roles. */
187
+ readonly title: string;
188
+ /** Visible text, for verbs presented as a labelled button. */
189
+ readonly label?: string | undefined;
190
+ /** Icon, for verbs presented as an icon button. */
191
+ readonly icon?: IconDefinition | undefined;
192
+ readonly placement: InspectionActionPlacement;
193
+ /** Toggle state (`aria-pressed`), for verbs that have one. */
194
+ readonly pressed?: boolean | undefined;
195
+ readonly disabled?: boolean | undefined;
196
+ readonly run: () => void | Promise<void>;
197
+ }
198
+
199
+ /** The subject's verbs for one placement — the ONE expression both
200
+ * projections filter with, so "the eye is on the identity row and the Asset
201
+ * Editor jump is in the preview box" cannot be true in one and false in the
202
+ * other. */
203
+ export function actionsPlacedAt(
204
+ subject: InspectionSubject,
205
+ placement: InspectionActionPlacement,
206
+ ): readonly InspectionAction[] {
207
+ return subject.quickActions.filter((action) => action.placement === placement);
208
+ }
209
+
210
+ /**
211
+ * A jump to a RELATED subject (the derivation chain: entity → its Asset Lab
212
+ * document → its state machine). Adapters publish these links from the same
213
+ * subject they inspect, so every projection and the serialized agent view get
214
+ * the same navigation without hand-rolled "Open in X" buttons.
215
+ */
216
+ export interface SubjectLink {
217
+ readonly id: string;
218
+ readonly title: string;
219
+ readonly open: () => void;
220
+ }
221
+
222
+ /** The editable name field on the identity row. */
223
+ export interface InspectionRename {
224
+ readonly readOnly: boolean;
225
+ readonly set: (next: string) => void;
226
+ }
227
+
228
+ /** A secondary provenance line under the identity row (today: where the
229
+ * object was constructed in the game's own source). */
230
+ export interface InspectionNote {
231
+ readonly text: string;
232
+ /** Long-form tooltip, when the one-line text is a summary. */
233
+ readonly title?: string | undefined;
234
+ readonly testId?: string | undefined;
235
+ }
236
+
237
+ /**
238
+ * The subject's identity ROW — the editable name, what to call its type, and
239
+ * the provenance line under it. Identity belongs to the SUBJECT, not to any
240
+ * section (design: ARCHITECTURE-CORE §Editor chrome), so it is one nullable
241
+ * group here rather than a boolean gate over loose fields. Sections are
242
+ * FACETS of the subject and never stand in for its identity; a projection
243
+ * renders this row exactly when it is present.
244
+ */
245
+ /**
246
+ * WHERE the subject's truth is written — the active adapter's own persistence
247
+ * destination, as a secondary line on the identity row.
248
+ *
249
+ * This is Blender's Properties datablock row, and it is the reason the
250
+ * Hierarchy panel no longer carries a breadcrumb row of its own: which file
251
+ * and which kind is a fact about the THING being inspected, not about the
252
+ * tree that lists it (Blender's Outliner header is one row and names no
253
+ * file). The seam word — `source`, an ingest's own label — is already on this
254
+ * row in {@link InspectionIdentity.kindLabel}, so the line carries the path
255
+ * and nothing else.
256
+ */
257
+ export interface InspectionDocumentLine {
258
+ /** The adapter's persistence destination, verbatim (`src/models/cube.ts`). */
259
+ readonly path: string;
260
+ /** Long-form provenance for the row's tooltip, when the seam declares one. */
261
+ readonly title?: string | undefined;
262
+ }
263
+
264
+ export interface InspectionIdentity {
265
+ readonly rename: InspectionRename;
266
+ /** What to CALL this thing's type (+ seam provenance), under the name. */
267
+ readonly kindLabel?: string | undefined;
268
+ /**
269
+ * The adapter's own KIND NAME for this thing — `mesh`, `light`,
270
+ * `mesh-data`, `three-source` — unformatted, which is the only difference
271
+ * between it and {@link InspectionIdentity.kindLabel}: both are built from
272
+ * the same `EditorNode.kind`, and a projection that has to DRAW the kind
273
+ * cannot draw a sentence.
274
+ *
275
+ * It exists because Blender's Properties breadcrumb leads with the
276
+ * DATABLOCK's glyph and never the open tab's — proved byte-identically on
277
+ * the frames: the first breadcrumb glyph in `properties-object.png`,
278
+ * `properties-modifier.png` and `properties-data-edit.png` is the same
279
+ * 28x28 device crop with 0 of 784 pixels differing, while the open tab is
280
+ * Object, Modifier and Data in turn. Neither derivation the row had could
281
+ * answer that: `sections[0].icon` is RAIL ORDER and the active tab's icon
282
+ * is the tab. The host already turns a kind name into a glyph in exactly
283
+ * one place (`hierarchy-kind-icon.ts`, which rules that the kind name is
284
+ * the carrier and `EditorNode` gains no field for it), so this carries the
285
+ * name there rather than a second glyph anywhere.
286
+ */
287
+ readonly kind?: string | undefined;
288
+ /** The document this subject is written back to. */
289
+ readonly document?: InspectionDocumentLine | undefined;
290
+ readonly note?: InspectionNote | undefined;
291
+ }
292
+
293
+ export interface InspectionSubject {
294
+ readonly id: string;
295
+ /** Display name of the thing being inspected. */
296
+ readonly title: string;
297
+ /** The identity row, or `null` for a subject that has no identity to show
298
+ * (a no-selection subject whose surface named no type). */
299
+ readonly identity: InspectionIdentity | null;
300
+ /**
301
+ * A quiet line for a subject with nothing to EDIT — today the no-selection
302
+ * subject's own explanation of what its surface inspects ("Select an
303
+ * element in the canvas…"). A projection renders it under
304
+ * {@link InspectionSubject.title} in place of the identity row; it is a
305
+ * string off the model, so no renderer learns which surface produced it.
306
+ */
307
+ readonly hint?: string | undefined;
308
+ /** Which projection FITS this subject's surface. The resolver
309
+ * (`inspector-presentation.ts`) picks the actual presentation from this
310
+ * plus the user's per-surface override. */
311
+ readonly presentation: InspectionPresentationAffinity;
312
+ /** Descriptor writes represented outside a section body. The identity-row
313
+ * visibility eye is the first case: it must stay one compact verb for a
314
+ * person while remaining the same `editor.setField` adjustment for an
315
+ * agent. This is a control seam only; projections render the owning chrome. */
316
+ readonly editable?: {
317
+ readonly fields: readonly FieldDescriptor[];
318
+ readonly io: InspectionFieldIo;
319
+ };
320
+ /**
321
+ * How many OTHER things are selected alongside this subject, when more than
322
+ * one is. The box describes ONE of them — the one whose fields these are —
323
+ * but a gizmo drag moves all of them, so a panel headed by a single name
324
+ * while three objects move is the box lying about its own scope: a tester
325
+ * shift-selected three models, watched all three move, and reported that
326
+ * "the inspector only shows the first object" (runhuman pass 94). Absent
327
+ * for a single selection, which is the overwhelmingly common case and needs
328
+ * no count.
329
+ */
330
+ readonly alsoSelected?: number | undefined;
331
+ readonly quickActions: readonly InspectionAction[];
332
+ readonly related: readonly SubjectLink[];
333
+ /** Sections in display order (already sorted by {@link InspectionSection.order}). */
334
+ readonly sections: readonly InspectionSection[];
335
+ }
336
+
337
+ // ---- Layer 2: sections ---------------------------------------------------
338
+
339
+ /**
340
+ * The JSON-safe VALUES a custom body publishes beside its render — the one
341
+ * thing an opaque body can honestly say about its own contents.
342
+ *
343
+ * A custom body replaces rendering, so the visual projections read nothing
344
+ * here and the serialized projection (`inspection/serialize.ts`) is its only
345
+ * reader: an agent calling `editor.inspect` gets the section's values instead
346
+ * of a name it cannot look inside. The channel is deliberately a flat,
347
+ * anonymous record rather than a per-section body kind — the producer
348
+ * (`inspection/compose.ts`) is the layer that knows what a section IS, and
349
+ * teaching the serializer one more content name would put that knowledge back
350
+ * in a projection.
351
+ *
352
+ * The rule for a producer filling it: publish WHAT THE BODY DISPLAYS, in the
353
+ * body's own units — the Transform section shows Euler XYZ degrees, so that
354
+ * is what it publishes, not the quaternion behind them.
355
+ */
356
+ export type InspectionSectionData = Readonly<Record<string, unknown>>;
357
+
358
+ export type InspectionSectionBody =
359
+ | {
360
+ readonly kind: 'fields';
361
+ readonly fields: readonly FieldDescriptor[];
362
+ readonly io: InspectionFieldIo;
363
+ }
364
+ /** An opaque block the model does not model — a contributed React section,
365
+ * or a built-in with chrome of its own (Transform, Stories). Custom
366
+ * bodies replace RENDERING, never identity: the section keeps its id,
367
+ * title, icon and order — and may publish its displayed values as
368
+ * {@link InspectionSectionData} for the readers that cannot render. */
369
+ | {
370
+ readonly kind: 'custom';
371
+ readonly render: () => ReactNode;
372
+ readonly data?: InspectionSectionData;
373
+ /**
374
+ * The WRITE half of {@link data}, for a body whose chrome is custom but
375
+ * whose values are ordinary editable fields.
376
+ *
377
+ * Without it, a custom body is readable over the wire and writable only
378
+ * by a person typing in its rendered rows — which for the TRANSFORM
379
+ * section meant an agent could read a position, read the sentence
380
+ * explaining whether it may be moved, and have no way to move it. An
381
+ * ingest root has no source file to hand-edit instead, so that was the
382
+ * whole authoring surface, closed.
383
+ *
384
+ * `io.set` must be the SAME write the rendered chrome performs (the
385
+ * Transform section's is `onCommit`'s begin/apply/end), so there is one
386
+ * write path and not two that can disagree.
387
+ */
388
+ readonly editable?: {
389
+ readonly fields: readonly FieldDescriptor[];
390
+ readonly io: InspectionFieldIo;
391
+ };
392
+ }
393
+ /**
394
+ * The subject's live PREVIEW — a square view of the thing itself. It is a
395
+ * section like every other: it has an id, a title, an icon and an order, it
396
+ * is one glyph on the section-icon strip and one block in the column, and it
397
+ * exists exactly when the subject has something honest to show.
398
+ *
399
+ * `render` fills whatever box it is given, at any size — the section body,
400
+ * the mini card's preview square, and the pill's small thumb — which is why
401
+ * one function serves them all and no host re-derives what the subject looks
402
+ * like. The {@link InspectionPreviewMode} is how the host says which of those
403
+ * it is; omitting it means `'section'`.
404
+ */
405
+ | {
406
+ readonly kind: 'preview';
407
+ readonly render: (mode?: InspectionPreviewMode) => ReactNode;
408
+ };
409
+
410
+ /**
411
+ * How a preview body is being HOSTED — the one thing a preview's renderer
412
+ * needs to know about its box, and deliberately not a second render function.
413
+ *
414
+ * - `section` (the default): the full box. The subject's `preview`-placed
415
+ * verbs sit in it, inside the section's own inset and border — the panel is
416
+ * the preview's landing view, so its verbs belong there.
417
+ * - `thumbnail`: chrome-free FILL — the live view alone, edge to edge, with no
418
+ * inset, no border and NO VERBS. The small hosts (the mini card's preview
419
+ * square, the pill's round thumb) clip it and own the single click on it
420
+ * themselves, so an interactive control inside would be both a second
421
+ * navigation from one press and a focusable fragment of a clipped button.
422
+ */
423
+ export type InspectionPreviewMode = 'section' | 'thumbnail';
424
+
425
+ /**
426
+ * One identified block of a subject. EVERY section is headed by its own title
427
+ * and icon in EVERY projection (owner, 2026-08-06: "the title of that specific
428
+ * section is always supposed to be at the top of the section — this should be
429
+ * consistent for all sections. And all sections need to have an icon") — the
430
+ * column, the mini card, and the Asset Lab's box alike. So
431
+ * there is no opt-out flag here: `title` and `icon` are required, and a
432
+ * projection renders the header unconditionally. A custom body that also
433
+ * printed its own name would say it twice, which is why the bodies that used
434
+ * to (Transform, Stories, Navigation) no longer do.
435
+ */
436
+ export interface InspectionSection {
437
+ /** Stable id — the section-icon strip's jump target, and the key a registry
438
+ * contribution CLAIMS to replace a built-in. */
439
+ readonly id: string;
440
+ readonly title: string;
441
+ readonly icon: IconDefinition;
442
+ /** Display order; the composer returns sections already sorted by it. */
443
+ readonly order: number;
444
+ readonly body: InspectionSectionBody;
445
+ /** Supporting line beside the title ("3 set of 12"). */
446
+ readonly description?: string | undefined;
447
+ /** Initial open state for the section header. */
448
+ readonly defaultOpen?: boolean | undefined;
449
+ /** `data-testid` for the section's wrapper, when it has one. */
450
+ readonly testId?: string | undefined;
451
+ /**
452
+ * Stay MOUNTED while another tab is showing. The properties column shows one
453
+ * section at a time; a section that HOSTS contributions which publish what
454
+ * they know while rendered (an asset's `asset.inspector` sections and the
455
+ * verbs they publish into the identity row and `editor.inspect()`) must keep
456
+ * rendering, hidden, or the verb would exist only after a person visits its
457
+ * tab. Sections that merely display leave this unset.
458
+ */
459
+ readonly keepMounted?: boolean | undefined;
460
+ /**
461
+ * WHICH GROUP OF THE RAIL this section belongs to — read by the PROPERTIES
462
+ * presentation alone, which draws a separator wherever the group changes.
463
+ *
464
+ * Blender's own rail is grouped rather than flat: `ED_buttons_tabs_list`
465
+ * (`space_buttons/space_buttons.cc:201-255`) calls `add_spacer()` between
466
+ * the tool tab, the scene group (Render, Output, View Layer, Scene, World),
467
+ * Collection, the object group (Object, Modifiers, Effects, Particles,
468
+ * Physics, Constraints, Data, Bone, Bone Constraints, Material) and
469
+ * Texture, and each spacer appends a `BCONTEXT_SEPARATOR` the rail draws as
470
+ * a gap rather than a tab. The name is free and compared for equality only;
471
+ * consecutive sections sharing one form a group, and sections that name
472
+ * none form a group of their own.
473
+ */
474
+ readonly railGroup?: string | undefined;
475
+ /**
476
+ * THE TAB THE RAIL OPENS ON, before a person has chosen one for this
477
+ * subject. The Properties presentation otherwise takes the FIRST tab, and
478
+ * Blender does not: its `SpaceProperties.context` is stored per screen in
479
+ * the startup file, and at factory settings `bpy.data.screens['Layout']`
480
+ * reads `OBJECT` while the rail's first tab is Render (measured against
481
+ * Blender 5.2 LTS, walk 5 parity row 3). At most one section should declare
482
+ * it; the first that does wins, and a rail with none opens on its first tab
483
+ * as before.
484
+ */
485
+ readonly railDefault?: boolean | undefined;
486
+ }
487
+
488
+ // ---- Section identity ----------------------------------------------------
489
+ //
490
+ // The ids are a CONTRACT: they are the section-icon strip's jump targets, and
491
+ // a registry contribution REPLACES a built-in by claiming its id
492
+ // (`inspection/compose.ts`) — the whole of the positive-space replacement
493
+ // protocol.
494
+
495
+ /** The subject's live preview. First in every projection: the first block in
496
+ * the column, and on the mini card the preview square above the name. */
497
+ export const PREVIEW_SECTION_ID = 'preview';
498
+ export const TRANSFORM_SECTION_ID = 'transform';
499
+ /**
500
+ * The adapter's DESCRIPTOR GRID — the ungrouped (loose) fields, plus the
501
+ * `group:<id>` sub-sections its named `PropertyDescriptor.group`s produce.
502
+ * Claiming this id therefore claims the whole descriptor channel: a
503
+ * contribution that renders a node's properties richly presents its groups
504
+ * too, and the generic grid must not double-render them beside it.
505
+ */
506
+ export const PROPERTIES_SECTION_ID = 'properties';
507
+ export const STORIES_SECTION_ID = 'stories';
508
+
509
+ /** A shared FACET id, contributed rather than built in: the args of the open
510
+ * story document. Every story-document surface (React CSF, three) registers
511
+ * its own body for it under this one identity, because it is the same facet
512
+ * of the same kind of subject seen from a different lane. */
513
+ export const STORY_ARGS_SECTION_ID = 'story-args';
514
+ export const STORY_ARGS_SECTION_TITLE = 'Story Args';
515
+ // The section's GLYPH lives in `components/story-args-section.ts` — this
516
+ // data-model module stays free of the icon package (see that file), and the
517
+ // icon must be DISTINCT from the generic property grid's `faSliders` so the
518
+ // section-icon strip's glyphs never collide.
519
+
520
+ /** A named `PropertyDescriptor.group`'s section (`groupId` is the slug from
521
+ * `inspector-property-grouping.ts`) — a sub-section OF
522
+ * {@link PROPERTIES_SECTION_ID}'s channel. */
523
+ export function groupSectionId(groupId: string): string {
524
+ return `group:${groupId}`;
525
+ }
526
+
527
+ // ---- Section order -------------------------------------------------------
528
+ //
529
+ // Display order, spaced so a channel can grow without colliding with the
530
+ // next. A contribution declares its own order on the same scale
531
+ // (`InspectorSectionContribution.order`); the composer sorts STABLY, so
532
+ // equal-ordered contributions keep registration order.
533
+
534
+ export const PREVIEW_SECTION_ORDER = 100;
535
+ export const TRANSFORM_SECTION_ORDER = 1000;
536
+ export const PROPERTIES_SECTION_ORDER = 2000;
537
+ export const GROUP_SECTION_ORDER = 3000;
538
+ export const STORIES_SECTION_ORDER = 4000;
539
+ /** Where a registry contribution sits unless it says otherwise: after every
540
+ * built-in block. A contribution that CLAIMS a built-in id replaces that
541
+ * block's identity, not necessarily its position. */
542
+ export const CONTRIBUTED_SECTION_ORDER = 5000;
@@ -0,0 +1,115 @@
1
+ /**
2
+ * The NO-SELECTION subject seam — `describeSubject(null)`, per adapter
3
+ * (design: `docs/ARCHITECTURE-CORE.md` §Editor chrome, "The Inspection
4
+ * Model"; build ledger: `docs/WORK.md` §Inspection Model program, W3).
5
+ *
6
+ * An empty inspector is not a shared blank: it is a SUBJECT, and whose
7
+ * subject it is depends entirely on which surface you are looking at. The
8
+ * defect this exists for (measured live, 2026-08-05): with a react/DOM
9
+ * document active and nothing selected in it, the inspector rendered the
10
+ * THREE scene's Background/Fog/Bake-NavMesh controls — another surface's
11
+ * subject leaking in, because "nothing selected" was ONE hardcoded branch in
12
+ * `components/Inspector.tsx` instead of an answer the active adapter gave.
13
+ *
14
+ * So the answer moves behind a provider keyed on the ADAPTER. A provider
15
+ * matches the adapters whose surface it speaks for and returns that surface's
16
+ * own empty-state subject; `composeInspectionSubject` turns it into the same
17
+ * {@link InspectionSubject} a real selection produces, and both projections
18
+ * stay dumb. No provider matching means the surface honestly has no
19
+ * empty-state subject — the inspector shows nothing at all, which is the
20
+ * correct answer, not a gap to fill with someone else's content.
21
+ *
22
+ * Why a provider list and not a method on `AuthoringAdapter`: an empty-state
23
+ * subject carries React section bodies, and the engine's adapter seam stays
24
+ * React-free (D6) — the same constraint that put
25
+ * `inspector-section-registry.ts` in the editor. Why not fold it INTO that
26
+ * registry: a registration there contributes one SECTION to a subject, while
27
+ * this names the subject itself (its title and its quiet hint). Registrations
28
+ * are import-time side effects (`authoring/null-inspection-subjects.tsx`,
29
+ * imported by `main.tsx`), so there is no store here — only a list and a
30
+ * first-match lookup.
31
+ */
32
+
33
+ import type { AuthoringAdapter } from '@volter/editor-project/adapter';
34
+ import type { EditorShellStore } from '../editor-shell-store';
35
+ import type {
36
+ InspectionAction,
37
+ InspectionNote,
38
+ InspectionSection,
39
+ InspectionSurfaceKind,
40
+ } from './model';
41
+
42
+ export interface NullSubjectContext {
43
+ /** The adapter whose surface is showing — the basis for the match. */
44
+ readonly adapter: AuthoringAdapter;
45
+ /** That adapter's surface, resolved once by the shell
46
+ * (`inspection/active-surface.ts`) so every provider matches against the
47
+ * same answer instead of re-deriving one. Absent in a bounded host, where
48
+ * no provider matches and the honest answer is no empty-state subject. */
49
+ readonly surface?: InspectionSurfaceKind | undefined;
50
+ readonly store: EditorShellStore;
51
+ /** Notify the shell that the adapter's (or scene's) truth changed. */
52
+ readonly onEdit: () => void;
53
+ }
54
+
55
+ /** One surface's answer to "what am I inspecting when nothing is selected?" */
56
+ export interface NullInspectionSubject {
57
+ /** Stable subject id (`InspectionSubject.id`). */
58
+ readonly id: string;
59
+ /** What this surface calls its empty state ("Scene", the UI root's name). */
60
+ readonly title: string;
61
+ /** The quiet line under the title, for a subject with nothing to edit. */
62
+ readonly hint?: string;
63
+ /** What to CALL this thing's type, under the name — an Asset Lab document
64
+ * says what KIND of document it is. Present ⇒ the composer gives the
65
+ * subject a read-only identity ROW instead of a bare headline (a document
66
+ * is a thing with a name, a type and a provenance; the three scene's empty
67
+ * state is not). */
68
+ readonly kindLabel?: string;
69
+ /** The provenance line under the identity row (an asset's source path). */
70
+ readonly note?: InspectionNote;
71
+ /** The surface's own no-selection sections, in any order — the composer
72
+ * sorts. Empty is a legitimate answer (title + hint, nothing to edit). */
73
+ readonly sections: readonly InspectionSection[];
74
+ /** Verbs this subject offers, the same shape a selected node's carry: the
75
+ * panel renders them and `editor.runAction(id)` runs them. An asset
76
+ * selection's come from the `asset.inspector` contributions that matched
77
+ * it, which is what gives a project's own Inspector section a door in the
78
+ * control API instead of only a mouse. */
79
+ readonly quickActions?: readonly InspectionAction[];
80
+ }
81
+
82
+ export interface NullSubjectProvider {
83
+ /** Which surfaces this provider speaks for. A provider that matches a
84
+ * surface it does not own is exactly the leak this seam removes. */
85
+ readonly match: (ctx: NullSubjectContext) => boolean;
86
+ readonly describe: (ctx: NullSubjectContext) => NullInspectionSubject | null;
87
+ }
88
+
89
+ const providers: NullSubjectProvider[] = [];
90
+
91
+ /** Register a provider. FIRST match wins, so a narrower provider must be
92
+ * registered before a broader one. Returns an unregister function. */
93
+ export function registerNullSubjectProvider(provider: NullSubjectProvider): () => void {
94
+ providers.push(provider);
95
+ return () => {
96
+ const index = providers.indexOf(provider);
97
+ if (index >= 0) providers.splice(index, 1);
98
+ };
99
+ }
100
+
101
+ /** The active adapter's no-selection subject, or `null` when this surface
102
+ * has none. */
103
+ export function describeNullInspectionSubject(
104
+ ctx: NullSubjectContext,
105
+ ): NullInspectionSubject | null {
106
+ for (const provider of providers) {
107
+ if (provider.match(ctx)) return provider.describe(ctx);
108
+ }
109
+ return null;
110
+ }
111
+
112
+ /** Test-only reset (mirrors `__resetInspectorSectionRegistryForTest`). */
113
+ export function __resetNullSubjectProvidersForTest(): void {
114
+ providers.length = 0;
115
+ }