@volter/sdk 0.0.0-stage → 0.5.203

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (523) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +20 -0
  3. package/README.md +38 -3
  4. package/package.json +510 -4
  5. package/src/account.ts +210 -0
  6. package/src/chrome.ts +88 -0
  7. package/src/client.ts +1646 -0
  8. package/src/commands.ts +66 -0
  9. package/src/contributions.ts +619 -0
  10. package/src/css-numeric-style.ts +97 -0
  11. package/src/document-probe.ts +282 -0
  12. package/src/editor-view.ts +225 -0
  13. package/src/extension.ts +40 -0
  14. package/src/generations.ts +178 -0
  15. package/src/host.ts +1157 -0
  16. package/src/http-transport.browser.ts +14 -0
  17. package/src/http-transport.node.ts +19 -0
  18. package/src/index.ts +131 -0
  19. package/src/kit/CapabilityCoverageSection.tsx +185 -0
  20. package/src/kit/account-client.ts +333 -0
  21. package/src/kit/action-registry.ts +317 -0
  22. package/src/kit/active-product.ts +76 -0
  23. package/src/kit/active-project.ts +155 -0
  24. package/src/kit/adapter-editor-config.ts +25 -0
  25. package/src/kit/adapter-module.ts +7 -0
  26. package/src/kit/adapter-observation.ts +49 -0
  27. package/src/kit/animation/animation-clock.ts +479 -0
  28. package/src/kit/animation/stage-transport.ts +385 -0
  29. package/src/kit/api/assets.ts +365 -0
  30. package/src/kit/api/project-open.ts +355 -0
  31. package/src/kit/api/project-source.ts +180 -0
  32. package/src/kit/api/project-state.ts +110 -0
  33. package/src/kit/api/relay.ts +270 -0
  34. package/src/kit/api/themes.ts +45 -0
  35. package/src/kit/api-asset-library-wire.ts +45 -0
  36. package/src/kit/api-base.ts +10 -0
  37. package/src/kit/api-build.ts +99 -0
  38. package/src/kit/api-git-wire.ts +56 -0
  39. package/src/kit/api-logs.ts +92 -0
  40. package/src/kit/api-project-identity.ts +74 -0
  41. package/src/kit/api-settings.ts +36 -0
  42. package/src/kit/api-worktrees.ts +205 -0
  43. package/src/kit/asset-capabilities.ts +344 -0
  44. package/src/kit/asset-compare-core.ts +171 -0
  45. package/src/kit/asset-editor-context.tsx +101 -0
  46. package/src/kit/asset-events.ts +96 -0
  47. package/src/kit/asset-inspector-actions.ts +87 -0
  48. package/src/kit/asset-selection-viewer-registry.ts +113 -0
  49. package/src/kit/asset-selection.ts +146 -0
  50. package/src/kit/asset-thumbnails.ts +25 -0
  51. package/src/kit/asset-viewers.ts +115 -0
  52. package/src/kit/asset-workflow/asset-import-jobs.ts +106 -0
  53. package/src/kit/asset-workflow/asset-ledger-backend.ts +126 -0
  54. package/src/kit/asset-workflow/asset-ledger.ts +156 -0
  55. package/src/kit/asset-workflow/asset-materialization-report.ts +140 -0
  56. package/src/kit/asset-workflow/asset-pack-manifest.ts +320 -0
  57. package/src/kit/asset-workflow/asset-types.ts +142 -0
  58. package/src/kit/asset-workflow/audio-preview-player.ts +193 -0
  59. package/src/kit/asset-workflow/audio-waveform.ts +22 -0
  60. package/src/kit/asset-workflow/cloud-asset-client.ts +263 -0
  61. package/src/kit/asset-workflow/hosted-asset-materialization.ts +236 -0
  62. package/src/kit/asset-workflow/image-view-scale.ts +31 -0
  63. package/src/kit/asset-workflow/import-contract.ts +124 -0
  64. package/src/kit/asset-workflow/ledger-write-lock.ts +244 -0
  65. package/src/kit/asset-workflow/pixi-spritesheet.ts +197 -0
  66. package/src/kit/asset-workflow/preview-resource-lifetime.ts +44 -0
  67. package/src/kit/asset-workflow/project-asset-commands.ts +20 -0
  68. package/src/kit/asset-workflow/project-content.ts +288 -0
  69. package/src/kit/asset-workflow/project-source-index.ts +545 -0
  70. package/src/kit/asset-workflow/thumbnail-system.ts +256 -0
  71. package/src/kit/authoring/active-adapter.ts +200 -0
  72. package/src/kit/authoring/active-systems.ts +422 -0
  73. package/src/kit/authoring/adapter-key.ts +18 -0
  74. package/src/kit/authoring/authoring-asset-url.ts +27 -0
  75. package/src/kit/authoring/bootstrap-state.ts +49 -0
  76. package/src/kit/authoring/boundary-authoring-adapter.ts +189 -0
  77. package/src/kit/authoring/canvas-scene-guides.ts +84 -0
  78. package/src/kit/authoring/composite-authoring-adapter.ts +2109 -0
  79. package/src/kit/authoring/consumer-actions.ts +531 -0
  80. package/src/kit/authoring/design-time-layers.ts +852 -0
  81. package/src/kit/authoring/design-time-mount-registry.ts +244 -0
  82. package/src/kit/authoring/edit-mode-authoring.ts +637 -0
  83. package/src/kit/authoring/empty-project-authoring.ts +22 -0
  84. package/src/kit/authoring/instance-source-menu.ts +135 -0
  85. package/src/kit/authoring/layered-pick.ts +185 -0
  86. package/src/kit/authoring/mounted-root-subjects.ts +146 -0
  87. package/src/kit/authoring/no-authoring-adapter.ts +59 -0
  88. package/src/kit/authoring/object3d-document-persistence.ts +122 -0
  89. package/src/kit/authoring/panel-authoring.ts +121 -0
  90. package/src/kit/authoring/project-authoring-session.ts +105 -0
  91. package/src/kit/authoring/provenance.ts +99 -0
  92. package/src/kit/authoring/react-canvas-navigation.ts +259 -0
  93. package/src/kit/authoring/react-design-canvas-style.ts +20 -0
  94. package/src/kit/authoring/react-story-board.ts +917 -0
  95. package/src/kit/authoring/selection-scope.ts +195 -0
  96. package/src/kit/authoring/shell-document-ops.ts +169 -0
  97. package/src/kit/authoring/story-board-chrome-fit.ts +107 -0
  98. package/src/kit/authoring/story-board-presentation.ts +111 -0
  99. package/src/kit/authoring/three-root.ts +67 -0
  100. package/src/kit/authoring/viewport-tool-context.ts +73 -0
  101. package/src/kit/authoring/viewport-tool-owner.ts +38 -0
  102. package/src/kit/authoring/world-session-state.ts +101 -0
  103. package/src/kit/authoring-seam-evidence.ts +300 -0
  104. package/src/kit/availability-tick.ts +66 -0
  105. package/src/kit/bitmap-label.ts +120 -0
  106. package/src/kit/boot-routing.ts +392 -0
  107. package/src/kit/breakpoint-state.ts +43 -0
  108. package/src/kit/build-identity.ts +16 -0
  109. package/src/kit/bytes-codec.ts +62 -0
  110. package/src/kit/cancellation-reason.ts +58 -0
  111. package/src/kit/canvas-frames.ts +88 -0
  112. package/src/kit/capture-camera-pose.ts +77 -0
  113. package/src/kit/capture-size.ts +88 -0
  114. package/src/kit/chrome-registry.ts +159 -0
  115. package/src/kit/chrome-slot-registry.ts +91 -0
  116. package/src/kit/collaboration-client.ts +264 -0
  117. package/src/kit/collaboration-presence.ts +41 -0
  118. package/src/kit/command-dispatch.ts +19 -0
  119. package/src/kit/command-listener.ts +2182 -0
  120. package/src/kit/command-registry.ts +71 -0
  121. package/src/kit/component-board-registry.ts +205 -0
  122. package/src/kit/component-states-registry.ts +199 -0
  123. package/src/kit/components/AlignToolbar.tsx +204 -0
  124. package/src/kit/components/ApplicationMenus.tsx +372 -0
  125. package/src/kit/components/AssetEditorShell.tsx +216 -0
  126. package/src/kit/components/AssetInspectorToolSection.tsx +124 -0
  127. package/src/kit/components/BoardRulers.tsx +354 -0
  128. package/src/kit/components/CanvasAddNodeDialogs.tsx +529 -0
  129. package/src/kit/components/CanvasSceneViewport.tsx +1195 -0
  130. package/src/kit/components/ChromeSlot.tsx +20 -0
  131. package/src/kit/components/CodeView.tsx +470 -0
  132. package/src/kit/components/CompactInspectorShell.tsx +39 -0
  133. package/src/kit/components/ConsolePanel.tsx +273 -0
  134. package/src/kit/components/GameplaySessionTimeline.tsx +295 -0
  135. package/src/kit/components/InspectionProjection.tsx +932 -0
  136. package/src/kit/components/Inspector.tsx +270 -0
  137. package/src/kit/components/InspectorCanvasPreview.tsx +35 -0
  138. package/src/kit/components/InspectorFieldsSection.tsx +290 -0
  139. package/src/kit/components/InspectorStoriesSection.tsx +92 -0
  140. package/src/kit/components/InspectorToolSection.tsx +96 -0
  141. package/src/kit/components/InspectorTransformSection.tsx +245 -0
  142. package/src/kit/components/LightExplorerPanel.tsx +433 -0
  143. package/src/kit/components/MediaProperties.tsx +145 -0
  144. package/src/kit/components/ProjectHeader.tsx +328 -0
  145. package/src/kit/components/ReactCanvasControls.tsx +358 -0
  146. package/src/kit/components/RootSelectionOverlay.tsx +3688 -0
  147. package/src/kit/components/RootTextEditor.tsx +79 -0
  148. package/src/kit/components/SaveStatus.tsx +70 -0
  149. package/src/kit/components/SurfaceCrashBoundary.tsx +105 -0
  150. package/src/kit/components/SurfaceStateOverlay.tsx +24 -0
  151. package/src/kit/components/ToolContributionSurfaces.tsx +49 -0
  152. package/src/kit/components/ToolHost.tsx +380 -0
  153. package/src/kit/components/Toolbar.tsx +811 -0
  154. package/src/kit/components/TransientHint.tsx +44 -0
  155. package/src/kit/components/VersionControlSection.tsx +470 -0
  156. package/src/kit/components/ViewportOverlaysMenu.tsx +177 -0
  157. package/src/kit/components/VolterLogo.tsx +18 -0
  158. package/src/kit/components/WorktreeSwitcher.tsx +712 -0
  159. package/src/kit/components/account-documents.tsx +1162 -0
  160. package/src/kit/components/asset-documents.tsx +794 -0
  161. package/src/kit/components/asset-editor-persistence.ts +216 -0
  162. package/src/kit/components/asset-selection-section.tsx +545 -0
  163. package/src/kit/components/asset-thumbnails.tsx +307 -0
  164. package/src/kit/components/asset-viewers/AudioViewer.tsx +201 -0
  165. package/src/kit/components/asset-viewers/GenericJsonViewer.tsx +102 -0
  166. package/src/kit/components/asset-viewers/ImageViewer.tsx +300 -0
  167. package/src/kit/components/asset-viewers/JsonAssetDocument.tsx +98 -0
  168. package/src/kit/components/asset-viewers/OnlineAssetDetail.tsx +426 -0
  169. package/src/kit/components/asset-viewers/SourceAssetViewer.tsx +356 -0
  170. package/src/kit/components/asset-viewers/SpritesheetSpriteView.tsx +102 -0
  171. package/src/kit/components/asset-viewers/VideoViewer.tsx +101 -0
  172. package/src/kit/components/asset-viewers/shader-source.ts +144 -0
  173. package/src/kit/components/board-guides.ts +150 -0
  174. package/src/kit/components/canvas-scene-hotkeys.ts +37 -0
  175. package/src/kit/components/canvas-temporary-pivot.ts +34 -0
  176. package/src/kit/components/core-utilities.tsx +94 -0
  177. package/src/kit/components/inspector-preview-section.tsx +223 -0
  178. package/src/kit/components/inspector-revert-label.ts +20 -0
  179. package/src/kit/components/inspector-selection.ts +42 -0
  180. package/src/kit/components/inspector-stories-gating.ts +171 -0
  181. package/src/kit/components/inspector-transform-subject.ts +11 -0
  182. package/src/kit/components/inspector-transform.ts +88 -0
  183. package/src/kit/components/kind-documents.tsx +544 -0
  184. package/src/kit/components/primitives/DraftColorInput.tsx +74 -0
  185. package/src/kit/components/project-tool-documents.tsx +402 -0
  186. package/src/kit/components/scene-documents.tsx +221 -0
  187. package/src/kit/components/status-contributions.tsx +407 -0
  188. package/src/kit/components/tool-documents.tsx +302 -0
  189. package/src/kit/components/tool-schema-form.tsx +262 -0
  190. package/src/kit/components/use-after-paint.ts +41 -0
  191. package/src/kit/components/use-project-image-assets.ts +86 -0
  192. package/src/kit/components/workspace-history.ts +32 -0
  193. package/src/kit/components/world-documents.tsx +570 -0
  194. package/src/kit/components/world-overlay-gestures.ts +1939 -0
  195. package/src/kit/composite-screenshot.ts +2238 -0
  196. package/src/kit/content-entry-source-registry.ts +184 -0
  197. package/src/kit/contribution-surfaces.ts +48 -0
  198. package/src/kit/coverage/canvas-reveal.ts +192 -0
  199. package/src/kit/coverage/design-time-surfaces.ts +101 -0
  200. package/src/kit/coverage/ontology-invariants.ts +466 -0
  201. package/src/kit/coverage/session-vitals.ts +503 -0
  202. package/src/kit/crash-null-boundary.ts +36 -0
  203. package/src/kit/creation-site-edit.ts +1491 -0
  204. package/src/kit/creation-site-registry.ts +160 -0
  205. package/src/kit/delegate-harness-registry.ts +134 -0
  206. package/src/kit/document-areas.ts +70 -0
  207. package/src/kit/document-context-registry.ts +193 -0
  208. package/src/kit/document-open-registry.ts +200 -0
  209. package/src/kit/document-play-extension.ts +221 -0
  210. package/src/kit/document-preview-source.ts +20 -0
  211. package/src/kit/document-renderer-session.ts +138 -0
  212. package/src/kit/document-stage-sessions.ts +26 -0
  213. package/src/kit/document-viewports.ts +120 -0
  214. package/src/kit/editor-api.ts +46 -0
  215. package/src/kit/editor-chrome-capture.ts +136 -0
  216. package/src/kit/editor-commands.ts +176 -0
  217. package/src/kit/editor-console.ts +580 -0
  218. package/src/kit/editor-current-view.ts +56 -0
  219. package/src/kit/editor-document-probe.ts +1166 -0
  220. package/src/kit/editor-git-client.ts +115 -0
  221. package/src/kit/editor-hotkeys.ts +728 -0
  222. package/src/kit/editor-lease-view.ts +39 -0
  223. package/src/kit/editor-lease.ts +415 -0
  224. package/src/kit/editor-mode.ts +19 -0
  225. package/src/kit/editor-notifications.ts +140 -0
  226. package/src/kit/editor-presence.ts +563 -0
  227. package/src/kit/editor-presentation-activity.ts +58 -0
  228. package/src/kit/editor-presentation-notice.ts +42 -0
  229. package/src/kit/editor-runtime.tsx +147 -0
  230. package/src/kit/editor-server-response.ts +86 -0
  231. package/src/kit/editor-session-attribution.ts +85 -0
  232. package/src/kit/editor-session-mode.ts +54 -0
  233. package/src/kit/editor-state-facets.ts +74 -0
  234. package/src/kit/editor-view-presentation.ts +777 -0
  235. package/src/kit/environment-images.ts +58 -0
  236. package/src/kit/eyedropper-session.ts +60 -0
  237. package/src/kit/files/file-provider.ts +62 -0
  238. package/src/kit/files/project-files.ts +270 -0
  239. package/src/kit/finders/index.ts +137 -0
  240. package/src/kit/finders/scenes-from-entrypoint-selection.ts +387 -0
  241. package/src/kit/frame/frame-parts.ts +30 -0
  242. package/src/kit/framed-document-capture.ts +34 -0
  243. package/src/kit/game-globals-prelude.ts +143 -0
  244. package/src/kit/game-surface-defaults.ts +33 -0
  245. package/src/kit/gameplay-dom-recording.ts +318 -0
  246. package/src/kit/gameplay-export-state.ts +14 -0
  247. package/src/kit/gameplay-replay.ts +417 -0
  248. package/src/kit/gameplay-session-time.ts +9 -0
  249. package/src/kit/gameplay-sessions.ts +204 -0
  250. package/src/kit/hierarchy-component-marks.ts +298 -0
  251. package/src/kit/hierarchy-internals.ts +197 -0
  252. package/src/kit/hierarchy-kind-icon.ts +217 -0
  253. package/src/kit/hierarchy-menu-registry.ts +67 -0
  254. package/src/kit/hierarchy-node-rows.ts +307 -0
  255. package/src/kit/hierarchy-panel-view.ts +280 -0
  256. package/src/kit/hierarchy-projection.ts +76 -0
  257. package/src/kit/hierarchy-row-media.ts +45 -0
  258. package/src/kit/hierarchy-row-model.ts +308 -0
  259. package/src/kit/hierarchy-rows.ts +11 -0
  260. package/src/kit/hierarchy-walk.ts +86 -0
  261. package/src/kit/history/editor-session.ts +25 -0
  262. package/src/kit/history/history-commands.ts +147 -0
  263. package/src/kit/history/history-delegate.ts +187 -0
  264. package/src/kit/history/history-limit-notices.ts +43 -0
  265. package/src/kit/history/history-service.ts +1189 -0
  266. package/src/kit/history/persistence-coordinator.ts +35 -0
  267. package/src/kit/history/project-file-history.ts +386 -0
  268. package/src/kit/history/project-root-history-backends.ts +139 -0
  269. package/src/kit/history/resource-registry.ts +209 -0
  270. package/src/kit/history/snapshot-store.ts +103 -0
  271. package/src/kit/history/source-history-backend.ts +546 -0
  272. package/src/kit/history-types.ts +124 -0
  273. package/src/kit/hmr-registration-group.ts +67 -0
  274. package/src/kit/hmr-stable-react-context.ts +23 -0
  275. package/src/kit/hotkeys.ts +190 -0
  276. package/src/kit/inference-diagnostics.ts +69 -0
  277. package/src/kit/initial-project.ts +80 -0
  278. package/src/kit/inspection/active-subject.ts +571 -0
  279. package/src/kit/inspection/active-surface.ts +142 -0
  280. package/src/kit/inspection/compose-subject.ts +1055 -0
  281. package/src/kit/inspection/compose.ts +7 -0
  282. package/src/kit/inspection/display.ts +171 -0
  283. package/src/kit/inspection/document-subject.ts +109 -0
  284. package/src/kit/inspection/game-subject.ts +85 -0
  285. package/src/kit/inspection/null-subject.ts +119 -0
  286. package/src/kit/inspection/serialize.ts +357 -0
  287. package/src/kit/inspection/use-active-inspection.ts +180 -0
  288. package/src/kit/inspection-model.ts +542 -0
  289. package/src/kit/inspection-node-media.ts +58 -0
  290. package/src/kit/inspector-presentation.ts +203 -0
  291. package/src/kit/inspector-property-grouping.ts +64 -0
  292. package/src/kit/inspector-section-registry.ts +221 -0
  293. package/src/kit/instance-source-actions.ts +163 -0
  294. package/src/kit/js-heap.ts +71 -0
  295. package/src/kit/key-actions.ts +91 -0
  296. package/src/kit/keymap-presets.ts +428 -0
  297. package/src/kit/layout-policy.ts +31 -0
  298. package/src/kit/light-explorer-model.ts +134 -0
  299. package/src/kit/live-canvas-frame.ts +55 -0
  300. package/src/kit/live-document.ts +296 -0
  301. package/src/kit/live-gesture-lock.ts +50 -0
  302. package/src/kit/live-seam-evidence.ts +11 -0
  303. package/src/kit/live-session-registry.ts +220 -0
  304. package/src/kit/live-transition.ts +391 -0
  305. package/src/kit/manifest-project.ts +107 -0
  306. package/src/kit/module-fetch-diagnosis.ts +192 -0
  307. package/src/kit/mount-failure-report.ts +154 -0
  308. package/src/kit/native-selection-style.ts +497 -0
  309. package/src/kit/object3d-document-write-policy.ts +137 -0
  310. package/src/kit/packaged-runtime.ts +108 -0
  311. package/src/kit/palettes/maya.palette.json +57 -0
  312. package/src/kit/palettes/substance.palette.json +57 -0
  313. package/src/kit/performance-profiler.ts +367 -0
  314. package/src/kit/performance-sources.ts +69 -0
  315. package/src/kit/photograph-notice.ts +141 -0
  316. package/src/kit/play-boot-phase.ts +166 -0
  317. package/src/kit/play-camera-flight.ts +35 -0
  318. package/src/kit/png-encode.worker.ts +26 -0
  319. package/src/kit/presentation-surface.ts +248 -0
  320. package/src/kit/product-command.ts +90 -0
  321. package/src/kit/project-adapter.ts +1140 -0
  322. package/src/kit/project-asset-refresh.ts +23 -0
  323. package/src/kit/project-asset-roots.ts +68 -0
  324. package/src/kit/project-local-state.ts +151 -0
  325. package/src/kit/project-manager.ts +243 -0
  326. package/src/kit/project-module-changes.ts +201 -0
  327. package/src/kit/project-module-split.ts +270 -0
  328. package/src/kit/project-play-layers.ts +25 -0
  329. package/src/kit/project-provenance.ts +115 -0
  330. package/src/kit/project-ready.ts +42 -0
  331. package/src/kit/project-shape.ts +68 -0
  332. package/src/kit/project-tools.ts +107 -0
  333. package/src/kit/projection-types.ts +44 -0
  334. package/src/kit/readiness.ts +113 -0
  335. package/src/kit/renderer-resource-counts.ts +27 -0
  336. package/src/kit/reported-play-state.ts +90 -0
  337. package/src/kit/resolve-contributed-command.ts +14 -0
  338. package/src/kit/resolve-relative-specifier.ts +33 -0
  339. package/src/kit/retained-document-states.ts +91 -0
  340. package/src/kit/scene-document-plan.ts +320 -0
  341. package/src/kit/scene-live-open.ts +210 -0
  342. package/src/kit/scoped-game-css.ts +152 -0
  343. package/src/kit/served-url.ts +5 -0
  344. package/src/kit/session-close.ts +17 -0
  345. package/src/kit/session-tombstone.ts +127 -0
  346. package/src/kit/settings/settings-provider.ts +82 -0
  347. package/src/kit/settings-store.ts +348 -0
  348. package/src/kit/shell-document-state.ts +27 -0
  349. package/src/kit/shell-store-door.ts +45 -0
  350. package/src/kit/shell-store.ts +722 -0
  351. package/src/kit/source-conflict.ts +122 -0
  352. package/src/kit/stage-context.ts +377 -0
  353. package/src/kit/stage-invalidation.ts +25 -0
  354. package/src/kit/stage-store-registry.ts +69 -0
  355. package/src/kit/startup-failure.ts +80 -0
  356. package/src/kit/state-report-deferral.ts +73 -0
  357. package/src/kit/storage/host-files-storage.ts +97 -0
  358. package/src/kit/storage/http-storage.ts +174 -0
  359. package/src/kit/storage/index.ts +75 -0
  360. package/src/kit/storage/mem-storage.ts +158 -0
  361. package/src/kit/storage/path-lock.ts +44 -0
  362. package/src/kit/storage/paths.ts +26 -0
  363. package/src/kit/storage-types.ts +127 -0
  364. package/src/kit/stories/StoryPreviewMount.tsx +306 -0
  365. package/src/kit/stories/compose-project-stories.ts +255 -0
  366. package/src/kit/stories/prefabs-finder.ts +54 -0
  367. package/src/kit/stories/prefabs-from-stories.ts +182 -0
  368. package/src/kit/stories/project-story-regions.ts +24 -0
  369. package/src/kit/stories/story-capture.ts +579 -0
  370. package/src/kit/stories/story-declared-medium.ts +126 -0
  371. package/src/kit/stories/story-discovery.ts +176 -0
  372. package/src/kit/stories/story-dom-runtime.ts +78 -0
  373. package/src/kit/stories/story-grouping.ts +111 -0
  374. package/src/kit/stories/story-mount-turn.ts +27 -0
  375. package/src/kit/stories/story-presentation.ts +215 -0
  376. package/src/kit/stories/story-preview-component.ts +7 -0
  377. package/src/kit/stories/story-registry.ts +530 -0
  378. package/src/kit/stories-scope.ts +35 -0
  379. package/src/kit/story-document-openers.ts +36 -0
  380. package/src/kit/story-thumbnails.ts +47 -0
  381. package/src/kit/surface-keyboard.ts +101 -0
  382. package/src/kit/surface-state.ts +135 -0
  383. package/src/kit/system-seam-evidence.ts +72 -0
  384. package/src/kit/tab-census.ts +202 -0
  385. package/src/kit/tab-lifecycle-client.ts +227 -0
  386. package/src/kit/theme-library.ts +897 -0
  387. package/src/kit/theme-preference.ts +429 -0
  388. package/src/kit/three-viewport-presentation.ts +23 -0
  389. package/src/kit/tool-contribution-play.ts +74 -0
  390. package/src/kit/tool-loader.ts +1918 -0
  391. package/src/kit/transform-mode-request.ts +66 -0
  392. package/src/kit/transient-hint.ts +78 -0
  393. package/src/kit/transport-strip.tsx +174 -0
  394. package/src/kit/ui-source/adapter-region-includes.ts +238 -0
  395. package/src/kit/ui-source/file-region-resolver.ts +302 -0
  396. package/src/kit/ui-source/inspect.ts +775 -0
  397. package/src/kit/ui-source/source-write-backend.ts +605 -0
  398. package/src/kit/ui-source/tier-source-write-backend.ts +279 -0
  399. package/src/kit/user-local-state.ts +105 -0
  400. package/src/kit/viewport-activation-timings.ts +840 -0
  401. package/src/kit/viewport-editor-controls.ts +22 -0
  402. package/src/kit/viewport-presentation.ts +668 -0
  403. package/src/kit/viewport-surface-status.tsx +55 -0
  404. package/src/kit/wait-until.ts +37 -0
  405. package/src/kit/worker-call-metrics.ts +166 -0
  406. package/src/kit/workspace-areas.ts +191 -0
  407. package/src/kit/workspace-aux-commands.ts +11 -0
  408. package/src/kit/workspace-available-documents.ts +142 -0
  409. package/src/kit/workspace-core-utilities.ts +31 -0
  410. package/src/kit/workspace-document-ids.ts +59 -0
  411. package/src/kit/workspace-document-registry.ts +624 -0
  412. package/src/kit/workspace-document-restore.ts +146 -0
  413. package/src/kit/workspace-host-commands.ts +141 -0
  414. package/src/kit/workspace-persistence-gate.ts +40 -0
  415. package/src/kit/workspace-play-utilities.ts +44 -0
  416. package/src/kit/workspace-presets.ts +446 -0
  417. package/src/kit/workspace-regions.ts +276 -0
  418. package/src/kit/workspace-static-panels.ts +73 -0
  419. package/src/kit/workspace-status-registry.ts +121 -0
  420. package/src/kit/workspace-storage.ts +35 -0
  421. package/src/kit/workspace-style.ts +226 -0
  422. package/src/kit/workspace-utility-commands.ts +74 -0
  423. package/src/kit/workspace-utility-registry.ts +263 -0
  424. package/src/kit/world-adoption-event.ts +23 -0
  425. package/src/kit/world-adoption.ts +115 -0
  426. package/src/kit/world-canvas-viewport-state.ts +35 -0
  427. package/src/kit/world-document-routing.ts +104 -0
  428. package/src/kit/world-pan-state.ts +198 -0
  429. package/src/kit/write-pipe.ts +173 -0
  430. package/src/layout-arrangements.ts +5 -0
  431. package/src/layouts.tsx +108 -0
  432. package/src/looks.ts +16 -0
  433. package/src/project/output-roots.ts +73 -0
  434. package/src/project/tab-census.ts +155 -0
  435. package/src/project-tool-catalog.ts +104 -0
  436. package/src/selection.tsx +107 -0
  437. package/src/services.ts +18 -0
  438. package/src/session/build-report.ts +22 -0
  439. package/src/session/collaboration-types.ts +262 -0
  440. package/src/session/command-table.ts +327 -0
  441. package/src/session/discovery.ts +100 -0
  442. package/src/session/editor-brand.ts +48 -0
  443. package/src/session/editor-compatibility.ts +317 -0
  444. package/src/session/editor-control-lifecycle.ts +68 -0
  445. package/src/session/editor-control-protocol.ts +5 -0
  446. package/src/session/entrypoint-selection-readers.ts +66 -0
  447. package/src/session/entrypoint-selection-source.ts +120 -0
  448. package/src/session/game-css-scope.ts +30 -0
  449. package/src/session/hosted-attachment.ts +225 -0
  450. package/src/session/limited-view.ts +82 -0
  451. package/src/session/product-create.ts +24 -0
  452. package/src/session/product-locator.ts +478 -0
  453. package/src/session/project-module-url.ts +242 -0
  454. package/src/session/project-serving.ts +164 -0
  455. package/src/session/project-upgrade.ts +403 -0
  456. package/src/session/registry-format.ts +210 -0
  457. package/src/session/relative-path-guard.ts +56 -0
  458. package/src/session/scoped-game-css.ts +461 -0
  459. package/src/session/source-glob.ts +15 -0
  460. package/src/session/tool-contribution-convention.ts +123 -0
  461. package/src/session/workbench-locator.ts +712 -0
  462. package/src/session.ts +41 -0
  463. package/src/share.ts +160 -0
  464. package/src/source-analysis.ts +28 -0
  465. package/src/source-authoring.ts +439 -0
  466. package/src/tools/errors.ts +91 -0
  467. package/src/tools/provider-execution.ts +70 -0
  468. package/src/tools/registry.ts +341 -0
  469. package/src/tools/types.ts +159 -0
  470. package/src/transport.ts +100 -0
  471. package/src/types.ts +1693 -0
  472. package/src/views.ts +164 -0
  473. package/src/widgets/design-system.ts +93 -0
  474. package/src/widgets/editor-appearance.ts +151 -0
  475. package/src/widgets/editor-material.ts +83 -0
  476. package/src/widgets/icon-set-registry.ts +105 -0
  477. package/src/widgets/index.ts +71 -0
  478. package/src/widgets/inspector-widgets/AlignmentGrid.tsx +182 -0
  479. package/src/widgets/inspector-widgets/AssetSlotPicker.tsx +123 -0
  480. package/src/widgets/inspector-widgets/BorderEditor.tsx +309 -0
  481. package/src/widgets/inspector-widgets/ColorPicker.tsx +549 -0
  482. package/src/widgets/inspector-widgets/CurveEditor.tsx +359 -0
  483. package/src/widgets/inspector-widgets/FilterEditor.tsx +108 -0
  484. package/src/widgets/inspector-widgets/FontPicker.tsx +191 -0
  485. package/src/widgets/inspector-widgets/GradientEditor.tsx +623 -0
  486. package/src/widgets/inspector-widgets/ScrubbableInput.tsx +180 -0
  487. package/src/widgets/inspector-widgets/ShadowEditor.tsx +319 -0
  488. package/src/widgets/inspector-widgets/color-utils.ts +201 -0
  489. package/src/widgets/inspector-widgets/curve-utils.ts +212 -0
  490. package/src/widgets/inspector-widgets/index.ts +25 -0
  491. package/src/widgets/inspector-widgets/shared.tsx +140 -0
  492. package/src/widgets/interactive-edit-scope.ts +33 -0
  493. package/src/widgets/patterns/Dialog.tsx +140 -0
  494. package/src/widgets/patterns/Fields.tsx +44 -0
  495. package/src/widgets/patterns/List.tsx +25 -0
  496. package/src/widgets/patterns/StateSurface.tsx +40 -0
  497. package/src/widgets/patterns/Surfaces.tsx +122 -0
  498. package/src/widgets/patterns/Tabs.tsx +80 -0
  499. package/src/widgets/patterns/Toolbar.tsx +72 -0
  500. package/src/widgets/patterns/Tree.tsx +72 -0
  501. package/src/widgets/primitives/AnchoredMenu.tsx +260 -0
  502. package/src/widgets/primitives/Button.tsx +62 -0
  503. package/src/widgets/primitives/ColorInput.tsx +78 -0
  504. package/src/widgets/primitives/DraftTextInput.tsx +63 -0
  505. package/src/widgets/primitives/EditorIcon.tsx +157 -0
  506. package/src/widgets/primitives/FormControls.tsx +88 -0
  507. package/src/widgets/primitives/HoverPreview.tsx +96 -0
  508. package/src/widgets/primitives/JsonInput.tsx +113 -0
  509. package/src/widgets/primitives/Layout.tsx +100 -0
  510. package/src/widgets/primitives/Menu.tsx +161 -0
  511. package/src/widgets/primitives/NumberInput.tsx +169 -0
  512. package/src/widgets/primitives/Panel.tsx +80 -0
  513. package/src/widgets/primitives/SectionHeader.tsx +77 -0
  514. package/src/widgets/primitives/Text.tsx +54 -0
  515. package/src/widgets/primitives/ThemeRootPortal.tsx +52 -0
  516. package/src/widgets/primitives/Tooltip.tsx +204 -0
  517. package/src/widgets/primitives/Vec3Input.tsx +70 -0
  518. package/src/widgets/primitives/banner-tones.ts +32 -0
  519. package/src/widgets/primitives/clamp-to-viewport.ts +44 -0
  520. package/src/widgets/primitives/editor-icons.ts +254 -0
  521. package/src/widgets/primitives/panel-header-styles.ts +42 -0
  522. package/src/widgets/theme.ts +2841 -0
  523. package/src/widgets/z-index.ts +25 -0
