@vgai/editor 0.2.0 → 0.4.0-canary.20260715.0

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 (430) hide show
  1. package/README.md +24 -0
  2. package/dist/assets/axe-C7YBtOuM.js +30 -0
  3. package/dist/assets/browserAll-DDtGGE48.js +1 -0
  4. package/dist/assets/create-runtime-DbTlBlKG.js +1 -0
  5. package/dist/assets/{game-BI111o5f.js → game-BE0r7DMI.js} +3 -3
  6. package/dist/assets/game-BdTHR2_X.js +1 -0
  7. package/dist/assets/{game-pt_1lQLv.js → game-C3iQGSqo.js} +1 -1
  8. package/dist/assets/game-CcHfYxjP.js +1 -0
  9. package/dist/assets/game-Cqzj_lpD.js +1 -0
  10. package/dist/assets/game-DSZdeCHu.js +1 -0
  11. package/dist/assets/game-Dch9sAPc.js +1 -0
  12. package/dist/assets/{game-xsOho_wg.js → game-SAFn90pA.js} +3 -3
  13. package/dist/assets/game-loop-DMIgSMV-.js +1 -0
  14. package/dist/assets/{game-source-CvidN7AB.js → game-source-Dk83w26t.js} +1 -1
  15. package/dist/assets/{index-Bp5cecD6.js → index-4idIsHHJ.js} +2 -2
  16. package/dist/assets/{index-DL7RcQ0n.js → index-C-LhOTBN.js} +1 -1
  17. package/dist/assets/{index-Cs8xwv3e.js → index-CDkxceqE.js} +1 -1
  18. package/dist/assets/index-CQEfi217.js +15412 -0
  19. package/dist/assets/index-Dvi-V0NE.css +1 -0
  20. package/dist/assets/ingest-siblings-s0P5I1Ub.js +1 -0
  21. package/dist/assets/mount-manifest-DXMOlF79.js +1 -0
  22. package/dist/assets/react-18-C9eHn8x1.js +1 -0
  23. package/dist/assets/webworkerAll-Fn0e-ouF.js +1 -0
  24. package/dist/assets/world-documents-GM0a9Kv7.js +1 -0
  25. package/dist/index.html +15 -13
  26. package/dist/ingest/racing-game/vgai.game.json +5 -4
  27. package/dist/ingest/simcity/vgai.game.json +5 -4
  28. package/dist/ingest/tanks/vgai.game.json +5 -4
  29. package/dist/project-scripts.bundle.js +3917 -0
  30. package/dist/scenes/untitled.vscn.json +2 -0
  31. package/dist-server/packaged.mjs +7697 -3435
  32. package/package.json +31 -4
  33. package/scripts/probe-reporter.ts +349 -0
  34. package/scripts/run-probe.ts +2260 -0
  35. package/server/asset-catalog-audit.ts +268 -0
  36. package/server/asset-catalog-v2.ts +146 -0
  37. package/server/asset-library-routes.ts +276 -58
  38. package/server/canonical-path.ts +1 -1
  39. package/server/dev.ts +148 -44
  40. package/server/editor-server.ts +888 -61
  41. package/server/editor-sse.ts +115 -4
  42. package/server/harness-chat-service.ts +796 -0
  43. package/server/local-asset-catalog.ts +157 -22
  44. package/server/packaged.ts +51 -21
  45. package/server/process-shutdown.ts +136 -0
  46. package/server/prod.ts +9 -6
  47. package/server/project-hmr-files.ts +41 -0
  48. package/server/project-operations.ts +343 -0
  49. package/server/project-optimize-deps-entries.ts +4 -4
  50. package/server/project-output-writer.ts +156 -0
  51. package/server/project-validation.ts +140 -0
  52. package/server/project-view.ts +8 -50
  53. package/server/server-utils.ts +75 -10
  54. package/server/session-registry.ts +12 -0
  55. package/src/EditorContext.tsx +107 -3
  56. package/src/action-registry.ts +115 -17
  57. package/src/adapter-resolver.ts +213 -478
  58. package/src/asset-events.ts +64 -1
  59. package/src/asset-preview.ts +906 -0
  60. package/src/asset-selection.ts +121 -0
  61. package/src/asset-workflow/asset-capabilities.ts +259 -0
  62. package/src/asset-workflow/asset-editor-errors.ts +46 -0
  63. package/src/asset-workflow/asset-import-pipeline.ts +176 -0
  64. package/src/asset-workflow/asset-library-query.ts +107 -0
  65. package/src/asset-workflow/asset-types.ts +192 -0
  66. package/src/asset-workflow/asset-workflow-quality.ts +65 -0
  67. package/src/asset-workflow/import-contract.ts +113 -0
  68. package/src/asset-workflow/model-conversion.ts +126 -0
  69. package/src/asset-workflow/model-inspection.ts +185 -0
  70. package/src/asset-workflow/project-asset-commands.ts +23 -0
  71. package/src/asset-workflow/project-asset-health.ts +153 -0
  72. package/src/asset-workflow/project-asset-operations.ts +119 -0
  73. package/src/asset-workflow/thumbnail-system.ts +172 -0
  74. package/src/authoring/active-systems.ts +15 -0
  75. package/src/authoring/boundary-authoring-adapter.ts +16 -5
  76. package/src/authoring/composite-authoring-adapter.ts +305 -124
  77. package/src/authoring/design-time-layers.ts +300 -117
  78. package/src/authoring/edit-mode-authoring.ts +278 -293
  79. package/src/authoring/embed-only-adapter.ts +4 -2
  80. package/src/authoring/first-party-hierarchy-menu.ts +7 -2
  81. package/src/authoring/first-party-inspector/AddSectionMenu.tsx +5 -12
  82. package/src/authoring/first-party-inspector/EnvironmentSection.tsx +53 -126
  83. package/src/authoring/first-party-inspector/HeaderSection.tsx +54 -65
  84. package/src/authoring/first-party-inspector/is-first-party-selection.ts +30 -11
  85. package/src/authoring/first-party-inspector/register.tsx +13 -2
  86. package/src/authoring/ingest-authoring-adapter.ts +142 -45
  87. package/src/authoring/mount-failure-report.ts +5 -5
  88. package/src/authoring/provenance.ts +41 -0
  89. package/src/authoring/react-dom-authoring-adapter.ts +92 -92
  90. package/src/authoring/react-inspector-section.tsx +489 -51
  91. package/src/authoring/react-world-authoring-adapter.ts +541 -306
  92. package/src/authoring/story-overlay.ts +1 -1
  93. package/src/authoring/story-types.ts +11 -0
  94. package/src/authoring/vgai-scene-authoring-adapter.ts +54 -25
  95. package/src/authoring/viewport-tool-context.ts +78 -0
  96. package/src/authoring/world-canvas-viewport-state.ts +35 -0
  97. package/src/authoring/world-hidden-viewport.ts +186 -0
  98. package/src/authoring/world-pan-state.ts +33 -17
  99. package/src/authoring/world-session-state.ts +1 -1
  100. package/src/authoring/world2d-authoring-adapter.ts +109 -52
  101. package/src/availability-tick.ts +56 -0
  102. package/src/browser-play-entry.ts +5 -5
  103. package/src/browser-project-scripts.ts +1 -0
  104. package/src/build-identity.ts +15 -0
  105. package/src/command-listener.ts +893 -19
  106. package/src/components/AlignToolbar.tsx +74 -63
  107. package/src/components/AppRoot.tsx +193 -26
  108. package/src/components/ApplicationMenus.tsx +272 -0
  109. package/src/components/AssetBrowser.tsx +1450 -293
  110. package/src/components/AssetEditorShell.tsx +141 -0
  111. package/src/components/AssetImportDetails.tsx +218 -0
  112. package/src/components/AssetLibraryPanel.tsx +14 -0
  113. package/src/components/CameraInfo.tsx +11 -20
  114. package/src/components/CenterDocuments.tsx +585 -0
  115. package/src/components/CommandPalette.tsx +75 -30
  116. package/src/components/ConsolePanel.css +55 -0
  117. package/src/components/ConsolePanel.tsx +57 -112
  118. package/src/components/DebugConsolePanel.tsx +461 -0
  119. package/src/components/DebuggerPanel.tsx +165 -0
  120. package/src/components/DefaultEditorLayout.tsx +167 -231
  121. package/src/components/GameHierarchy.tsx +873 -290
  122. package/src/components/GamePerformanceOverlay.tsx +46 -0
  123. package/src/components/HarnessChatPanel.tsx +2352 -0
  124. package/src/components/HistoryPanel.tsx +226 -0
  125. package/src/components/Inspector.tsx +153 -99
  126. package/src/components/InspectorToolSection.tsx +6 -4
  127. package/src/components/MountFailureBanner.tsx +31 -48
  128. package/src/components/NetworkSection.tsx +25 -14
  129. package/src/components/OnlineAssetBrowser.tsx +794 -343
  130. package/src/components/OverlayReportBanner.tsx +38 -64
  131. package/src/components/PerformancePanel.tsx +206 -0
  132. package/src/components/PlayBar.tsx +93 -263
  133. package/src/components/PrefabSaveDialog.tsx +55 -127
  134. package/src/components/ProjectHeader.css +60 -0
  135. package/src/components/ProjectHeader.tsx +170 -105
  136. package/src/components/ProjectScreen.tsx +246 -184
  137. package/src/components/ReactCanvasControls.tsx +185 -0
  138. package/src/components/ResolutionPicker.tsx +85 -0
  139. package/src/components/RootActivateDialog.tsx +39 -68
  140. package/src/components/SaveDialog.tsx +55 -127
  141. package/src/components/SaveStatus.tsx +11 -29
  142. package/src/components/StartupLoadingScreen.tsx +96 -0
  143. package/src/components/StateWatchPanel.tsx +302 -0
  144. package/src/components/StatsOverlay.tsx +12 -5
  145. package/src/components/StatusBar.tsx +64 -0
  146. package/src/components/ThemeManagerDialog.css +89 -0
  147. package/src/components/ThemeManagerDialog.tsx +371 -0
  148. package/src/components/ToolHost.tsx +26 -15
  149. package/src/components/Toolbar.tsx +117 -214
  150. package/src/components/VgaiVoxelLogo.tsx +89 -0
  151. package/src/components/ViewportOverlay.tsx +97 -172
  152. package/src/components/ViewportPanel.tsx +130 -31
  153. package/src/components/WorkspaceDock.tsx +891 -0
  154. package/src/components/WorldSelectionOverlay.tsx +51 -63
  155. package/src/components/WorldTextEditor.tsx +9 -5
  156. package/src/components/asset-documents.tsx +390 -0
  157. package/src/components/asset-editor-persistence.ts +44 -0
  158. package/src/components/asset-selection-section.tsx +338 -0
  159. package/src/components/asset-viewers/AudioViewer.tsx +73 -21
  160. package/src/components/asset-viewers/GenericJsonViewer.tsx +26 -11
  161. package/src/components/asset-viewers/ImageViewer.tsx +43 -11
  162. package/src/components/asset-viewers/InputMapViewer.tsx +512 -134
  163. package/src/components/asset-viewers/MaterialAssetEditor.tsx +540 -0
  164. package/src/components/asset-viewers/ModelViewer.tsx +805 -121
  165. package/src/components/asset-viewers/OnlineAssetDetail.tsx +177 -60
  166. package/src/components/asset-viewers/SourceAssetViewer.tsx +121 -0
  167. package/src/components/asset-workflow.css +506 -0
  168. package/src/components/build-documents.tsx +696 -0
  169. package/src/components/core-utilities.tsx +75 -0
  170. package/src/components/data-documents.tsx +364 -0
  171. package/src/components/{DataPanel.tsx → data-editor.tsx} +138 -288
  172. package/src/components/debugger-panel-state.ts +57 -0
  173. package/src/components/inspector-widgets/AlignmentGrid.tsx +8 -14
  174. package/src/components/inspector-widgets/BorderEditor.tsx +41 -33
  175. package/src/components/inspector-widgets/ColorPicker.tsx +39 -39
  176. package/src/components/inspector-widgets/FontPicker.tsx +13 -21
  177. package/src/components/inspector-widgets/GradientEditor.tsx +11 -19
  178. package/src/components/inspector-widgets/ScrubbableInput.tsx +6 -3
  179. package/src/components/inspector-widgets/ShadowEditor.tsx +20 -33
  180. package/src/components/inspector-widgets/shared.tsx +90 -49
  181. package/src/components/inspectors/AnimationSection.tsx +39 -40
  182. package/src/components/inspectors/AudioSection.tsx +28 -39
  183. package/src/components/inspectors/BoneAttachmentSection.tsx +19 -24
  184. package/src/components/inspectors/CameraSection.tsx +14 -23
  185. package/src/components/inspectors/ComponentsSection.tsx +39 -43
  186. package/src/components/inspectors/JointsSection.tsx +34 -43
  187. package/src/components/inspectors/LightSection.tsx +90 -35
  188. package/src/components/inspectors/MaterialSection.tsx +137 -174
  189. package/src/components/inspectors/MeshSection.tsx +9 -17
  190. package/src/components/inspectors/NavigationSection.tsx +8 -15
  191. package/src/components/inspectors/ParticleSection.tsx +91 -76
  192. package/src/components/inspectors/PhysicsSection.tsx +42 -46
  193. package/src/components/inspectors/PostProcessingSection.tsx +28 -36
  194. package/src/components/inspectors/RenderingSection.tsx +12 -20
  195. package/src/components/inspectors/ShadowSection.tsx +7 -8
  196. package/src/components/inspectors/SplineSection.tsx +31 -42
  197. package/src/components/inspectors/TransformSection.tsx +14 -22
  198. package/src/components/patterns/Dialog.tsx +95 -0
  199. package/src/components/patterns/Fields.tsx +44 -0
  200. package/src/components/patterns/List.tsx +25 -0
  201. package/src/components/patterns/StateSurface.tsx +40 -0
  202. package/src/components/patterns/Surfaces.tsx +115 -0
  203. package/src/components/patterns/Tabs.tsx +80 -0
  204. package/src/components/patterns/Toolbar.tsx +51 -0
  205. package/src/components/patterns/Tree.tsx +72 -0
  206. package/src/components/primitives/Button.tsx +46 -0
  207. package/src/components/primitives/ColorInput.tsx +11 -47
  208. package/src/components/primitives/EditorIcon.tsx +99 -0
  209. package/src/components/primitives/FormControls.tsx +71 -0
  210. package/src/components/primitives/JsonInput.tsx +15 -2
  211. package/src/components/primitives/Layout.tsx +100 -0
  212. package/src/components/primitives/Menu.tsx +105 -0
  213. package/src/components/primitives/NumberInput.tsx +8 -35
  214. package/src/components/primitives/Panel.tsx +49 -44
  215. package/src/components/primitives/SectionHeader.tsx +10 -28
  216. package/src/components/primitives/Text.tsx +46 -0
  217. package/src/components/primitives/Tooltip.tsx +20 -12
  218. package/src/components/primitives/Vec3Input.tsx +3 -0
  219. package/src/components/primitives/banner-tones.ts +33 -0
  220. package/src/components/primitives/editor-icons.ts +102 -0
  221. package/src/components/primitives/panel-header-styles.ts +30 -0
  222. package/src/components/project-operation-documents.tsx +226 -0
  223. package/src/components/status-contributions.tsx +175 -0
  224. package/src/components/story-documents-register.ts +15 -0
  225. package/src/components/story-documents.tsx +1185 -0
  226. package/src/components/tool-documents.tsx +110 -0
  227. package/src/components/workspace-dock.css +293 -0
  228. package/src/components/workspace-history.ts +33 -0
  229. package/src/components/world-documents.tsx +145 -0
  230. package/src/components/xstate-documents.tsx +209 -0
  231. package/src/composite-screenshot.ts +248 -0
  232. package/src/design-system/index.ts +70 -0
  233. package/src/design-system-stories/Foundation.stories.tsx +183 -0
  234. package/src/design-system-stories/Patterns.stories.tsx +251 -0
  235. package/src/design-system-stories/Workspace.stories.tsx +538 -0
  236. package/src/doctor/report.ts +57 -13
  237. package/src/editor-api.ts +295 -31
  238. package/src/editor-compatibility.ts +200 -0
  239. package/src/editor-console.ts +35 -17
  240. package/src/editor-hotkeys.ts +85 -33
  241. package/src/editor-store.ts +538 -233
  242. package/src/editor-viewport.ts +160 -34
  243. package/src/entity-factory.ts +14 -3
  244. package/src/gizmo-registry.ts +21 -5
  245. package/src/harness-chat-editor-context.ts +37 -0
  246. package/src/harness-chat-indicator.ts +68 -0
  247. package/src/harness-chat-layout.ts +53 -0
  248. package/src/harness-chat-lifecycle.ts +170 -0
  249. package/src/harness-chat-reconnect.ts +85 -0
  250. package/src/harness-chat-types.ts +409 -0
  251. package/src/hierarchy-drop.ts +50 -0
  252. package/src/hierarchy-expansion-state.ts +100 -0
  253. package/src/hierarchy-menu-registry.ts +1 -1
  254. package/src/hierarchy-projection.ts +76 -0
  255. package/src/history/editor-session.ts +21 -0
  256. package/src/history/history-commands.ts +147 -0
  257. package/src/history/history-service.ts +904 -0
  258. package/src/history/json-history-resource.ts +165 -0
  259. package/src/history/persistence-coordinator.ts +35 -0
  260. package/src/history/project-file-history.ts +266 -0
  261. package/src/history/project-root-history-backends.ts +53 -0
  262. package/src/history/resource-registry.ts +209 -0
  263. package/src/history/snapshot-store.ts +108 -0
  264. package/src/history/source-history-backend.ts +374 -0
  265. package/src/history/types.ts +100 -0
  266. package/src/hmr-registration-group.ts +67 -0
  267. package/src/hmr-stable-react-context.ts +23 -0
  268. package/src/hosted-example.ts +12 -2
  269. package/src/hotkeys.ts +89 -18
  270. package/src/ingest/discovery-react.ts +9 -10
  271. package/src/ingest/discovery.ts +4 -4
  272. package/src/ingest/discovery2d.ts +5 -5
  273. package/src/ingest/games/bloom-composer/vgai.game.json +3 -3
  274. package/src/ingest/games/embed-bundle/vgai.game.json +3 -3
  275. package/src/ingest/games/games-fps/vgai.game.json +3 -3
  276. package/src/ingest/games/iframe-reachable/vgai.game.json +3 -3
  277. package/src/ingest/games/interactive-cubes/vgai.game.json +3 -3
  278. package/src/ingest/games/mismatched-three/vgai.game.json +3 -3
  279. package/src/ingest/games/own-three-bundled/vgai.game.json +3 -3
  280. package/src/ingest/games/pointerlock-maze/vgai.game.json +7 -4
  281. package/src/ingest/games-2d/bubbo-bubbo/vgai.game.json +3 -3
  282. package/src/ingest/games-2d/bunnymark/vgai.game.json +3 -3
  283. package/src/ingest/games-2d/flappy/vgai.game.json +3 -3
  284. package/src/ingest/games-2d/flappy-pixi/vgai.game.json +3 -3
  285. package/src/ingest/games-2d/puzzling-potions/vgai.game.json +3 -3
  286. package/src/ingest/games-2d/tilemap-camera/vgai.game.json +3 -3
  287. package/src/ingest/games-react/react-rpg/vgai.game.json +3 -3
  288. package/src/ingest/types.ts +1 -1
  289. package/src/ingest-mode.ts +47 -52
  290. package/src/ingest-siblings.ts +23 -33
  291. package/src/initial-scene.ts +1 -2
  292. package/src/main.tsx +16 -8
  293. package/src/manifest-project.ts +10 -12
  294. package/src/model-thumbnail.ts +261 -26
  295. package/src/module-mode.ts +44 -50
  296. package/src/play-log-events.ts +26 -0
  297. package/src/play-mode.ts +495 -401
  298. package/src/play-scene-adoption.ts +23 -0
  299. package/src/playground/main.ts +68 -24
  300. package/src/playwright-shim.ts +473 -0
  301. package/src/project-manager.ts +90 -10
  302. package/src/project-operations.ts +112 -0
  303. package/src/project-story-discovery.ts +25 -0
  304. package/src/project-tool-discovery.ts +43 -0
  305. package/src/scene-serializer.ts +0 -6
  306. package/src/scene-sync.ts +7 -2
  307. package/src/script-loader.ts +3 -3
  308. package/src/skeleton-helper.ts +57 -0
  309. package/src/storage/seed.ts +68 -8
  310. package/src/stories/StoryPreviewMount.tsx +265 -0
  311. package/src/stories/action-stories.fixture.tsx +44 -0
  312. package/src/stories/button-stories.fixture.tsx +50 -0
  313. package/src/stories/compose-project-stories.ts +182 -0
  314. package/src/stories/loader-stories.fixture.tsx +53 -0
  315. package/src/stories/story-discovery.ts +130 -0
  316. package/src/stories/story-registry.ts +146 -0
  317. package/src/theme-css.ts +1049 -0
  318. package/src/theme-library.ts +238 -0
  319. package/src/theme-preference.ts +130 -0
  320. package/src/theme.ts +527 -0
  321. package/src/tool-loader.ts +80 -24
  322. package/src/ui-source/inspect.ts +27 -4
  323. package/src/ui-source/source-write-backend.ts +83 -22
  324. package/src/widgets/index.ts +9 -18
  325. package/src/workspace-aux-commands.ts +11 -0
  326. package/src/workspace-dock-controller.ts +64 -0
  327. package/src/workspace-document-ids.ts +5 -0
  328. package/src/workspace-document-registry.ts +367 -0
  329. package/src/workspace-state-persistence.ts +455 -0
  330. package/src/workspace-status-registry.ts +110 -0
  331. package/src/workspace-utility-commands.ts +49 -0
  332. package/src/workspace-utility-registry.ts +161 -0
  333. package/src/world-document-routing.ts +16 -0
  334. package/src/xstate-inspect/XStateMachineInspector.tsx +544 -0
  335. package/src/xstate-inspect/character-animation-machine.fixture.ts +74 -0
  336. package/src/xstate-inspect/use-live-actor-state.ts +39 -0
  337. package/src/xstate-inspect/xstate-graph.ts +265 -0
  338. package/src/xstate-inspect/xstate-layout.ts +76 -0
  339. package/src/z-index.ts +26 -0
  340. package/template/.claude/skills/editor/SKILL.md +129 -90
  341. package/template/AGENTS.md +1110 -0
  342. package/template/CLAUDE.md +1 -512
  343. package/template/IDIOMS.md +50 -0
  344. package/template/check-idioms.ts +706 -0
  345. package/template/manifest-entry-modules-plugin.ts +53 -0
  346. package/template/package.json +13 -4
  347. package/template/public/scenes/default.scn2d.json +6 -0
  348. package/template/public/scenes/default.vscn.json +7 -1
  349. package/template/public/scenes/untitled.vscn.json +10 -0
  350. package/template/scripts/playtest.ts +40 -0
  351. package/template/server/loopback.ts +75 -0
  352. package/template/server/rooms/arena-room.ts +69 -1
  353. package/template/server/rooms/game-room.ts +68 -1
  354. package/template/src/data/README.md +9 -4
  355. package/template/src/data/data-ref.ts +35 -0
  356. package/template/src/data/tuning.schema.ts +1 -1
  357. package/template/src/main.ts +41 -62
  358. package/template/src/manifest-entry-modules.d.ts +3 -0
  359. package/template/src/operations/README.md +88 -0
  360. package/template/src/runtime/pixi-adapter.ts +24 -0
  361. package/template/src/scripts/components/data-spinner.ts +43 -2
  362. package/template/src/scripts/components/spin-lap-math.ts +27 -0
  363. package/template/src/tools/README.md +5 -3
  364. package/template/src/tools/example.tool.tsx +13 -7
  365. package/template/src/ui/Button.stories.tsx +66 -0
  366. package/template/src/ui/RebindPanel.tsx +2 -6
  367. package/template/src/ui/game.tsx +17 -0
  368. package/template/tests/acceptance/example.spec.ts +64 -0
  369. package/template/tests/logic/example.test.ts +31 -0
  370. package/template/tests/logic/room.test.ts +100 -0
  371. package/template/tests/tsconfig.json +30 -0
  372. package/template/validate-manifest.ts +5 -5
  373. package/template/validate-scenes.ts +50 -18
  374. package/template/vgai.game.json +20 -13
  375. package/template/vite.config.ts +77 -16
  376. package/vite-plugin-ui-oid.ts +261 -17
  377. package/dist/assets/CCDIKSolver-Dz-ysxZF.js +0 -1
  378. package/dist/assets/SelectionBox-BXsv_6aH.js +0 -1
  379. package/dist/assets/browser-project-scripts-DOru4L1x.js +0 -2
  380. package/dist/assets/browserAll-CEkWYlFk.js +0 -1
  381. package/dist/assets/create-runtime-DYIWr3va.js +0 -1
  382. package/dist/assets/data-asset-Bb9sIM7i.js +0 -5
  383. package/dist/assets/game-8SDZPPgH.js +0 -1
  384. package/dist/assets/game-CevorxyV.js +0 -1
  385. package/dist/assets/game-Di7XlywD.js +0 -1
  386. package/dist/assets/game-DjnCaw8R.js +0 -1
  387. package/dist/assets/game-Q9A0aXSV.js +0 -1
  388. package/dist/assets/index-CPVV6pjw.js +0 -1
  389. package/dist/assets/index-CpOnYyeD.js +0 -213
  390. package/dist/assets/index-Dr8H_6Rl.js +0 -1
  391. package/dist/assets/index-_bCaipUk.js +0 -13650
  392. package/dist/assets/ingest-siblings-Dz8eEqrV.js +0 -1
  393. package/dist/assets/mount-manifest-Bhk0ohsl.js +0 -1
  394. package/dist/assets/scene-query-BivAHhJu.js +0 -1
  395. package/dist/assets/webworkerAll-BLrH0F6F.js +0 -1
  396. package/dist/assets/xstate-animation-binding-1NGLmw6y.js +0 -1
  397. package/dist/assets/xstate.esm-BgUD33nl.js +0 -3
  398. package/src/authoring/scene-ui-layer.ts +0 -485
  399. package/src/authoring/ui-authoring-adapter.ts +0 -325
  400. package/src/authoring/ui-hierarchy-menu.ts +0 -40
  401. package/src/authoring/ui-inspector-sections.tsx +0 -156
  402. package/src/authoring/undo-timeline.ts +0 -145
  403. package/src/components/BottomPanel.tsx +0 -326
  404. package/src/components/BuildPanel.tsx +0 -455
  405. package/src/components/FolderTree.tsx +0 -179
  406. package/src/components/RightPanel.tsx +0 -166
  407. package/src/components/WorldContextMenu.tsx +0 -257
  408. package/src/components/asset-viewers/AssetViewer.tsx +0 -38
  409. package/src/ingest/games-react/react-rpg/src/ui/game-state.tsx +0 -129
  410. package/src/scene-ui-mode/active-scene-ui.ts +0 -58
  411. package/src/scene-ui-mode/scene-ui-palette-panel.tsx +0 -152
  412. package/src/scene-ui-mode/scene-ui-timeline-tab.tsx +0 -29
  413. package/src/scene-ui-mode/ui-prefab-dialog-host.tsx +0 -74
  414. package/src/scene-ui-mode/ui-prefab-hierarchy-menu.ts +0 -49
  415. package/src/scene-ui-mode/ui-prefab-io.ts +0 -76
  416. package/src/ui-editor/inspector.tsx +0 -563
  417. package/src/ui-editor/node-ops.ts +0 -266
  418. package/src/ui-editor/overlay.tsx +0 -380
  419. package/src/ui-editor/palette.tsx +0 -114
  420. package/src/ui-editor/react-store.ts +0 -78
  421. package/src/ui-editor/timeline-panel.tsx +0 -443
  422. package/src/ui-editor/ui-edit-store.ts +0 -552
  423. package/src/ui-editor/ui-prefab.ts +0 -95
  424. package/template/project.json +0 -9
  425. package/template/src/scripts/main.ts +0 -94
  426. package/template/src/ui/DefaultHud.tsx +0 -40
  427. package/template/src/ui/game-state.tsx +0 -37
  428. package/template/src/ui/mount-default-hud.tsx +0 -19
  429. package/template/src/ui/mount-ui.ts +0 -15
  430. package/vite-plugin-react-world-provider.ts +0 -81
