@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,324 @@
1
+ import { z } from "zod";
2
+
3
+ import {
4
+ ProjectRenderEncoderRecipeSchema,
5
+ ProjectRenderOutputRequestSchema,
6
+ ProjectRenderSyncPolicySchema,
7
+ ProjectRenderTargetSchema,
8
+ ProjectRenderToolchainSchema,
9
+ resolveProjectRenderEncoderRecipe,
10
+ type ProjectRenderToolchain,
11
+ } from "../../../contracts";
12
+ import {
13
+ canonicalJson,
14
+ canonicalJsonSha256,
15
+ } from "../../../core";
16
+ import {
17
+ CreativeCandidateRevisionReferenceV1Schema,
18
+ } from "../../creative-iteration";
19
+ import { ApplicationError } from "../../errors";
20
+ import type { OperationDefinition } from "../../operation";
21
+ import {
22
+ ProjectRenderPlanReferenceSchema,
23
+ RenderableProjectEditRevisionReferenceSchema,
24
+ } from "../../receipts";
25
+ import { throwIfAborted } from "../shared";
26
+
27
+ /**
28
+ * Increment this ABI whenever Slopcamera's project-render implementation can
29
+ * change encoded output without changing the render plan or encoder recipe.
30
+ */
31
+ export const SLOPCAMERA_PROJECT_RENDERER_ABI =
32
+ "slopcamera-project-renderer-abi-v1" as const;
33
+
34
+ export const CandidateProjectRendererAbiSchema = z.string()
35
+ .min(1)
36
+ .max(80)
37
+ .regex(/^slopcamera-project-renderer-abi-v[1-9][0-9]*$/u);
38
+
39
+ const CandidateRenderDerivationBodyV1Schema = z.strictObject({
40
+ binding: ProjectRenderToolchainSchema,
41
+ candidateRevision: CreativeCandidateRevisionReferenceV1Schema,
42
+ encoderRecipe: ProjectRenderEncoderRecipeSchema,
43
+ kind: z.union([
44
+ z.literal("slopcamera.candidate-render-derivation"),
45
+ ]),
46
+ maximumBytes: ProjectRenderOutputRequestSchema.shape.maximumBytes,
47
+ plan: ProjectRenderPlanReferenceSchema,
48
+ rendererAbi: CandidateProjectRendererAbiSchema,
49
+ revision: RenderableProjectEditRevisionReferenceSchema,
50
+ schemaVersion: z.literal(1),
51
+ syncPolicy: ProjectRenderSyncPolicySchema,
52
+ target: ProjectRenderTargetSchema,
53
+ });
54
+
55
+ export const CandidateRenderDerivationV1Schema =
56
+ CandidateRenderDerivationBodyV1Schema.extend({
57
+ derivationSha256: z.string().regex(/^[a-f0-9]{64}$/u),
58
+ }).strict().superRefine((derivation, context) => {
59
+ const body = CandidateRenderDerivationBodyV1Schema.parse({
60
+ binding: derivation.binding,
61
+ candidateRevision: derivation.candidateRevision,
62
+ encoderRecipe: derivation.encoderRecipe,
63
+ kind: derivation.kind,
64
+ maximumBytes: derivation.maximumBytes,
65
+ plan: derivation.plan,
66
+ rendererAbi: derivation.rendererAbi,
67
+ revision: derivation.revision,
68
+ schemaVersion: derivation.schemaVersion,
69
+ syncPolicy: derivation.syncPolicy,
70
+ target: derivation.target,
71
+ });
72
+ if (candidateRenderDerivationSha256(body) !== derivation.derivationSha256) {
73
+ context.addIssue({
74
+ code: "custom",
75
+ message: "Candidate render derivation hash does not match its exact inputs.",
76
+ path: ["derivationSha256"],
77
+ });
78
+ }
79
+ if (!candidateRenderRelationshipsAgree(derivation)) {
80
+ context.addIssue({
81
+ code: "custom",
82
+ message: "Candidate revision, renderable revision, and render plan must describe one exact derivation.",
83
+ });
84
+ }
85
+ if (
86
+ canonicalJson(derivation.encoderRecipe)
87
+ !== canonicalJson(resolveProjectRenderEncoderRecipe(derivation.target.tier))
88
+ ) {
89
+ context.addIssue({
90
+ code: "custom",
91
+ message: "Candidate render encoder recipe must match its exact target tier.",
92
+ path: ["encoderRecipe"],
93
+ });
94
+ }
95
+ });
96
+
97
+ export const BindCandidateRenderOutputInputRequestSchema = z.strictObject({
98
+ binding: ProjectRenderToolchainSchema.optional(),
99
+ candidateRevision: CreativeCandidateRevisionReferenceV1Schema,
100
+ maximumBytes: ProjectRenderOutputRequestSchema.shape.maximumBytes,
101
+ plan: ProjectRenderPlanReferenceSchema,
102
+ rendererAbi: CandidateProjectRendererAbiSchema.optional(),
103
+ revision: RenderableProjectEditRevisionReferenceSchema,
104
+ syncPolicy: ProjectRenderSyncPolicySchema,
105
+ target: ProjectRenderTargetSchema,
106
+ });
107
+
108
+ export const BindCandidateRenderOutputInputSchema =
109
+ BindCandidateRenderOutputInputRequestSchema.extend({
110
+ binding: ProjectRenderToolchainSchema,
111
+ rendererAbi: CandidateProjectRendererAbiSchema,
112
+ }).strict();
113
+
114
+ export const CandidateProjectRenderInputSchema = z.strictObject({
115
+ binding: ProjectRenderToolchainSchema,
116
+ derivation: CandidateRenderDerivationV1Schema,
117
+ output: ProjectRenderOutputRequestSchema,
118
+ plan: ProjectRenderPlanReferenceSchema,
119
+ syncPolicy: ProjectRenderSyncPolicySchema,
120
+ target: ProjectRenderTargetSchema,
121
+ }).superRefine((input, context) => {
122
+ if (
123
+ input.output.maximumBytes !== input.derivation.maximumBytes
124
+ || canonicalJson(input.binding) !== canonicalJson(input.derivation.binding)
125
+ || canonicalJson(input.plan) !== canonicalJson(input.derivation.plan)
126
+ || input.syncPolicy !== input.derivation.syncPolicy
127
+ || canonicalJson(input.target) !== canonicalJson(input.derivation.target)
128
+ ) {
129
+ context.addIssue({
130
+ code: "custom",
131
+ message: "Candidate render request does not match its complete derivation.",
132
+ });
133
+ }
134
+ const expectedPath = candidateRenderOutputPath(input.derivation);
135
+ if (input.output.path !== expectedPath) {
136
+ context.addIssue({
137
+ code: "custom",
138
+ message: "Candidate render output path is not addressed by its complete derivation.",
139
+ path: ["output", "path"],
140
+ });
141
+ }
142
+ });
143
+
144
+ export type BindCandidateRenderOutputInput = z.infer<
145
+ typeof BindCandidateRenderOutputInputSchema
146
+ >;
147
+ export type BindCandidateRenderOutputInputRequest = z.infer<
148
+ typeof BindCandidateRenderOutputInputRequestSchema
149
+ >;
150
+ export type CandidateProjectRenderInput = z.infer<
151
+ typeof CandidateProjectRenderInputSchema
152
+ >;
153
+ export type CandidateRenderDerivationV1 = z.infer<
154
+ typeof CandidateRenderDerivationV1Schema
155
+ >;
156
+
157
+ function candidateRenderRelationshipsAgree(input: {
158
+ readonly candidateRevision: BindCandidateRenderOutputInput["candidateRevision"];
159
+ readonly plan: BindCandidateRenderOutputInput["plan"];
160
+ readonly revision: BindCandidateRenderOutputInput["revision"];
161
+ }): boolean {
162
+ const candidate = input.candidateRevision;
163
+ const revision = input.revision;
164
+ const plan = input.plan;
165
+ return !(
166
+ candidate.projectId !== revision.projectId
167
+ || candidate.projectSha256 !== revision.projectSha256
168
+ || candidate.projectStructureSha256 !== revision.projectStructureSha256
169
+ || candidate.projectEditPlanSha256 !== revision.projectEditPlanSha256
170
+ || candidate.revisionSha256 !== revision.revisionSha256
171
+ || candidate.planId !== revision.planId
172
+ || canonicalJson(candidate.artifact) !== canonicalJson(revision.artifact)
173
+ || canonicalJson(candidate.base.generation) !== canonicalJson(revision.baseGeneration)
174
+ || plan.projectId !== revision.projectId
175
+ || plan.projectSha256 !== revision.projectSha256
176
+ || plan.projectEditPlanSha256 !== revision.projectEditPlanSha256
177
+ || plan.revisionSha256 !== revision.revisionSha256
178
+ || plan.outputGeometrySha256 !== revision.outputGeometrySha256
179
+ );
180
+ }
181
+
182
+ function validateCandidateRenderRelationships(
183
+ input: BindCandidateRenderOutputInput,
184
+ ): void {
185
+ if (!candidateRenderRelationshipsAgree(input)) {
186
+ throw new ApplicationError(
187
+ "conflict",
188
+ "Candidate revision, renderable revision, and render plan must describe one exact derivation.",
189
+ );
190
+ }
191
+ }
192
+
193
+ export function assertCurrentCandidateProjectRendererAbi(
194
+ rendererAbi: string,
195
+ ): void {
196
+ if (rendererAbi !== SLOPCAMERA_PROJECT_RENDERER_ABI) {
197
+ throw new ApplicationError(
198
+ "incompatible",
199
+ "Candidate renderer ABI differs from the current Slopcamera project renderer.",
200
+ {
201
+ currentRendererAbi: SLOPCAMERA_PROJECT_RENDERER_ABI,
202
+ rendererAbi,
203
+ },
204
+ );
205
+ }
206
+ }
207
+
208
+ export function candidateRenderDerivationSha256(
209
+ input: z.input<typeof CandidateRenderDerivationBodyV1Schema>,
210
+ ): string {
211
+ const body = CandidateRenderDerivationBodyV1Schema.parse(input);
212
+ return canonicalJsonSha256({
213
+ domain: "slopcamera.candidate-render-derivation/v1",
214
+ ...body,
215
+ });
216
+ }
217
+
218
+ export function createCandidateRenderDerivationV1(
219
+ input: BindCandidateRenderOutputInput,
220
+ ): CandidateRenderDerivationV1 {
221
+ const exact = BindCandidateRenderOutputInputSchema.parse(input);
222
+ assertCurrentCandidateProjectRendererAbi(exact.rendererAbi);
223
+ validateCandidateRenderRelationships(exact);
224
+ const encoderRecipe = resolveProjectRenderEncoderRecipe(exact.target.tier);
225
+ const body = CandidateRenderDerivationBodyV1Schema.parse({
226
+ ...exact,
227
+ encoderRecipe,
228
+ kind: "slopcamera.candidate-render-derivation",
229
+ schemaVersion: 1,
230
+ });
231
+ return CandidateRenderDerivationV1Schema.parse({
232
+ ...body,
233
+ derivationSha256: candidateRenderDerivationSha256(body),
234
+ });
235
+ }
236
+
237
+ export function candidateRenderOutputPath(
238
+ derivationInput: CandidateRenderDerivationV1,
239
+ ): string {
240
+ const derivation = CandidateRenderDerivationV1Schema.parse(derivationInput);
241
+ return ProjectRenderOutputRequestSchema.shape.path.parse(
242
+ `renders/${derivation.candidateRevision.candidate.namespace}/${derivation.revision.revisionSha256}/derivations/${derivation.derivationSha256}.mp4`,
243
+ );
244
+ }
245
+
246
+ export function bindCandidateRenderOutputInput(
247
+ resolvedInput: unknown,
248
+ hostToolchain: ProjectRenderToolchain,
249
+ ): BindCandidateRenderOutputInput {
250
+ const requested = BindCandidateRenderOutputInputRequestSchema.parse(
251
+ resolvedInput,
252
+ );
253
+ const binding = ProjectRenderToolchainSchema.parse(hostToolchain);
254
+ if (
255
+ requested.binding !== undefined
256
+ && canonicalJson(requested.binding) !== canonicalJson(binding)
257
+ ) {
258
+ throw new ApplicationError(
259
+ "conflict",
260
+ "Candidate render tool binding changed after exact node planning.",
261
+ );
262
+ }
263
+ if (requested.rendererAbi !== undefined) {
264
+ assertCurrentCandidateProjectRendererAbi(requested.rendererAbi);
265
+ }
266
+ const exact = BindCandidateRenderOutputInputSchema.parse({
267
+ ...requested,
268
+ binding,
269
+ rendererAbi: SLOPCAMERA_PROJECT_RENDERER_ABI,
270
+ });
271
+ validateCandidateRenderRelationships(exact);
272
+ return exact;
273
+ }
274
+
275
+ export const bindCandidateRenderOutputOperationDefinition = {
276
+ inputSchema: BindCandidateRenderOutputInputSchema,
277
+ inputSchemaId: "slopcamera.operation.render.bind-candidate-output.input/v1",
278
+ kind: "render.bind-candidate-output",
279
+ lifecycle: {
280
+ kind: "pure",
281
+ execute: (context, input) => {
282
+ throwIfAborted(context.abortSignal);
283
+ const derivation = createCandidateRenderDerivationV1(input);
284
+ return Promise.resolve(CandidateProjectRenderInputSchema.parse({
285
+ binding: input.binding,
286
+ derivation,
287
+ output: {
288
+ maximumBytes: input.maximumBytes,
289
+ path: candidateRenderOutputPath(derivation),
290
+ },
291
+ plan: input.plan,
292
+ syncPolicy: input.syncPolicy,
293
+ target: input.target,
294
+ }));
295
+ },
296
+ },
297
+ outputSchema: CandidateProjectRenderInputSchema,
298
+ outputSchemaId: "slopcamera.operation.render.bind-candidate-output.output/v1",
299
+ policy: {
300
+ cache: "content-addressed",
301
+ cancellable: true,
302
+ effect: "pure",
303
+ maxDurationMs: 5_000,
304
+ maxFanOut: 0,
305
+ maxInputBytes: 64 * 1024,
306
+ maxOutputBytes: 64 * 1024,
307
+ preparation: [],
308
+ resources: [{ amount: 1, resource: "cpu" }],
309
+ resume: "deterministic",
310
+ },
311
+ summarize: output => ({
312
+ fields: {
313
+ derivationSha256: output.derivation.derivationSha256,
314
+ outputPath: output.output.path,
315
+ renderPlanSha256: output.plan.renderPlanSha256,
316
+ },
317
+ kind: "render.bind-candidate-output",
318
+ }),
319
+ version: 1,
320
+ } satisfies OperationDefinition<
321
+ "render.bind-candidate-output",
322
+ BindCandidateRenderOutputInput,
323
+ CandidateProjectRenderInput
324
+ >;
@@ -0,0 +1,322 @@
1
+ import { z } from "zod";
2
+
3
+ import {
4
+ canonicalJson,
5
+ sha256Hex,
6
+ } from "../../../core";
7
+ import {
8
+ createDeliveryMaterializationReceiptV1,
9
+ CreativeRenderNameSchema,
10
+ CreativeVariantKeySchema,
11
+ DeliveryMaterializationReceiptReferenceV1Schema,
12
+ DeliveryMaterializationReceiptV1Schema,
13
+ deliveryMaterializationReceiptPath,
14
+ deliveryMaterializationReceiptReferenceV1,
15
+ VariantSelectionReferenceV1Schema,
16
+ type DeliveryMaterializationReceiptV1,
17
+ } from "../../creative-iteration";
18
+ import {
19
+ ProjectRenderOutputPathSchema,
20
+ } from "../../../contracts";
21
+ import type { ApplicationContext } from "../../context";
22
+ import { ApplicationError } from "../../errors";
23
+ import type { OperationDefinition } from "../../operation";
24
+ import { withOutputPublicationLease } from "../../output-publication-lease";
25
+ import { ProjectReferenceSchema, throwIfAborted } from "../shared";
26
+ import {
27
+ creativeProjectFileSystem,
28
+ loadCreativeCandidate,
29
+ loadVariantMatrix,
30
+ loadVariantSelection,
31
+ publishCreativeDocument,
32
+ verifyCandidateRender,
33
+ } from "../iteration/shared";
34
+ import { ProjectRenderOutputReferenceSchema } from "../../receipts";
35
+
36
+ const MaterializeVariantSelectionUnboundInputSchema = z.strictObject({
37
+ deliveryKey: CreativeVariantKeySchema.default("delivery"),
38
+ destinationPath: ProjectRenderOutputPathSchema.optional(),
39
+ project: ProjectReferenceSchema,
40
+ renderName: CreativeRenderNameSchema,
41
+ selection: VariantSelectionReferenceV1Schema,
42
+ }).superRefine((input, context) => {
43
+ if (input.project !== input.selection.base.projectId) {
44
+ context.addIssue({
45
+ code: "custom",
46
+ message: "Delivery materialization project does not match its selection.",
47
+ path: ["project"],
48
+ });
49
+ }
50
+ });
51
+
52
+ export const MaterializeVariantSelectionInputSchema =
53
+ MaterializeVariantSelectionUnboundInputSchema.safeExtend({
54
+ destinationPath: ProjectRenderOutputPathSchema,
55
+ }).strict();
56
+
57
+ export const MaterializeVariantSelectionOutputSchema = z.strictObject({
58
+ output: ProjectRenderOutputReferenceSchema,
59
+ receipt: DeliveryMaterializationReceiptReferenceV1Schema,
60
+ });
61
+
62
+ export type MaterializeVariantSelectionInput = z.infer<
63
+ typeof MaterializeVariantSelectionInputSchema
64
+ >;
65
+ export type MaterializeVariantSelectionOutput = z.infer<
66
+ typeof MaterializeVariantSelectionOutputSchema
67
+ >;
68
+
69
+ export function defaultDeliveryMaterializationPath(input: {
70
+ readonly deliveryKey: string;
71
+ readonly renderName: string;
72
+ readonly selectionSha256: string;
73
+ }): string {
74
+ return ProjectRenderOutputPathSchema.parse(
75
+ `renders/deliveries/selections/${input.selectionSha256}/${
76
+ CreativeVariantKeySchema.parse(input.deliveryKey)
77
+ }/${CreativeRenderNameSchema.parse(input.renderName)}.mp4`,
78
+ );
79
+ }
80
+
81
+ export function bindMaterializeVariantSelectionInput(
82
+ _application: ApplicationContext,
83
+ input: unknown,
84
+ ): MaterializeVariantSelectionInput {
85
+ const request = MaterializeVariantSelectionUnboundInputSchema.parse(input);
86
+ return MaterializeVariantSelectionInputSchema.parse({
87
+ ...request,
88
+ destinationPath: request.destinationPath
89
+ ?? defaultDeliveryMaterializationPath({
90
+ deliveryKey: request.deliveryKey,
91
+ renderName: request.renderName,
92
+ selectionSha256: request.selection.selectionSha256,
93
+ }),
94
+ });
95
+ }
96
+
97
+ function missing(error: unknown): boolean {
98
+ return error instanceof Error && "code" in error && error.code === "ENOENT";
99
+ }
100
+
101
+ async function loadExistingMaterialization(input: {
102
+ readonly fileSystem: Awaited<ReturnType<typeof creativeProjectFileSystem>>;
103
+ readonly path: string;
104
+ }): Promise<{
105
+ readonly artifact: {
106
+ readonly bytes: number;
107
+ readonly path: string;
108
+ readonly sha256: string;
109
+ };
110
+ readonly receipt: DeliveryMaterializationReceiptV1;
111
+ } | null> {
112
+ let contents: string;
113
+ try {
114
+ contents = await input.fileSystem.readText(input.path);
115
+ } catch (error) {
116
+ if (missing(error)) return null;
117
+ throw error;
118
+ }
119
+ let value: unknown;
120
+ try {
121
+ value = JSON.parse(contents) as unknown;
122
+ } catch {
123
+ throw new ApplicationError(
124
+ "invalid-data",
125
+ "Delivery materialization receipt is not valid JSON.",
126
+ );
127
+ }
128
+ const receipt = DeliveryMaterializationReceiptV1Schema.parse(value);
129
+ if (contents !== `${canonicalJson(receipt)}\n`) {
130
+ throw new ApplicationError(
131
+ "invalid-data",
132
+ "Delivery materialization receipt is not canonical immutable JSON.",
133
+ );
134
+ }
135
+ return {
136
+ artifact: {
137
+ bytes: new TextEncoder().encode(contents).byteLength,
138
+ path: input.path,
139
+ sha256: sha256Hex(contents),
140
+ },
141
+ receipt,
142
+ };
143
+ }
144
+
145
+ export const materializeVariantSelectionOperationDefinition = {
146
+ inputSchema: MaterializeVariantSelectionInputSchema,
147
+ inputSchemaId: "slopcamera.operation.render.materialize-selection.input/v1",
148
+ kind: "render.materialize-selection",
149
+ lifecycle: {
150
+ kind: "local-artifact",
151
+ execute: async (context, input) => {
152
+ throwIfAborted(context.abortSignal);
153
+ const fileSystem = await creativeProjectFileSystem(
154
+ context.application,
155
+ input.project,
156
+ );
157
+ const selection = await loadVariantSelection({
158
+ fileSystem,
159
+ reference: input.selection,
160
+ });
161
+ const matrix = await loadVariantMatrix({
162
+ fileSystem,
163
+ reference: selection.matrix,
164
+ });
165
+ const chosen = matrix.candidates.find(candidate => (
166
+ candidate.candidate.candidateId === selection.chosen.candidate.candidateId
167
+ ));
168
+ if (
169
+ chosen === undefined
170
+ || canonicalJson(chosen) !== canonicalJson(selection.chosen)
171
+ ) {
172
+ throw new ApplicationError(
173
+ "conflict",
174
+ "Delivery selection is not an exact member of its closed matrix.",
175
+ );
176
+ }
177
+ const candidate = await loadCreativeCandidate({
178
+ fileSystem,
179
+ reference: chosen,
180
+ });
181
+ const render = candidate.renders.find(item => item.name === input.renderName);
182
+ if (render === undefined) {
183
+ throw new ApplicationError(
184
+ "not-found",
185
+ `Selected candidate has no verified render named ${input.renderName}.`,
186
+ );
187
+ }
188
+ if (!selection.result.renders.some(result => (
189
+ result.name === render.name
190
+ && result.outputSha256 === render.output.sha256
191
+ && result.receiptSha256 === render.receipt.receiptSha256
192
+ ))) {
193
+ throw new ApplicationError(
194
+ "conflict",
195
+ "Selected render hashes are absent from the immutable selection result.",
196
+ );
197
+ }
198
+ await verifyCandidateRender({ candidate, fileSystem, render });
199
+ if (render.output.path === input.destinationPath) {
200
+ throw new ApplicationError(
201
+ "conflict",
202
+ "Delivery materialization requires a new output path.",
203
+ );
204
+ }
205
+ const receipt = createDeliveryMaterializationReceiptV1({
206
+ candidate: chosen,
207
+ destinationPath: input.destinationPath,
208
+ renderName: input.renderName,
209
+ selection: input.selection,
210
+ source: render.output,
211
+ });
212
+ const receiptPath = deliveryMaterializationReceiptPath(
213
+ receipt.materializationSha256,
214
+ );
215
+ throwIfAborted(context.abortSignal);
216
+ return await withOutputPublicationLease(
217
+ context.application,
218
+ {
219
+ outputPath: input.destinationPath,
220
+ projectId: input.project,
221
+ },
222
+ async () => {
223
+ const existing = await loadExistingMaterialization({
224
+ fileSystem,
225
+ path: receiptPath,
226
+ });
227
+ if (existing !== null) {
228
+ if (canonicalJson(existing.receipt) !== canonicalJson(receipt)) {
229
+ throw new ApplicationError(
230
+ "conflict",
231
+ "Delivery materialization receipt path contains another result.",
232
+ );
233
+ }
234
+ if (fileSystem.inspectFile === undefined) {
235
+ throw new ApplicationError(
236
+ "internal",
237
+ "Project storage does not support delivery verification.",
238
+ );
239
+ }
240
+ const integrity = await fileSystem.inspectFile(input.destinationPath);
241
+ if (
242
+ integrity.bytes !== receipt.destination.bytes
243
+ || integrity.sha256 !== receipt.destination.sha256
244
+ ) {
245
+ throw new ApplicationError(
246
+ "conflict",
247
+ "Existing materialized delivery no longer matches its receipt.",
248
+ );
249
+ }
250
+ const reference = deliveryMaterializationReceiptReferenceV1(existing);
251
+ return MaterializeVariantSelectionOutputSchema.parse({
252
+ output: receipt.destination,
253
+ receipt: reference,
254
+ });
255
+ }
256
+ if (fileSystem.copyFileNoReplace === undefined) {
257
+ throw new ApplicationError(
258
+ "internal",
259
+ "Project storage does not support immutable delivery materialization.",
260
+ );
261
+ }
262
+ throwIfAborted(context.abortSignal);
263
+ await context.workflow?.beforePublication();
264
+ throwIfAborted(context.abortSignal);
265
+ await fileSystem.copyFileNoReplace(
266
+ render.output.path,
267
+ input.destinationPath,
268
+ render.output,
269
+ );
270
+ // Copy publication is the point of no return. Finalize its deterministic
271
+ // receipt even if cancellation arrives immediately afterward.
272
+ const artifact = await publishCreativeDocument({
273
+ document: receipt,
274
+ fileSystem,
275
+ path: receiptPath,
276
+ schema: DeliveryMaterializationReceiptV1Schema,
277
+ });
278
+ const reference = deliveryMaterializationReceiptReferenceV1({
279
+ artifact,
280
+ receipt,
281
+ });
282
+ return MaterializeVariantSelectionOutputSchema.parse({
283
+ output: receipt.destination,
284
+ receipt: reference,
285
+ });
286
+ },
287
+ );
288
+ },
289
+ },
290
+ outputSchema: MaterializeVariantSelectionOutputSchema,
291
+ outputSchemaId: "slopcamera.operation.render.materialize-selection.output/v1",
292
+ policy: {
293
+ cache: "none",
294
+ cancellable: true,
295
+ effect: "local-derived-write",
296
+ maxDurationMs: 6 * 60 * 60_000,
297
+ maxFanOut: 0,
298
+ maxInputBytes: 32 * 1024,
299
+ maxOutputBytes: 32 * 1024,
300
+ preparation: ["local-media"],
301
+ resources: [
302
+ { amount: 1, resource: "local-io" },
303
+ { amount: 1, resource: "output-publication" },
304
+ ],
305
+ resume: "deterministic",
306
+ },
307
+ receiptReference: output => output.receipt.artifact.path,
308
+ summarize: output => ({
309
+ fields: {
310
+ materializationSha256: output.receipt.materializationSha256,
311
+ outputPath: output.output.path,
312
+ outputSha256: output.output.sha256,
313
+ selectionSha256: output.receipt.selectionSha256,
314
+ },
315
+ kind: "render.materialize-selection",
316
+ }),
317
+ version: 1,
318
+ } satisfies OperationDefinition<
319
+ "render.materialize-selection",
320
+ MaterializeVariantSelectionInput,
321
+ MaterializeVariantSelectionOutput
322
+ >;