@@ -0,0 +1,140 @@
1
+ /**
2
+ * The FAILURE CHANNEL for declared-asset-pack materialization (D-AP4):
3
+ * *"Failure = loud degradation, not fabrication. ... the missing asset is
4
+ * reported in the editor console + status surface with a retry affordance, and
5
+ * dependent features degrade honestly."*
6
+ *
7
+ * `materializeDeclaredAssetPacks` already fails closed per entry — it never
8
+ * writes placeholder bytes and never blocks the other entries — but it only
9
+ * RETURNS a `failed` array, and an array with no reader is the hazard: a seed
10
+ * that lands without its clips would look like a working editor with a
11
+ * mysteriously dead animation, which is the worst possible outcome and
12
+ * precisely what the anti-shim rule forbids.
13
+ *
14
+ * This module is that reader, and it is deliberately TWO channels, because
15
+ * neither alone is enough — D-AP4's own words, *"reported in the editor
16
+ * console + status surface with a retry affordance"*:
17
+ *
18
+ * 1. `editorConsole.error` — one line per failed entry, subsystem `assets`,
19
+ * naming the library key, the destination path, the reason, and what
20
+ * degrades.
21
+ * 2. A module-level report slot the status bar's `asset-materialization`
22
+ * contribution reads (`../components/status-contributions.tsx`),
23
+ * carrying the RETRY affordance. Retry re-runs materialization against
24
+ * the active backend, which is safe and cheap by construction: the
25
+ * materializer skips every entry already in the ledger, so a retry only
26
+ * refetches what is still missing.
27
+ *
28
+ * That status item used to be a red banner across the top of the shell. The
29
+ * editor has ONE error home — console line, bottom-left status item, the
30
+ * Console utility behind it — and a second one only taught users two places
31
+ * to look, so the banner is gone.
32
+ *
33
+ * Same plain module-singleton + own-`subscribe` shape as
34
+ * `../authoring/mount-failure-report.ts`.
35
+ */
36
+
37
+ import { editorConsole } from '@volter/sdk/kit/editor-console';
38
+ import type { StorageBackend } from '@volter/sdk/kit/storage-types';
39
+ import type { AssetPackMaterializationResult } from './hosted-asset-materialization';
40
+
41
+ /** One declared pack entry that did not materialize — the exact fields both
42
+ * channels show. Flattened out of `AssetPackMaterializationFailure` so the
43
+ * banner never has to know the materializer's own types. */
44
+ export interface AssetMaterializationFailure {
45
+ /** Library key, `source:id` (e.g. `local:a7c5288306d9e98cb7dbdbd2`). */
46
+ readonly key: string;
47
+ /** Project-relative destination the bytes were meant to land at. */
48
+ readonly dest: string;
49
+ /** Declaring pack name from `asset-manifest.json`. */
50
+ readonly pack: string;
51
+ /** The materializer's own reason string — never fabricated, never softened. */
52
+ readonly reason: string;
53
+ }
54
+
55
+ let _failures: readonly AssetMaterializationFailure[] = [];
56
+ const _listeners = new Set<() => void>();
57
+
58
+ /** `useSyncExternalStore`-compatible subscribe for the banner. */
59
+ export function subscribeToAssetMaterializationFailures(callback: () => void): () => void {
60
+ _listeners.add(callback);
61
+ return () => _listeners.delete(callback);
62
+ }
63
+
64
+ /** Every declared entry that failed to materialize, in declaration order. */
65
+ export function getAssetMaterializationFailures(): readonly AssetMaterializationFailure[] {
66
+ return _failures;
67
+ }
68
+
69
+ /** Clear the slot (the banner's dismiss). Does not retry. */
70
+ export function clearAssetMaterializationFailures(): void {
71
+ _failures = [];
72
+ notify();
73
+ }
74
+
75
+ function notify(): void {
76
+ for (const listener of _listeners) listener();
77
+ }
78
+
79
+ /**
80
+ * The message BOTH channels use, so the console line and the banner row can
81
+ * never drift apart. Names the key, the destination and the reason, then says
82
+ * what degrades — a reader who sees only this line knows what is broken and
83
+ * what it costs them.
84
+ */
85
+ export function formatAssetMaterializationFailure(failure: AssetMaterializationFailure): string {
86
+ return (
87
+ `Starter asset "${failure.key}" (pack "${failure.pack}") did not materialize into ` +
88
+ `${failure.dest}: ${failure.reason} Nothing was written for it — features that read ` +
89
+ 'that file degrade (a missing clips GLB leaves the character standing without ' +
90
+ 'locomotion clips). Use Retry once the cause is fixed.'
91
+ );
92
+ }
93
+
94
+ /**
95
+ * Report a materialization result through both channels. Called by every
96
+ * production materialization site (today: `../storage/seed.ts`'s
97
+ * `seedIfEmpty`) so no caller can forget to read `failed`.
98
+ *
99
+ * A result with no failures CLEARS the slot: that is what makes a successful
100
+ * retry dismiss its own banner.
101
+ */
102
+ export function reportAssetMaterialization(result: AssetPackMaterializationResult): void {
103
+ const failures = result.failed.map((failure) => ({
104
+ key: failure.entry.key,
105
+ dest: failure.entry.dest,
106
+ pack: failure.entry.pack,
107
+ reason: failure.reason,
108
+ }));
109
+ for (const failure of failures) {
110
+ editorConsole.error(formatAssetMaterializationFailure(failure), 'assets');
111
+ }
112
+ _failures = failures;
113
+ notify();
114
+ }
115
+
116
+ /**
117
+ * Re-run materialization against `backend` and re-report. Retry-safe by
118
+ * construction (the materializer skips ledger-present entries), so this
119
+ * refetches only what is still missing.
120
+ *
121
+ * A THROW here is the manifest itself being unreadable/invalid — not a
122
+ * per-entry failure — so it degrades through the console too rather than
123
+ * becoming an unhandled rejection in a click handler.
124
+ */
125
+ export async function retryAssetMaterialization(backend: StorageBackend): Promise<void> {
126
+ try {
127
+ // Lazy for the same reason the seed's call is: the materializer is the
128
+ // heaviest thing this report knows, and only the retry needs it.
129
+ const { materializeDeclaredAssetPacks } = await import('./hosted-asset-materialization');
130
+ const result = await materializeDeclaredAssetPacks(backend);
131
+ reportAssetMaterialization(result);
132
+ } catch (error) {
133
+ editorConsole.error(
134
+ `Retrying asset materialization failed before any entry was attempted: ${
135
+ error instanceof Error ? error.message : String(error)
136
+ }`,
137
+ 'assets',
138
+ );
139
+ }
140
+ }
@@ -0,0 +1,320 @@
1
+ /**
2
+ * Asset packs — `asset-manifest.json` (D-AP1) and the pure sync/check planner
3
+ * behind `npm run asset-packs:sync` (D-AP2)..
4
+ *
5
+ * A PACK is a named list of `{ key, dest }`: library asset keys and the
6
+ * project-relative paths their bytes are copied to. It is an INPUT TO
7
+ * MATERIALIZATION, never a runtime concept — nothing in a running game or a
8
+ * scaffolded project resolves a pack. It is deliberately NOT a `volter.project.json`
9
+ * field: the manifest says what a project IS, a pack says how its reference
10
+ * material was PRODUCED.
11
+ *
12
+ * The file lives beside `volter.project.json` in `packages/game-editor/template/` and each
13
+ * `examples/<id>/`. A scaffolded user project does not carry it; its record is
14
+ * the ledger (`asset-ledger.ts`, D-AP3).
15
+ *
16
+ * The binaries stay COMMITTED — creating a project must work offline and CI must stay
17
+ * hermetic (D-AP2/D-AP6). What the pack adds is that they are now GENERATED: the
18
+ * library is the origin, and `--check` re-verifies the committed bytes against
19
+ * the library's own `sourceHash` without touching the network.
20
+ *
21
+ * On KEYS: a key is `source:id`, the same identity as `onlineAssetKey`. For the
22
+ * SSD/cloud catalog the source name is `local`, and the id is a VARIANT id
23
+ * (`local:a7c5288306d9e98cb7dbdbd2`), not a family id — a family has several
24
+ * format variants, so only the variant pins bytes. `findLocalAsset` /
25
+ * `findCloudAsset` both resolve variant ids, so this is an ordinary library key.
26
+ */
27
+
28
+ import { z } from 'zod';
29
+
30
+ export const AssetPackEntrySchema = z
31
+ .object({
32
+ /** `source:id` — the library's identity for the asset (variant-precise). */
33
+ key: z.string().regex(/^[^:]+:.+$/, 'An asset key must be "source:id"'),
34
+ /** Project-relative destination for the asset's main file. */
35
+ dest: z.string().min(1),
36
+ /**
37
+ * The PIN: sha256 of the bytes this entry declares, bare lowercase hex.
38
+ *
39
+ * Required, and the reason is trust-on-first-use. A materializer that
40
+ * learns the expected digest from the same response that delivers the
41
+ * bytes has authenticated nothing on the first fetch — a bad or moved
42
+ * answer is self-consistent, gets written, and its digest becomes the
43
+ * project's permanent `sourceHash` in the ledger. A pin is a CHECKED-IN
44
+ * fact reviewed in a diff, so the first fetch is verified like every
45
+ * later one. `asset-packs:sync --check` cross-checks it against
46
+ * `catalog/cloud/manifest.json` (hermetic — both sides are repo files),
47
+ * and `asset-pack-manifest.test.ts` asserts no in-repo pin was invented.
48
+ */
49
+ sha256: z
50
+ .string()
51
+ .regex(
52
+ /^[a-f0-9]{64}$/,
53
+ 'A pack entry must pin the sha256 of its bytes as 64 lowercase hex digits',
54
+ ),
55
+ })
56
+ .strict();
57
+
58
+ export const AssetPackManifestSchema = z
59
+ .object({
60
+ packs: z.record(z.string().min(1), z.array(AssetPackEntrySchema)),
61
+ })
62
+ .strict();
63
+
64
+ export type AssetPackEntry = z.infer<typeof AssetPackEntrySchema>;
65
+ export type AssetPackManifest = z.infer<typeof AssetPackManifestSchema>;
66
+
67
+ /** Parse an `asset-manifest.json`. Throws loudly — a half-read pack
68
+ * declaration would silently stop guarding the files it dropped. */
69
+ export function parseAssetPackManifest(input: unknown): AssetPackManifest {
70
+ return AssetPackManifestSchema.parse(input);
71
+ }
72
+
73
+ export interface FlattenedPackEntry extends AssetPackEntry {
74
+ readonly pack: string;
75
+ }
76
+
77
+ /** Flatten every pack to a single entry list, rejecting two packs that claim
78
+ * the same destination (whichever ran last would silently win). */
79
+ export function flattenAssetPacks(manifest: AssetPackManifest): FlattenedPackEntry[] {
80
+ const flattened: FlattenedPackEntry[] = [];
81
+ const byDest = new Map<string, string>();
82
+ for (const [pack, entries] of Object.entries(manifest.packs)) {
83
+ for (const entry of entries) {
84
+ const owner = byDest.get(entry.dest);
85
+ if (owner !== undefined) {
86
+ throw new Error(
87
+ `Two packs declare the same destination "${entry.dest}": "${owner}" and "${pack}".`,
88
+ );
89
+ }
90
+ byDest.set(entry.dest, pack);
91
+ flattened.push({ ...entry, pack });
92
+ }
93
+ }
94
+ return flattened;
95
+ }
96
+
97
+ /**
98
+ * Build the library index `planAssetPackSync` needs from a parsed
99
+ * `catalog/cloud/manifest.json`.
100
+ *
101
+ * That file has TWO shapes on disk and both are live. v1 is a flat `assets`
102
+ * array; v2 is the canonical `families` graph whose `variants` are the assets
103
+ * (a family holds several format variants, and only a variant pins bytes).
104
+ * The checked-in snapshot is still v1 while `scripts/cloud-asset-library.ts`
105
+ * already emits v2, so the FIRST regeneration of that file — which ingesting
106
+ * anything into the library requires — flips the shape under this reader.
107
+ * `packages/cloud-asset-library/src/worker.ts` accepts both for exactly this
108
+ * reason; so does this. A reader that understood only the shape it happened to
109
+ * be born with would turn `asset-packs:sync --check` red on a correct tree.
110
+ *
111
+ * Throws on anything else rather than returning an empty index: an index that
112
+ * silently came back empty would report every declared asset as an unknown key.
113
+ */
114
+ export function libraryIndexFromCloudManifest(
115
+ manifest: unknown,
116
+ source: string,
117
+ ): Map<string, LibraryAsset> {
118
+ const root = manifest as {
119
+ version?: unknown;
120
+ assets?: unknown;
121
+ families?: unknown;
122
+ } | null;
123
+ const flat = Array.isArray(root?.families)
124
+ ? (root.families as ManifestFamily[]).flatMap((family) =>
125
+ (family.variants ?? []).map((variant) => ({ ...family, ...variant })),
126
+ )
127
+ : Array.isArray(root?.assets)
128
+ ? (root.assets as ManifestAsset[])
129
+ : null;
130
+ if (!flat) {
131
+ throw new Error(
132
+ 'A cloud asset manifest must have a v1 "assets" array or a v2 "families" array; ' +
133
+ `this one has neither (version ${JSON.stringify(root?.version)}).`,
134
+ );
135
+ }
136
+
137
+ const index = new Map<string, LibraryAsset>();
138
+ for (const asset of flat) {
139
+ const file = asset.files?.[0];
140
+ if (!file) continue;
141
+ const key = `${source}:${asset.id}`;
142
+ index.set(key, {
143
+ key,
144
+ name: asset.name,
145
+ license: asset.license,
146
+ sourceSha256: file.main.sha256,
147
+ sizeBytes: file.main.sizeBytes,
148
+ relativePath: file.main.relativePath,
149
+ dependencyCount: file.dependencies.length,
150
+ });
151
+ }
152
+ return index;
153
+ }
154
+
155
+ interface ManifestObject {
156
+ sha256: string;
157
+ sizeBytes: number;
158
+ relativePath: string;
159
+ }
160
+ interface ManifestAsset {
161
+ id: string;
162
+ name: string;
163
+ license: string;
164
+ files?: { main: ManifestObject; dependencies: ManifestObject[] }[];
165
+ }
166
+ interface ManifestFamily extends Omit<ManifestAsset, 'id' | 'files'> {
167
+ variants?: Omit<ManifestAsset, 'name' | 'license'>[];
168
+ }
169
+
170
+ /** One asset as the LIBRARY describes it — the only source of `sourceSha256`. */
171
+ export interface LibraryAsset {
172
+ readonly key: string;
173
+ readonly name: string;
174
+ readonly license: string;
175
+ readonly sourceSha256: string;
176
+ readonly sizeBytes: number;
177
+ /** The library's own filename for the main file. */
178
+ readonly relativePath: string;
179
+ /** Sibling files the main file needs. See `unsupported-dependencies` below. */
180
+ readonly dependencyCount: number;
181
+ }
182
+
183
+ export type AssetPackDecision =
184
+ /** Committed bytes are the library's bytes. Nothing to do. */
185
+ | { readonly status: 'match'; readonly entry: FlattenedPackEntry }
186
+ /** Declared but not committed — materialize it. */
187
+ | { readonly status: 'missing'; readonly entry: FlattenedPackEntry; readonly asset: LibraryAsset }
188
+ /** Committed but not the library's bytes — hand-edited, or the library moved. */
189
+ | {
190
+ readonly status: 'stale';
191
+ readonly entry: FlattenedPackEntry;
192
+ readonly asset: LibraryAsset;
193
+ readonly committedSha256: string;
194
+ }
195
+ /** The key names nothing in the library. Never guessed around. */
196
+ | { readonly status: 'unresolved-key'; readonly entry: FlattenedPackEntry }
197
+ /**
198
+ * The declaration's pin and the library index disagree about the asset's
199
+ * bytes. Two independent CHECKED-IN facts contradict each other, so neither
200
+ * can be assumed: copying library bytes would silently overrule a reviewed
201
+ * pin, and trusting the pin would hide a library that moved. A human
202
+ * resolves it; sync never does.
203
+ */
204
+ | {
205
+ readonly status: 'pin-mismatch';
206
+ readonly entry: FlattenedPackEntry;
207
+ readonly asset: LibraryAsset;
208
+ }
209
+ /** Multi-file assets are not expressible as one `dest`; refuse rather than
210
+ * silently drop the siblings the main file needs. */
211
+ | {
212
+ readonly status: 'unsupported-dependencies';
213
+ readonly entry: FlattenedPackEntry;
214
+ readonly asset: LibraryAsset;
215
+ };
216
+
217
+ export interface AssetPackSyncInputs {
218
+ /** Library index by `source:id`. */
219
+ readonly library: ReadonlyMap<string, LibraryAsset>;
220
+ /** sha256 of each declared dest as committed, or null when absent. */
221
+ readonly committed: ReadonlyMap<string, string | null>;
222
+ }
223
+
224
+ /**
225
+ * Decide what each declared entry needs. Pure: the caller supplies the library
226
+ * index and the committed hashes, so this is testable without fs or network.
227
+ */
228
+ export function planAssetPackSync(
229
+ entries: readonly FlattenedPackEntry[],
230
+ inputs: AssetPackSyncInputs,
231
+ ): AssetPackDecision[] {
232
+ return entries.map((entry) => {
233
+ const asset = inputs.library.get(entry.key);
234
+ if (!asset) return { status: 'unresolved-key', entry } as const;
235
+ if (asset.dependencyCount > 0) {
236
+ return { status: 'unsupported-dependencies', entry, asset } as const;
237
+ }
238
+ // The pin is checked BEFORE anything about the committed copy: while the
239
+ // two checked-in facts disagree there is no defensible expected digest to
240
+ // judge the copy against.
241
+ if (entry.sha256 !== asset.sourceSha256) {
242
+ return { status: 'pin-mismatch', entry, asset } as const;
243
+ }
244
+ const committedSha256 = inputs.committed.get(entry.dest) ?? null;
245
+ if (committedSha256 === null) return { status: 'missing', entry, asset } as const;
246
+ return committedSha256 === entry.sha256
247
+ ? ({ status: 'match', entry } as const)
248
+ : ({ status: 'stale', entry, asset, committedSha256 } as const);
249
+ });
250
+ }
251
+
252
+ /** Decisions `--check` must fail on. A `missing`/`stale` copy means the
253
+ * committed tree no longer matches what the library says it is. */
254
+ export function assetPackCheckFailures(
255
+ decisions: readonly AssetPackDecision[],
256
+ ): AssetPackDecision[] {
257
+ return decisions.filter((decision) => decision.status !== 'match');
258
+ }
259
+
260
+ /**
261
+ * Decisions sync can NEITHER accept nor repair — it must stop on them.
262
+ *
263
+ * Derived, not hand-listed: anything that is not already correct (`match`) and
264
+ * is not a work item is by definition a refusal. The hand-written version of
265
+ * this list silently omitted `pin-mismatch` the day that status was added, and
266
+ * the consequence was not a missed error but a FABRICATED one — sync would
267
+ * have gone on to record a `sourceHash` for bytes it never fetched or
268
+ * verified, which is exactly what the anti-shim rule forbids.
269
+ */
270
+ export function assetPackBlockingDecisions(
271
+ decisions: readonly AssetPackDecision[],
272
+ ): AssetPackDecision[] {
273
+ const repairable = new Set<AssetPackDecision>(assetPackWorkItems(decisions));
274
+ return decisions.filter((decision) => decision.status !== 'match' && !repairable.has(decision));
275
+ }
276
+
277
+ /** Decisions `assets:sync` can fix by copying library bytes in. */
278
+ export function assetPackWorkItems(
279
+ decisions: readonly AssetPackDecision[],
280
+ ): Extract<AssetPackDecision, { status: 'missing' | 'stale' }>[] {
281
+ return decisions.flatMap((decision) =>
282
+ decision.status === 'missing' || decision.status === 'stale' ? [decision] : [],
283
+ );
284
+ }
285
+
286
+ /** One line explaining a decision, for both `--check` failures and sync logs. */
287
+ export function describeAssetPackDecision(decision: AssetPackDecision): string {
288
+ const where = `${decision.entry.dest} (pack "${decision.entry.pack}", key ${decision.entry.key})`;
289
+ switch (decision.status) {
290
+ case 'match':
291
+ return `ok ${where}`;
292
+ case 'missing':
293
+ return `MISSING ${where} — declared but not committed`;
294
+ case 'stale':
295
+ return (
296
+ `STALE ${where} — committed bytes are sha256:${decision.committedSha256.slice(0, 12)}…, ` +
297
+ `the library has sha256:${decision.asset.sourceSha256.slice(0, 12)}… ` +
298
+ '(either the copy was hand-edited or the library moved)'
299
+ );
300
+ case 'unresolved-key':
301
+ return `UNKNOWN ${where} — no such asset in the library index`;
302
+ case 'pin-mismatch':
303
+ return (
304
+ `PIN ${where} — the declaration pins sha256:${decision.entry.sha256.slice(0, 12)}… ` +
305
+ `but the library index says sha256:${decision.asset.sourceSha256.slice(0, 12)}… ` +
306
+ '(re-pin the declaration only after confirming the library moved deliberately; ' +
307
+ 'nothing is fetched or copied while these disagree)'
308
+ );
309
+ case 'unsupported-dependencies':
310
+ return (
311
+ `MULTIFILE ${where} — the library asset has ${decision.asset.dependencyCount} ` +
312
+ 'dependency file(s); a pack entry declares exactly one destination file'
313
+ );
314
+ }
315
+ }
316
+
317
+ /** Where a project declares its library asset packs. Lives here, beside the
318
+ * manifest's shape, so a reader of the PATH (the seed) does not carry the
319
+ * materializer (the cloud client, the ledger, its locks). */
320
+ export const ASSET_MANIFEST_PATH = 'asset-manifest.json';
@@ -0,0 +1,142 @@
1
+ import { z } from 'zod';
2
+
3
+ export type AssetHealthCode =
4
+ | 'healthy'
5
+ | 'source-only'
6
+ | 'missing-file'
7
+ | 'missing-dependency'
8
+ | 'missing-thumbnail'
9
+ | 'unsupported-format'
10
+ | 'invalid-metadata'
11
+ | 'conversion-failed'
12
+ | 'missing-attribution'
13
+ | 'broken-asset-reference';
14
+
15
+ export interface AssetHealth {
16
+ readonly status: 'healthy' | 'warning' | 'error';
17
+ readonly codes: readonly AssetHealthCode[];
18
+ }
19
+
20
+ export const AssetFileSchema = z
21
+ .object({
22
+ label: z.string().min(1),
23
+ path: z.string().min(1),
24
+ format: z.string().min(1),
25
+ sizeBytes: z.number().int().nonnegative(),
26
+ dependencies: z.array(z.string().min(1)).optional(),
27
+ sha256: z
28
+ .string()
29
+ .regex(/^[a-f0-9]{64}$/)
30
+ .optional(),
31
+ })
32
+ .strict();
33
+
34
+ export const AssetDeliverySchema = z
35
+ .object({
36
+ id: z.string().min(1),
37
+ kind: z.enum(['local-ssd', 'cloud', 'remote']),
38
+ available: z.boolean(),
39
+ fileIndexes: z.array(z.number().int().nonnegative()).min(1),
40
+ })
41
+ .strict();
42
+
43
+ export const AssetThumbnailSchema = z
44
+ .object({
45
+ path: z.string().min(1),
46
+ state: z.enum(['generated', 'upstream', 'fallback', 'unsupported', 'failed']),
47
+ profileVersion: z.string().min(1),
48
+ sourceHash: z
49
+ .string()
50
+ .regex(/^[a-f0-9]{64}$/)
51
+ .optional(),
52
+ resultHash: z
53
+ .string()
54
+ .regex(/^[a-f0-9]{64}$/)
55
+ .optional(),
56
+ issueCode: z.string().min(1).optional(),
57
+ })
58
+ .strict();
59
+
60
+ export const AssetVariantSchema = z
61
+ .object({
62
+ id: z.string().regex(/^[a-f0-9]{24}$/),
63
+ label: z.string().min(1),
64
+ type: z.enum(['model', 'animation', 'source']),
65
+ files: z.array(AssetFileSchema).min(1),
66
+ deliveries: z.array(AssetDeliverySchema).min(1),
67
+ thumbnail: AssetThumbnailSchema,
68
+ animationCount: z.number().int().nonnegative().optional(),
69
+ clipNames: z.array(z.string()).optional(),
70
+ })
71
+ .strict();
72
+
73
+ export const AssetFamilySchema = z
74
+ .object({
75
+ id: z.string().regex(/^[a-f0-9]{24}$/),
76
+ source: z.string().min(1),
77
+ name: z.string().min(1),
78
+ type: z.enum(['model', 'animation', 'source']),
79
+ categories: z.array(z.string()),
80
+ tags: z.array(z.string()),
81
+ license: z.string().min(1),
82
+ author: z.string().min(1),
83
+ sourceUrl: z.string().url(),
84
+ variants: z.array(AssetVariantSchema).min(1),
85
+ })
86
+ .strict();
87
+
88
+ export const AssetCatalogEnvelopeSchema = z
89
+ .object({
90
+ version: z.literal(2),
91
+ generatedAt: z.string().datetime(),
92
+ families: z.array(z.unknown()),
93
+ })
94
+ .strict();
95
+
96
+ export type AssetFile = z.infer<typeof AssetFileSchema>;
97
+ export type AssetDelivery = z.infer<typeof AssetDeliverySchema>;
98
+ export type AssetVariant = z.infer<typeof AssetVariantSchema>;
99
+ export type AssetFamily = z.infer<typeof AssetFamilySchema>;
100
+
101
+ export interface AssetCatalogIssue {
102
+ readonly familyIndex: number | null;
103
+ readonly familyId?: string;
104
+ readonly path: readonly (string | number)[];
105
+ readonly message: string;
106
+ }
107
+
108
+ export interface AssetCatalog {
109
+ readonly version: 2;
110
+ readonly generatedAt: string;
111
+ readonly families: readonly AssetFamily[];
112
+ readonly issues: readonly AssetCatalogIssue[];
113
+ }
114
+
115
+ export function parseAssetCatalog(input: unknown): AssetCatalog {
116
+ const envelope = AssetCatalogEnvelopeSchema.parse(input);
117
+ const families: AssetFamily[] = [];
118
+ const issues: AssetCatalogIssue[] = [];
119
+ for (const [familyIndex, candidate] of envelope.families.entries()) {
120
+ const result = AssetFamilySchema.safeParse(candidate);
121
+ if (result.success) {
122
+ families.push(result.data);
123
+ continue;
124
+ }
125
+ const familyId =
126
+ candidate &&
127
+ typeof candidate === 'object' &&
128
+ 'id' in candidate &&
129
+ typeof candidate.id === 'string'
130
+ ? candidate.id
131
+ : undefined;
132
+ for (const issue of result.error.issues) {
133
+ issues.push({
134
+ familyIndex,
135
+ ...(familyId ? { familyId } : {}),
136
+ path: issue.path.map((part) => (typeof part === 'symbol' ? String(part) : part)),
137
+ message: issue.message,
138
+ });
139
+ }
140
+ }
141
+ return { version: 2, generatedAt: envelope.generatedAt, families, issues };
142
+ }