@@ -1,64 +1,22 @@
1
- // T3.3 slice 1 — server-side compat-view synthesis for `project.json` reads
2
- // (docs/CLI-ON-FOLDER-DESIGN.md §1C).
3
- //
4
- // A project folder's config view can come from two places: `project.json`
5
- // itself (legacy, still authoritative when present — including fields like
6
- // `appId` that have no manifest home) or, when that file is ABSENT, a
7
- // synthesized `{ name, defaultScene }` view derived from `vgai.game.json`
8
- // (`name` from the manifest; `defaultScene` from the first world's `scene`,
9
- // explicitly `null` if that world has none — e.g. an `entry`-based or ingest
10
- // world — NEVER omitted: a consumer that saw the key simply missing collapsed
11
- // "not declared" into "guess a path" via `?? 'scenes/default.vscn.json'`,
12
- // which is what caused `initial-scene.ts` to silently WRITE a placeholder
13
- // scene for a legal entry-only first world — §7.1-12 / R2b fix 1. `null` is
14
- // the explicit, typed "no scene declared" the consumer is forced to branch
15
- // on instead of defaulting through.
16
- //
17
- // This is the ONE place the project.json/manifest fallback rule lives —
18
- // every server route that reads project config goes through `readProjectView`
19
- // rather than re-implementing the fallback (editor-server.ts's static
20
- // `/project.json` serve, `GET /__editor/project`, `POST /__editor/open-project`'s
21
- // existence check, and the recent-projects existence check all call this).
1
+ /** Server-side editor view of the single v2 project configuration. */
22
2
 
