@volter/sdk 0.0.0-stage → 0.5.204

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 +1168 -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 +329 -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 +669 -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,101 @@
1
+ /**
2
+ * DOES OUR SURFACE HOLD THE KEYBOARD? — the term the play-input predicate was
3
+ * missing, and it was missing because until the Code-OSS frame there was
4
+ * nothing else on the page that could want a keystroke.
5
+ *
6
+ * The documented rule is "game input only fires while play is running AND the
7
+ * Game tab is active" (the repo's CLAUDE.md, §Play-mode input isolation), and
8
+ * standalone the editor's `edit` command those two clauses are the whole truth: the editor page
9
+ * IS the surface, so a keystroke that reaches it was meant for it. Under the
10
+ * frame (WORK.md §The core is Code-OSS, U2) the page is a VS Code workbench and
11
+ * our stage is ONE EDITOR PANE in it. A person typing into Monaco in the group
12
+ * beside a running game is typing into the same `document` the game's listeners
13
+ * are on, and both clauses above are still true — the game is playing and the
14
+ * Game document is still the active volter document, because activating another
15
+ * EDITOR did not close it. So the keystroke lands in the file AND moves the
16
+ * game. That is U6's incident (keys typed into Monaco reaching the volter
17
+ * viewport as hotkeys, twice measured) repeated one layer down, on the GAME's
18
+ * input rather than the editor's, and U6's fix does not cover it: keyboard
19
+ * OWNERSHIP decides which dispatcher owns a chord, while this decides whether a
20
+ * running game hears raw DOM events at all.
21
+ *
22
+ * ## Why this is a third TERM and not a correction to the second
23
+ *
24
+ * The obvious-looking fix — have the frame write `activeViewportTab = 'edit'`
25
+ * when the pane stops being the active editor — is a defect, and the code says
26
+ * so out loud: `syncCenterDocuments` (`components/CenterDocuments.tsx`) reads an
27
+ * `'edit'` tab with the GAME document active as a genuine disagreement and
28
+ * activates the SCENE document to correct it. Under the frame the layout host
29
+ * renders the ACTIVE document into the editor pane, so that correction would
30
+ * unmount the Game document, release the live document's container out from
31
+ * under the running runtime, and end the game. The tab is about WHICH DOCUMENT
32
+ * is open, the probe below is about WHO IS TYPING, and conflating them costs
33
+ * the game.
34
+ *
35
+ * ## The shape
36
+ *
37
+ * A single installed probe, default absent, and absent means TRUE. Standalone
38
+ * nothing installs one and every predicate reads exactly as it did before this
39
+ * module existed — the same "an unset value is upstream's own behaviour"
40
+ * discipline U9's core edit follows. The frame installs one from the workbench's
41
+ * own notion of the active editor (`ActiveEditorContext` over the volter pane's
42
+ * type id), which is the right question rather than DOM focus: clicking a game
43
+ * canvas that carries no `tabindex` moves focus to `body` while the pane stays
44
+ * the active editor, and gating on focus would have killed input on the first
45
+ * click into the game.
46
+ *
47
+ * ## Its reader
48
+ *
49
+ * `gated-globals.ts` covers every RAW `window`/`document` listener a project
50
+ * module registers — first-party games, ingest mounts and the module lane
51
+ * alike, since the dev server's lexical shadow is what they all go through. It
52
+ * reads this per event through play mode's `instanceInputActive`, so a change
53
+ * of answer needs no notification.
54
+ */
55
+
56
+ type SurfaceKeyboardProbe = () => boolean;
57
+
58
+ let probe: SurfaceKeyboardProbe | null = null;
59
+
60
+ /**
61
+ * True while the surface a game is mounted in holds the keyboard.
62
+ *
63
+ * Absent probe = true, deliberately: the standalone editor page is the only
64
+ * surface there is, and a host that has not answered must never be read as a
65
+ * refusal — a silently dead keyboard is the worst failure this module could
66
+ * have.
67
+ */
68
+ export function surfaceHoldsKeyboard(): boolean {
69
+ if (!probe) return true;
70
+ try {
71
+ return probe();
72
+ } catch {
73
+ // A probe that throws is a broken frame, not a person who stopped typing.
74
+ return true;
75
+ }
76
+ }
77
+
78
+ /** Raw play input belongs to the active surface, never to a text field. */
79
+ export function surfaceAcceptsKey(event: KeyboardEvent): boolean {
80
+ const target = event.target;
81
+ return surfaceHoldsKeyboard() && !(target instanceof HTMLElement &&
82
+ (target.isContentEditable || target.closest('input, textarea, select') !== null));
83
+ }
84
+
85
+ /**
86
+ * Install the frame's answer. Returns the uninstall, which restores the
87
+ * always-true default rather than leaving the last answer pinned — a frame
88
+ * going away must not leave a game deaf.
89
+ */
90
+ export function setSurfaceKeyboardProbe(next: SurfaceKeyboardProbe | null): () => void {
91
+ probe = next;
92
+ return () => {
93
+ if (probe !== next) return;
94
+ probe = null;
95
+ };
96
+ }
97
+
98
+ /** Test-only reset. */
99
+ export function __resetSurfaceKeyboardForTest(): void {
100
+ probe = null;
101
+ }
@@ -0,0 +1,135 @@
1
+ import type { MountFailureReport } from '@volter/sdk/kit/mount-failure-report';
2
+ import type { RootReadiness } from '@volter/sdk/kit/readiness';
3
+
4
+ export type SurfaceContentState = 'unknown' | 'present' | 'empty';
5
+ export type SurfacePhase = 'loading' | 'ready';
6
+
7
+ export interface SurfaceExplanation {
8
+ readonly tone: 'loading' | 'error' | 'neutral';
9
+ readonly title: string;
10
+ readonly description: string;
11
+ }
12
+
13
+ export interface ExplainSurfaceInput {
14
+ /** Human name of the surface, e.g. Scene, Game, or Story. */
15
+ readonly surface: string;
16
+ /** True when the surface's design mount is DELIBERATELY suspended because
17
+ * the game is playing — the wait is not progress and must not read as one
18
+ * (a human sat on "waiting for world to finish mounting" on an auto-played
19
+ * example and reported the Scene tab broken — runhuman pass 37). */
20
+ readonly playSuspended?: boolean;
21
+ /** Exact root identities owned by this surface. Empty means not identified yet. */
22
+ readonly rootIds: readonly string[];
23
+ readonly phase: SurfacePhase;
24
+ readonly content: SurfaceContentState;
25
+ readonly readiness?: readonly RootReadiness[];
26
+ readonly failures?: readonly MountFailureReport[];
27
+ /** Why this surface has no editor for its root, when the editor has said so
28
+ * (a Boundary's disclosure): the answer, not a wait. */
29
+ readonly disclosure?: string | null;
30
+ }
31
+
32
+ function quoted(ids: readonly string[]): string {
33
+ return ids.map((id) => `“${id}”`).join(', ');
34
+ }
35
+
36
+ function failureExplanation(
37
+ surface: string,
38
+ failures: readonly MountFailureReport[],
39
+ ): SurfaceExplanation {
40
+ const failedIds = failures.map((failure) => failure.worldId);
41
+ return {
42
+ tone: 'error',
43
+ title:
44
+ failedIds.length === 1
45
+ ? `${surface} root ${quoted(failedIds)} failed`
46
+ : `${failedIds.length} ${surface} roots failed`,
47
+ description: `${failures
48
+ .map(
49
+ (failure) =>
50
+ `${failure.worldId} (${failure.kind}, ${failure.identity}): ${failure.message}`,
51
+ )
52
+ .join(
53
+ '\n',
54
+ )}\nIf this followed an edit, Undo (Ctrl+Z) restores the previous source and remounts.`,
55
+ };
56
+ }
57
+
58
+ function loadingExplanation(surface: string, rootIds: readonly string[]): SurfaceExplanation {
59
+ const title =
60
+ rootIds.length === 0
61
+ ? `Loading ${surface}`
62
+ : rootIds.length === 1
63
+ ? `Loading ${surface} root ${quoted(rootIds)}`
64
+ : `Loading ${rootIds.length} ${surface} roots`;
65
+ return {
66
+ tone: 'loading',
67
+ title,
68
+ description:
69
+ rootIds.length === 0
70
+ ? 'Reading the project declaration to identify the root that belongs here.'
71
+ : `Waiting for ${quoted(rootIds)} to finish mounting.`,
72
+ };
73
+ }
74
+
75
+ function emptyExplanation(surface: string, rootIds: readonly string[]): SurfaceExplanation {
76
+ if (rootIds.length === 0) {
77
+ return {
78
+ tone: 'neutral',
79
+ title: `No ${surface} root`,
80
+ description: 'No declared root belongs to this surface.',
81
+ };
82
+ }
83
+ return {
84
+ tone: 'neutral',
85
+ title: 'No renderable content',
86
+ // The second sentence is load-bearing: a world whose content exists only
87
+ // under its game systems (the shipped shooters and strategy examples all
88
+ // do this) presents exactly this card the moment Play stops, and a human
89
+ // tester read it as breakage ("why did it stop? no renderable content" —
90
+ // runhuman pass 13, 2026-08-28). Name the way forward on the card itself.
91
+ description:
92
+ (rootIds.length === 1
93
+ ? `Root ${quoted(rootIds)} mounted successfully but currently produces no renderable content.`
94
+ : `Roots ${quoted(rootIds)} mounted successfully but currently produce no renderable content.`) +
95
+ ' If this world builds its content under its game systems, press Play (▶) to run it.',
96
+ };
97
+ }
98
+
99
+ /**
100
+ * The one precedence rule for a surface which otherwise has nothing to draw.
101
+ * A real rendered result always wins. When there is no result, a named failure
102
+ * wins over a named wait, which wins over the honest successful-empty state.
103
+ */
104
+ export function explainSurface(input: ExplainSurfaceInput): SurfaceExplanation | null {
105
+ if (input.content === 'present') return null;
106
+
107
+ if (input.playSuspended) {
108
+ return {
109
+ tone: 'neutral',
110
+ title: 'Editing paused during Play',
111
+ description: `${quoted(input.rootIds)} is running in the Game tab. Press Stop (⏹) to edit it here.`,
112
+ };
113
+ }
114
+
115
+ const owned = new Set(input.rootIds);
116
+ const scopedFailures = (input.failures ?? []).filter((failure) => owned.has(failure.worldId));
117
+ if (scopedFailures.length > 0) return failureExplanation(input.surface, scopedFailures);
118
+
119
+ if (input.disclosure) {
120
+ return {
121
+ tone: 'neutral',
122
+ title: `No ${input.surface} editor for ${quoted(input.rootIds)}`,
123
+ description: input.disclosure,
124
+ };
125
+ }
126
+
127
+ const waitingIds = (input.readiness ?? [])
128
+ .filter((entry) => entry.state === 'waiting' && owned.has(entry.rootId))
129
+ .map((entry) => entry.rootId);
130
+ const loadingIds = waitingIds.length > 0 ? waitingIds : input.rootIds;
131
+ if (input.phase === 'loading' || waitingIds.length > 0 || input.content === 'unknown') {
132
+ return loadingExplanation(input.surface, loadingIds);
133
+ }
134
+ return emptyExplanation(input.surface, input.rootIds);
135
+ }
@@ -0,0 +1,72 @@
1
+ /** Structural/operational evidence for one mounted SystemAdapters slot. */
2
+
3
+ import {
4
+ displayKeyedPhysics,
5
+ gradeSeamCarrier,
6
+ inspectSeamShape,
7
+ PHYSICS_2D_ADAPTER_SHAPE,
8
+ PHYSICS_ADAPTER_SHAPE,
9
+ type SeamEvidenceReceipt,
10
+ type SeamEvidenceVerdict,
11
+ type SeamShape,
12
+ SYSTEM_ADAPTERS_SHAPE,
13
+ SYSTEM_PROVIDER_SHAPES,
14
+ type SystemAdapters,
15
+ } from '@volter/project/adapter';
16
+ import { liveSeamEvidence } from '@volter/sdk/kit/live-seam-evidence';
17
+
18
+ const EPOCHS = new WeakMap<object, string>();
19
+ let nextEpoch = 1;
20
+
21
+ export function systemAdapterEpoch(value: object): string {
22
+ const found = EPOCHS.get(value);
23
+ if (found) return found;
24
+ const epoch = `system-${nextEpoch++}`;
25
+ EPOCHS.set(value, epoch);
26
+ return epoch;
27
+ }
28
+
29
+ export function inspectSystemAdapterSeam<K extends keyof SystemAdapters>(options: {
30
+ readonly slot: K;
31
+ readonly adapter: NonNullable<SystemAdapters[K]>;
32
+ readonly subject: string;
33
+ readonly epoch?: string | undefined;
34
+ readonly receipts?: readonly SeamEvidenceReceipt[] | undefined;
35
+ }): SeamEvidenceVerdict {
36
+ const epoch = options.epoch ?? systemAdapterEpoch(options.adapter as object);
37
+ const seam = `system.${options.slot}`;
38
+ const bag = { [options.slot]: options.adapter } as Partial<SystemAdapters>;
39
+ const nestedShape =
40
+ options.slot === 'physics'
41
+ ? displayKeyedPhysics(options.adapter as SystemAdapters['physics'])
42
+ ? PHYSICS_2D_ADAPTER_SHAPE
43
+ : PHYSICS_ADAPTER_SHAPE
44
+ : SYSTEM_PROVIDER_SHAPES[options.slot as Exclude<keyof SystemAdapters, 'physics'>];
45
+ const receipts: SeamEvidenceReceipt[] = [
46
+ ...inspectSeamShape<SystemAdapters>({
47
+ prefix: 'system',
48
+ value: bag,
49
+ shape: SYSTEM_ADAPTERS_SHAPE,
50
+ subject: options.subject,
51
+ epoch,
52
+ }).filter((receipt) => receipt.seam === seam),
53
+ ...inspectSeamShape({
54
+ prefix: seam,
55
+ value: options.adapter,
56
+ shape: nestedShape as SeamShape<object>,
57
+ subject: options.subject,
58
+ epoch,
59
+ }),
60
+ ...liveSeamEvidence.receipts({ subject: options.subject, epoch }),
61
+ ...(options.receipts ?? []),
62
+ ];
63
+
64
+ return gradeSeamCarrier({
65
+ seam,
66
+ subject: options.subject,
67
+ epoch,
68
+ required: SYSTEM_ADAPTERS_SHAPE[options.slot].required,
69
+ receipts,
70
+ shape: nestedShape as SeamShape<object>,
71
+ });
72
+ }
@@ -0,0 +1,202 @@
1
+ /**
2
+ * THE TAB RESOURCE CENSUS, page side — what this tab is holding, sampled
3
+ * cheaply and handed to the heartbeat worker to ride out on the next beat.
4
+ *
5
+ * WHY (measured 2026-08-10): a game tab's Chrome renderer process was killed
6
+ * repeatedly — WS close code 1006, no goodbye — deterministically on one user
7
+ * flow, with a 3840x2080 WebGL world and an HDR bloom chain resident and
8
+ * painting. JS heap stayed flat at ~190 MB the whole time, so the kill was
9
+ * GPU/compositor-side, at a per-process ceiling Chrome neither documents nor
10
+ * announces. The tab-presence system recovered perfectly and recorded NOTHING
11
+ * about why. This is the "why".
12
+ *
13
+ * The failure class is agent-native: an agent authors lush effects with zero
14
+ * cost feedback, because the quality loop grades looks and never cost.
15
+ *
16
+ * IT ALSO CARRIES THE LANES' WORKER CALLS. Each lane's worker call times and
17
+ * this thread's long-task stalls (`worker-call-metrics.ts`) ride the same
18
+ * sample, because the beat is the one channel that still moves while the page
19
+ * or a worker is blocked — which is exactly when those numbers are the whole
20
+ * story. Absent, not zeroed, in a tab where no lane published a meter.
21
+ *
22
+ * MEASUREMENT ONLY — nothing here enforces a budget. Budgets are a later
23
+ * decision, made from real profiles rather than from a guess about them.
24
+ *
25
+ * WHAT IT COSTS. One sample every five seconds on the main thread, skipped
26
+ * entirely while the tab is hidden: a `querySelectorAll('canvas')`, two
27
+ * property reads, a scan of the bounded Resource Timing buffer, and — only
28
+ * when a game is actually mounted — the render-debug adapter's existing
29
+ * memory snapshot, which the Profiler's Memory view already polls five times
30
+ * as often. Never per frame.
31
+ *
32
+ * WHAT IT DOES NOT DO. It adds no global, no new endpoint, and no second way
33
+ * to reach a renderer: the renderer counts come from `RenderDebugAdapter`
34
+ * (`authoring/active-systems.ts`), the one seam a mounted game already
35
+ * registers, and they are ABSENT — not zero — when nothing has registered one.
36
+ * A zero would read as "no textures", which is a different claim from "nobody
37
+ * measured".
38
+ */
39
+
40
+ import { PROJECT_MOUNT_QUERY } from '@volter/sdk/session/project-module-url';
41
+ import type { TabCensus, TabStallMetrics, WorkerCallTabMetrics } from '@volter/sdk/tab-census';
42
+ import { getActiveRenderDebug } from './authoring/active-systems';
43
+ import { tabStallMetrics, workerCallTabMetrics } from './worker-call-metrics';
44
+ import { isJsHeapReading, type JsHeapReading, readJsHeap } from '@volter/sdk/kit/js-heap';
45
+
46
+ /** How often the page samples itself. Slow on purpose — see the header. */
47
+ export const TAB_CENSUS_INTERVAL_MS = 5_000;
48
+
49
+ /** Bytes a canvas backing store holds per pixel (RGBA8). */
50
+ const CANVAS_BYTES_PER_PIXEL = 4;
51
+
52
+ const BYTES_PER_MB = 1024 * 1024;
53
+
54
+ /**
55
+ * One resource profile — THIS module is its producer, and `@volter/sdk/tab-census`
56
+ * is where the shape is declared for every unit that speaks it (the node server
57
+ * that files it, the SDK status response, the journal line that prints it).
58
+ * Re-exported here because this file's own callers look for it here.
59
+ */
60
+ export type { TabCensus };
61
+
62
+ /** The three readings a sample is made of, injected so the sampler is pure. */
63
+ export interface TabCensusSources {
64
+ /** Feature-detected JS heap (`readJsHeap`), or its unavailable-reason. */
65
+ heap(): JsHeapReading | { readonly unavailable: string };
66
+ /** Distinct `?volter-mount=<id>` generations in Resource Timing. */
67
+ mountEpochs(): number;
68
+ /** Every canvas in the document, in BACKING-BUFFER pixels (not CSS px). */
69
+ canvases(): readonly { readonly width: number; readonly height: number }[];
70
+ /** Renderer resource counts, or null when no render-debug adapter is up. */
71
+ rendererCounts(): {
72
+ readonly geometries: number;
73
+ readonly textures: number;
74
+ readonly programs: number | null;
75
+ } | null;
76
+ /** Each lane's worker call times, or null when no lane has published a meter
77
+ * (`worker-call-metrics.ts`). Optional so a caller measuring only the
78
+ * resource half omits it and gets no block, rather than fabricating one. */
79
+ workerCalls?(): Readonly<Record<string, WorkerCallTabMetrics>> | null;
80
+ /** The main thread's stalls, or null while nobody is watching them. */
81
+ stalls?(): TabStallMetrics | null;
82
+ }
83
+
84
+ /** Two decimals of an MB — enough to see a 4K framebuffer, short enough to read. */
85
+ function mb(bytes: number): number {
86
+ return Math.round((bytes / BYTES_PER_MB) * 100) / 100;
87
+ }
88
+
89
+ /**
90
+ * Take one census. PURE: everything it reads comes from `sources`, so the test
91
+ * drives the absent-heap, absent-adapter and populated branches without a
92
+ * browser.
93
+ */
94
+ export function sampleTabCensus(sources: TabCensusSources): TabCensus {
95
+ const heap = sources.heap();
96
+ const canvases = sources.canvases();
97
+ const counts = sources.rendererCounts();
98
+ const workerCalls = sources.workerCalls?.() ?? null;
99
+ const stalls = sources.stalls?.() ?? null;
100
+ let canvasBytes = 0;
101
+ for (const canvas of canvases) {
102
+ canvasBytes += canvas.width * canvas.height * CANVAS_BYTES_PER_PIXEL;
103
+ }
104
+ return {
105
+ heapUsedMB: isJsHeapReading(heap) ? mb(heap.usedBytes) : null,
106
+ heapLimitMB: isJsHeapReading(heap) && heap.limitBytes !== null ? mb(heap.limitBytes) : null,
107
+ mountEpochs: sources.mountEpochs(),
108
+ canvases: canvases.length,
109
+ canvasMB: mb(canvasBytes),
110
+ ...(workerCalls === null ? {} : { workerCalls }),
111
+ ...(stalls === null ? {} : { stalls }),
112
+ ...(counts === null
113
+ ? {}
114
+ : {
115
+ textures: counts.textures,
116
+ geometries: counts.geometries,
117
+ // `renderer.info.programs` is populated only after a first render,
118
+ // and a count nobody could read stays absent rather than becoming 0.
119
+ ...(counts.programs === null ? {} : { programs: counts.programs }),
120
+ }),
121
+ };
122
+ }
123
+
124
+ /**
125
+ * Count the project module generations this document has fetched.
126
+ *
127
+ * Resource Timing is the browser-visible population we can measure without
128
+ * instrumenting project modules or pretending the ES-module registry exposes
129
+ * an enumeration API. The entries live for the document lifetime (the same
130
+ * lifetime as its module registry), and the project mount split watch raises
131
+ * the resource buffer before imports begin. A reload resets both populations.
132
+ */
133
+ export function countProjectMountEpochs(resources: readonly { readonly name: string }[]): number {
134
+ const epochs = new Set<string>();
135
+ for (const resource of resources) {
136
+ try {
137
+ const epoch = new URL(resource.name, 'http://volter.invalid').searchParams.get(
138
+ PROJECT_MOUNT_QUERY,
139
+ );
140
+ if (epoch !== null && epoch.length > 0) epochs.add(epoch);
141
+ } catch {
142
+ // Resource Timing normally supplies absolute URLs. A malformed entry is
143
+ // not evidence of a mount and must not sink the rest of the census.
144
+ }
145
+ }
146
+ return epochs.size;
147
+ }
148
+
149
+ /** The real readings: this document, this browser, whatever game is mounted. */
150
+ export function documentCensusSources(): TabCensusSources {
151
+ return {
152
+ heap: () => readJsHeap(),
153
+ mountEpochs: () => countProjectMountEpochs(performance.getEntriesByType('resource')),
154
+ canvases: () => [...document.querySelectorAll('canvas')],
155
+ rendererCounts: () => getActiveRenderDebug()?.memorySnapshot?.().counts ?? null,
156
+ workerCalls: () => workerCallTabMetrics(),
157
+ stalls: () => tabStallMetrics(),
158
+ };
159
+ }
160
+
161
+ let latest: TabCensus | null = null;
162
+
163
+ /** The newest census this page took, for the stats overlay to print. Null
164
+ * until the first sample (and while the tab has only ever been hidden). */
165
+ export function latestTabCensus(): TabCensus | null {
166
+ return latest;
167
+ }
168
+
169
+ export interface TabCensusLoopOptions {
170
+ /** Hand the profile to the heartbeat worker (`editor-presence.ts`). */
171
+ report(census: TabCensus): void;
172
+ sources?: TabCensusSources;
173
+ intervalMs?: number;
174
+ /** True while the tab is backgrounded — a hidden tab is not sampled. */
175
+ hidden?(): boolean;
176
+ }
177
+
178
+ /**
179
+ * Start sampling. Returns the stop function.
180
+ *
181
+ * A HIDDEN tab is skipped rather than throttled: it is painting nothing, so a
182
+ * sample would only re-report the moment it was backgrounded. Skipping is
183
+ * SAFE — and only safe — because the worker carries each profile on one beat
184
+ * and then drops it, so a tab that stops sampling stops sending and its
185
+ * profile's reported age climbs honestly. (When the worker echoed its cache
186
+ * instead, this skip is precisely what turned into the lie: a background tab
187
+ * killed under memory pressure — a mainline path for this feature — reported
188
+ * a half-second-old profile that was half an hour old.)
189
+ */
190
+ export function startTabCensus(options: TabCensusLoopOptions): () => void {
191
+ const sources = options.sources ?? documentCensusSources();
192
+ const hidden = options.hidden ?? (() => document.visibilityState === 'hidden');
193
+ const tick = (): void => {
194
+ if (hidden()) return;
195
+ const census = sampleTabCensus(sources);
196
+ latest = census;
197
+ options.report(census);
198
+ };
199
+ tick();
200
+ const timer = setInterval(tick, options.intervalMs ?? TAB_CENSUS_INTERVAL_MS);
201
+ return () => clearInterval(timer);
202
+ }