@hraness/slopcamera 3.2.4

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 (441) hide show
  1. package/LICENSE +21 -0
  2. package/NOTICE.md +60 -0
  3. package/PRIVACY.md +46 -0
  4. package/README.md +311 -0
  5. package/SECURITY.md +21 -0
  6. package/apps/desktop/README.md +966 -0
  7. package/apps/desktop/analysis/protocol.ts +223 -0
  8. package/apps/desktop/application/capability-binding.ts +594 -0
  9. package/apps/desktop/application/context.ts +97 -0
  10. package/apps/desktop/application/creative-iteration.ts +1385 -0
  11. package/apps/desktop/application/default-registry.ts +146 -0
  12. package/apps/desktop/application/directing-contract.ts +218 -0
  13. package/apps/desktop/application/directing-plan.ts +178 -0
  14. package/apps/desktop/application/errors.ts +18 -0
  15. package/apps/desktop/application/gateway-port.ts +867 -0
  16. package/apps/desktop/application/html-overlay-browser-runtime.ts +687 -0
  17. package/apps/desktop/application/html-overlay-integrity.ts +337 -0
  18. package/apps/desktop/application/html-overlay-renderer.ts +45 -0
  19. package/apps/desktop/application/index.ts +13 -0
  20. package/apps/desktop/application/operation-completion-checkpoint.ts +333 -0
  21. package/apps/desktop/application/operation-effects.ts +94 -0
  22. package/apps/desktop/application/operation.ts +224 -0
  23. package/apps/desktop/application/operations/analysis/faces.ts +244 -0
  24. package/apps/desktop/application/operations/analysis/music.ts +248 -0
  25. package/apps/desktop/application/operations/analysis/project-auto-zooms.ts +302 -0
  26. package/apps/desktop/application/operations/analysis/project-inactivity.ts +381 -0
  27. package/apps/desktop/application/operations/analysis/scenes.ts +272 -0
  28. package/apps/desktop/application/operations/analysis/shared.ts +202 -0
  29. package/apps/desktop/application/operations/derive/edit-batch.ts +967 -0
  30. package/apps/desktop/application/operations/derive/follow-faces.ts +454 -0
  31. package/apps/desktop/application/operations/edit/bind-candidate-revision.ts +91 -0
  32. package/apps/desktop/application/operations/edit/create-candidate-revision.ts +377 -0
  33. package/apps/desktop/application/operations/edit/create-revision.ts +255 -0
  34. package/apps/desktop/application/operations/edit/freeze-revision.ts +182 -0
  35. package/apps/desktop/application/operations/gateway/image.ts +41 -0
  36. package/apps/desktop/application/operations/gateway/index.ts +17 -0
  37. package/apps/desktop/application/operations/gateway/shared.ts +122 -0
  38. package/apps/desktop/application/operations/gateway/speech.ts +41 -0
  39. package/apps/desktop/application/operations/gateway/transcription.ts +42 -0
  40. package/apps/desktop/application/operations/gateway/video.ts +41 -0
  41. package/apps/desktop/application/operations/index.ts +31 -0
  42. package/apps/desktop/application/operations/iteration/create-candidate.ts +240 -0
  43. package/apps/desktop/application/operations/iteration/create-matrix.ts +117 -0
  44. package/apps/desktop/application/operations/iteration/select.ts +155 -0
  45. package/apps/desktop/application/operations/iteration/shared.ts +250 -0
  46. package/apps/desktop/application/operations/media/audio-effects.ts +376 -0
  47. package/apps/desktop/application/operations/media/binding.ts +79 -0
  48. package/apps/desktop/application/operations/media/capabilities.ts +112 -0
  49. package/apps/desktop/application/operations/media/color-grade.ts +343 -0
  50. package/apps/desktop/application/operations/media/html-overlay.ts +802 -0
  51. package/apps/desktop/application/operations/media/index.ts +8 -0
  52. package/apps/desktop/application/operations/media/ingest.ts +303 -0
  53. package/apps/desktop/application/operations/media/overlay.ts +729 -0
  54. package/apps/desktop/application/operations/media/shared.ts +845 -0
  55. package/apps/desktop/application/operations/media/transform-platform.ts +120 -0
  56. package/apps/desktop/application/operations/project/commit-edits.ts +2054 -0
  57. package/apps/desktop/application/operations/project/promote-selection.ts +495 -0
  58. package/apps/desktop/application/operations/project/snapshot.ts +95 -0
  59. package/apps/desktop/application/operations/recording/index.ts +5 -0
  60. package/apps/desktop/application/operations/recording/pause.ts +34 -0
  61. package/apps/desktop/application/operations/recording/resume.ts +34 -0
  62. package/apps/desktop/application/operations/recording/shared.ts +199 -0
  63. package/apps/desktop/application/operations/recording/start.ts +169 -0
  64. package/apps/desktop/application/operations/recording/stop.ts +34 -0
  65. package/apps/desktop/application/operations/render/bind-candidate-output.ts +324 -0
  66. package/apps/desktop/application/operations/render/materialize-selection.ts +322 -0
  67. package/apps/desktop/application/operations/render/project-caption-plan.ts +287 -0
  68. package/apps/desktop/application/operations/render/project-plan.ts +939 -0
  69. package/apps/desktop/application/operations/render/project-spatial-receipt.ts +70 -0
  70. package/apps/desktop/application/operations/render/project.ts +1922 -0
  71. package/apps/desktop/application/operations/shared.ts +67 -0
  72. package/apps/desktop/application/operations/slopcamera-portable.ts +1188 -0
  73. package/apps/desktop/application/operations/slopcamera-visuals.ts +784 -0
  74. package/apps/desktop/application/operations/spatial-project.ts +209 -0
  75. package/apps/desktop/application/operations/spatial-render.ts +415 -0
  76. package/apps/desktop/application/operations/spatial-scene.ts +97 -0
  77. package/apps/desktop/application/operations/studio.ts +143 -0
  78. package/apps/desktop/application/output-publication-lease.ts +163 -0
  79. package/apps/desktop/application/project-publication-lease.ts +233 -0
  80. package/apps/desktop/application/project-store.ts +196 -0
  81. package/apps/desktop/application/receipts.ts +533 -0
  82. package/apps/desktop/application/registry.ts +182 -0
  83. package/apps/desktop/application/spatial-assets.ts +675 -0
  84. package/apps/desktop/application/spatial-compositor-cadence.ts +23 -0
  85. package/apps/desktop/application/spatial-project-authority.ts +35 -0
  86. package/apps/desktop/application/spatial-project-lease.ts +126 -0
  87. package/apps/desktop/application/spatial-project-render-preparation.ts +225 -0
  88. package/apps/desktop/application/spatial-project-store.ts +286 -0
  89. package/apps/desktop/application/spatial-render-projection.ts +201 -0
  90. package/apps/desktop/application/spatial-render.ts +677 -0
  91. package/apps/desktop/application/spatial-spz.ts +44 -0
  92. package/apps/desktop/application/spatial-world-import.ts +135 -0
  93. package/apps/desktop/application/spatial-world-provenance.ts +46 -0
  94. package/apps/desktop/application/studio-port.ts +58 -0
  95. package/apps/desktop/application/verified-receipt-reconciliation.ts +1574 -0
  96. package/apps/desktop/capture/protocol.ts +689 -0
  97. package/apps/desktop/cli/analyzer.ts +406 -0
  98. package/apps/desktop/cli/args.ts +3181 -0
  99. package/apps/desktop/cli/asset-ingest.ts +747 -0
  100. package/apps/desktop/cli/atomic-render-effects.ts +210 -0
  101. package/apps/desktop/cli/atomic-render-platform.ts +205 -0
  102. package/apps/desktop/cli/atomic-render.ts +50 -0
  103. package/apps/desktop/cli/audio-analysis.ts +252 -0
  104. package/apps/desktop/cli/bounded-map.ts +39 -0
  105. package/apps/desktop/cli/bundle-service.ts +256 -0
  106. package/apps/desktop/cli/capabilities.ts +212 -0
  107. package/apps/desktop/cli/capture-bundle.ts +1117 -0
  108. package/apps/desktop/cli/command-host-resources.ts +251 -0
  109. package/apps/desktop/cli/commands.ts +6836 -0
  110. package/apps/desktop/cli/directing-blob.ts +291 -0
  111. package/apps/desktop/cli/directing-media.ts +517 -0
  112. package/apps/desktop/cli/directing-quote.ts +89 -0
  113. package/apps/desktop/cli/directing-service.ts +288 -0
  114. package/apps/desktop/cli/emoji-assets.ts +538 -0
  115. package/apps/desktop/cli/errors.ts +29 -0
  116. package/apps/desktop/cli/face-analysis-service.ts +940 -0
  117. package/apps/desktop/cli/filter-script.ts +76 -0
  118. package/apps/desktop/cli/gateway-application-port.ts +1142 -0
  119. package/apps/desktop/cli/gateway-credential.ts +81 -0
  120. package/apps/desktop/cli/gateway-media-artifacts.ts +723 -0
  121. package/apps/desktop/cli/gateway-media-catalog.ts +922 -0
  122. package/apps/desktop/cli/gateway-media-service.ts +3106 -0
  123. package/apps/desktop/cli/gateway-media-signature.ts +122 -0
  124. package/apps/desktop/cli/gateway-provider-options.ts +562 -0
  125. package/apps/desktop/cli/gateway-scene-provider.ts +391 -0
  126. package/apps/desktop/cli/help.ts +501 -0
  127. package/apps/desktop/cli/html-overlay-gpu.ts +97 -0
  128. package/apps/desktop/cli/html-overlay-renderer.ts +2478 -0
  129. package/apps/desktop/cli/io.ts +290 -0
  130. package/apps/desktop/cli/main.ts +123 -0
  131. package/apps/desktop/cli/media-effects-service.ts +885 -0
  132. package/apps/desktop/cli/media-ingest-model.ts +364 -0
  133. package/apps/desktop/cli/media-ingest-platform.ts +227 -0
  134. package/apps/desktop/cli/media-ingest-program.ts +200 -0
  135. package/apps/desktop/cli/media-ingest.ts +30 -0
  136. package/apps/desktop/cli/music-analysis-service.ts +434 -0
  137. package/apps/desktop/cli/mutation-lock.ts +530 -0
  138. package/apps/desktop/cli/native-assets.d.ts +12 -0
  139. package/apps/desktop/cli/native-media-runtime.macos.ts +7 -0
  140. package/apps/desktop/cli/overlay-playback.ts +177 -0
  141. package/apps/desktop/cli/paths.ts +265 -0
  142. package/apps/desktop/cli/portable-surface.ts +242 -0
  143. package/apps/desktop/cli/project-camera-receipt.ts +112 -0
  144. package/apps/desktop/cli/project-face-camera.ts +394 -0
  145. package/apps/desktop/cli/project-inactivity-service.ts +552 -0
  146. package/apps/desktop/cli/project-media-integrity.ts +121 -0
  147. package/apps/desktop/cli/project-renderer.ts +1526 -0
  148. package/apps/desktop/cli/project-service.ts +519 -0
  149. package/apps/desktop/cli/project-state-transaction.ts +520 -0
  150. package/apps/desktop/cli/query-limits.ts +1 -0
  151. package/apps/desktop/cli/recording-controller.ts +1567 -0
  152. package/apps/desktop/cli/recording-daemon.ts +931 -0
  153. package/apps/desktop/cli/recording-ref.ts +56 -0
  154. package/apps/desktop/cli/renamed-environment.ts +6 -0
  155. package/apps/desktop/cli/renderer.ts +1439 -0
  156. package/apps/desktop/cli/run-cli-test-helper.ts +60 -0
  157. package/apps/desktop/cli/scene-analysis-service.ts +879 -0
  158. package/apps/desktop/cli/spatial-compositor-verifier.ts +213 -0
  159. package/apps/desktop/cli/spatial-project-service.ts +90 -0
  160. package/apps/desktop/cli/spatial-scene-service.ts +105 -0
  161. package/apps/desktop/cli/spatial-world-service.ts +39 -0
  162. package/apps/desktop/cli/speech-analysis-service.ts +682 -0
  163. package/apps/desktop/cli/studio-assemble.ts +58 -0
  164. package/apps/desktop/cli/studio-command.ts +60 -0
  165. package/apps/desktop/cli/studio-custody.ts +60 -0
  166. package/apps/desktop/cli/studio-encode.ts +216 -0
  167. package/apps/desktop/cli/studio-exr.ts +52 -0
  168. package/apps/desktop/cli/studio-files.ts +179 -0
  169. package/apps/desktop/cli/studio-output-validation.ts +162 -0
  170. package/apps/desktop/cli/studio-process.ts +145 -0
  171. package/apps/desktop/cli/studio-runtime.ts +77 -0
  172. package/apps/desktop/cli/studio-scaffold.ts +70 -0
  173. package/apps/desktop/cli/studio-service.ts +301 -0
  174. package/apps/desktop/cli/studio-spatial-asset.ts +248 -0
  175. package/apps/desktop/cli/studio-template-names.ts +3 -0
  176. package/apps/desktop/cli/studio-workflow.ts +19 -0
  177. package/apps/desktop/cli/time.ts +25 -0
  178. package/apps/desktop/cli/workflow-code.ts +584 -0
  179. package/apps/desktop/cli/workflow-runs.ts +576 -0
  180. package/apps/desktop/code/advanced.ts +139 -0
  181. package/apps/desktop/code/application-node-planner.ts +1288 -0
  182. package/apps/desktop/code/compiler.ts +329 -0
  183. package/apps/desktop/code/contracts.ts +13 -0
  184. package/apps/desktop/code/creative-recipes.ts +94 -0
  185. package/apps/desktop/code/define-workflow.ts +115 -0
  186. package/apps/desktop/code/editing.ts +284 -0
  187. package/apps/desktop/code/file-candidate-provenance.ts +420 -0
  188. package/apps/desktop/code/file-candidate.ts +69 -0
  189. package/apps/desktop/code/graph-builder.ts +10 -0
  190. package/apps/desktop/code/host-resource-policy.ts +55 -0
  191. package/apps/desktop/code/plan-contracts.ts +159 -0
  192. package/apps/desktop/code/planning.ts +361 -0
  193. package/apps/desktop/code/public.ts +134 -0
  194. package/apps/desktop/code/reference-projection.ts +62 -0
  195. package/apps/desktop/code/run-contracts.ts +466 -0
  196. package/apps/desktop/code/run-store.ts +2478 -0
  197. package/apps/desktop/code/runtime-identity.ts +328 -0
  198. package/apps/desktop/code/scheduler.ts +3067 -0
  199. package/apps/desktop/code/semantic-builder.ts +1436 -0
  200. package/apps/desktop/code/source-bundle.ts +1641 -0
  201. package/apps/desktop/code/source-typecheck.ts +211 -0
  202. package/apps/desktop/code/testing.ts +79 -0
  203. package/apps/desktop/code/worker-client.ts +1675 -0
  204. package/apps/desktop/code/worker-effects.ts +141 -0
  205. package/apps/desktop/code/worker-entry.ts +435 -0
  206. package/apps/desktop/code/worker-lease-guardian.ts +179 -0
  207. package/apps/desktop/code/worker-process-identity.ts +484 -0
  208. package/apps/desktop/code/worker-protocol.ts +211 -0
  209. package/apps/desktop/code/workflow-effects.ts +132 -0
  210. package/apps/desktop/contracts/analysis.ts +949 -0
  211. package/apps/desktop/contracts/edit.ts +576 -0
  212. package/apps/desktop/contracts/index.ts +9 -0
  213. package/apps/desktop/contracts/media-effects.ts +139 -0
  214. package/apps/desktop/contracts/project-render.ts +644 -0
  215. package/apps/desktop/contracts/project.ts +740 -0
  216. package/apps/desktop/contracts/recording.ts +1434 -0
  217. package/apps/desktop/contracts/render.ts +334 -0
  218. package/apps/desktop/contracts/runtime.ts +155 -0
  219. package/apps/desktop/contracts/spatial-compositor.ts +58 -0
  220. package/apps/desktop/contracts/spatial-project.ts +159 -0
  221. package/apps/desktop/contracts/spatial-world.ts +48 -0
  222. package/apps/desktop/contracts/video-effects.ts +120 -0
  223. package/apps/desktop/core/alignment-apply.ts +400 -0
  224. package/apps/desktop/core/audio-alignment.ts +466 -0
  225. package/apps/desktop/core/auto-zoom.ts +209 -0
  226. package/apps/desktop/core/canonical-json.ts +14 -0
  227. package/apps/desktop/core/emoji.ts +210 -0
  228. package/apps/desktop/core/events.ts +409 -0
  229. package/apps/desktop/core/face-framing.ts +533 -0
  230. package/apps/desktop/core/face-tracks.ts +326 -0
  231. package/apps/desktop/core/inactivity.ts +137 -0
  232. package/apps/desktop/core/index.ts +30 -0
  233. package/apps/desktop/core/intervals.ts +123 -0
  234. package/apps/desktop/core/montage.ts +236 -0
  235. package/apps/desktop/core/music-analysis.ts +518 -0
  236. package/apps/desktop/core/plan.ts +244 -0
  237. package/apps/desktop/core/project-auto-zoom.ts +75 -0
  238. package/apps/desktop/core/project-camera-spatial.ts +676 -0
  239. package/apps/desktop/core/project-camera.ts +403 -0
  240. package/apps/desktop/core/project-captions.ts +888 -0
  241. package/apps/desktop/core/project-inactivity.ts +125 -0
  242. package/apps/desktop/core/project-metadata.ts +927 -0
  243. package/apps/desktop/core/project-plan.ts +375 -0
  244. package/apps/desktop/core/project-render-plan.ts +303 -0
  245. package/apps/desktop/core/project-time.ts +469 -0
  246. package/apps/desktop/core/render-plan.ts +442 -0
  247. package/apps/desktop/core/scene-cache.ts +174 -0
  248. package/apps/desktop/core/scene-sampling.ts +448 -0
  249. package/apps/desktop/core/spatial-compositor.ts +22 -0
  250. package/apps/desktop/core/spatial-durability.ts +99 -0
  251. package/apps/desktop/core/spatial-project.ts +169 -0
  252. package/apps/desktop/core/spatial-shot-clock.ts +32 -0
  253. package/apps/desktop/core/speech-analysis.ts +333 -0
  254. package/apps/desktop/core/storage.ts +970 -0
  255. package/apps/desktop/core/time-map.ts +91 -0
  256. package/apps/desktop/core/time.ts +61 -0
  257. package/apps/desktop/core/video-effects.ts +660 -0
  258. package/apps/desktop/dist/cli/NebulaSans-Bold-26se8aek.otf +0 -0
  259. package/apps/desktop/dist/cli/NebulaSans-Bold-bcz7y08t.woff2 +0 -0
  260. package/apps/desktop/dist/cli/NebulaSans-Book-5ax05zvn.woff2 +0 -0
  261. package/apps/desktop/dist/cli/NebulaSans-Book-8cenzchw.otf +0 -0
  262. package/apps/desktop/dist/cli/main.js +5086 -0
  263. package/apps/desktop/html-overlay/catalog.ts +171 -0
  264. package/apps/desktop/html-overlay/contracts.ts +372 -0
  265. package/apps/desktop/html-overlay/execution-profile.ts +77 -0
  266. package/apps/desktop/html-overlay/index.ts +98 -0
  267. package/apps/desktop/html-overlay/libraries.ts +263 -0
  268. package/apps/desktop/html-overlay/random.ts +49 -0
  269. package/apps/desktop/html-overlay/runtime.ts +813 -0
  270. package/apps/desktop/html-overlay/scaffolds.ts +792 -0
  271. package/apps/desktop/html-overlay/spark-runtime.ts +88 -0
  272. package/apps/desktop/html-overlay/spatial-splat-runtime.ts +60 -0
  273. package/apps/desktop/html-overlay/spatial.ts +720 -0
  274. package/apps/desktop/studio/assets/README.md +39 -0
  275. package/apps/desktop/studio/assets/contracts.ts +129 -0
  276. package/apps/desktop/studio/assets/network.ts +64 -0
  277. package/apps/desktop/studio/assets/poly-haven.ts +148 -0
  278. package/apps/desktop/studio/drivers/blender_driver.py +466 -0
  279. package/apps/desktop/studio/drivers/cadquery_driver.py +176 -0
  280. package/apps/desktop/studio/education/driver.py +308 -0
  281. package/apps/desktop/studio/education/lesson.py +180 -0
  282. package/apps/desktop/studio/education/toolkit.py +249 -0
  283. package/apps/desktop/workflows/chaptered-demo.ts +48 -0
  284. package/apps/desktop/workflows/creative-iteration.ts +107 -0
  285. package/apps/desktop/workflows/creative-selection.ts +92 -0
  286. package/apps/desktop/workflows/fragments.ts +486 -0
  287. package/apps/desktop/workflows/index.ts +93 -0
  288. package/apps/desktop/workflows/polished-screen-demo.ts +128 -0
  289. package/apps/desktop/workflows/scene-direction.ts +12 -0
  290. package/apps/desktop/workflows/social-variants.ts +75 -0
  291. package/apps/desktop/workflows/talking-head-cleanup.ts +53 -0
  292. package/dist/NebulaSans-Bold-26se8aek.otf +0 -0
  293. package/dist/NebulaSans-Bold-bcz7y08t.woff2 +0 -0
  294. package/dist/NebulaSans-Book-5ax05zvn.woff2 +0 -0
  295. package/dist/NebulaSans-Book-8cenzchw.otf +0 -0
  296. package/dist/cli.js +479 -0
  297. package/dist/code/advanced.js +270 -0
  298. package/dist/code/index.js +2240 -0
  299. package/dist/generate.js +24 -0
  300. package/dist/host-resources.js +26 -0
  301. package/dist/index-42zsesc1.js +2257 -0
  302. package/dist/index-7308egqr.js +48 -0
  303. package/dist/index-8txs6fkn.js +712 -0
  304. package/dist/index-mcy8z0br.js +192 -0
  305. package/dist/index-p63wavx0.js +2029 -0
  306. package/dist/index-r7gdhmsp.js +424 -0
  307. package/dist/index-sh6xbav6.js +1219 -0
  308. package/dist/index-z1w83f81.js +4 -0
  309. package/dist/index-z7239b4h.js +2363 -0
  310. package/dist/index-zfeg9hmw.js +2013 -0
  311. package/dist/index.js +241 -0
  312. package/dist/operations.js +29 -0
  313. package/dist/skill-install-dh0ntqba.js +10 -0
  314. package/dist/vectorize/worker.js +142 -0
  315. package/dist/workflow.js +16 -0
  316. package/docs/README.md +38 -0
  317. package/docs/studio.md +215 -0
  318. package/examples/studio/blender/README.md +26 -0
  319. package/examples/studio/blender/character.py +152 -0
  320. package/examples/studio/blender/cloth.py +101 -0
  321. package/examples/studio/blender/color_chart.py +29 -0
  322. package/examples/studio/blender/fluid.py +78 -0
  323. package/examples/studio/blender/import_model.py +74 -0
  324. package/examples/studio/blender/product.py +53 -0
  325. package/examples/studio/blender/shaded_street.py +481 -0
  326. package/examples/studio/blender/studio_scene.py +147 -0
  327. package/examples/studio/cadquery/README.md +13 -0
  328. package/examples/studio/cadquery/bracket.py +36 -0
  329. package/examples/studio/cadquery/import_step.py +12 -0
  330. package/examples/studio/education/README.md +46 -0
  331. package/examples/studio/education/lesson.json +99 -0
  332. package/examples/studio/education/scene.py +7 -0
  333. package/examples/studio/hybrid-scene.ts +96 -0
  334. package/examples/studio/native-workflow.ts +14 -0
  335. package/examples/studio/vgpu/README.md +64 -0
  336. package/examples/studio/vgpu/heat-field.mjs +290 -0
  337. package/package.json +304 -0
  338. package/packages/scene/src/index.ts +1 -0
  339. package/packages/scene/src/scene.ts +215 -0
  340. package/schema/diagram.schema.json +334 -0
  341. package/skills/slopcamera/SKILL.md +45 -0
  342. package/skills/slopcamera/agents/openai.yaml +4 -0
  343. package/skills/slopcamera/references/customization.md +77 -0
  344. package/skills/slopcamera/references/diagrams.md +153 -0
  345. package/skills/slopcamera/references/directed-scenes.md +42 -0
  346. package/skills/slopcamera/references/directing-video.md +18 -0
  347. package/skills/slopcamera/references/educational-video.md +26 -0
  348. package/skills/slopcamera/references/gateway-media.md +134 -0
  349. package/skills/slopcamera/references/install.md +62 -0
  350. package/skills/slopcamera/references/native-studio.md +31 -0
  351. package/skills/slopcamera/references/reference-led-3d.md +140 -0
  352. package/skills/slopcamera/references/rubber-stamp-examples/poster-example-1.jpg +0 -0
  353. package/skills/slopcamera/references/rubber-stamp-examples/poster-example-2.jpg +0 -0
  354. package/skills/slopcamera/references/rubber-stamp-examples/stamp-style-1.png +0 -0
  355. package/skills/slopcamera/references/rubber-stamp-examples/stamp-style-2.png +0 -0
  356. package/skills/slopcamera/references/rubber-stamp-field-notes.md +144 -0
  357. package/skills/slopcamera/references/vectorization.md +29 -0
  358. package/skills/slopcamera/references/video-projects.md +187 -0
  359. package/skills/slopcamera/references/visual-communication.md +120 -0
  360. package/skills/slopcamera/references/workflows-sdk.md +45 -0
  361. package/skills/slopcamera/scripts/compose-rubber-stamp-field-note.ts +229 -0
  362. package/src/artifacts.ts +106 -0
  363. package/src/assets/fonts/nebula-sans/LICENSE.txt +96 -0
  364. package/src/assets/fonts/nebula-sans/NebulaSans-Bold.otf +0 -0
  365. package/src/assets/fonts/nebula-sans/NebulaSans-Bold.woff2 +0 -0
  366. package/src/assets/fonts/nebula-sans/NebulaSans-Book.otf +0 -0
  367. package/src/assets/fonts/nebula-sans/NebulaSans-Book.woff2 +0 -0
  368. package/src/assets/fonts/nebula-sans/PROVENANCE.md +21 -0
  369. package/src/assets.d.ts +9 -0
  370. package/src/cli.ts +601 -0
  371. package/src/cloud-errors.ts +26 -0
  372. package/src/code/advanced.ts +10 -0
  373. package/src/code/boundary.ts +21 -0
  374. package/src/code/canonical-json.ts +129 -0
  375. package/src/code/compiler.ts +953 -0
  376. package/src/code/contracts.ts +576 -0
  377. package/src/code/define-workflow.ts +334 -0
  378. package/src/code/errors.ts +41 -0
  379. package/src/code/graph-builder.ts +945 -0
  380. package/src/code/index.ts +121 -0
  381. package/src/code/json-snapshot.ts +899 -0
  382. package/src/code/json-utf8.ts +88 -0
  383. package/src/code/portable-builder.ts +136 -0
  384. package/src/code/projection.ts +378 -0
  385. package/src/code/public-operations.ts +450 -0
  386. package/src/code/runtime.ts +580 -0
  387. package/src/code/sha256.ts +36 -0
  388. package/src/config.ts +180 -0
  389. package/src/desktop.ts +253 -0
  390. package/src/fs.ts +10 -0
  391. package/src/generate.ts +704 -0
  392. package/src/host-resource-posix.ts +161 -0
  393. package/src/host-resources.ts +1749 -0
  394. package/src/icons.ts +58 -0
  395. package/src/index.ts +200 -0
  396. package/src/label-layout.ts +130 -0
  397. package/src/layout.ts +413 -0
  398. package/src/lint.ts +127 -0
  399. package/src/mcp/boundary.ts +354 -0
  400. package/src/mcp/index.ts +33 -0
  401. package/src/mcp/server.ts +272 -0
  402. package/src/mcp/tools.ts +963 -0
  403. package/src/mcp/types.ts +71 -0
  404. package/src/operations.ts +775 -0
  405. package/src/parse.ts +861 -0
  406. package/src/process-environment.ts +17 -0
  407. package/src/render.ts +437 -0
  408. package/src/skill-install.ts +49 -0
  409. package/src/spatial-scene/authoring.ts +27 -0
  410. package/src/spatial-scene/camera-track.ts +83 -0
  411. package/src/spatial-scene/contracts.ts +277 -0
  412. package/src/spatial-scene/evaluate.ts +145 -0
  413. package/src/spatial-scene/gltf.ts +558 -0
  414. package/src/spatial-scene/identity.ts +260 -0
  415. package/src/spatial-scene/index.ts +10 -0
  416. package/src/spatial-scene/inspect.ts +68 -0
  417. package/src/spatial-scene/math.ts +280 -0
  418. package/src/spatial-scene/patch.ts +131 -0
  419. package/src/spatial-scene/time.ts +53 -0
  420. package/src/studio/contracts.ts +129 -0
  421. package/src/studio/index.ts +2 -0
  422. package/src/studio/plan.ts +156 -0
  423. package/src/studio/shared.ts +41 -0
  424. package/src/theme.ts +68 -0
  425. package/src/tldr.ts +474 -0
  426. package/src/types.ts +212 -0
  427. package/src/vectorize/archive.ts +101 -0
  428. package/src/vectorize/command.ts +797 -0
  429. package/src/vectorize/index.ts +27 -0
  430. package/src/vectorize/limits.ts +61 -0
  431. package/src/vectorize/metrics.ts +351 -0
  432. package/src/vectorize/pixels.ts +323 -0
  433. package/src/vectorize/supervisor.ts +339 -0
  434. package/src/vectorize/svg.ts +188 -0
  435. package/src/vectorize/tool.ts +542 -0
  436. package/src/vectorize/types.ts +113 -0
  437. package/src/vectorize/vectorize.ts +634 -0
  438. package/src/vectorize/worker-protocol.ts +40 -0
  439. package/src/vectorize/worker.ts +209 -0
  440. package/src/version.ts +1 -0
  441. package/src/workflow.ts +409 -0