23
- import { readFile } from 'node:fs/promises';
24
3
  import { join } from 'node:path';
25
4
  import { loadGameManifestFile } from '../../engine/src/manifest/load-file';
26
5
 
27
6
  export type ProjectView = Record<string, unknown>;
28
7
 
29
8
  /**
30
- * Read the compat project view for `root`.
31
- *
32
- * - `project.json` present -> its parsed contents verbatim (whatever fields
33
- * it has, including `appId`).
34
- * - `project.json` absent, `vgai.game.json` present -> synthesized
35
- * `{ name, defaultScene }`, where `defaultScene` is the first world's
36
- * `scene` if declared, else explicit `null` (never omitted — appId is
37
- * omitted, though: it has no manifest home and nothing reads it per
38
- * docs/CLI-ON-FOLDER-DESIGN.md §1C).
39
- * - Neither present, or the manifest exists but fails to parse -> `null`.
40
- * (The hard fail-loud-on-a-broken-manifest behavior lives at the CLI
41
- * discovery gate, `packages/vgai-cli/src/discovery.ts` — a server route
42
- * reading a broken manifest degrades to "no project" rather than crashing
43
- * the request.)
9
+ * Read `vgai.game.json` and derive the editor's focused scene. There is no
10
+ * fallback config file: a missing or invalid manifest is not a project.
44
11
  */
