@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,840 @@
1
+ /**
2
+ * Wall-clock stamps for "this design surface just painted its first frame
3
+ * after becoming active."
4
+ *
5
+ * A tab flip used to look like a hung editor: the canvas went blank and
6
+ * nothing said how long the rebuild was taking. Doctor `--timings` (and any
7
+ * later product door) reads these stamps off `/__editor/state` so the wait
8
+ * is a measured number rather than a guess.
9
+ *
10
+ * `firstFrameAtMs` is `Date.now()` at the FIRST completed render of that
11
+ * activation, so a doctor clock started at `active-tab` send can subtract
12
+ * and get tab-activation → first painted frame, including the board's own
13
+ * deferred story-mount, not just the renderer constructor.
14
+ *
15
+ * One latest sample per document. `activation` increments every time a new
16
+ * first frame is recorded, so a second flip is distinguishable from the
17
+ * first without the reader inventing a generation token.
18
+ *
19
+ * Per-segment breakdown is OPT-IN. First-frame stamps stay always-on (a
20
+ * Date.now is cheap); the named segments and per-story list allocate only
21
+ * when {@link viewportTimingsEnabled} is true — doctor `--timings` sets
22
+ * `window.__VGAI_VIEWPORT_TIMINGS__` before boot, or the URL carries
23
+ * `?vgaiTimings=1`. Off by default so a normal session never pays for it.
24
+ *
25
+ * The breakdown clock starts at the ACTIVATION GESTURE (`setActive`), not at
26
+ * board-build start. Time between those two marks is the prefix window
27
+ * (workspace notify, React commit, reveal effect, the host's own activation)
28
+ * that used to fall into a catch-all "unaccounted" row. `unattributedMs` is the
29
+ * honesty term: leftover after every named segment, always published, even
30
+ * at 0.
31
+ */
32
+
33
+ export interface ViewportStoryMountSample {
34
+ readonly id: string;
35
+ readonly ms: number;
36
+ readonly runtimeMs: number;
37
+ readonly loadMs: number;
38
+ readonly fiberMs: number;
39
+ readonly settleMs: number;
40
+ readonly ok: boolean;
41
+ }
42
+
43
+ export interface StoryDiscoveryModuleTiming {
44
+ readonly modulePath: string;
45
+ readonly loadMs: number;
46
+ readonly composeMs: number;
47
+ readonly ok: boolean;
48
+ }
49
+
50
+ export interface StoryDiscoveryTiming {
51
+ readonly ms: number;
52
+ readonly completedAtMs: number;
53
+ readonly moduleCount: number;
54
+ readonly storyCount: number;
55
+ /** Fetch the story-file index and optional `.storybook/preview` module. */
56
+ readonly previewAnnotationsMs: number;
57
+ /** Resolve Storybook's portable runtime and apply project annotations. */
58
+ readonly runtimeAnnotationsMs: number;
59
+ /** Fetch the live story-file index used to create lazy module loaders. */
60
+ readonly fileScanMs: number;
61
+ /** Import and compose the immediately declared CSF modules in parallel. */
62
+ readonly moduleLoadAndComposeMs: number;
63
+ /** Per-module clocks reveal the critical import graph hidden by Promise.all. */
64
+ readonly modules: readonly StoryDiscoveryModuleTiming[];
65
+ }
66
+
67
+ /** How a named segment spends its wall time. Opposite fixes: busy vs wait. */
68
+ export type ViewportSegmentKind = 'cpu' | 'idle' | 'mixed';
69
+
70
+ export interface ViewportAttributionRow {
71
+ readonly name: string;
72
+ readonly ms: number;
73
+ readonly busyMs: number;
74
+ readonly waitMs: number;
75
+ readonly kind: ViewportSegmentKind;
76
+ }
77
+
78
+ export type ViewportActivationKind = 'first-open' | 'switch-back';
79
+
80
+ export interface ViewportActivationBreakdown {
81
+ /** Browser-reported visibility at the activation gesture. A timing without
82
+ * this fact cannot distinguish product work from browser throttling. */
83
+ readonly visibilityState: DocumentVisibilityState | 'unavailable';
84
+ readonly startedAtMs: number;
85
+ readonly reactActiveAtMs: number | null;
86
+ readonly boardBuildStartedAtMs: number | null;
87
+ readonly boardReadyAtMs: number | null;
88
+ readonly constructStartedAtMs: number | null;
89
+ readonly viewportReadyAtMs: number | null;
90
+ readonly rafResumeAtMs: number | null;
91
+ readonly firstRenderStartedAtMs: number | null;
92
+ readonly firstFrameAtMs: number;
93
+ readonly activationKind: ViewportActivationKind;
94
+ readonly workspaceSyncMs: number;
95
+ readonly revealScheduleMs: number;
96
+ readonly componentIndexMs: number;
97
+ readonly candidateCollectMs: number;
98
+ readonly storyMountTotalMs: number;
99
+ readonly storyMountBusyMs: number;
100
+ readonly storyMountWaitMs: number;
101
+ readonly boundsMs: number;
102
+ readonly layoutMs: number;
103
+ readonly assembleMs: number;
104
+ readonly reactCommitMs: number;
105
+ readonly webglContextMs: number;
106
+ readonly rendererMs: number;
107
+ readonly adapterSetupMs: number;
108
+ readonly iblBakeMs: number;
109
+ readonly dressingMs: number;
110
+ readonly editorViewportMs: number;
111
+ readonly framingMs: number;
112
+ readonly resizeBindMs: number;
113
+ readonly viewportBindMs: number;
114
+ readonly rafWaitMs: number;
115
+ readonly firstRenderMs: number;
116
+ readonly firstPaintMs: number;
117
+ readonly unattributedMs: number;
118
+ readonly accountedMs: number;
119
+ readonly candidateCount: number;
120
+ readonly exhibitCount: number;
121
+ readonly skippedCount: number;
122
+ readonly modulesAlreadyLoaded: boolean;
123
+ readonly stories: readonly ViewportStoryMountSample[];
124
+ readonly storyDiscovery: StoryDiscoveryTiming | null;
125
+ }
126
+
127
+ export interface ViewportActivationSample {
128
+ readonly documentId: string;
129
+ readonly activation: number;
130
+ readonly firstFrameAtMs: number;
131
+ readonly breakdown?: ViewportActivationBreakdown;
132
+ }
133
+
134
+ const latest = new Map<string, ViewportActivationSample>();
135
+ const counts = new Map<string, number>();
136
+
137
+ function reportEmbeddedViewportReady(): void {
138
+ if (typeof window === 'undefined' || window.parent === window || latest.size === 0) return;
139
+ window.parent.postMessage({ type: 'vgai:viewport-ready', documents: [...latest.keys()] }, '*');
140
+ }
141
+
142
+ // A host may hydrate after this iframe has already painted. Answer its ready
143
+ // query as well as announcing the first frame; iframe load is only HTML ready.
144
+ if (typeof window !== 'undefined' && window.parent !== window) {
145
+ window.addEventListener('message', (event) => {
146
+ if (event.source === window.parent && event.data?.type === 'vgai:request-viewport-ready')
147
+ reportEmbeddedViewportReady();
148
+ });
149
+ }
150
+
151
+ let timingsForced: boolean | null = null;
152
+ let activeBreakdown: MutableBreakdown | null = null;
153
+ let lastDiscovery: StoryDiscoveryTiming | null = null;
154
+
155
+ interface MutableBreakdown {
156
+ documentId: string;
157
+ visibilityState: DocumentVisibilityState | 'unavailable';
158
+ startedAtMs: number;
159
+ reactActiveAtMs: number | null;
160
+ boardBuildStartedAtMs: number | null;
161
+ boardReadyAtMs: number | null;
162
+ constructStartedAtMs: number | null;
163
+ viewportReadyAtMs: number | null;
164
+ rafResumeAtMs: number | null;
165
+ firstRenderStartedAtMs: number | null;
166
+ workspaceSyncMs: number;
167
+ revealScheduleMs: number;
168
+ componentIndexMs: number;
169
+ componentIndexBusyMs: number;
170
+ componentIndexWaitMs: number;
171
+ candidateCollectMs: number;
172
+ storyMountTotalMs: number;
173
+ boundsMs: number;
174
+ layoutMs: number;
175
+ assembleMs: number;
176
+ webglContextMs: number;
177
+ rendererMs: number;
178
+ adapterSetupMs: number;
179
+ iblBakeMs: number;
180
+ dressingMs: number;
181
+ editorViewportMs: number;
182
+ framingMs: number;
183
+ resizeBindMs: number;
184
+ viewportBindMs: number;
185
+ firstRenderMs: number;
186
+ candidateCount: number;
187
+ exhibitCount: number;
188
+ skippedCount: number;
189
+ modulesAlreadyLoaded: boolean;
190
+ stories: ViewportStoryMountSample[];
191
+ }
192
+
193
+ export type ViewportSegmentName =
194
+ | 'component-index'
195
+ | 'candidate-collect'
196
+ | 'story-mounts'
197
+ | 'bounds'
198
+ | 'layout'
199
+ | 'assemble'
200
+ | 'webgl-context'
201
+ | 'renderer'
202
+ | 'adapter-setup'
203
+ | 'ibl-bake'
204
+ | 'dressing'
205
+ | 'editor-viewport'
206
+ | 'framing'
207
+ | 'resize-bind'
208
+ | 'viewport-bind'
209
+ | 'first-render';
210
+
211
+ export function viewportTimingsEnabled(): boolean {
212
+ if (timingsForced !== null) return timingsForced;
213
+ if (typeof window === 'undefined') return false;
214
+ const flag = (window as Window & { __VGAI_VIEWPORT_TIMINGS__?: unknown })
215
+ .__VGAI_VIEWPORT_TIMINGS__;
216
+ if (flag === true || flag === '1') return true;
217
+ try {
218
+ return new URLSearchParams(window.location.search).get('vgaiTimings') === '1';
219
+ } catch {
220
+ return false;
221
+ }
222
+ }
223
+
224
+ function emptyBreakdown(
225
+ documentId: string,
226
+ startedAtMs: number,
227
+ options: { readonly modulesAlreadyLoaded?: boolean },
228
+ ): MutableBreakdown {
229
+ return {
230
+ documentId,
231
+ visibilityState: typeof document === 'undefined' ? 'unavailable' : document.visibilityState,
232
+ startedAtMs,
233
+ reactActiveAtMs: null,
234
+ boardBuildStartedAtMs: null,
235
+ boardReadyAtMs: null,
236
+ constructStartedAtMs: null,
237
+ viewportReadyAtMs: null,
238
+ rafResumeAtMs: null,
239
+ firstRenderStartedAtMs: null,
240
+ workspaceSyncMs: 0,
241
+ revealScheduleMs: 0,
242
+ componentIndexMs: 0,
243
+ componentIndexBusyMs: 0,
244
+ componentIndexWaitMs: 0,
245
+ candidateCollectMs: 0,
246
+ storyMountTotalMs: 0,
247
+ boundsMs: 0,
248
+ layoutMs: 0,
249
+ assembleMs: 0,
250
+ webglContextMs: 0,
251
+ rendererMs: 0,
252
+ adapterSetupMs: 0,
253
+ iblBakeMs: 0,
254
+ dressingMs: 0,
255
+ editorViewportMs: 0,
256
+ framingMs: 0,
257
+ resizeBindMs: 0,
258
+ viewportBindMs: 0,
259
+ firstRenderMs: 0,
260
+ candidateCount: 0,
261
+ exhibitCount: 0,
262
+ skippedCount: 0,
263
+ modulesAlreadyLoaded: options.modulesAlreadyLoaded === true,
264
+ stories: [],
265
+ };
266
+ }
267
+
268
+ function storyMountSplit(stories: readonly ViewportStoryMountSample[]): {
269
+ busyMs: number;
270
+ waitMs: number;
271
+ } {
272
+ let busyMs = 0;
273
+ let waitMs = 0;
274
+ for (const story of stories) {
275
+ busyMs += Math.max(0, story.runtimeMs) + Math.max(0, story.fiberMs);
276
+ waitMs += Math.max(0, story.loadMs) + Math.max(0, story.settleMs);
277
+ }
278
+ return { busyMs, waitMs };
279
+ }
280
+
281
+ function finalizeBreakdown(
282
+ pending: MutableBreakdown,
283
+ firstFrameAtMs: number,
284
+ ): ViewportActivationBreakdown {
285
+ const workspaceSyncMs =
286
+ pending.reactActiveAtMs === null
287
+ ? 0
288
+ : Math.max(0, pending.reactActiveAtMs - pending.startedAtMs);
289
+ const revealOrigin = pending.reactActiveAtMs ?? pending.startedAtMs;
290
+ const revealEnd = pending.boardBuildStartedAtMs;
291
+ const revealScheduleMs = revealEnd === null ? 0 : Math.max(0, revealEnd - revealOrigin);
292
+ const reactCommitMs =
293
+ pending.boardReadyAtMs === null || pending.constructStartedAtMs === null
294
+ ? 0
295
+ : Math.max(0, pending.constructStartedAtMs - pending.boardReadyAtMs);
296
+ const loopStart = pending.viewportReadyAtMs ?? pending.rafResumeAtMs;
297
+ const loopArrived = pending.firstRenderStartedAtMs ?? firstFrameAtMs;
298
+ const rafWaitMs = loopStart === null ? 0 : Math.max(0, loopArrived - loopStart);
299
+ const firstPaintMs =
300
+ loopStart === null
301
+ ? Math.max(0, firstFrameAtMs - pending.startedAtMs)
302
+ : Math.max(0, firstFrameAtMs - loopStart);
303
+ const mounts = storyMountSplit(pending.stories);
304
+ const activationKind: ViewportActivationKind =
305
+ pending.boardBuildStartedAtMs === null ? 'switch-back' : 'first-open';
306
+ const named: ViewportAttributionRow[] = attributionRowsFromParts({
307
+ workspaceSyncMs,
308
+ revealScheduleMs,
309
+ componentIndexMs: pending.componentIndexMs,
310
+ componentIndexBusyMs: pending.componentIndexBusyMs,
311
+ componentIndexWaitMs: pending.componentIndexWaitMs,
312
+ candidateCollectMs: pending.candidateCollectMs,
313
+ storyMountTotalMs: pending.storyMountTotalMs,
314
+ storyMountBusyMs: mounts.busyMs,
315
+ storyMountWaitMs: mounts.waitMs,
316
+ boundsMs: pending.boundsMs,
317
+ layoutMs: pending.layoutMs,
318
+ assembleMs: pending.assembleMs,
319
+ reactCommitMs,
320
+ webglContextMs: pending.webglContextMs,
321
+ rendererMs: pending.rendererMs,
322
+ adapterSetupMs: pending.adapterSetupMs,
323
+ iblBakeMs: pending.iblBakeMs,
324
+ dressingMs: pending.dressingMs,
325
+ editorViewportMs: pending.editorViewportMs,
326
+ framingMs: pending.framingMs,
327
+ resizeBindMs: pending.resizeBindMs,
328
+ viewportBindMs: pending.viewportBindMs,
329
+ rafWaitMs,
330
+ firstRenderMs: pending.firstRenderMs,
331
+ });
332
+ const accountedMs = named.reduce((sum, row) => sum + row.ms, 0);
333
+ const spanMs = Math.max(0, firstFrameAtMs - pending.startedAtMs);
334
+ return {
335
+ visibilityState: pending.visibilityState,
336
+ startedAtMs: pending.startedAtMs,
337
+ reactActiveAtMs: pending.reactActiveAtMs,
338
+ boardBuildStartedAtMs: pending.boardBuildStartedAtMs,
339
+ boardReadyAtMs: pending.boardReadyAtMs,
340
+ constructStartedAtMs: pending.constructStartedAtMs,
341
+ viewportReadyAtMs: pending.viewportReadyAtMs,
342
+ rafResumeAtMs: pending.rafResumeAtMs,
343
+ firstRenderStartedAtMs: pending.firstRenderStartedAtMs,
344
+ firstFrameAtMs,
345
+ activationKind,
346
+ workspaceSyncMs,
347
+ revealScheduleMs,
348
+ componentIndexMs: pending.componentIndexMs,
349
+ candidateCollectMs: pending.candidateCollectMs,
350
+ storyMountTotalMs: pending.storyMountTotalMs,
351
+ storyMountBusyMs: mounts.busyMs,
352
+ storyMountWaitMs: mounts.waitMs,
353
+ boundsMs: pending.boundsMs,
354
+ layoutMs: pending.layoutMs,
355
+ assembleMs: pending.assembleMs,
356
+ reactCommitMs,
357
+ webglContextMs: pending.webglContextMs,
358
+ rendererMs: pending.rendererMs,
359
+ adapterSetupMs: pending.adapterSetupMs,
360
+ iblBakeMs: pending.iblBakeMs,
361
+ dressingMs: pending.dressingMs,
362
+ editorViewportMs: pending.editorViewportMs,
363
+ framingMs: pending.framingMs,
364
+ resizeBindMs: pending.resizeBindMs,
365
+ viewportBindMs: pending.viewportBindMs,
366
+ rafWaitMs,
367
+ firstRenderMs: pending.firstRenderMs,
368
+ firstPaintMs,
369
+ unattributedMs: Math.max(0, spanMs - accountedMs),
370
+ accountedMs,
371
+ candidateCount: pending.candidateCount,
372
+ exhibitCount: pending.exhibitCount,
373
+ skippedCount: pending.skippedCount,
374
+ modulesAlreadyLoaded: pending.modulesAlreadyLoaded,
375
+ stories: pending.stories,
376
+ storyDiscovery: lastDiscovery,
377
+ };
378
+ }
379
+
380
+ function cpuRow(name: string, ms: number): ViewportAttributionRow {
381
+ const value = Math.max(0, ms);
382
+ return { name, ms: value, busyMs: value, waitMs: 0, kind: 'cpu' };
383
+ }
384
+
385
+ function idleRow(name: string, ms: number): ViewportAttributionRow {
386
+ const value = Math.max(0, ms);
387
+ return { name, ms: value, busyMs: 0, waitMs: value, kind: 'idle' };
388
+ }
389
+
390
+ function mixedRow(
391
+ name: string,
392
+ wallMs: number,
393
+ busyMs: number,
394
+ waitMs: number,
395
+ ): ViewportAttributionRow {
396
+ const ms = Math.max(0, wallMs);
397
+ let busy = Math.max(0, busyMs);
398
+ let wait = Math.max(0, waitMs);
399
+ if (busy + wait > ms) {
400
+ const scale = ms / (busy + wait);
401
+ busy *= scale;
402
+ wait *= scale;
403
+ } else if (busy + wait < ms) {
404
+ wait += ms - busy - wait;
405
+ }
406
+ return { name, ms, busyMs: busy, waitMs: wait, kind: 'mixed' };
407
+ }
408
+
409
+ function attributionRowsFromParts(parts: {
410
+ readonly workspaceSyncMs: number;
411
+ readonly revealScheduleMs: number;
412
+ readonly componentIndexMs: number;
413
+ readonly componentIndexBusyMs: number;
414
+ readonly componentIndexWaitMs: number;
415
+ readonly candidateCollectMs: number;
416
+ readonly storyMountTotalMs: number;
417
+ readonly storyMountBusyMs: number;
418
+ readonly storyMountWaitMs: number;
419
+ readonly boundsMs: number;
420
+ readonly layoutMs: number;
421
+ readonly assembleMs: number;
422
+ readonly reactCommitMs: number;
423
+ readonly webglContextMs: number;
424
+ readonly rendererMs: number;
425
+ readonly adapterSetupMs: number;
426
+ readonly iblBakeMs: number;
427
+ readonly dressingMs: number;
428
+ readonly editorViewportMs: number;
429
+ readonly framingMs: number;
430
+ readonly resizeBindMs: number;
431
+ readonly viewportBindMs: number;
432
+ readonly rafWaitMs: number;
433
+ readonly firstRenderMs: number;
434
+ }): ViewportAttributionRow[] {
435
+ return [
436
+ idleRow('workspace-sync', parts.workspaceSyncMs),
437
+ idleRow('reveal-schedule', parts.revealScheduleMs),
438
+ mixedRow(
439
+ 'component-index',
440
+ parts.componentIndexMs,
441
+ parts.componentIndexBusyMs,
442
+ parts.componentIndexWaitMs > 0 || parts.componentIndexMs === 0
443
+ ? parts.componentIndexWaitMs
444
+ : parts.componentIndexMs,
445
+ ),
446
+ cpuRow('candidate-collect', parts.candidateCollectMs),
447
+ mixedRow(
448
+ 'story-mounts',
449
+ parts.storyMountTotalMs,
450
+ parts.storyMountBusyMs,
451
+ parts.storyMountWaitMs,
452
+ ),
453
+ cpuRow('bounds', parts.boundsMs),
454
+ cpuRow('layout', parts.layoutMs),
455
+ cpuRow('assemble', parts.assembleMs),
456
+ idleRow('react-commit (board→viewport)', parts.reactCommitMs),
457
+ cpuRow('webgl-context', parts.webglContextMs),
458
+ cpuRow('renderer', parts.rendererMs),
459
+ cpuRow('adapter-setup', parts.adapterSetupMs),
460
+ cpuRow('ibl-bake (three PMREM)', parts.iblBakeMs),
461
+ cpuRow('dressing', parts.dressingMs),
462
+ cpuRow('editor-viewport', parts.editorViewportMs),
463
+ cpuRow('framing', parts.framingMs),
464
+ cpuRow('resize-bind', parts.resizeBindMs),
465
+ cpuRow('viewport-bind', parts.viewportBindMs),
466
+ idleRow('raf-wait', parts.rafWaitMs),
467
+ cpuRow('first-render', parts.firstRenderMs),
468
+ ];
469
+ }
470
+
471
+ /**
472
+ * Named rows for one activation, plus the honesty term. `clockOriginMs` is
473
+ * the doctor's send time when the printed clock starts before the editor
474
+ * gesture; omit it to attribute from the gesture alone.
475
+ */
476
+ export function buildViewportAttributionTable(
477
+ breakdown: ViewportActivationBreakdown,
478
+ clock: { readonly originMs?: number; readonly totalMs: number } = {
479
+ totalMs: Math.max(0, breakdown.firstFrameAtMs - breakdown.startedAtMs),
480
+ },
481
+ ): { readonly rows: readonly ViewportAttributionRow[]; readonly totalMs: number } {
482
+ const totalMs = Math.max(0, clock.totalMs);
483
+ const originMs = clock.originMs ?? breakdown.startedAtMs;
484
+ const commandQueueMs = Math.max(0, breakdown.startedAtMs - originMs);
485
+ const rows: ViewportAttributionRow[] = [];
486
+ if (commandQueueMs > 0 || clock.originMs !== undefined) {
487
+ rows.push(idleRow('command-queue', commandQueueMs));
488
+ }
489
+ rows.push(
490
+ ...attributionRowsFromParts({
491
+ workspaceSyncMs: breakdown.workspaceSyncMs,
492
+ revealScheduleMs: breakdown.revealScheduleMs,
493
+ componentIndexMs: breakdown.componentIndexMs,
494
+ componentIndexBusyMs: 0,
495
+ componentIndexWaitMs: breakdown.componentIndexMs,
496
+ candidateCollectMs: breakdown.candidateCollectMs,
497
+ storyMountTotalMs: breakdown.storyMountTotalMs,
498
+ storyMountBusyMs: breakdown.storyMountBusyMs,
499
+ storyMountWaitMs: breakdown.storyMountWaitMs,
500
+ boundsMs: breakdown.boundsMs,
501
+ layoutMs: breakdown.layoutMs,
502
+ assembleMs: breakdown.assembleMs,
503
+ reactCommitMs: breakdown.reactCommitMs,
504
+ webglContextMs: breakdown.webglContextMs,
505
+ rendererMs: breakdown.rendererMs,
506
+ adapterSetupMs: breakdown.adapterSetupMs,
507
+ iblBakeMs: breakdown.iblBakeMs,
508
+ dressingMs: breakdown.dressingMs,
509
+ editorViewportMs: breakdown.editorViewportMs,
510
+ framingMs: breakdown.framingMs,
511
+ resizeBindMs: breakdown.resizeBindMs,
512
+ viewportBindMs: breakdown.viewportBindMs,
513
+ rafWaitMs: breakdown.rafWaitMs,
514
+ firstRenderMs: breakdown.firstRenderMs,
515
+ }),
516
+ );
517
+ const accounted = rows.reduce((sum, row) => sum + row.ms, 0);
518
+ rows.push(idleRow('unattributed', Math.max(0, totalMs - accounted)));
519
+ return { rows, totalMs };
520
+ }
521
+
522
+ export function formatViewportAttributionTable(
523
+ breakdown: ViewportActivationBreakdown,
524
+ clock: { readonly originMs?: number; readonly totalMs: number },
525
+ ): string {
526
+ const { rows, totalMs } = buildViewportAttributionTable(breakdown, clock);
527
+ const accounted = rows
528
+ .filter((row) => row.name !== 'unattributed')
529
+ .reduce((sum, row) => sum + row.ms, 0);
530
+ const pct = (ms: number): string => (totalMs > 0 ? `${((ms / totalMs) * 100).toFixed(1)}%` : '—');
531
+ const lines = [
532
+ ` activation kind: ${breakdown.activationKind}`,
533
+ ` document.visibilityState at gesture: ${breakdown.visibilityState}`,
534
+ ` modules already loaded at build start: ${breakdown.modulesAlreadyLoaded ? 'yes' : 'no'}`,
535
+ ` exhibits=${breakdown.exhibitCount} skipped=${breakdown.skippedCount} candidates=${breakdown.candidateCount}`,
536
+ ` accounted ${accounted}ms / ${totalMs}ms (${pct(accounted).trim()} of clock)`,
537
+ ' segment ms busy wait kind % of clock',
538
+ ];
539
+ for (const row of rows) {
540
+ if (row.ms === 0 && row.name !== 'unattributed') continue;
541
+ lines.push(
542
+ ` ${row.name.padEnd(32)} ${String(Math.round(row.ms)).padStart(6)} ${String(Math.round(row.busyMs)).padStart(7)} ${String(Math.round(row.waitMs)).padStart(7)} ${row.kind.padEnd(5)} ${pct(row.ms).padStart(7)}`,
543
+ );
544
+ }
545
+ return lines.join('\n');
546
+ }
547
+
548
+ export function recordViewportFirstFrame(
549
+ documentId: string,
550
+ atMs: number = Date.now(),
551
+ ): ViewportActivationSample {
552
+ const activation = (counts.get(documentId) ?? 0) + 1;
553
+ counts.set(documentId, activation);
554
+ const sample: ViewportActivationSample = { documentId, activation, firstFrameAtMs: atMs };
555
+ const pending = activeBreakdown;
556
+ if (pending && pending.documentId === documentId) {
557
+ const withBreakdown: ViewportActivationSample = {
558
+ ...sample,
559
+ breakdown: finalizeBreakdown(pending, atMs),
560
+ };
561
+ activeBreakdown = null;
562
+ latest.set(documentId, withBreakdown);
563
+ resolveFirstViewportFrameWaiters();
564
+ notifyViewportActivationListeners();
565
+ return withBreakdown;
566
+ }
567
+ latest.set(documentId, sample);
568
+ resolveFirstViewportFrameWaiters();
569
+ notifyViewportActivationListeners();
570
+ return sample;
571
+ }
572
+
573
+ let firstViewportFrameWaiters = new Set<() => void>();
574
+ const viewportActivationListeners = new Set<() => void>();
575
+
576
+ function notifyViewportActivationListeners(): void {
577
+ reportEmbeddedViewportReady();
578
+ for (const listener of viewportActivationListeners) listener();
579
+ }
580
+
581
+ /**
582
+ * Subscribe to completed viewport frames.
583
+ *
584
+ * The timing is part of the editor state snapshot, so its producer must wake
585
+ * that snapshot when a frame lands. Without this signal, a remote reader had
586
+ * to send another `active-tab` command merely to make the page re-report. On
587
+ * a large component board that probe queues behind the synchronous first
588
+ * render, exhausts the ordinary 5-second command budget, and leaves a false
589
+ * `play-stall` condition even though the requested frame completes.
590
+ */
591
+ export function subscribeViewportActivationTimings(listener: () => void): () => void {
592
+ viewportActivationListeners.add(listener);
593
+ return () => viewportActivationListeners.delete(listener);
594
+ }
595
+
596
+ function resolveFirstViewportFrameWaiters(): void {
597
+ if (latest.size === 0) return;
598
+ releaseFirstViewportFrameWaiters();
599
+ }
600
+
601
+ function releaseFirstViewportFrameWaiters(): void {
602
+ const waiters = firstViewportFrameWaiters;
603
+ firstViewportFrameWaiters = new Set();
604
+ for (const resolve of waiters) resolve();
605
+ }
606
+
607
+ /** A hidden tab paints nothing, so the frame this signal names is not coming
608
+ * (see `after-paint.ts`). Release every waiter the moment the page goes
609
+ * hidden: the deferral exists to protect a paint critical path that does not
610
+ * exist there, so continuing to hold callers is pure loss. */
611
+ let hiddenReleaseListenerAttached = false;
612
+ function attachHiddenRelease(): void {
613
+ if (hiddenReleaseListenerAttached || typeof document === 'undefined') return;
614
+ hiddenReleaseListenerAttached = true;
615
+ document.addEventListener('visibilitychange', () => {
616
+ if (document.hidden) releaseFirstViewportFrameWaiters();
617
+ });
618
+ }
619
+
620
+ /**
621
+ * Resolves after any authored viewport has produced its first honest frame —
622
+ * or immediately when this tab cannot produce one, because it is hidden.
623
+ *
624
+ * This is a presentation readiness signal, not profiling: background work
625
+ * that can saturate Vite's module graph uses it to stay off the opening
626
+ * viewport's critical path even when timing capture is disabled. Callers may
627
+ * have no timeout of their own (`project-story-discovery.ts` deliberately has
628
+ * none), so the hidden case must resolve here or a backgrounded editor never
629
+ * discovers the project's stories at all.
630
+ */
631
+ export function waitForFirstViewportFrame(): Promise<void> {
632
+ if (latest.size > 0) return Promise.resolve();
633
+ if (typeof document !== 'undefined' && document.hidden) return Promise.resolve();
634
+ attachHiddenRelease();
635
+ return new Promise((resolve) => firstViewportFrameWaiters.add(resolve));
636
+ }
637
+
638
+ export function viewportActivationTimings(): readonly ViewportActivationSample[] {
639
+ return [...latest.values()];
640
+ }
641
+
642
+ export function latestViewportActivation(documentId: string): ViewportActivationSample | null {
643
+ return latest.get(documentId) ?? null;
644
+ }
645
+
646
+ export function lastStoryDiscoveryTiming(): StoryDiscoveryTiming | null {
647
+ return lastDiscovery;
648
+ }
649
+
650
+ /**
651
+ * True start of an activation: the workspace `setActive` gesture. A later
652
+ * {@link beginViewportBreakdown} joins this clock instead of resetting it,
653
+ * so the prefix window (notify → React → reveal) is named rather than
654
+ * dumped into unattributed.
655
+ */
656
+ export function noteViewportActivationGesture(documentId: string): void {
657
+ if (!viewportTimingsEnabled()) return;
658
+ activeBreakdown = emptyBreakdown(documentId, Date.now(), {});
659
+ }
660
+
661
+ export function beginViewportBreakdown(
662
+ documentId: string,
663
+ options: { readonly modulesAlreadyLoaded?: boolean } = {},
664
+ ): void {
665
+ if (!viewportTimingsEnabled()) return;
666
+ const now = Date.now();
667
+ if (activeBreakdown && activeBreakdown.documentId === documentId) {
668
+ if (activeBreakdown.boardBuildStartedAtMs === null) {
669
+ activeBreakdown.boardBuildStartedAtMs = now;
670
+ }
671
+ if (options.modulesAlreadyLoaded === true) activeBreakdown.modulesAlreadyLoaded = true;
672
+ return;
673
+ }
674
+ activeBreakdown = emptyBreakdown(documentId, now, options);
675
+ activeBreakdown.boardBuildStartedAtMs = now;
676
+ }
677
+
678
+ export function cancelViewportBreakdown(documentId?: string): void {
679
+ if (!activeBreakdown) return;
680
+ if (documentId && activeBreakdown.documentId !== documentId) return;
681
+ activeBreakdown = null;
682
+ }
683
+
684
+ export function markViewportSegment(
685
+ name: ViewportSegmentName,
686
+ ms: number,
687
+ split?: { readonly busyMs?: number; readonly waitMs?: number },
688
+ ): void {
689
+ if (!activeBreakdown) return;
690
+ const value = Math.max(0, ms);
691
+ switch (name) {
692
+ case 'component-index':
693
+ activeBreakdown.componentIndexMs = value;
694
+ activeBreakdown.componentIndexBusyMs = Math.max(0, split?.busyMs ?? 0);
695
+ activeBreakdown.componentIndexWaitMs = Math.max(0, split?.waitMs ?? value);
696
+ break;
697
+ case 'candidate-collect':
698
+ activeBreakdown.candidateCollectMs = value;
699
+ break;
700
+ case 'story-mounts':
701
+ activeBreakdown.storyMountTotalMs = value;
702
+ break;
703
+ case 'bounds':
704
+ activeBreakdown.boundsMs = value;
705
+ break;
706
+ case 'layout':
707
+ activeBreakdown.layoutMs = value;
708
+ break;
709
+ case 'assemble':
710
+ activeBreakdown.assembleMs = value;
711
+ break;
712
+ case 'webgl-context':
713
+ activeBreakdown.webglContextMs = value;
714
+ break;
715
+ case 'renderer':
716
+ activeBreakdown.rendererMs = value;
717
+ break;
718
+ case 'adapter-setup':
719
+ activeBreakdown.adapterSetupMs = value;
720
+ break;
721
+ case 'ibl-bake':
722
+ activeBreakdown.iblBakeMs = value;
723
+ break;
724
+ case 'dressing':
725
+ activeBreakdown.dressingMs = value;
726
+ break;
727
+ case 'editor-viewport':
728
+ activeBreakdown.editorViewportMs = value;
729
+ break;
730
+ case 'framing':
731
+ activeBreakdown.framingMs = value;
732
+ break;
733
+ case 'resize-bind':
734
+ activeBreakdown.resizeBindMs = value;
735
+ break;
736
+ case 'viewport-bind':
737
+ activeBreakdown.viewportBindMs = value;
738
+ break;
739
+ case 'first-render':
740
+ activeBreakdown.firstRenderMs = value;
741
+ break;
742
+ default: {
743
+ const _exhaustive: never = name;
744
+ void _exhaustive;
745
+ }
746
+ }
747
+ }
748
+
749
+ export function markViewportReactActive(documentId: string): void {
750
+ if (!activeBreakdown || activeBreakdown.documentId !== documentId) return;
751
+ if (activeBreakdown.reactActiveAtMs !== null) return;
752
+ activeBreakdown.reactActiveAtMs = Date.now();
753
+ }
754
+
755
+ export function markViewportRafResume(documentId: string): void {
756
+ if (!activeBreakdown || activeBreakdown.documentId !== documentId) return;
757
+ if (activeBreakdown.rafResumeAtMs !== null) return;
758
+ activeBreakdown.rafResumeAtMs = Date.now();
759
+ }
760
+
761
+ export function markViewportFirstRenderStart(documentId: string): void {
762
+ if (!activeBreakdown || activeBreakdown.documentId !== documentId) return;
763
+ if (activeBreakdown.firstRenderStartedAtMs !== null) return;
764
+ activeBreakdown.firstRenderStartedAtMs = Date.now();
765
+ }
766
+
767
+ export function noteViewportBreakdownCounts(countsIn: {
768
+ readonly candidateCount?: number;
769
+ readonly exhibitCount?: number;
770
+ readonly skippedCount?: number;
771
+ }): void {
772
+ if (!activeBreakdown) return;
773
+ if (countsIn.candidateCount !== undefined)
774
+ activeBreakdown.candidateCount = countsIn.candidateCount;
775
+ if (countsIn.exhibitCount !== undefined) activeBreakdown.exhibitCount = countsIn.exhibitCount;
776
+ if (countsIn.skippedCount !== undefined) activeBreakdown.skippedCount = countsIn.skippedCount;
777
+ }
778
+
779
+ export function markViewportBoardReady(): void {
780
+ if (!activeBreakdown) return;
781
+ activeBreakdown.boardReadyAtMs = Date.now();
782
+ }
783
+
784
+ export function markViewportConstructStarted(): void {
785
+ if (!activeBreakdown) return;
786
+ activeBreakdown.constructStartedAtMs = Date.now();
787
+ }
788
+
789
+ export function markViewportConstructReady(): void {
790
+ if (!activeBreakdown) return;
791
+ activeBreakdown.viewportReadyAtMs = Date.now();
792
+ }
793
+
794
+ export function recordViewportStoryMount(sample: ViewportStoryMountSample): void {
795
+ if (!activeBreakdown) return;
796
+ activeBreakdown.stories.push(sample);
797
+ }
798
+
799
+ export function activeViewportBreakdownDocumentId(): string | null {
800
+ return activeBreakdown?.documentId ?? null;
801
+ }
802
+
803
+ export function recordStoryDiscoveryTiming(timing: StoryDiscoveryTiming): void {
804
+ if (!viewportTimingsEnabled()) return;
805
+ lastDiscovery = timing;
806
+ }
807
+
808
+ /**
809
+ * Drop the measurements of the project that just closed. Registered with
810
+ * `onProjectSessionEnd`.
811
+ *
812
+ * Every sample here is keyed by DOCUMENT id, and document ids repeat across
813
+ * projects (`workspace:game`, a scene document's own id) — so without this the
814
+ * next project's first activation reads as its Nth, `latestViewportActivation`
815
+ * hands back the previous project's timing for a document it never opened, and
816
+ * a breakdown left open by the closing project keeps collecting segments under
817
+ * the new one. `timingsForced` is NOT reset: it is a URL/debug switch, not
818
+ * session state.
819
+ */
820
+ export function resetViewportActivationTimingsForNewProject(): void {
821
+ latest.clear();
822
+ counts.clear();
823
+ activeBreakdown = null;
824
+ lastDiscovery = null;
825
+ }
826
+
827
+ /** Test-only reset. */
828
+ export function __resetViewportActivationTimingsForTest(): void {
829
+ latest.clear();
830
+ counts.clear();
831
+ timingsForced = null;
832
+ activeBreakdown = null;
833
+ lastDiscovery = null;
834
+ firstViewportFrameWaiters.clear();
835
+ }
836
+
837
+ /** Test-only override. `null` restores the window/URL check. */
838
+ export function __setViewportTimingsEnabledForTest(value: boolean | null): void {
839
+ timingsForced = value;
840
+ }