@@ -0,0 +1,286 @@
1
+ import {
2
+ SPATIAL_PROJECT_LIMITS,
3
+ SpatialProjectAttemptV1Schema,
4
+ SpatialProjectArtifactSchema,
5
+ SpatialProjectBasisSchema,
6
+ SpatialProjectHeadV2Schema,
7
+ SpatialProjectRevisionV2Schema,
8
+ SpatialProjectSettlementV1Schema,
9
+ SpatialTransactionIdSchema,
10
+ type SpatialProjectArtifact,
11
+ type SpatialProjectBasis,
12
+ type SpatialProjectHeadV2,
13
+ type SpatialProjectRevisionV2,
14
+ type SpatialProjectSceneSource,
15
+ } from "../contracts/spatial-project";
16
+ import { ProjectEditPlanV1Schema, VideoProjectV1Schema } from "../contracts/project";
17
+ import { canonicalJson, sha256Hex } from "../core/canonical-json";
18
+ import type { SpatialDurabilityPort } from "../core/spatial-durability";
19
+ import {
20
+ spatialProjectArtifact,
21
+ spatialProjectContents,
22
+ spatialProjectDocumentText,
23
+ spatialProjectRevisionSha256,
24
+ validateSpatialProjectContents,
25
+ type SpatialProjectContents,
26
+ } from "../core/spatial-project";
27
+ import { saveImmutableText, type BundleFileSystem } from "../core/storage";
28
+ import { parseSpatialScene, spatialSceneSha256 } from "../../../src/spatial-scene/index";
29
+ import { hashProjectGeneration } from "./project-store";
30
+ import { createProjectEditRevisionDocument } from "./receipts";
31
+
32
+ /** Adapter-owned authority. Never constructed from operation input. */
33
+ export interface SpatialProjectCustody {
34
+ assertHeld(): Promise<void>;
35
+ assertLegacyTransactionSettled(): Promise<void>;
36
+ }
37
+ export interface SpatialProjectStorePorts {
38
+ /** Exact adapter-owned project identity, supplied by every production adapter. */
39
+ readonly projectId?: string;
40
+ readonly fileSystem: BundleFileSystem;
41
+ readonly durability: SpatialDurabilityPort;
42
+ readonly custody: SpatialProjectCustody;
43
+ }
44
+ export interface SpatialProjectSnapshot {
45
+ readonly version: 2;
46
+ readonly basis: SpatialProjectBasis;
47
+ readonly headText: string;
48
+ readonly head: SpatialProjectHeadV2;
49
+ readonly revision: SpatialProjectRevisionV2;
50
+ readonly contents: SpatialProjectContents;
51
+ }
52
+ export interface SpatialLegacyProjectSnapshot {
53
+ readonly version: 1;
54
+ readonly basis: SpatialProjectBasis;
55
+ readonly headText: string;
56
+ readonly contents: SpatialProjectContents;
57
+ }
58
+ export type SpatialProjectAuthority = SpatialProjectSnapshot | SpatialLegacyProjectSnapshot;
59
+ export type SpatialProjectCommitResult =
60
+ | { readonly kind: "completed"; readonly attempt: SpatialProjectArtifact; readonly settlement: SpatialProjectArtifact; readonly projectRevisionSha256: string; readonly currentHeadMatches: boolean }
61
+ | { readonly kind: "conflict" | "precommit"; readonly message: string; readonly attempt?: SpatialProjectArtifact }
62
+ | { readonly kind: "ambiguous"; readonly attempt: SpatialProjectArtifact; readonly message: string };
63
+
64
+ const messageOf = (error: unknown): string => error instanceof Error ? error.message : String(error);
65
+ const isMissing = (error: unknown): boolean => error instanceof Error && "code" in error && error.code === "ENOENT";
66
+ function assertNotCancelled(signal?: AbortSignal): void {
67
+ if (signal?.aborted === true) throw new Error("Spatial publication cancelled before head dispatch.");
68
+ }
69
+ async function readBoundedText(fs: BundleFileSystem, path: string, maximum = SPATIAL_PROJECT_LIMITS.documentBytes): Promise<string> {
70
+ if (fs.inspectFile !== undefined && (await fs.inspectFile(path, maximum)).bytes > maximum) throw new Error("Spatial structured byte budget exceeded.");
71
+ const text = await fs.readText(path, maximum);
72
+ if (new TextEncoder().encode(text).byteLength > maximum) throw new Error("Spatial structured byte budget exceeded.");
73
+ return text;
74
+ }
75
+ async function readArtifact(fs: BundleFileSystem, input: SpatialProjectArtifact): Promise<string> {
76
+ const ref = SpatialProjectArtifactSchema.parse(input);
77
+ const text = await readBoundedText(fs, ref.path, ref.bytes);
78
+ if (sha256Hex(text) !== ref.sha256 || new TextEncoder().encode(text).byteLength !== ref.bytes) throw new Error("Spatial artifact integrity mismatch.");
79
+ return text;
80
+ }
81
+ async function publish(ports: SpatialProjectStorePorts, reference: SpatialProjectArtifact, text: string): Promise<void> {
82
+ await ports.custody.assertHeld();
83
+ await saveImmutableText({
84
+ ...ports.fileSystem,
85
+ readText: path => ports.fileSystem.readText(path, reference.bytes),
86
+ }, reference.path, text, reference.sha256);
87
+ await ports.durability.syncExactFile(reference.path, reference);
88
+ if (await readArtifact(ports.fileSystem, reference) !== text) throw new Error("Spatial immutable durability readback changed.");
89
+ }
90
+ async function verifyPayloads(fs: BundleFileSystem, contents: SpatialProjectContents, durability?: SpatialDurabilityPort): Promise<void> {
91
+ const payloads = new Map<string, { readonly path: string; readonly bytes: number; readonly sha256: string }>();
92
+ let sourceBytes = 0;
93
+ let outputBytes = 0;
94
+ const add = (payload: { readonly path: string; readonly bytes: number; readonly sha256: string }, kind: "source" | "output"): void => {
95
+ const prior = payloads.get(payload.path);
96
+ if (prior !== undefined) {
97
+ if (prior.bytes !== payload.bytes || prior.sha256 !== payload.sha256) throw new Error("Conflicting physical payload identity.");
98
+ return;
99
+ }
100
+ payloads.set(payload.path, payload);
101
+ if (kind === "source") sourceBytes += payload.bytes;
102
+ else outputBytes += payload.bytes;
103
+ };
104
+ for (const scene of contents.scenes) for (const asset of scene.document.assets) add(asset.payload, "source");
105
+ for (const candidate of contents.candidates) for (const output of candidate.outputs) add(output, "output");
106
+ if (sourceBytes > 256 * 1024 * 1024 || outputBytes > 1_024 * 1024 * 1024) throw new Error("Spatial project payload budget exceeded.");
107
+ if (payloads.size > 0 && fs.inspectFile === undefined) throw new Error("Physical payload inspection is required for spatial source and candidate publication.");
108
+ for (const payload of payloads.values()) {
109
+ const actual = await fs.inspectFile?.(payload.path, payload.bytes);
110
+ if (actual === undefined || actual.bytes !== payload.bytes || actual.sha256 !== payload.sha256) throw new Error("Spatial physical payload integrity mismatch.");
111
+ await durability?.syncExactFile(payload.path, payload);
112
+ }
113
+ }
114
+ async function loadExactHead(fs: BundleFileSystem, head: SpatialProjectHeadV2, headText: string): Promise<SpatialProjectSnapshot> {
115
+ const revisionText = await readArtifact(fs, head.revision);
116
+ const revision = SpatialProjectRevisionV2Schema.parse(JSON.parse(revisionText));
117
+ if (revisionText !== spatialProjectDocumentText(revision)
118
+ || spatialProjectRevisionSha256(revision) !== head.projectRevisionSha256
119
+ || revision.projectId !== head.projectId || revision.transactionId !== head.transactionId) throw new Error("Spatial head and revision binding mismatch.");
120
+ // Reuse the unchanged V1 revision verifier, including its structural/hash laws.
121
+ createProjectEditRevisionDocument(revision.legacy.project, revision.legacy.projectEditPlan);
122
+ const scenes: SpatialProjectSceneSource[] = [];
123
+ for (const reference of revision.scenes) {
124
+ const text = await readArtifact(fs, reference.artifact);
125
+ const document = parseSpatialScene(JSON.parse(text));
126
+ if (text !== spatialProjectDocumentText(document) || spatialSceneSha256(document) !== reference.sceneSha256) throw new Error("Spatial source digest or canonical bytes mismatch.");
127
+ scenes.push({ sceneSha256: reference.sceneSha256, document: structuredClone(document) as SpatialProjectSceneSource["document"] });
128
+ }
129
+ const contents = spatialProjectContents(revision, scenes);
130
+ await verifyPayloads(fs, contents);
131
+ return { version: 2, basis: { version: 2, sha256: head.projectRevisionSha256 }, headText, head, revision, contents };
132
+ }
133
+ /** V2 reads consult only project.json and immutable references, never historical V1 pointers. */
134
+ export async function loadSpatialProject(fs: BundleFileSystem): Promise<SpatialProjectSnapshot> {
135
+ const text = await readBoundedText(fs, "project.json");
136
+ const head = SpatialProjectHeadV2Schema.parse(JSON.parse(text));
137
+ if (text !== spatialProjectDocumentText(head)) throw new Error("Noncanonical spatial head.");
138
+ return await loadExactHead(fs, head, text);
139
+ }
140
+ export async function readSpatialProjectAuthority(ports: SpatialProjectStorePorts): Promise<SpatialProjectAuthority> {
141
+ const text = await readBoundedText(ports.fileSystem, "project.json");
142
+ const value: unknown = JSON.parse(text);
143
+ const head = SpatialProjectHeadV2Schema.safeParse(value);
144
+ if (head.success) {
145
+ if (ports.projectId !== undefined && ports.projectId !== head.data.projectId) throw new Error("Spatial head belongs to another project.");
146
+ if (text !== spatialProjectDocumentText(head.data)) throw new Error("Noncanonical spatial head.");
147
+ return await loadExactHead(ports.fileSystem, head.data, text);
148
+ }
149
+ const project = VideoProjectV1Schema.parse(value);
150
+ if (ports.projectId !== undefined && ports.projectId !== project.projectId) throw new Error("Legacy head belongs to another project.");
151
+ await ports.custody.assertLegacyTransactionSettled();
152
+ // Match the existing V1 reader's authoritative pair exactly, including a
153
+ // nullable historical currentEditPlanPath field in the frozen project value.
154
+ const projectEditPlan = ProjectEditPlanV1Schema.parse(JSON.parse(await readBoundedText(ports.fileSystem, "edits/current.json")));
155
+ createProjectEditRevisionDocument(project, projectEditPlan);
156
+ return {
157
+ version: 1,
158
+ basis: { version: 1, sha256: hashProjectGeneration(project, projectEditPlan).generationSha256 },
159
+ headText: text,
160
+ contents: { legacy: { project, projectEditPlan }, scenes: [], shots: [], candidates: [], selections: [] },
161
+ };
162
+ }
163
+ export interface SpatialProjectCommitOptions {
164
+ readonly ports: SpatialProjectStorePorts;
165
+ readonly expected: SpatialProjectBasis;
166
+ readonly transactionId: string;
167
+ readonly change: (current: SpatialProjectAuthority) => SpatialProjectContents;
168
+ readonly signal?: AbortSignal;
169
+ }
170
+ /** Must run under the existing publication lease, which remains owned until settlement. */
171
+ export async function commitSpatialProjectRevision(options: SpatialProjectCommitOptions): Promise<SpatialProjectCommitResult> {
172
+ const { ports } = options;
173
+ let attempt: SpatialProjectArtifact | undefined;
174
+ let dispatched = false;
175
+ try {
176
+ await ports.custody.assertHeld();
177
+ assertNotCancelled(options.signal);
178
+ const expected = SpatialProjectBasisSchema.parse(options.expected);
179
+ const transactionId = SpatialTransactionIdSchema.parse(options.transactionId);
180
+ if (ports.fileSystem.writeTextAtomicGuarded === undefined) throw new Error("Spatial head publication requires the guarded atomic-replace capability.");
181
+ const current = await readSpatialProjectAuthority(ports);
182
+ if (canonicalJson(current.basis) !== canonicalJson(expected)) return { kind: "conflict", message: "Expected complete project revision is stale." };
183
+ const contents = validateSpatialProjectContents(options.change(current));
184
+ const scenes = contents.scenes.map(source => ({ sceneSha256: source.sceneSha256, artifact: spatialProjectArtifact("scenes", spatialProjectDocumentText(source.document)) }));
185
+ const revision = SpatialProjectRevisionV2Schema.parse({
186
+ kind: "slopcamera.spatial-project-revision", schemaVersion: 2, projectId: current.contents.legacy.project.projectId,
187
+ parent: expected, transactionId, legacy: contents.legacy, scenes, shots: contents.shots, candidates: contents.candidates, selections: contents.selections,
188
+ });
189
+ // All source dependencies are validated and made durable before publishing a head.
190
+ await verifyPayloads(ports.fileSystem, contents, ports.durability);
191
+ for (const source of contents.scenes) {
192
+ const text = spatialProjectDocumentText(source.document);
193
+ await publish(ports, spatialProjectArtifact("scenes", text), text);
194
+ }
195
+ const revisionText = spatialProjectDocumentText(revision);
196
+ const reference = spatialProjectArtifact("revisions", revisionText);
197
+ await publish(ports, reference, revisionText);
198
+ const after = SpatialProjectHeadV2Schema.parse({
199
+ kind: "slopcamera.spatial-project-head", schemaVersion: 2, projectId: revision.projectId,
200
+ projectRevisionSha256: spatialProjectRevisionSha256(revision), revision: reference, transactionId,
201
+ });
202
+ const attemptText = spatialProjectDocumentText(SpatialProjectAttemptV1Schema.parse({
203
+ kind: "slopcamera.spatial-project-attempt", schemaVersion: 1, beforeHeadSha256: sha256Hex(current.headText), expected, after,
204
+ }));
205
+ attempt = spatialProjectArtifact("attempts", attemptText);
206
+ await publish(ports, attempt, attemptText);
207
+ await ports.custody.assertHeld();
208
+ assertNotCancelled(options.signal);
209
+ const last = await readSpatialProjectAuthority(ports);
210
+ if (canonicalJson(last.basis) !== canonicalJson(expected) || last.headText !== current.headText) return { kind: "conflict", attempt, message: "Project changed before publication." };
211
+ const afterText = spatialProjectDocumentText(after);
212
+ // The final authority read is asynchronous. Its completion is not evidence
213
+ // that the lease or cancellation state survived that read.
214
+ await ports.custody.assertHeld();
215
+ assertNotCancelled(options.signal);
216
+ await ports.fileSystem.writeTextAtomicGuarded("project.json", afterText, async () => {
217
+ // The native adapter stages and flushes its temporary file before this
218
+ // fence, then starts rename immediately after it returns. A cancellation
219
+ // or lost lease during staging therefore cannot publish an authority.
220
+ await ports.custody.assertHeld();
221
+ assertNotCancelled(options.signal);
222
+ // Beyond this exact dispatch point a thrown write cannot prove noncommit.
223
+ dispatched = true;
224
+ });
225
+ await ports.durability.syncExactFile("project.json", { bytes: new TextEncoder().encode(afterText).byteLength, sha256: sha256Hex(afterText) });
226
+ if (await readBoundedText(ports.fileSystem, "project.json") !== afterText) throw new Error("Spatial head readback mismatch.");
227
+ await loadExactHead(ports.fileSystem, after, afterText);
228
+ const receiptText = settlementText(attempt, afterText);
229
+ const settlement = spatialProjectArtifact("receipts", receiptText);
230
+ await publish(ports, settlement, receiptText);
231
+ return { kind: "completed", attempt, settlement, projectRevisionSha256: after.projectRevisionSha256, currentHeadMatches: true };
232
+ } catch (error) {
233
+ if (dispatched && attempt !== undefined) return { kind: "ambiguous", attempt, message: messageOf(error) };
234
+ return { kind: "precommit", message: messageOf(error), ...(attempt === undefined ? {} : { attempt }) };
235
+ }
236
+ }
237
+ export async function migrateSpatialProject(options: Omit<SpatialProjectCommitOptions, "change"> & {
238
+ readonly scenes: readonly SpatialProjectSceneSource[];
239
+ readonly shots: SpatialProjectContents["shots"];
240
+ }): Promise<SpatialProjectCommitResult> {
241
+ return await commitSpatialProjectRevision({ ...options, change(current) {
242
+ if (current.version !== 1) throw new Error("Spatial migration requires an existing V1 authority.");
243
+ return { ...current.contents, scenes: options.scenes, shots: options.shots };
244
+ } });
245
+ }
246
+ function settlementText(attempt: SpatialProjectArtifact, headText: string): string {
247
+ return spatialProjectDocumentText(SpatialProjectSettlementV1Schema.parse({
248
+ kind: "slopcamera.spatial-project-settlement", schemaVersion: 1, attempt, headSha256: sha256Hex(headText),
249
+ }));
250
+ }
251
+ /** Reconciliation proves an exact commit; it never restores, overwrites, or replays a head. */
252
+ export async function reconcileSpatialProjectCommit(options: {
253
+ readonly ports: SpatialProjectStorePorts;
254
+ readonly attempt: SpatialProjectArtifact;
255
+ }): Promise<SpatialProjectCommitResult> {
256
+ const { ports } = options;
257
+ const reference = SpatialProjectArtifactSchema.parse(options.attempt);
258
+ try {
259
+ await ports.custody.assertHeld();
260
+ if (!reference.path.startsWith("spatial/attempts/")) throw new Error("Reconciliation requires an immutable attempt reference.");
261
+ const text = await readArtifact(ports.fileSystem, reference);
262
+ const attempt = SpatialProjectAttemptV1Schema.parse(JSON.parse(text));
263
+ if (ports.projectId !== undefined && ports.projectId !== attempt.after.projectId) throw new Error("Spatial attempt belongs to another project.");
264
+ if (text !== spatialProjectDocumentText(attempt)) throw new Error("Noncanonical spatial attempt.");
265
+ const headText = spatialProjectDocumentText(attempt.after);
266
+ const receiptText = settlementText(reference, headText);
267
+ const receipt = spatialProjectArtifact("receipts", receiptText);
268
+ const snapshot = await loadExactHead(ports.fileSystem, attempt.after, headText);
269
+ if (canonicalJson(snapshot.revision.parent) !== canonicalJson(attempt.expected)) throw new Error("Spatial attempt does not bind its revision parent.");
270
+ let provenReceipt = false;
271
+ try {
272
+ if (await readArtifact(ports.fileSystem, receipt) !== receiptText) throw new Error("Spatial settlement receipt mismatch.");
273
+ // Existing identical bytes may come from a failed link/fsync attempt.
274
+ await ports.durability.syncExactFile(receipt.path, receipt);
275
+ provenReceipt = true;
276
+ } catch (error) { if (!isMissing(error)) throw error; }
277
+ const matches = await readBoundedText(ports.fileSystem, "project.json") === headText;
278
+ if (!provenReceipt) {
279
+ if (!matches) throw new Error("No durable completion proof and current head differs; rollback and replay are forbidden.");
280
+ await ports.durability.syncExactFile("project.json", { bytes: new TextEncoder().encode(headText).byteLength, sha256: sha256Hex(headText) });
281
+ if (await readBoundedText(ports.fileSystem, "project.json") !== headText) throw new Error("Spatial head changed during reconciliation.");
282
+ await publish(ports, receipt, receiptText);
283
+ }
284
+ return { kind: "completed", attempt: reference, settlement: receipt, projectRevisionSha256: attempt.after.projectRevisionSha256, currentHeadMatches: matches };
285
+ } catch (error) { return { kind: "ambiguous", attempt: reference, message: messageOf(error) }; }
286
+ }
@@ -0,0 +1,201 @@
1
+ import { z } from "zod";
2
+ import { HtmlOverlayExecutionProfileSchema } from "../html-overlay/execution-profile";
3
+
4
+ import { createBoundedJsonValueSnapshot, deepFreezeJson } from "../../../src/code/json-snapshot";
5
+ import { reduceSpatialFrameRate, spatialFrameCount } from "../../../src/spatial-scene/index";
6
+ import { SpatialDigestSchema, SpatialFrameRateSchema, SpatialShotIdSchema, SpatialShotV1Schema } from "../../../src/spatial-scene/contracts";
7
+ import { ProjectEditPlanV1Schema, VideoProjectV1Schema } from "../contracts/project";
8
+ import { RepositoryRelativePathSchema } from "../contracts/recording";
9
+ import { SPATIAL_PROJECT_LIMITS, SpatialProjectBasisSchema, SpatialProjectHeadV2Schema, SpatialProjectRevisionV2Schema } from "../contracts/spatial-project";
10
+ import { canonicalJson, canonicalJsonSha256, sha256Hex } from "../core/canonical-json";
11
+ import { hashProjectStructure } from "../core/project-plan";
12
+ import { compileProjectRenderPlan } from "../core/project-render-plan";
13
+ import { SpatialProjectContentsSchema, spatialProjectArtifact, spatialProjectContents, spatialProjectDocumentText, spatialProjectRevisionSha256, spatialShotSha256 } from "../core/spatial-project";
14
+ import { projectEditRevisionPath } from "../core/storage";
15
+ import { createProjectEditRevisionDocument, ProjectEditRevisionArtifactSchema } from "./receipts";
16
+ import type { SpatialProjectSnapshot } from "./spatial-project-store";
17
+
18
+ export const SpatialSceneProgramPolicySchema = z.strictObject({
19
+ kind: z.literal("full-frame-above-legacy-video-below-overlays"),
20
+ alpha: z.enum(["opaque", "straight"]),
21
+ });
22
+ export const SpatialProjectionOutputSchema = z.strictObject({
23
+ executionProfile: HtmlOverlayExecutionProfileSchema.optional(),
24
+ pixelWidth: z.number().int().positive().max(16_384),
25
+ pixelHeight: z.number().int().positive().max(16_384),
26
+ frameRate: SpatialFrameRateSchema,
27
+ background: z.string().regex(/^#[a-fA-F0-9]{6}ff$/u),
28
+ /** Canvas transfer; final codec conversion is separately recorded by the encoder. */
29
+ colorSpace: z.literal("srgb"),
30
+ }).superRefine((output, context) => {
31
+ if (output.pixelWidth * output.pixelHeight > 33_554_432 || output.frameRate.numerator / output.frameRate.denominator > 240) context.addIssue({ code: "custom", message: "Projection exceeds the existing compositor dimensions or frame-rate limit." });
32
+ });
33
+ export const SpatialMaterializedShotVideoSchema = z.strictObject({
34
+ shotId: SpatialShotIdSchema,
35
+ shotSha256: SpatialDigestSchema,
36
+ sceneSha256: SpatialDigestSchema,
37
+ receiptSha256: SpatialDigestSchema,
38
+ artifact: z.strictObject({
39
+ path: RepositoryRelativePathSchema.refine(path => /^spatial\/outputs\/[a-f0-9]{64}\.(?:mov|mp4|webm)$/u.test(path)),
40
+ sha256: SpatialDigestSchema,
41
+ bytes: z.number().int().positive().max(256 * 1024 * 1024),
42
+ }).superRefine((artifact, context) => {
43
+ if (!artifact.path.startsWith(`spatial/outputs/${artifact.sha256}.`)) context.addIssue({ code: "custom", message: "Materialized shot path must name its exact payload digest." });
44
+ }),
45
+ pixelWidth: z.number().int().positive().max(16_384),
46
+ pixelHeight: z.number().int().positive().max(16_384),
47
+ frameRate: SpatialFrameRateSchema,
48
+ frameCount: z.number().int().positive().max(864_000),
49
+ alpha: z.enum(["opaque", "straight"]),
50
+ colorSpace: z.literal("srgb"),
51
+ codec: z.enum(["qtrle", "h264", "vp9", "prores"]),
52
+ container: z.enum(["mov", "mp4", "webm"]),
53
+ streamIndex: z.number().int().min(0).max(255),
54
+ }).superRefine((video, context) => {
55
+ if (!video.artifact.path.endsWith(`.${video.container}`)) context.addIssue({ code: "custom", message: "Materialized shot extension and container must match." });
56
+ if (((video.codec === "qtrle" || video.codec === "prores") && video.container !== "mov")
57
+ || (video.codec === "vp9" && video.container !== "webm")
58
+ || (video.codec === "h264" && video.container === "webm")) context.addIssue({ code: "custom", message: "Materialized codec and container are incompatible." });
59
+ if (video.alpha === "straight" && (video.container !== "mov" || video.codec !== "qtrle")) context.addIssue({ code: "custom", message: "The initial straight-alpha projection requires the qualified qtrle MOV profile." });
60
+ });
61
+ export const SceneRenderProjectionV1Schema = z.strictObject({
62
+ kind: z.literal("slopcamera.scene-render-projection"),
63
+ schemaVersion: z.literal(1),
64
+ source: SpatialProjectHeadV2Schema,
65
+ policy: SpatialSceneProgramPolicySchema,
66
+ output: SpatialProjectionOutputSchema,
67
+ shots: z.array(z.strictObject({ shot: SpatialShotV1Schema, materialized: SpatialMaterializedShotVideoSchema })).max(1_024),
68
+ legacyFrameRateAdapter: z.strictObject({
69
+ kind: z.literal("numeric-ratio-for-planning-only"),
70
+ value: z.number().positive().max(240),
71
+ requiredEncoderArgument: z.string().regex(/^[1-9][0-9]*\/[1-9][0-9]*$/u),
72
+ }),
73
+ derivedV1RevisionSha256: SpatialDigestSchema,
74
+ derivedV1Revision: ProjectEditRevisionArtifactSchema,
75
+ compositionPlanSha256: SpatialDigestSchema,
76
+ }).superRefine((projection, context) => {
77
+ const rate = reduceSpatialFrameRate(projection.output.frameRate);
78
+ if (canonicalJson(rate) !== canonicalJson(projection.output.frameRate)
79
+ || projection.legacyFrameRateAdapter.value !== rate.numerator / rate.denominator
80
+ || projection.legacyFrameRateAdapter.requiredEncoderArgument !== `${rate.numerator}/${rate.denominator}`) context.addIssue({ code: "custom", message: "Projection frame-rate identities must agree exactly." });
81
+ if (projection.derivedV1Revision.path !== projectEditRevisionPath(projection.derivedV1Revision.sha256)) context.addIssue({ code: "custom", message: "Derived V1 revision must use its immutable byte-digest path." });
82
+ const seen = new Set<string>();
83
+ let endUs = 0;
84
+ for (const { shot, materialized } of projection.shots) {
85
+ if (seen.has(shot.shotId) || shot.range.startUs < endUs) context.addIssue({ code: "custom", message: "Projection shots must be unique, ordered, and nonoverlapping." });
86
+ seen.add(shot.shotId);
87
+ endUs = shot.range.endUs;
88
+ if (materialized.shotId !== shot.shotId || materialized.shotSha256 !== spatialShotSha256(shot)
89
+ || materialized.sceneSha256 !== shot.sceneSha256 || materialized.alpha !== projection.policy.alpha
90
+ || materialized.pixelWidth !== projection.output.pixelWidth || materialized.pixelHeight !== projection.output.pixelHeight
91
+ || materialized.colorSpace !== projection.output.colorSpace
92
+ || canonicalJson(materialized.frameRate) !== canonicalJson(rate)
93
+ || materialized.frameCount !== spatialFrameCount(shot.range.endUs - shot.range.startUs, rate)) context.addIssue({ code: "custom", message: "Projection materialized shot does not match its exact authored shot and output profile." });
94
+ }
95
+ });
96
+ export type SpatialMaterializedShotVideo = z.infer<typeof SpatialMaterializedShotVideoSchema>;
97
+ export type SpatialProjectionOutput = z.infer<typeof SpatialProjectionOutputSchema>;
98
+ export type SpatialSceneProgramPolicy = z.infer<typeof SpatialSceneProgramPolicySchema>;
99
+ export type SceneRenderProjectionV1 = z.infer<typeof SceneRenderProjectionV1Schema>;
100
+ const ProjectionRequestSchema = z.strictObject({
101
+ snapshot: z.strictObject({
102
+ version: z.literal(2), basis: SpatialProjectBasisSchema,
103
+ headText: z.string().max(SPATIAL_PROJECT_LIMITS.documentBytes),
104
+ head: SpatialProjectHeadV2Schema, revision: SpatialProjectRevisionV2Schema,
105
+ contents: SpatialProjectContentsSchema,
106
+ }),
107
+ materializedShots: z.array(SpatialMaterializedShotVideoSchema).max(SPATIAL_PROJECT_LIMITS.shots),
108
+ policy: SpatialSceneProgramPolicySchema,
109
+ output: SpatialProjectionOutputSchema,
110
+ });
111
+
112
+ export function spatialProjectionEncoderFrameRate(rateInput: unknown): string {
113
+ const rate = reduceSpatialFrameRate(rateInput);
114
+ return `${rate.numerator}/${rate.denominator}`;
115
+ }
116
+
117
+ /**
118
+ * Pure lowering from verified V2 authority and already-materialized, receipt-bound
119
+ * source-clock shot videos. This function never reads a mutable project or starts
120
+ * a render. The caller verifies the supplied physical videos/receipts before use.
121
+ *
122
+ * New video placements enter the logical source clock before the V1 compositor
123
+ * applies global cuts and speed once. V1 overlays are intentionally preserved:
124
+ * appending a shot as an overlay would incorrectly use compressed output time.
125
+ */
126
+ export function createSpatialRenderProjection(input: {
127
+ readonly snapshot: SpatialProjectSnapshot;
128
+ readonly materializedShots: readonly SpatialMaterializedShotVideo[];
129
+ readonly policy: SpatialSceneProgramPolicy;
130
+ readonly output: SpatialProjectionOutput;
131
+ }) {
132
+ const request = ProjectionRequestSchema.parse(createBoundedJsonValueSnapshot(input, SPATIAL_PROJECT_LIMITS.totalSceneBytes + 2 * SPATIAL_PROJECT_LIMITS.documentBytes, "spatial projection input", { maximumDepth: 48, maximumValues: 2_000_000 }).value);
133
+ const head = request.snapshot.head;
134
+ const aggregate = request.snapshot.revision;
135
+ if (request.snapshot.version !== 2 || request.snapshot.basis.version !== 2
136
+ || request.snapshot.basis.sha256 !== head.projectRevisionSha256
137
+ || spatialProjectRevisionSha256(aggregate) !== head.projectRevisionSha256
138
+ || aggregate.projectId !== head.projectId || aggregate.transactionId !== head.transactionId
139
+ || canonicalJson(spatialProjectArtifact("revisions", spatialProjectDocumentText(aggregate))) !== canonicalJson(head.revision)) throw new Error("Render projection requires the exact verified V2 aggregate and head.");
140
+ const contents = spatialProjectContents(aggregate, request.snapshot.contents.scenes);
141
+ const references = contents.scenes.map(scene => ({ sceneSha256: scene.sceneSha256, artifact: spatialProjectArtifact("scenes", spatialProjectDocumentText(scene.document)) }));
142
+ if (canonicalJson(references) !== canonicalJson(aggregate.scenes)) throw new Error("Render projection scene sources do not match the immutable aggregate.");
143
+ const policy = SpatialSceneProgramPolicySchema.parse(request.policy);
144
+ const rawOutput = SpatialProjectionOutputSchema.parse(request.output);
145
+ const output = { ...rawOutput, frameRate: reduceSpatialFrameRate(rawOutput.frameRate) };
146
+ const videos = request.materializedShots.map(video => SpatialMaterializedShotVideoSchema.parse(video));
147
+ if (videos.length !== contents.shots.length || new Set(videos.map(video => video.shotId)).size !== videos.length) throw new Error("Projection requires exactly one materialized video per shot.");
148
+ const shots = [...contents.shots].sort((a, b) => a.range.startUs - b.range.startUs || a.shotId.localeCompare(b.shotId));
149
+ for (let index = 1; index < shots.length; index++) if (shots[index]!.range.startUs < shots[index - 1]!.range.endUs) throw new Error("Full-frame camera-program projection rejects overlapping shot ranges.");
150
+ const base = contents.legacy;
151
+ const layers = base.project.placements.flatMap(placement => placement.enabled ? placement.video.flatMap(video => video.presentation.enabled ? [video.presentation.layer] : []) : []);
152
+ const layer = Math.max(-1, ...layers) + 1;
153
+ if (!Number.isSafeInteger(layer)) throw new Error("No safe integer video layer remains above legacy video.");
154
+ const numericFrameRate = output.frameRate.numerator / output.frameRate.denominator;
155
+ const assets = [...base.project.assets];
156
+ const placements = [...base.project.placements];
157
+ const boundShots: z.infer<typeof SceneRenderProjectionV1Schema>["shots"] = [];
158
+ for (const shot of shots) {
159
+ const materialized = videos.find(video => video.shotId === shot.shotId);
160
+ if (materialized === undefined || materialized.shotSha256 !== spatialShotSha256(shot)
161
+ || materialized.sceneSha256 !== shot.sceneSha256) throw new Error("Materialized video does not bind the exact shot and source scene.");
162
+ const durationUs = shot.range.endUs - shot.range.startUs;
163
+ if (materialized.pixelWidth !== output.pixelWidth || materialized.pixelHeight !== output.pixelHeight
164
+ || materialized.alpha !== policy.alpha || materialized.colorSpace !== output.colorSpace
165
+ || canonicalJson(reduceSpatialFrameRate(materialized.frameRate)) !== canonicalJson(output.frameRate)
166
+ || materialized.frameCount !== spatialFrameCount(durationUs, output.frameRate)) throw new Error("Materialized shot does not match the exact source duration and render profile.");
167
+ const key = spatialShotSha256(shot).slice(0, 48);
168
+ const assetId = `asset_spatial_${key}`;
169
+ const placementId = `placement_spatial_${key}`;
170
+ const streamId = `stream_spatial_${key}`;
171
+ if (assets.some(asset => asset.assetId === assetId || asset.streams.some(stream => stream.streamId === streamId))
172
+ || placements.some(placement => placement.placementId === placementId)) throw new Error("Derived spatial identity collides with a retained media identity.");
173
+ assets.push(VideoProjectV1Schema.shape.assets.element.parse({
174
+ assetId, createdAt: base.project.updatedAt, durationUs, label: `Spatial shot ${shot.shotId}`, role: "b-roll",
175
+ source: { kind: "generated", generator: "slopcamera.spatial-render-projection", generatorVersion: "1", sourceSha256: materialized.shotSha256 },
176
+ streams: [{ streamId, label: `Spatial shot ${shot.shotId}`, kind: "video", role: "b-roll", frameRate: numericFrameRate, pixelWidth: output.pixelWidth, pixelHeight: output.pixelHeight,
177
+ segments: [{ assetRange: { startUs: 0, endUs: durationUs }, fileRange: { startUs: 0, endUs: durationUs }, ...materialized.artifact, codec: materialized.codec, container: materialized.container, streamIndex: materialized.streamIndex }] }],
178
+ }));
179
+ placements.push({
180
+ placementId: placementId as typeof placements[number]["placementId"], assetId: assetId as typeof placements[number]["assetId"],
181
+ assetRange: { startUs: 0, endUs: durationUs }, enabled: true, audio: [],
182
+ sync: { anchors: [{ assetTimeUs: 0, projectTimeUs: shot.range.startUs }, { assetTimeUs: durationUs, projectTimeUs: shot.range.endUs }], provenance: { kind: "identity" } },
183
+ video: [{ streamId: streamId as typeof base.project.assets[number]["streams"][number]["streamId"], presentation: { enabled: true, blendMode: "normal", crop: { kind: "none" }, fit: "fill", layer, layout: { kind: "normalized", x: 0, y: 0, width: 1, height: 1 }, opacity: 1 } }],
184
+ });
185
+ boundShots.push({ shot: SpatialShotV1Schema.parse(shot), materialized: { ...materialized, frameRate: reduceSpatialFrameRate(materialized.frameRate) } });
186
+ }
187
+ const project = VideoProjectV1Schema.parse({ ...base.project, assets, placements });
188
+ const plan = ProjectEditPlanV1Schema.parse({ ...base.projectEditPlan, projectStructureSha256: hashProjectStructure(project) });
189
+ const revision = createProjectEditRevisionDocument(project, plan);
190
+ const revisionText = spatialProjectDocumentText(revision);
191
+ const artifactSha256 = sha256Hex(revisionText);
192
+ const renderPlan = compileProjectRenderPlan(project, plan, { frameRate: numericFrameRate, pixelWidth: output.pixelWidth, pixelHeight: output.pixelHeight, background: output.background });
193
+ const projection = SceneRenderProjectionV1Schema.parse({
194
+ kind: "slopcamera.scene-render-projection", schemaVersion: 1, source: head, policy, output, shots: boundShots,
195
+ legacyFrameRateAdapter: { kind: "numeric-ratio-for-planning-only", value: numericFrameRate, requiredEncoderArgument: spatialProjectionEncoderFrameRate(output.frameRate) },
196
+ derivedV1RevisionSha256: revision.revisionSha256,
197
+ derivedV1Revision: { bytes: new TextEncoder().encode(revisionText).byteLength, sha256: artifactSha256, path: projectEditRevisionPath(artifactSha256) },
198
+ compositionPlanSha256: renderPlan.planSha256,
199
+ });
200
+ return deepFreezeJson({ projection, projectionSha256: canonicalJsonSha256({ domain: "slopcamera.scene-render-projection/v1", projection }), revision, renderPlan });
201
+ }