45
12
  export async function readProjectView(root: string): Promise<ProjectView | null> {
46
- try {
47
- const raw = await readFile(join(root, 'project.json'), 'utf-8');
48
- return JSON.parse(raw) as ProjectView;
49
- } catch {
50
- // project.json absent/unreadable — fall through to the manifest.
51
- }
52
-
53
13
  try {
54
14
  const manifest = loadGameManifestFile(join(root, 'vgai.game.json'));
55
- const firstWorld = manifest.worlds[0];
56
- // Always set the key — explicit `null`, not an omitted property, when the
57
- // first world declares no scene (e.g. `entry`-only). See the module doc
58
- // comment above: an omitted key is what let a naive `?? 'scenes/
59
- // default.vscn.json'` consumer silently guess a path.
60
- const view: ProjectView = { name: manifest.name, defaultScene: firstWorld?.scene ?? null };
61
- return view;
15
+ const firstSceneRoot = manifest.roots.find((candidate) => candidate.scene !== undefined);
16
+ return {
17
+ ...manifest,
18
+ defaultScene: firstSceneRoot?.scene ?? null,
19
+ };
62
20
  } catch {
63
21
  return null;
64
22
  }
@@ -203,9 +203,8 @@ export function isAllowedEditorOrigin(
203
203
  * editor server — otherwise the exact version-skew class Phase B exists to
204
204
  * kill (an editor silently serving a different engine version than the one
205
205
  * the project declares) reappears one layer down, inside script-serving.
206
- * `packageName`'s `exports` map must publish a `./package.json` entry (both
207
- * `@vgai/engine` and `@vgai/scene-ui` do, as of B1a) for `require.resolve` to
208
- * find it.
206
+ * `packageName`'s `exports` map must publish a `./package.json` entry for
207
+ * `require.resolve` to find it.
209
208
  *
210
209
  * Returns `null` (never throws) when `packageName` isn't resolvable from
211
210
  * `fromDir` — no project open, a pre-Phase-B project with no such
@@ -337,25 +336,85 @@ export function validateManifestWrite(
337
336
  * Which editor list a `src/**` add/unlink invalidates, or `null` if it's
338
337
  * irrelevant. Feeds the editor-server's second `src/`-scoped chokidar
339
338
  * watcher (`startWatcher()` in editor-server.ts) so a NEW
340
- * `src/tools/*.tool.tsx` or `src/data/*.data.json`/`*.schema.json` shows up
339
+ * `src/tools/*.tool.tsx`, project operations, or data/schema files show up
341
340
  * in the dock/DATA tab without a full editor reload (spec §7 W4 field note
342
341
  * c). `.schema.json` is included on the `data` side: its add/unlink flips the
343
342
  * DATA tab between the no-emitted-schema teaching message and real widgets.
343
+ * `stories` (C3, spec §9) is the same physics for a new/removed
344
+ * `*.stories.tsx`/`*.stories.ts` anywhere under `src/` — the Stories tab.
344
345
  *
345
346
  * `relPath` is project-root-relative with forward slashes (same convention
346
347
  * `/__editor/data-files` and `/__editor/tool-files` already use).
347
348
  */
348
- export function classifyProjectSrcPath(relPath: string): 'tools' | 'data' | null {
349
+ export function classifyProjectSrcPath(
350
+ relPath: string,
351
+ ): 'tools' | 'data' | 'stories' | 'operations' | null {
349
352
  if (relPath.startsWith('src/tools/') && relPath.endsWith('.tool.tsx')) return 'tools';
353
+ if (
354
+ relPath.startsWith('src/operations/') &&
355
+ (relPath.endsWith('.operation.ts') || relPath.endsWith('.operation.js'))
356
+ ) {
357
+ return 'operations';
358
+ }
350
359
  if (
351
360
  relPath.startsWith('src/data/') &&
352
361
  (relPath.endsWith('.data.json') || relPath.endsWith('.schema.json'))
353
362
  ) {
354
363
  return 'data';
355
364
  }
365
+ // C3 (spec §9) — conventional CSF story files, colocated anywhere under
366
+ // `src/` (not confined to one subfolder like tools/data).
367
+ if (
368
+ relPath.startsWith('src/') &&
369
+ (relPath.endsWith('.stories.tsx') || relPath.endsWith('.stories.ts'))
370
+ ) {
371
+ return 'stories';
372
+ }
356
373
  return null;
357
374
  }
358
375
 
376
+ // ---------------------------------------------------------------------------
377
+ // Watcher polling resolution (#131)
378
+ // ---------------------------------------------------------------------------
379
+
380
+ /**
381
+ * Chokidar options fragment deciding whether an editor-server watcher polls.
382
+ *
383
+ * #131: on WSL drvfs mounts (`/mnt/<drive>/…`) inotify never fires, so every
384
+ * SSE broadcast the editor UI lives on (`scene-changed`, `asset-moved`,
385
+ * `tool/data/story-files-changed`, manifest validation) was structurally dead
386
+ * there — the owner watched an agent author a scene and the open editor never
387
+ * repainted until a manual browser refresh. dev.ts already auto-polls VITE's
388
+ * watcher on drvfs (`startProjectPollWatcher`) but deliberately never feeds
389
+ * these watchers (see the decoupling note at the srcWatcher construction), so
390
+ * they need their own decision. Chokidar's scoped `usePolling` is safe here
391
+ * where Vite-wide polling was not: these watchers cover only a game project's
392
+ * `public/`+`src/` trees and one manifest file, not the whole engine tree
393
+ * that made drvfs stat-flood starve the event loop (dev.ts field note
394
+ * 2026-07-10).
395
+ *
396
+ * Same env contract as dev.ts's poller: `VGAI_WATCH_POLL=0` forces off
397
+ * anywhere, `=1` forces on (default 1000ms interval), `=<ms>` forces on with
398
+ * that interval. Unset: auto-enable iff `root` sits on a drvfs mount
399
+ * (linux + `/mnt/<drive>/`). Pass `root: null` to opt out of auto-detection
400
+ * (engine-repo-rooted watchers, where `public/` includes the vendored-game
401
+ * trees and polling would be needlessly broad).
402
+ */
403
+ export function resolveWatcherPollOptions(
404
+ root: string | null,
405
+ env: Record<string, string | undefined> = process.env,
406
+ platform: NodeJS.Platform = process.platform,
407
+ ): { usePolling: true; interval: number } | Record<string, never> {
408
+ const raw = env['VGAI_WATCH_POLL'];
409
+ if (raw !== undefined && raw !== '') {
410
+ if (raw === '0') return {};
411
+ const ms = Number(raw);
412
+ return { usePolling: true, interval: Number.isFinite(ms) && ms > 1 ? ms : 1000 };
413
+ }
414
+ const onDrvfs = root !== null && platform === 'linux' && /^\/mnt\/[a-z]\//i.test(root);
415
+ return onDrvfs ? { usePolling: true, interval: 1000 } : {};
416
+ }
417
+
359
418
  // ---------------------------------------------------------------------------
360
419
  // Command-relay response shaping (SC1)
361
420
  // ---------------------------------------------------------------------------
@@ -364,15 +423,21 @@ export interface CommandResult {
364
423
  ok?: boolean;
365
424
  timedOut?: boolean;
366
425
  error?: string;
367
- /** Optional payload for commands that answer with data (e.g. `capture-viewport`'s base64 PNG). */
426
+ /** Optional payload for commands that answer with data (e.g.
427
+ * `capture-viewport`'s base64 PNG, the Wave 5 debug-seam reads). On the
428
+ * failure path this carries structured markers (e.g. `{ code:
429
+ * 'UNKNOWN_COMMAND_TYPE' }`, registered-name lists) the SDK matches on —
430
+ * never message prose. Keep in sync with `command-listener.ts`'s
431
+ * `CommandResult`. */
368
432
  data?: Record<string, unknown>;
369
433
  }
370
434
 
371
435
  /** Map a relayed-command result to an HTTP status + body. A timeout (no editor
372
436
  * connected) is a distinct 504 error rather than a fake success. (SC1)
373
- * `data`, when present on a success, is spread into the response body
374
- * alongside `ok: true` so callers (`HttpEditorTransport.sendCommand`) see it
375
- * at the top level rather than needing a second field of indirection. */
437
+ * `data` is spread into the response body at the top level — alongside
438
+ * `ok: true` on success (so `HttpEditorTransport.sendCommand` sees it
439
+ * without a second field of indirection) and alongside `ok: false`/`error`
440
+ * on the 400 path (Wave 5: the structured error-marker channel). */
376
441
  export function commandResponseFor(result: CommandResult): {
377
442
  status: number;
378
443
  body: Record<string, unknown>;
@@ -384,7 +449,7 @@ export function commandResponseFor(result: CommandResult): {
384
449
  body: { ok: false, error: result.error ?? 'Command timed out — no editor connected.' },
385
450
  };
386
451
  }
387
- return { status: 400, body: { ok: false, error: result.error } };
452
+ return { status: 400, body: { ok: false, error: result.error, ...(result.data ?? {}) } };
388
453
  }
389
454
 
390
455
  // ---------------------------------------------------------------------------
@@ -23,6 +23,18 @@ export interface EditorSession {
23
23
  pid: number;
24
24
  /** ISO timestamp of server start. */
25
25
  startedAt: string;
26
+ /**
27
+ * Additive (ACCEPTANCE-DRIVER-BUILD-PLAN.md Task 3.4): absent/undefined for
28
+ * every pre-existing editor session (an ordinary `vgai edit` dev server).
29
+ * `'probe'` marks a standalone game-page server booted by `vgai probe` —
30
+ * registered so it shows up in `vgai sessions`/dies via `vgai close`, and so
31
+ * a later `vgai probe` run can warm-reuse it instead of re-booting. Both
32
+ * this writer's `isSession` and the CLI reader's own copy
33
+ * (`packages/vgai-cli/src/editor-sessions.ts`) validate only the fields
34
+ * above and tolerate any extra key, so this addition is backward compatible
35
+ * with entries written by an older build.
36
+ */
37
+ kind?: string;
26
38
  }
27
39
 
28
40
  const REGISTRY_DIR = join(homedir(), '.vgai');
@@ -1,8 +1,26 @@
1
- import { createContext, type ReactNode, Suspense, useContext, useEffect, useRef } from 'react';
1
+ import {
2
+ type ReactNode,
3
+ Suspense,
4
+ useContext,
5
+ useEffect,
6
+ useRef,
7
+ useSyncExternalStore,
8
+ } from 'react';
2
9
  import { connectCommandListener } from './command-listener';
3
10
  import { EditorStore } from './editor-store';
11
+ import { setHarnessChatEditorStore } from './harness-chat-editor-context';
12
+ import { EditorSession } from './history/editor-session';
13
+ import type { HistoryCommandSnapshot, HistoryCommands } from './history/history-commands';
14
+ import type { HistoryService, HistorySnapshot } from './history/history-service';
15
+ import { getProjectFileHistory } from './history/project-file-history';
16
+ import { getDataHistoryBackend } from './history/project-root-history-backends';
17
+ import { createHmrStableReactContext } from './hmr-stable-react-context';
4
18
  import { initProject } from './initial-scene';
5
19
  import { type InteractiveEditScope, InteractiveEditScopeContext } from './interactive-edit-scope';
20
+ import { getCurrentProject } from './project-manager';
21
+ import { startProjectOperationDiscovery } from './project-operations';
22
+ import { startProjectStoryDiscovery } from './project-story-discovery';
23
+ import { startProjectToolDiscovery } from './project-tool-discovery';
6
24
 
7
25
  export interface EditorStats {
8
26
  fps: number;
@@ -17,14 +35,26 @@ interface EditorContextValue {
17
35
  store: EditorStore;
18
36
  stats: EditorStats;
19
37
  initPromise: Promise<void>;
38
+ session: EditorSession;
20
39
  }
21
40
 
22
- const EditorContext = createContext<EditorContextValue | null>(null);
41
+ const EditorContext = createHmrStableReactContext<EditorContextValue | null>(
42
+ import.meta.hot?.data,
43
+ 'EditorContext',
44
+ null,
45
+ );
23
46
 
24
47
  export function EditorProvider({ children }: { children: ReactNode }) {
25
48
  const storeRef = useRef<EditorStore | null>(null);
26
49
  if (!storeRef.current) storeRef.current = new EditorStore();
27
50
 
51
+ const sessionRef = useRef<EditorSession | null>(null);
52
+ if (!sessionRef.current) {
53
+ const project = getCurrentProject();
54
+ sessionRef.current = new EditorSession(project?.rootPath ?? 'unknown-project');
55
+ }
56
+ storeRef.current.attachHistory(sessionRef.current.history);
57
+
28
58
  const statsRef = useRef<EditorStats | null>(null);
29
59
  if (!statsRef.current) {
30
60
  statsRef.current = {
@@ -57,9 +87,56 @@ export function EditorProvider({ children }: { children: ReactNode }) {
57
87
  return connectCommandListener(storeRef.current!);
58
88
  }, []);
59
89
 
90
+ // W0 (docs/EDITOR-WORKSPACE-SHELL-TODO.md §7.2/§9): project-tool discovery
91
+ // is EDITOR-INIT lifecycle, not a bottom-dock side effect — it runs (and
92
+ // keeps re-running on project change / tool-file add/unlink) whether or
93
+ // not the Dockview workspace is mounted. WorkspaceDock only consumes the
94
+ // discovered registrations.
95
+ useEffect(() => startProjectToolDiscovery(), []);
96
+
97
+ useEffect(() => startProjectOperationDiscovery(), []);
98
+
99
+ // CSF stories may exist without a currently mounted React root. Discover
100
+ // them at editor init so hierarchy/Inspector story affordances and restored
101
+ // story documents are complete before any story document is opened.
102
+ useEffect(() => startProjectStoryDiscovery(), []);
103
+
104
+ useEffect(() => {
105
+ setHarnessChatEditorStore(storeRef.current);
106
+ return () => setHarnessChatEditorStore(null);
107
+ }, []);
108
+
109
+ useEffect(() => () => sessionRef.current?.dispose(), []);
110
+
111
+ useEffect(() => {
112
+ const target = globalThis as typeof globalThis & {
113
+ __vgaiHistoryWriteData?: (path: string, content: string) => Promise<void>;
114
+ };
115
+ const writer = async (path: string, content: string): Promise<void> => {
116
+ await getProjectFileHistory(
117
+ sessionRef.current!.history,
118
+ getDataHistoryBackend(),
119
+ 'project-data',
120
+ ).write(path, content, {
121
+ label: `Edit ${path.split('/').pop() ?? 'Data'}`,
122
+ kind: 'data',
123
+ contentType: 'application/json',
124
+ });
125
+ };
126
+ target.__vgaiHistoryWriteData = writer;
127
+ return () => {
128
+ if (target.__vgaiHistoryWriteData === writer) delete target.__vgaiHistoryWriteData;
129
+ };
130
+ }, []);
131
+
60
132
  return (
61
133
  <EditorContext.Provider
62
- value={{ store: storeRef.current, stats: statsRef.current, initPromise: initRef.current }}
134
+ value={{
135
+ store: storeRef.current,
136
+ stats: statsRef.current,
137
+ initPromise: initRef.current,
138
+ session: sessionRef.current,
139
+ }}
63
140
  >
64
141
  <InteractiveEditScopeContext.Provider value={editScopeRef.current}>
65
142
  <Suspense>{children}</Suspense>
@@ -85,3 +162,30 @@ export function useEditorInit(): Promise<void> {
85
162
  if (!ctx) throw new Error('useEditorInit must be used within <EditorProvider>');
86
163
  return ctx.initPromise;
87
164
  }
165
+
166
+ export function useHistoryService(): HistoryService {
167
+ const ctx = useContext(EditorContext);
168
+ if (!ctx) throw new Error('useHistoryService must be used within <EditorProvider>');
169
+ return ctx.session.history;
170
+ }
171
+
172
+ /** History-aware panels may still be rendered in isolated component tests. */
173
+ export function useOptionalHistoryService(): HistoryService | null {
174
+ return useContext(EditorContext)?.session.history ?? null;
175
+ }
176
+
177
+ export function useHistoryCommands(): HistoryCommands {
178
+ const ctx = useContext(EditorContext);
179
+ if (!ctx) throw new Error('useHistoryCommands must be used within <EditorProvider>');
180
+ return ctx.session.historyCommands;
181
+ }
182
+
183
+ export function useHistoryCommandSnapshot(): HistoryCommandSnapshot {
184
+ const history = useHistoryCommands();
185
+ return useSyncExternalStore(history.subscribe, history.getSnapshot, history.getSnapshot);
186
+ }
187
+
188
+ export function useHistorySnapshot(): HistorySnapshot {
189
+ const history = useHistoryService();
190
+ return useSyncExternalStore(history.subscribe, history.getSnapshot, history.getSnapshot);
191
+ }
@@ -1,12 +1,18 @@
1
- import { timelineRedo, timelineUndo } from './authoring/undo-timeline';
1
+ import { PROJECT_ASSET_COMMANDS } from './asset-workflow/project-asset-commands';
2
+ import { openBuildProfilesDocument } from './components/build-documents';
3
+ import { openDebuggerPanel } from './components/debugger-panel-state';
4
+ import { getEditorMode } from './editor-mode';
2
5
  import type { EditorStore } from './editor-store';
6
+ import type { HistoryCommandSnapshot, HistoryCommands } from './history/history-commands';
7
+ import { openUndoHistory } from './workspace-aux-commands';
8
+ import { showWorkspaceNavigator, toggleWorkspaceFocus } from './workspace-dock-controller';
3
9
 
4
10
  export interface EditorAction {
5
11
  id: string;
6
12
  label: string;
7
13
  category: 'action' | 'entity' | 'asset';
8
14
  shortcut?: string;
9
- execute: () => void;
15
+ execute: () => void | Promise<void>;
10
16
  }
11
17
 
12
18
  const RECENT_KEY = 'editor:recent-actions';
@@ -28,28 +34,34 @@ export function pushRecentAction(id: string): void {
28
34
  }
29
35
 
30
36
  /** Build the static list of editor command actions. */
31
- export function buildStaticActions(store: EditorStore): EditorAction[] {
37
+ export function buildStaticActions(
38
+ store: EditorStore,
39
+ history: HistoryCommands,
40
+ historySnapshot?: HistoryCommandSnapshot,
41
+ ): EditorAction[] {
32
42
  const isMac = navigator.platform.includes('Mac');
33
43
  const mod = isMac ? '\u2318' : 'Ctrl+';
34
44
 
35
45
  return [
36
46
  {
37
47
  id: 'editor.undo',
38
- label: 'Undo',
48
+ label: historySnapshot?.undoLabel ? `Undo ${historySnapshot.undoLabel}` : 'Undo',
39
49
  category: 'action',
40
50
  shortcut: `${mod}Z`,
41
- // T3.2 slice 2: through the editor-global timeline, NOT `store.undo()`
42
- // directly \u2014 same reasoning as the Ctrl+Z hotkey (docs/
43
- // PERSISTENCE-PROVIDER-DESIGN.md \u00A73): whichever adapter (first-party/
44
- // ingest/UI) recorded the most recent op, not always the first-party store.
45
- execute: () => timelineUndo(),
51
+ // H2: shell actions use the project-scoped command service. Its temporary
52
+ // compatibility bridge preserves chronology with producers not yet migrated.
53
+ execute: async () => {
54
+ await history.undo();
55
+ },
46
56
  },
47
57
  {
48
58
  id: 'editor.redo',
49
- label: 'Redo',
59
+ label: historySnapshot?.redoLabel ? `Redo ${historySnapshot.redoLabel}` : 'Redo',
50
60
  category: 'action',
51
61
  shortcut: `${mod}\u21E7Z`,
52
- execute: () => timelineRedo(),
62
+ execute: async () => {
63
+ await history.redo();
64
+ },
53
65
  },
54
66
  {
55
67
  id: 'editor.copy',
@@ -236,21 +248,107 @@ export function buildStaticActions(store: EditorStore): EditorAction[] {
236
248
  },
237
249
  },
238
250
  {
239
- id: 'build.web',
240
- label: 'Build for Web (itch.io)',
251
+ id: 'view.focusMode',
252
+ label: 'Toggle Focus Mode',
241
253
  category: 'action',
254
+ shortcut: `${mod}⇧F`,
242
255
  execute: () => {
243
- window.dispatchEvent(new CustomEvent('editor:show-build-tab'));
256
+ toggleWorkspaceFocus();
244
257
  },
245
258
  },
246
259
  {
247
- id: 'build.steam',
248
- label: 'Build for Desktop (Steam)',
260
+ id: 'view.undoHistory',
261
+ label: 'Undo History',
249
262
  category: 'action',
250
263
  execute: () => {
251
- window.dispatchEvent(new CustomEvent('editor:show-build-tab'));
264
+ // Undo History is an on-demand panel, not a permanent tab. Dockview
265
+ // defaults it beside Inspector but preserves a user's later move.
266
+ // §8 naming: 'Undo History', not 'History'.
267
+ openUndoHistory();
252
268
  },
253
269
  },
270
+ {
271
+ id: 'view.profiler',
272
+ label: 'Open Profiler',
273
+ category: 'action',
274
+ execute: () => openDebuggerPanel('profiler'),
275
+ },
276
+ {
277
+ id: 'view.state-watch',
278
+ label: 'Open State Watch',
279
+ category: 'action',
280
+ execute: () => openDebuggerPanel('state'),
281
+ },
282
+ {
283
+ id: 'view.network-debugger',
284
+ label: 'Open Network Diagnostics',
285
+ category: 'action',
286
+ execute: () => openDebuggerPanel('network'),
287
+ },
288
+ {
289
+ id: 'view.machine-debugger',
290
+ label: 'Open State Machines',
291
+ category: 'action',
292
+ execute: () => openDebuggerPanel('machines'),
293
+ },
294
+ {
295
+ id: 'view.debug-commands',
296
+ label: 'Open Debug Commands',
297
+ category: 'action',
298
+ execute: () => openDebuggerPanel('commands'),
299
+ },
300
+ ...Object.values(PROJECT_ASSET_COMMANDS)
301
+ .filter((command) => command.id !== PROJECT_ASSET_COMMANDS.open.id)
302
+ .map((command) => ({
303
+ id: command.id,
304
+ label: `${command.id
305
+ .replace('project-asset.', '')
306
+ .split('-')
307
+ .map((part) => part[0]?.toUpperCase() + part.slice(1))
308
+ .join(' ')} Project Asset`,
309
+ category: 'asset' as const,
310
+ ...(command.shortcut ? { shortcut: command.shortcut.replace('Mod', mod) } : {}),
311
+ execute: () => {
312
+ window.dispatchEvent(
313
+ new CustomEvent('editor:project-asset-command', { detail: { id: command.id } }),
314
+ );
315
+ },
316
+ })),
317
+ // W3 build split (build-documents.tsx): the build actions open the Build
318
+ // Profiles CENTER document (config + the Build trigger); the log streams
319
+ // into the Build Output utility. Server mode only — builds spawn npm
320
+ // scripts server-side (pre-W3 these dispatched an event no tab handled
321
+ // in browser mode).
322
+ ...(getEditorMode() === 'server'
323
+ ? [
324
+ {
325
+ // Assets and Library are permanent peer navigators; individual
326
+ // results open as center asset documents.
327
+ id: 'view.asset-library',
328
+ label: 'Asset Library',
329
+ category: 'action' as const,
330
+ execute: () => {
331
+ showWorkspaceNavigator('asset-library');
332
+ },
333
+ },
334
+ {
335
+ id: 'build.web',
336
+ label: 'Build for Web (itch.io)',
337
+ category: 'action' as const,
338
+ execute: () => {
339
+ openBuildProfilesDocument(store);
340
+ },
341
+ },
342
+ {
343
+ id: 'build.steam',
344
+ label: 'Build for Desktop (Steam)',
345
+ category: 'action' as const,
346
+ execute: () => {
347
+ openBuildProfilesDocument(store);
348
+ },
349
+ },
350
+ ]
351
+ : []),
254
352
  ];
255
353
  }
256
354