@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,377 @@
1
+ import { z } from "zod";
2
+
3
+ import {
4
+ canonicalJson,
5
+ canonicalJsonSha256,
6
+ hashProjectEditPlan,
7
+ hashProjectStructure,
8
+ saveProjectEditRevision,
9
+ sha256Hex,
10
+ } from "../../../core";
11
+ import {
12
+ CandidateRevisionHostBindingsV1Schema,
13
+ CandidateProjectEditBatchV3Schema,
14
+ canonicalCandidateRevisionHostBindingsV1,
15
+ candidateRevisionDerivationSha256,
16
+ createCreativeBaseV1,
17
+ createCreativeCandidateIdentityV1,
18
+ CreativeBaseV1Schema,
19
+ CreativeCandidateIdentityV1Schema,
20
+ CreativeCandidateRevisionReferenceV1Schema,
21
+ creativeBaseIdentityV1,
22
+ CreativeVariantKeySchema,
23
+ } from "../../creative-iteration";
24
+ import type { ApplicationContext } from "../../context";
25
+ import { ApplicationError } from "../../errors";
26
+ import type { OperationDefinition } from "../../operation";
27
+ import {
28
+ assertProjectEditBasis,
29
+ openProjectSnapshot,
30
+ } from "../../project-store";
31
+ import {
32
+ createProjectEditRevisionDocument,
33
+ ProjectEditRevisionDocumentSchema,
34
+ } from "../../receipts";
35
+ import {
36
+ bindProjectCommitEditsInputV3FromSnapshot,
37
+ deriveProjectEditPlanV3,
38
+ revalidateProjectEditBindingsV3,
39
+ } from "../project/commit-edits";
40
+ import { ProjectSnapshotOutputSchema } from "../project/snapshot";
41
+ import {
42
+ ProjectReferenceSchema,
43
+ throwIfAborted,
44
+ } from "../shared";
45
+
46
+ const MAXIMUM_PROJECT_EDIT_REVISION_BYTES = 256 * 1024 * 1024;
47
+
48
+ function logicalCandidateRevisionTimestamp(base: z.infer<
49
+ typeof CreativeBaseV1Schema
50
+ >): string {
51
+ return Date.parse(base.currentPlan.updatedAt) >= Date.parse(base.project.updatedAt)
52
+ ? base.currentPlan.updatedAt
53
+ : base.project.updatedAt;
54
+ }
55
+
56
+ const CreateCandidateRevisionExactUnboundInputSchema = z.strictObject({
57
+ base: CreativeBaseV1Schema,
58
+ batch: CandidateProjectEditBatchV3Schema,
59
+ bindings: CandidateRevisionHostBindingsV1Schema.optional(),
60
+ candidate: CreativeCandidateIdentityV1Schema,
61
+ project: ProjectReferenceSchema,
62
+ updatedAt: z.string().datetime({ offset: true }).optional(),
63
+ }).superRefine((input, context) => {
64
+ if (
65
+ input.project !== input.base.projectId
66
+ || !input.candidate.namespace.startsWith(
67
+ `iterations/${input.base.baseSha256}/`,
68
+ )
69
+ ) {
70
+ context.addIssue({
71
+ code: "custom",
72
+ message: "Candidate revision project, base, and namespace disagree.",
73
+ });
74
+ }
75
+ if (
76
+ input.updatedAt !== undefined
77
+ && Date.parse(input.updatedAt) < Date.parse(
78
+ logicalCandidateRevisionTimestamp(input.base),
79
+ )
80
+ ) {
81
+ context.addIssue({
82
+ code: "custom",
83
+ message: "Candidate revision time cannot precede its frozen project or edit plan.",
84
+ path: ["updatedAt"],
85
+ });
86
+ }
87
+ });
88
+
89
+ export const CreateCandidateRevisionRequestSchema = z.strictObject({
90
+ batch: CandidateProjectEditBatchV3Schema,
91
+ project: ProjectReferenceSchema,
92
+ snapshot: ProjectSnapshotOutputSchema,
93
+ updatedAt: z.string().datetime({ offset: true }).optional(),
94
+ variantKey: CreativeVariantKeySchema,
95
+ }).superRefine((input, context) => {
96
+ if (input.project !== input.snapshot.project.projectId) {
97
+ context.addIssue({
98
+ code: "custom",
99
+ message: "Candidate revision project does not match its frozen snapshot.",
100
+ path: ["project"],
101
+ });
102
+ }
103
+ });
104
+
105
+ export type CreateCandidateRevisionRequest = z.infer<
106
+ typeof CreateCandidateRevisionRequestSchema
107
+ >;
108
+
109
+ const CreateCandidateRevisionUnboundInputSchema = z.union([
110
+ CreateCandidateRevisionRequestSchema,
111
+ CreateCandidateRevisionExactUnboundInputSchema,
112
+ ]);
113
+
114
+ export const CreateCandidateRevisionInputSchema =
115
+ CreateCandidateRevisionExactUnboundInputSchema.safeExtend({
116
+ bindings: CandidateRevisionHostBindingsV1Schema,
117
+ updatedAt: z.string().datetime({ offset: true }),
118
+ }).strict();
119
+
120
+ export const CreateCandidateRevisionOutputSchema =
121
+ CreativeCandidateRevisionReferenceV1Schema;
122
+
123
+ export type CreateCandidateRevisionInput = z.infer<
124
+ typeof CreateCandidateRevisionInputSchema
125
+ >;
126
+ export type CreateCandidateRevisionOutput = z.infer<
127
+ typeof CreateCandidateRevisionOutputSchema
128
+ >;
129
+
130
+ /**
131
+ * Resolve every recording-backed V3 edit binding before exact node planning.
132
+ * A supplied binding is accepted only when it equals the host result.
133
+ */
134
+ export async function bindCreateCandidateRevisionInput(
135
+ application: ApplicationContext,
136
+ input: unknown,
137
+ ): Promise<CreateCandidateRevisionInput> {
138
+ const unbound = CreateCandidateRevisionUnboundInputSchema.parse(input);
139
+ const requested = "snapshot" in unbound
140
+ ? (() => {
141
+ const base = createCreativeBaseV1({
142
+ currentPlan: unbound.snapshot.currentPlan,
143
+ project: unbound.snapshot.project,
144
+ });
145
+ if (
146
+ canonicalJson(base.editBasis)
147
+ !== canonicalJson(unbound.snapshot.editBasis)
148
+ || canonicalJson(base.generation)
149
+ !== canonicalJson(unbound.snapshot.generation)
150
+ ) {
151
+ throw new ApplicationError(
152
+ "conflict",
153
+ "Candidate revision snapshot hashes do not match its exact documents.",
154
+ );
155
+ }
156
+ return CreateCandidateRevisionExactUnboundInputSchema.parse({
157
+ base,
158
+ batch: unbound.batch,
159
+ candidate: createCreativeCandidateIdentityV1({
160
+ base,
161
+ variantKey: unbound.variantKey,
162
+ }),
163
+ project: unbound.project,
164
+ updatedAt: unbound.updatedAt,
165
+ });
166
+ })()
167
+ : unbound;
168
+ const updatedAt = requested.updatedAt
169
+ ?? logicalCandidateRevisionTimestamp(requested.base);
170
+ if (
171
+ Date.parse(updatedAt) < Date.parse(
172
+ logicalCandidateRevisionTimestamp(requested.base),
173
+ )
174
+ ) {
175
+ throw new ApplicationError(
176
+ "conflict",
177
+ "Candidate revision time cannot precede its frozen project or edit plan.",
178
+ );
179
+ }
180
+ const snapshot = await openProjectSnapshot(
181
+ application.paths.projectRoot,
182
+ requested.project,
183
+ );
184
+ assertProjectEditBasis(requested.base.editBasis, snapshot);
185
+ const bindings = requested.batch.ordered.length === 0
186
+ ? canonicalCandidateRevisionHostBindingsV1({})
187
+ : await bindProjectCommitEditsInputV3FromSnapshot(
188
+ application,
189
+ {
190
+ batch: requested.batch,
191
+ basis: requested.base.editBasis,
192
+ project: requested.project,
193
+ updatedAt,
194
+ },
195
+ snapshot,
196
+ ).then(boundCommit => canonicalCandidateRevisionHostBindingsV1({
197
+ ...(boundCommit.manualZoomBindings === undefined
198
+ ? {}
199
+ : { manualZoomBindings: boundCommit.manualZoomBindings }),
200
+ ...(boundCommit.metadataBinding === undefined
201
+ ? {}
202
+ : { metadataBinding: boundCommit.metadataBinding }),
203
+ }));
204
+ if (
205
+ requested.bindings !== undefined
206
+ && canonicalJson(requested.bindings) !== canonicalJson(bindings)
207
+ ) {
208
+ throw new ApplicationError(
209
+ "conflict",
210
+ "Candidate revision host bindings changed after exact node planning.",
211
+ );
212
+ }
213
+ return CreateCandidateRevisionInputSchema.parse({
214
+ ...requested,
215
+ bindings,
216
+ updatedAt,
217
+ });
218
+ }
219
+
220
+ export const createCandidateRevisionOperationDefinition = {
221
+ inputSchema: CreateCandidateRevisionInputSchema,
222
+ inputSchemaId: "slopcamera.operation.edit.create-candidate-revision.input/v1",
223
+ kind: "edit.create-candidate-revision",
224
+ lifecycle: {
225
+ kind: "local-artifact",
226
+ execute: async (context, input) => {
227
+ throwIfAborted(context.abortSignal);
228
+ const snapshot = await openProjectSnapshot(
229
+ context.application.paths.projectRoot,
230
+ input.project,
231
+ );
232
+ assertProjectEditBasis(input.base.editBasis, snapshot);
233
+ const nextPlan = await deriveProjectEditPlanV3({
234
+ abortSignal: context.abortSignal,
235
+ application: context.application,
236
+ batch: input.batch,
237
+ manualZoomBindings: input.bindings.manualZoomBindings,
238
+ ...(input.bindings.metadataBinding === null
239
+ ? {}
240
+ : { metadataBinding: input.bindings.metadataBinding }),
241
+ plan: input.base.currentPlan,
242
+ project: input.base.project,
243
+ updatedAt: input.updatedAt,
244
+ });
245
+ const nextPlanSha256 = hashProjectEditPlan(nextPlan);
246
+ const revision = createProjectEditRevisionDocument(
247
+ input.base.project,
248
+ nextPlan,
249
+ );
250
+ const contents = `${canonicalJson(revision)}\n`;
251
+ const artifactSha256 = sha256Hex(contents);
252
+ const artifactBytes = new TextEncoder().encode(contents).byteLength;
253
+ if (artifactBytes > MAXIMUM_PROJECT_EDIT_REVISION_BYTES) {
254
+ throw new ApplicationError(
255
+ "unsupported-plan",
256
+ "Creative candidate revision exceeds the 256 MiB structured-artifact limit.",
257
+ { artifactBytes },
258
+ );
259
+ }
260
+
261
+ await revalidateProjectEditBindingsV3({
262
+ abortSignal: context.abortSignal,
263
+ application: context.application,
264
+ batch: input.batch,
265
+ manualZoomBindings: input.bindings.manualZoomBindings,
266
+ ...(input.bindings.metadataBinding === null
267
+ ? {}
268
+ : { metadataBinding: input.bindings.metadataBinding }),
269
+ project: input.base.project,
270
+ });
271
+ throwIfAborted(context.abortSignal);
272
+ await context.workflow?.beforePublication();
273
+ throwIfAborted(context.abortSignal);
274
+ const publicationSnapshot = await openProjectSnapshot(
275
+ context.application.paths.projectRoot,
276
+ input.project,
277
+ );
278
+ assertProjectEditBasis(input.base.editBasis, publicationSnapshot);
279
+ const path = await saveProjectEditRevision(
280
+ publicationSnapshot.openProject.fileSystem,
281
+ contents,
282
+ artifactSha256,
283
+ );
284
+ const publishedText = await publicationSnapshot.openProject.fileSystem
285
+ .readText(path);
286
+ let publishedInput: unknown;
287
+ try {
288
+ publishedInput = JSON.parse(publishedText) as unknown;
289
+ } catch {
290
+ throw new ApplicationError(
291
+ "conflict",
292
+ "Published creative candidate revision is not valid JSON.",
293
+ );
294
+ }
295
+ const published = ProjectEditRevisionDocumentSchema.parse(publishedInput);
296
+ if (
297
+ publishedText !== contents
298
+ || sha256Hex(publishedText) !== artifactSha256
299
+ || published.revisionSha256 !== revision.revisionSha256
300
+ || published.projectSha256 !== input.base.generation.projectSha256
301
+ || published.projectEditPlanSha256 !== nextPlanSha256
302
+ ) {
303
+ throw new ApplicationError(
304
+ "conflict",
305
+ "Published creative candidate revision failed immutable verification.",
306
+ );
307
+ }
308
+ const finalSnapshot = await openProjectSnapshot(
309
+ context.application.paths.projectRoot,
310
+ input.project,
311
+ );
312
+ assertProjectEditBasis(input.base.editBasis, finalSnapshot);
313
+ const bindingsSha256 = canonicalJsonSha256(input.bindings);
314
+ const derivationSha256 = candidateRevisionDerivationSha256({
315
+ baseSha256: input.base.baseSha256,
316
+ batch: input.batch,
317
+ bindings: input.bindings,
318
+ candidate: input.candidate,
319
+ projectEditPlanSha256: revision.projectEditPlanSha256,
320
+ revisionSha256: revision.revisionSha256,
321
+ updatedAt: input.updatedAt,
322
+ });
323
+ return CreateCandidateRevisionOutputSchema.parse({
324
+ artifact: {
325
+ bytes: artifactBytes,
326
+ path,
327
+ sha256: artifactSha256,
328
+ },
329
+ base: creativeBaseIdentityV1(input.base),
330
+ batchSha256: input.batch.sha256,
331
+ bindingsSha256,
332
+ candidate: input.candidate,
333
+ derivationSha256,
334
+ kind: "slopcamera.creative-candidate-revision-reference",
335
+ planId: nextPlan.planId,
336
+ projectEditPlanSha256: revision.projectEditPlanSha256,
337
+ projectId: input.base.projectId,
338
+ projectSha256: revision.projectSha256,
339
+ projectStructureSha256: hashProjectStructure(input.base.project),
340
+ revisionSha256: revision.revisionSha256,
341
+ schemaVersion: 1,
342
+ updatedAt: input.updatedAt,
343
+ });
344
+ },
345
+ },
346
+ outputSchema: CreateCandidateRevisionOutputSchema,
347
+ outputSchemaId: "slopcamera.operation.edit.create-candidate-revision.output/v1",
348
+ policy: {
349
+ cache: "content-addressed",
350
+ cancellable: true,
351
+ effect: "local-derived-write",
352
+ maxDurationMs: 90_000,
353
+ maxFanOut: 0,
354
+ maxInputBytes: 128 * 1024 * 1024,
355
+ maxOutputBytes: 16 * 1024,
356
+ preparation: ["project-state", "recording-metadata"],
357
+ resources: [
358
+ { amount: 1, resource: "cpu" },
359
+ { amount: 1, resource: "local-io" },
360
+ ],
361
+ resume: "deterministic",
362
+ },
363
+ summarize: output => ({
364
+ fields: {
365
+ candidateId: output.candidate.candidateId,
366
+ derivationSha256: output.derivationSha256,
367
+ projectId: output.projectId,
368
+ revisionSha256: output.revisionSha256,
369
+ },
370
+ kind: "edit.create-candidate-revision",
371
+ }),
372
+ version: 1,
373
+ } satisfies OperationDefinition<
374
+ "edit.create-candidate-revision",
375
+ CreateCandidateRevisionInput,
376
+ CreateCandidateRevisionOutput
377
+ >;
@@ -0,0 +1,255 @@
1
+ import { z } from "zod";
2
+
3
+ import {
4
+ canonicalJson,
5
+ canonicalJsonSha256,
6
+ assertProjectCameraMoveBindings,
7
+ hashProjectEditPlan,
8
+ hashProjectStructure,
9
+ normalizeProjectEditPlan,
10
+ saveProjectEditRevision,
11
+ sha256Hex,
12
+ } from "../../../core";
13
+ import { ApplicationError } from "../../errors";
14
+ import type { OperationDefinition } from "../../operation";
15
+ import {
16
+ assertProjectGeneration,
17
+ openProjectSnapshot,
18
+ } from "../../project-store";
19
+ import {
20
+ createProjectEditRevisionDocument,
21
+ hashProjectEditRevisionOutputGeometry,
22
+ ProjectEditRevisionDocumentSchema,
23
+ ProjectEditRevisionReferenceSchema,
24
+ } from "../../receipts";
25
+ import {
26
+ FaceFollowRevisionDraftSchema,
27
+ } from "../derive/follow-faces";
28
+ import {
29
+ ProjectReferenceSchema,
30
+ throwIfAborted,
31
+ } from "../shared";
32
+
33
+ const MAXIMUM_PROJECT_EDIT_REVISION_BYTES = 256 * 1024 * 1024;
34
+
35
+ export const CreateProjectEditRevisionInputSchema = z.strictObject({
36
+ draft: FaceFollowRevisionDraftSchema,
37
+ project: ProjectReferenceSchema,
38
+ });
39
+
40
+ export type CreateProjectEditRevisionInput = z.infer<
41
+ typeof CreateProjectEditRevisionInputSchema
42
+ >;
43
+ export type CreateProjectEditRevisionOutput = z.infer<
44
+ typeof ProjectEditRevisionReferenceSchema
45
+ >;
46
+
47
+ function assertDraftMatchesSnapshot(
48
+ snapshot: Awaited<ReturnType<typeof openProjectSnapshot>>,
49
+ draft: z.infer<typeof FaceFollowRevisionDraftSchema>,
50
+ ): void {
51
+ assertProjectGeneration(
52
+ draft.provenance.baseGeneration.generationSha256,
53
+ snapshot.generation,
54
+ );
55
+ const structureSha256 = hashProjectStructure(snapshot.project);
56
+ if (
57
+ draft.provenance.projectId !== snapshot.project.projectId
58
+ || draft.provenance.projectStructureSha256 !== structureSha256
59
+ || snapshot.plan.projectStructureSha256 !== structureSha256
60
+ || draft.provenance.basePlanId !== snapshot.plan.planId
61
+ ) {
62
+ throw new ApplicationError(
63
+ "conflict",
64
+ "Face-follow draft does not match the current project structure and base plan.",
65
+ );
66
+ }
67
+ const reference = snapshot.project.analyses.find(
68
+ candidate => candidate.analysisId === draft.provenance.analysisId,
69
+ );
70
+ if (
71
+ reference?.kind !== "faces"
72
+ || reference.sha256 !== draft.provenance.analysisSha256
73
+ || reference.subjectIntegritySha256
74
+ !== draft.provenance.subjectIntegritySha256
75
+ ) {
76
+ throw new ApplicationError(
77
+ "conflict",
78
+ "Face-follow draft analysis provenance is not current.",
79
+ );
80
+ }
81
+ if (
82
+ snapshot.plan.cameraMoves.some(
83
+ move => move.cameraMoveId === draft.cameraMove.cameraMoveId,
84
+ )
85
+ ) {
86
+ throw new ApplicationError(
87
+ "conflict",
88
+ "Face-follow draft camera move already exists in the base plan.",
89
+ );
90
+ }
91
+ assertProjectCameraMoveBindings(snapshot.project, draft.cameraMove);
92
+ const expectedPlan = normalizeProjectEditPlan({
93
+ ...snapshot.plan,
94
+ cameraMoves: [...snapshot.plan.cameraMoves, draft.cameraMove],
95
+ planId: draft.plan.planId,
96
+ });
97
+ if (
98
+ hashProjectEditPlan(expectedPlan) !== draft.planSha256
99
+ || canonicalJsonSha256(expectedPlan) !== canonicalJsonSha256(draft.plan)
100
+ ) {
101
+ throw new ApplicationError(
102
+ "conflict",
103
+ "Face-follow draft contains changes outside its reviewed camera move.",
104
+ );
105
+ }
106
+ }
107
+
108
+ export const createProjectEditRevisionOperationDefinition = {
109
+ inputSchema: CreateProjectEditRevisionInputSchema,
110
+ inputSchemaId: "slopcamera.operation.edit.create-revision.input/v1",
111
+ kind: "edit.create-revision",
112
+ lifecycle: {
113
+ kind: "local-artifact",
114
+ execute: async (context, input) => {
115
+ throwIfAborted(context.abortSignal);
116
+ const snapshot = await openProjectSnapshot(
117
+ context.application.paths.projectRoot,
118
+ input.project,
119
+ );
120
+ assertProjectGeneration(
121
+ context.expectedProjectGeneration,
122
+ snapshot.generation,
123
+ );
124
+ assertDraftMatchesSnapshot(snapshot, input.draft);
125
+ throwIfAborted(context.abortSignal);
126
+
127
+ // Recheck the full project/current-plan generation immediately before
128
+ // immutable publication. The caller owns the outer publication lease.
129
+ const publicationSnapshot = await openProjectSnapshot(
130
+ context.application.paths.projectRoot,
131
+ snapshot.project.projectId,
132
+ );
133
+ assertProjectGeneration(
134
+ snapshot.generation.generationSha256,
135
+ publicationSnapshot.generation,
136
+ );
137
+ const revision = createProjectEditRevisionDocument(
138
+ publicationSnapshot.project,
139
+ input.draft.plan,
140
+ );
141
+ const contents = `${canonicalJson(revision)}\n`;
142
+ const artifactSha256 = sha256Hex(contents);
143
+ const artifactBytes = new TextEncoder().encode(contents).byteLength;
144
+ if (artifactBytes > MAXIMUM_PROJECT_EDIT_REVISION_BYTES) {
145
+ throw new ApplicationError(
146
+ "unsupported-plan",
147
+ "Frozen project edit revision exceeds the 256 MiB structured-artifact limit.",
148
+ { artifactBytes },
149
+ );
150
+ }
151
+ throwIfAborted(context.abortSignal);
152
+ await context.workflow?.beforePublication();
153
+ const path = await saveProjectEditRevision(
154
+ publicationSnapshot.openProject.fileSystem,
155
+ contents,
156
+ artifactSha256,
157
+ );
158
+
159
+ const publishedText = await publicationSnapshot.openProject.fileSystem
160
+ .readText(path);
161
+ let publishedInput: unknown;
162
+ try {
163
+ publishedInput = JSON.parse(publishedText) as unknown;
164
+ } catch {
165
+ throw new ApplicationError(
166
+ "conflict",
167
+ "Published project edit revision is not valid JSON.",
168
+ );
169
+ }
170
+ const published = ProjectEditRevisionDocumentSchema.parse(publishedInput);
171
+ if (
172
+ publishedText !== contents
173
+ || sha256Hex(publishedText) !== artifactSha256
174
+ || canonicalJsonSha256(published.project) !== revision.projectSha256
175
+ || canonicalJsonSha256(published.projectEditPlan)
176
+ !== revision.projectEditPlanSha256
177
+ || published.revisionSha256 !== revision.revisionSha256
178
+ ) {
179
+ throw new ApplicationError(
180
+ "conflict",
181
+ "Published project edit revision failed content-addressed verification.",
182
+ );
183
+ }
184
+ const finalSnapshot = await openProjectSnapshot(
185
+ context.application.paths.projectRoot,
186
+ snapshot.project.projectId,
187
+ );
188
+ assertProjectGeneration(
189
+ snapshot.generation.generationSha256,
190
+ finalSnapshot.generation,
191
+ );
192
+ const outputGeometrySha256 = hashProjectEditRevisionOutputGeometry({
193
+ pixelHeight: input.draft.pixelHeight,
194
+ pixelWidth: input.draft.pixelWidth,
195
+ revisionSha256: revision.revisionSha256,
196
+ });
197
+ return ProjectEditRevisionReferenceSchema.parse({
198
+ analysisId: input.draft.provenance.analysisId,
199
+ analysisSha256: input.draft.provenance.analysisSha256,
200
+ artifact: {
201
+ bytes: artifactBytes,
202
+ path,
203
+ sha256: artifactSha256,
204
+ },
205
+ aspect: input.draft.provenance.parameters.aspect,
206
+ baseGeneration: input.draft.provenance.baseGeneration,
207
+ derivationSha256: input.draft.derivationSha256,
208
+ kind: "slopcamera.project-edit-revision-reference",
209
+ outputGeometrySha256,
210
+ pixelHeight: input.draft.pixelHeight,
211
+ pixelWidth: input.draft.pixelWidth,
212
+ planId: input.draft.plan.planId,
213
+ projectEditPlanSha256: revision.projectEditPlanSha256,
214
+ projectId: snapshot.project.projectId,
215
+ projectSha256: revision.projectSha256,
216
+ projectStructureSha256: input.draft.provenance.projectStructureSha256,
217
+ revisionSha256: revision.revisionSha256,
218
+ schemaVersion: 1,
219
+ });
220
+ },
221
+ },
222
+ outputSchema: ProjectEditRevisionReferenceSchema,
223
+ outputSchemaId: "slopcamera.operation.edit.create-revision.output/v1",
224
+ policy: {
225
+ cache: "content-addressed",
226
+ cancellable: true,
227
+ effect: "local-derived-write",
228
+ maxDurationMs: 30_000,
229
+ maxFanOut: 0,
230
+ maxInputBytes: 32 * 1024 * 1024,
231
+ maxOutputBytes: 8_192,
232
+ preparation: ["project-state"],
233
+ resources: [
234
+ { amount: 1, resource: "cpu" },
235
+ { amount: 1, resource: "local-io" },
236
+ { amount: 1, resource: "project-publication" },
237
+ ],
238
+ resume: "deterministic",
239
+ },
240
+ summarize: output => ({
241
+ fields: {
242
+ aspect: output.aspect,
243
+ artifactSha256: output.artifact.sha256,
244
+ projectEditPlanSha256: output.projectEditPlanSha256,
245
+ projectId: output.projectId,
246
+ revisionSha256: output.revisionSha256,
247
+ },
248
+ kind: "edit.create-revision",
249
+ }),
250
+ version: 1,
251
+ } satisfies OperationDefinition<
252
+ "edit.create-revision",
253
+ CreateProjectEditRevisionInput,
254
+ CreateProjectEditRevisionOutput
255
+ >;