@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,966 @@
1
+ # Slopcamera desktop and CLI
2
+
3
+ Slopcamera captures synchronized raw inputs into repository-local bundles, combines independent camera and audio takes on one typed project clock, then applies non-destructive edits through the `slopcamera` CLI. The CLI is the product surface for agents. The macOS window remains only start, pause, resume, stop, and input status.
4
+
5
+ ## Recording bundles
6
+
7
+ The default root is `artifacts/slopcamera/recordings/`, resolved from the Slopcamera checkout. `artifacts/` is gitignored and excluded from Vercel uploads. Slopcamera never falls back to an external data directory.
8
+
9
+ ```text
10
+ rec_<id>/
11
+ ├── manifest.json
12
+ ├── events/
13
+ │ ├── segment_0001-cursor.jsonl
14
+ │ ├── segment_0001-input.jsonl
15
+ │ ├── segment_0001-windows.jsonl
16
+ │ └── segment_0001-focus.jsonl
17
+ ├── segments/
18
+ │ ├── segment_0001/
19
+ │ │ ├── display_<id>.mp4
20
+ │ │ ├── camera_<id>.mov
21
+ │ │ └── microphone_<id>.m4a
22
+ │ └── segment_0002/
23
+ ├── edits/
24
+ ├── analysis/
25
+ └── renders/
26
+ ```
27
+
28
+ Each connected display is recorded independently. System audio, microphone audio, and webcam video remain independently addressable logical tracks even when a native container carries multiple streams. Pause finalizes the current synchronized segment; resume opens another. Finalized media and event streams are immutable.
29
+
30
+ Cursor, click, key activity, focused-input bounds, window geometry, display topology, and lifecycle metadata use integer source-time microseconds plus native monotonic timestamps. Typed-text capture is disabled by default. Secure fields are always redacted.
31
+
32
+ ## Multi-asset projects
33
+
34
+ Projects live under the equally gitignored `artifacts/slopcamera/projects/` root. Generated images, videos, speech, transcripts, local effects, and immutable invocation receipts live under `artifacts/slopcamera/generated/`. A project owns references to immutable recording tracks and content-addressed imported media, not rewritten raw files.
35
+
36
+ ```text
37
+ project_<id>/
38
+ ├── project.json # assets, streams, placements, sync maps, analysis refs
39
+ ├── imports/ # extension-independent, content-addressed camera/audio takes
40
+ ├── edits/current.json # one global project-time edit plan
41
+ ├── analysis/
42
+ │ ├── alignment/ # immutable audio-alignment evidence
43
+ │ ├── faces/ # local face boxes and geometry-continuity tracks
44
+ │ ├── inactivity/ # synchronized freeze, silence, and interaction evidence
45
+ │ ├── music/ # presence, tempo/changes, and musical key
46
+ │ ├── scenes/ # sampled-frame descriptions and upload provenance
47
+ │ ├── speech/ # words, utterances, and filler candidates
48
+ │ └── scene-frames/ # bounded derived JPEG samples
49
+ ├── assets/ # content-addressed overlay inputs
50
+ └── renders/ # immutable plans plus verified video receipts
51
+ ```
52
+
53
+ Every imported take starts with an `unverified` placement. Audio alignment produces immutable candidates; applying one creates a checked, drift-aware map from that asset clock into project time. Cuts, trims, speed changes, camera moves, metadata zooms, and overlays exist once in project time, so all video and audio placements remain synchronized. Every asset-derived filler decision records the placement sync hash used to project it; stale decisions fail closed.
54
+
55
+ One output-time camera evaluator drives both the rendered video crop and the
56
+ metadata compositor. Cursor samples, click cues, and focused-input typing
57
+ therefore follow manual or face-derived pans and pushes through cuts and speed
58
+ changes instead of detaching from the pixels they annotate.
59
+
60
+ ## CLI
61
+
62
+ Run commands from the repository root:
63
+
64
+ ```sh
65
+ # Capture and inspect one synchronized recording.
66
+ slopcamera doctor
67
+ slopcamera record start
68
+ slopcamera record start \
69
+ --display <display-id> \
70
+ --camera-device <camera-id> \
71
+ --microphone-device <microphone-id>
72
+ slopcamera record pause
73
+ slopcamera record resume
74
+ slopcamera record stop
75
+ slopcamera recordings list --json
76
+ slopcamera inspect <recording>
77
+ slopcamera events <recording> --kind click --around 12.5s --jsonl
78
+ slopcamera render plan <recording> --display primary --json
79
+ slopcamera render run <recording> --output renders/final.mp4
80
+
81
+ # Build and align a multi-angle project.
82
+ slopcamera projects create --from-recording <recording> --name 'Slopcamera take'
83
+ slopcamera project add <project> camera-a.mov --role camera
84
+ slopcamera project add <project> field-recorder.wav --role portable-audio
85
+ slopcamera align analyze <project> --reference <asset:audio-stream> --target <asset:audio-stream> --apply
86
+ slopcamera project inspect <project> --json
87
+
88
+ # Discover and run every current Vercel AI Gateway media model.
89
+ slopcamera ai models list --type image --json
90
+ slopcamera ai models list --type video --json
91
+ slopcamera ai models show google/veo-3.1-generate-001 --json
92
+ AI_GATEWAY_API_KEY="$AI_GATEWAY_API_KEY" slopcamera ai models list --type image
93
+ slopcamera ai image generate --model openai/gpt-image-1.5 --prompt 'minimal chapter card'
94
+ slopcamera ai image generate --model google/gemini-3.1-flash-image \
95
+ --prompt 'revise this composition' --image reference.png --allow-cloud-upload
96
+ slopcamera ai video generate --model google/veo-3.1-generate-001 \
97
+ --prompt-file shot.txt --frame first=opening.png --frame last=closing.png \
98
+ --duration 8 --resolution 1080p --generate-audio true --allow-cloud-upload
99
+ slopcamera ai video generate --model alibaba/wan-v2.7-r2v \
100
+ --prompt 'continue the camera move' \
101
+ --reference 'https://cdn.example/source.mp4' \
102
+ --provider-options artifacts/slopcamera/private/wan-reference.json --allow-cloud-upload
103
+ slopcamera ai speech generate --model xai/grok-tts --text-file narration.txt --voice eve
104
+ slopcamera ai transcribe interview.wav --model openai/whisper-1 \
105
+ --allow-cloud-audio-upload --format all
106
+
107
+ # Create non-destructive local derivatives.
108
+ slopcamera media audio interview.wav --denoise --compressor --volume-db -2
109
+ slopcamera media audio screen.mp4 --delay-ms 160 --reverb room
110
+ slopcamera media color screen.mp4 --preset cinematic --temperature 0.08
111
+
112
+ # Structure local media evidence.
113
+ slopcamera analyze inactivity <project> --min-duration 3s --handle cut
114
+ slopcamera analyze inactivity <project> --min-duration 3s --handle cut --apply
115
+ slopcamera analyze music <project> --source <asset:audio-stream> --window 20s
116
+ slopcamera analyze faces <project> --source <asset:video-stream>
117
+ slopcamera faces list <project> <face-analysis-id> --min-duration 750ms
118
+ slopcamera analyze scenes <project> --source <asset:video-stream>
119
+ AI_GATEWAY_API_KEY=… slopcamera doctor
120
+ slopcamera analyze scenes <project> --source <asset:video-stream> --execute --allow-cloud-upload
121
+ slopcamera analyze speech <project> --source <asset:audio-stream> --model /path/to/ggml-model.bin
122
+ slopcamera fillers list <project> <speech-analysis-id> --auto-only
123
+ slopcamera fillers apply <project> <speech-analysis-id> <candidate-id>
124
+
125
+ # Project-wide edits and output.
126
+ slopcamera project edit <project> cut 8s 11.2s
127
+ slopcamera project edit <project> speed 20s 35s 1.5
128
+ slopcamera project edit <project> camera push --placement <id> --stream <id> --from 4s --to 6s --center 0.68,0.42 --end-zoom 1.8
129
+ slopcamera project edit <project> camera reframe --placement <id> --stream <id> --from 10s --to 14s --from-frame 0.5,0.5,1 --to-frame 0.67,0.45,2
130
+ slopcamera project edit <project> camera path --placement <id> --stream <id> --keyframe 0s,0.5,0.5,1 --keyframe 2s,0.65,0.42,1.4 --keyframe 5s,0.4,0.5,2
131
+ slopcamera project edit <project> camera follow-faces --placement <id> --analysis <face-analysis-id> --from 20s --to 35s --select largest
132
+ slopcamera project edit <project> zoom --from 12s --to 16s --target focused-input --source-placement <recording-placement>
133
+ slopcamera project edit <project> cursor on --click-highlight true --source-placement <recording-placement>
134
+ slopcamera project edit <project> typed-text on --idle-timeout 900ms --source-placement <recording-placement>
135
+ slopcamera project edit <project> overlay add --kind gif --source reaction.gif --from 4s --to 9s --loop
136
+ slopcamera project render plan <project> --json
137
+ slopcamera project render run <project> --output renders/final.mp4
138
+ ```
139
+
140
+ `record start` defaults to every connected display, system audio, the default
141
+ camera, and the default microphone. `doctor --json` exposes the exact selectable
142
+ IDs. Repeat `--display` for a bounded display subset, or pass
143
+ `--camera-device`/`--microphone-device` to pin a device instead of following the
144
+ system default. Duplicate IDs, unavailable IDs, and selections above the
145
+ 16-display capture bound fail before media starts.
146
+
147
+ Read commands default to a bounded text summary and accept `--json`; event queries also accept `--jsonl`. Mutations write atomically and return a normalized plan hash. Camera mutation receipts additionally return the created move ID, keyframe count, bounded face selection when applicable, and exact `camera show`/`camera remove` next commands.
148
+
149
+ ### Agent code mode
150
+
151
+ Code mode lets an agent describe the whole edit as a typed TypeScript graph instead of issuing one CLI command after another. Built-in workflows, custom programs, and the migrated CLI slices resolve through the same closed application-operation registry; legacy CLI-only analyzers and mutations remain characterized adapters until they are migrated operation by operation. The host owns every registered operation's schema, privacy classification, resource claims, retry rules, and receipts.
152
+
153
+ The surface is progressively disclosed:
154
+
155
+ | Need | Surface |
156
+ | --- | --- |
157
+ | One edit or analysis | Existing `slopcamera` command |
158
+ | A common complete recipe | `slopcamera workflows ...` |
159
+ | A project-specific composition | `@hraness/slopcamera/local/code` semantic builder |
160
+ | A reusable operation set | A namespaced TypeScript workflow fragment |
161
+ | A new privileged capability | A reviewed application operation and registry entry |
162
+
163
+ Discover the installed vocabulary and the six reusable recipes:
164
+
165
+ ```sh
166
+ slopcamera operations list --json
167
+ slopcamera operations show render.project@2 --json
168
+ slopcamera workflows list --json
169
+ slopcamera workflows show polished-screen-demo --json
170
+ slopcamera workflows show creative-iteration --json
171
+ slopcamera workflows show creative-selection --json
172
+ ```
173
+
174
+ List output stays compact; `operations show <kind>[@<version>] --json`
175
+ expands the selected operation's owned input and output JSON Schemas. A kind
176
+ with multiple registered versions must include `@<version>`.
177
+ `workflows show --json` expands the selected workflow's input JSON Schema. An
178
+ agent can therefore discover one contract without loading the entire catalog.
179
+
180
+ `code check`, `code plan`, and `code run` semantically typecheck custom
181
+ TypeScript before evaluating it. Planning then builds and validates the
182
+ complete graph, derives its effect and resource envelope, binds the current
183
+ structural project state, and prints deterministic dependency waves. It does
184
+ not execute registered operations. Typechecking and bundling consume the same
185
+ private immutable snapshot of the bytes that passed import-policy scanning.
186
+ Running with an expected custom-code plan hash fails if source, input,
187
+ registry, Bun revision, worker implementation, selected native-helper bytes,
188
+ or a bound subject changed.
189
+
190
+ ```sh
191
+ # A built-in workflow: independent analyses join at one checked edit commit,
192
+ # then a face-derived camera path becomes the immutable render revision.
193
+ slopcamera workflows plan polished-screen-demo \
194
+ --input artifacts/slopcamera/private/polished-input.json --json
195
+ slopcamera workflows run polished-screen-demo \
196
+ --input artifacts/slopcamera/private/polished-input.json --jobs 4 --jsonl
197
+
198
+ # A custom workflow starts from a non-overwriting typed template.
199
+ slopcamera code init artifacts/slopcamera/private/workflows/my-demo.ts
200
+ slopcamera code check artifacts/slopcamera/private/workflows/my-demo.ts --json
201
+ slopcamera code plan artifacts/slopcamera/private/workflows/my-demo.ts \
202
+ --input artifacts/slopcamera/private/my-demo-input.json --json
203
+ slopcamera code run artifacts/slopcamera/private/workflows/my-demo.ts \
204
+ --input artifacts/slopcamera/private/my-demo-input.json \
205
+ --plan <graph-plan-sha256> --jobs 4 --jsonl
206
+ ```
207
+
208
+ The polished input names the exact camera placement and project-time range; the
209
+ workflow never guesses which layer contains the presenter. Selecting `all`
210
+ uses group framing by default, while `largest` uses medium framing:
211
+
212
+ ```json
213
+ {
214
+ "cameraSource": "asset_camera01:stream_camera01",
215
+ "faceFollow": {
216
+ "placementId": "placement_camera01",
217
+ "projectRange": { "startUs": 0, "endUs": 30000000 },
218
+ "selection": { "kind": "all" }
219
+ },
220
+ "musicSource": "asset_music01:stream_music01",
221
+ "project": "project_demo01"
222
+ }
223
+ ```
224
+
225
+ Workflow construction is declarative: a method returns a typed `Ref<T>`, and embedding that reference in another node infers and independently verifies the dependency. Namespaces give reusable fragments stable node identities. Ordinary TypeScript remains available for loops over known variants, calculations from validated inputs, and composition:
226
+
227
+ ```ts
228
+ import { z } from "zod";
229
+ import { defineWorkflow } from "@hraness/slopcamera/local/code";
230
+ import {
231
+ renderFrozenProject,
232
+ resolveWorkflowRenderOptions,
233
+ } from "@hraness/slopcamera/local/code/workflows";
234
+
235
+ const Input = z.strictObject({
236
+ project: z.string(),
237
+ });
238
+
239
+ export default defineWorkflow({
240
+ id: "my-demo",
241
+ inputSchema: Input,
242
+ inputSchemaId: "example.workflow.my-demo.input/v1",
243
+ version: 1,
244
+ build(workflow, input) {
245
+ const project = workflow.project.snapshot("project", input.project);
246
+ const evidence = workflow.namespace("evidence");
247
+ const inactivity = evidence.analysis.inactivity("inactivity", { project });
248
+ const edits = workflow.edits.batch("edits", {
249
+ cutRanges: inactivity.select("cuts"),
250
+ });
251
+ const committed = workflow.project.commitEdits("commit", {
252
+ batch: edits,
253
+ project,
254
+ });
255
+ const rendered = renderFrozenProject(workflow, "final", {
256
+ target: {
257
+ canvas: { kind: "profile", profileId: "landscape" },
258
+ tier: "final",
259
+ },
260
+ output: resolveWorkflowRenderOptions(
261
+ undefined,
262
+ "renders/my-demo/final.mp4",
263
+ ),
264
+ project: committed,
265
+ });
266
+ return { render: rendered.output };
267
+ },
268
+ });
269
+ ```
270
+
271
+ `social-variants@3` uses the same target model for 16:9, 9:16, 1:1, and 4:5.
272
+ It defaults to full-duration 24 fps preview geometry and accepts
273
+ `"tier": "final"` for the 30 fps final canvas sizes. When captions are requested,
274
+ clean and burn-in outputs share one immutable geometry revision; independent
275
+ geometry branches remain explicit in the graph. V2 render nodes reserve the
276
+ shared bounded CPU and FFmpeg pools plus one exclusive video-encode slot. Every
277
+ other FFmpeg operation also reserves the complete pools until its recipe binds
278
+ and proves a smaller execution-wide thread budget. On
279
+ macOS and Linux, that admission state is machine-global across Slopcamera
280
+ processes and Git worktrees, so encodes from parallel agents cannot contend
281
+ with one another. Other ready work remains eligible when its declared
282
+ resources fit.
283
+
284
+ `creative-iteration@1` takes two through sixteen stable variant keys. Every
285
+ candidate uses the same frozen project snapshot, owns an immutable edit
286
+ revision, and renders a full-length preview at the selected standard profile.
287
+ The workflow closes the verified candidate set into a matrix and stops. It
288
+ does not choose or promote a winner:
289
+
290
+ ```json
291
+ {
292
+ "project": "project_demo01",
293
+ "previewProfile": "portrait",
294
+ "candidates": [
295
+ { "variantKey": "baseline" },
296
+ {
297
+ "variantKey": "tight-cut",
298
+ "ordered": [
299
+ { "kind": "trim", "range": { "startUs": 0, "endUs": 30000000 } }
300
+ ]
301
+ }
302
+ ]
303
+ }
304
+ ```
305
+
306
+ Use `creative-selection@1` with the matrix reference returned by that run.
307
+ The selection is always an immutable artifact. Setting `"promote": true`
308
+ adds a checked editorial compare-and-swap. Named deliveries copy a selected
309
+ verified render without changing the current edit plan:
310
+
311
+ ```json
312
+ {
313
+ "matrix": { "...": "the exact matrix reference from the prior run" },
314
+ "variantKey": "tight-cut",
315
+ "promote": true,
316
+ "deliveries": [
317
+ {
318
+ "deliveryKey": "review-copy",
319
+ "renderName": "preview",
320
+ "destinationPath": "renders/review/selected.mp4"
321
+ }
322
+ ]
323
+ }
324
+ ```
325
+
326
+ Custom Bun workflows can split this lifecycle across agents. Parse prior run
327
+ outputs with `ProjectSnapshotOutputSchema`,
328
+ `CreativeCandidateReferenceV1Schema`, `VariantMatrixReferenceV1Schema`, or
329
+ `VariantSelectionReferenceV1Schema`. Then adopt them with
330
+ `workflow.iteration.baseFromSnapshot`, `candidateFromReference`,
331
+ `matrixFromReference`, or `selectionFromReference`. Immutable candidate
332
+ publication can overlap across processes. One canonical project store owns the
333
+ media state; worktrees are for code authoring, not competing project copies.
334
+ Promotion accepts only the exact frozen edit basis. A concurrent editorial
335
+ change leaves every candidate intact and rejects the promotion.
336
+ Candidate preview outputs use a stable full derivation identity. An exact run
337
+ can adopt the original immutable output and verified receipt before any FFmpeg
338
+ preparation; a changed revision, plan, target, encoder recipe, byte policy,
339
+ sync policy, Slopcamera renderer ABI, or probed toolchain receives a distinct
340
+ path. This specialized
341
+ reuse does not claim that unrelated render operations share a generic cache.
342
+
343
+ References embedded in node inputs create data dependencies. For causal order
344
+ without passing a value, every semantic helper also accepts `after`:
345
+
346
+ ```ts
347
+ const started = workflow.recording.start("start", recordingOptions);
348
+ const paused = workflow.recording.pause("pause", { after: started });
349
+ const resumed = workflow.recording.resume("resume", { after: paused });
350
+ const stopped = workflow.recording.stop("stop", { after: resumed });
351
+ ```
352
+
353
+ An `after` reference must already belong to the same builder, so control edges
354
+ cannot point forward, cross graphs, or create a cycle.
355
+
356
+ Overlay preparation is also a first-class operation. Independent image, SVG,
357
+ GIF, video, and checked emoji preparations run in parallel; `addOverlays`
358
+ becomes their explicit join, and one checked project transaction publishes the
359
+ complete composition. A Gateway output reference can feed an overlay directly
360
+ without converting it to an ambient path:
361
+
362
+ ```ts
363
+ const title = workflow.media.overlay("title", {
364
+ project,
365
+ range: { startUs: 0, endUs: 3_000_000 },
366
+ source: { artifact: { path: "assets/title.svg" }, kind: "svg" },
367
+ });
368
+ const generated = workflow.gateway.image("generated-card", {
369
+ model: "openai/gpt-image-1.5",
370
+ prompt: "A restrained chapter card on transparent black.",
371
+ });
372
+ const generatedCard = workflow.media.overlay("generated-overlay", {
373
+ project,
374
+ range: { startUs: 3_000_000, endUs: 6_000_000 },
375
+ source: {
376
+ artifact: generated.select("outputs").at(0),
377
+ kind: "image",
378
+ },
379
+ });
380
+ const overlayBatch = workflow.edits.addOverlays(
381
+ "overlay-batch",
382
+ [title, generatedCard],
383
+ );
384
+ const composed = workflow.project.commitEdits("overlay-commit", {
385
+ batch: overlayBatch,
386
+ project,
387
+ });
388
+ ```
389
+
390
+ Each prepared layer receives a content-derived ID, an immutable preparation
391
+ receipt, and a project-local content-addressed asset. Stable `identityKey`
392
+ values distinguish deliberate duplicate uses of the same bytes. The built-in
393
+ `chaptered-demo@3` packages the same prepare-many/commit-once pattern behind a
394
+ bounded overlay-set input.
395
+
396
+ Complete edit transactions are an explicit second layer. Ordinary
397
+ `edits.batch` / `commitEdits` nodes stay on the metadata-free version-1
398
+ contract. A workflow that needs interaction effects, manual camera moves, or
399
+ zoom operations opts into the stable `completeBatch` /
400
+ `commitCompleteEdits` semantic surface. Those names advance to the newest
401
+ resource-bounded host contract; workflow authors do not select storage
402
+ versions:
403
+
404
+ ```ts
405
+ import {
406
+ polishedInteractionEffects,
407
+ } from "@hraness/slopcamera/local/code";
408
+
409
+ const autoZooms = workflow.analysis.projectAutoZooms("auto-zooms", {
410
+ project,
411
+ });
412
+ const complete = workflow.edits.completeBatch("complete-edit", {
413
+ ordered: [
414
+ {
415
+ kind: "add-zooms",
416
+ zooms: autoZooms.select("operations"),
417
+ },
418
+ polishedInteractionEffects(autoZooms.select("sourcePlacementId")),
419
+ ],
420
+ });
421
+ const polished = workflow.project.commitCompleteEdits("commit-complete", {
422
+ batch: complete,
423
+ project,
424
+ });
425
+ ```
426
+
427
+ Manual zoom intent is the next additive layer. `manualZoom` accepts ordinary
428
+ string IDs and may omit both placement and display selectors. The host
429
+ transaction resolves those selectors from the current project and recording,
430
+ then binds the stopped manifest and accepted placement synchronization before
431
+ publishing:
432
+
433
+ ```ts
434
+ import { manualZoom } from "@hraness/slopcamera/local/code";
435
+
436
+ const focus = manualZoom({
437
+ placementId: "placement_screen01",
438
+ range: { startUs: 12_000_000, endUs: 16_000_000 },
439
+ scale: 2,
440
+ target: { kind: "focused-input", paddingPx: 24 },
441
+ zoomId: "zoom_focusedinput01",
442
+ });
443
+ const zoomBatch = workflow.edits.addManualZooms("focus-zoom", [focus]);
444
+ const zoomed = workflow.project.commitCompleteEdits("commit-focus-zoom", {
445
+ batch: zoomBatch,
446
+ project,
447
+ });
448
+ ```
449
+
450
+ The complete metadata edit replaces cursor, click, keystroke, typed-text, and
451
+ metadata-placement settings together, so a recipe never inherits hidden prior
452
+ state. `setMetadataEffects` exposes the exact form; the conservative
453
+ `polishedInteractionEffects` preset keeps typed text off. `cameraPush` and
454
+ `cameraReframe` create binding-free normalized keyframes, while
455
+ `addManualCameraMoves`, `removeCameraMoves`, and `removeZooms` compose them into
456
+ the same ordered batch. Camera poses apply only inside each move range, so
457
+ adjacent moves should share a boundary pose when the shot must remain
458
+ continuous. The host—not workflow code—binds camera geometry, manual-zoom
459
+ display/recording identity, placement synchronization, and the exact
460
+ recording-manifest hash needed by metadata-driven effects. It rechecks that
461
+ evidence at the publication gate. Persisted version-1 and version-2 graphs
462
+ remain runnable; exact historical authoring is intentionally isolated under
463
+ the advanced namespace for immutable built-in workflows and migrations.
464
+ The current complete-batch contract accepts at most 10,000 expanded atomic
465
+ edits arranged into at most 64 adjacent normalization phases. Put related
466
+ additions or removals in one array: the host reduces each phase in linear time,
467
+ then validates the normalized boundary once. Workflows that must reproduce an
468
+ older, more highly alternating version-2 graph can select the exact historical
469
+ contract through `workflow.advanced`.
470
+
471
+ Local media passed directly to a media or Gateway node becomes a structural
472
+ file candidate automatically. If trusted compute must choose among files,
473
+ declare each workflow-input choice with `fileCandidate(...)` and validate it
474
+ with `WorkflowFileCandidateSchema`. Static planning binds the declared path,
475
+ media type, and optional exact byte/hash constraints without opening the file.
476
+ Only the chosen registered operation may then open and hash it while producing
477
+ the exact node plan; a compute-minted undeclared path fails before host
478
+ preparation or an approval prompt.
479
+
480
+ `workflow.analysis.scenes` runs the local FFmpeg scene planner without
481
+ uploading frames. Its node output contains the complete bounded scene ranges,
482
+ requested sample times, and sample reasons, while the ordinary completion
483
+ summary keeps only the plan digest and counts. Return the needed fields as
484
+ workflow outputs, or inspect the persisted evidence with
485
+ `slopcamera runs show <run-id> --nodes all --json`. Gateway scene descriptions
486
+ remain an explicit local `slopcamera analyze scenes ... --execute
487
+ --allow-cloud-upload` action.
488
+
489
+ The scheduler runs dependency-ready nodes concurrently while obeying the stricter of `--jobs`, the four-worker hard cap, and host resource pools for FFmpeg, Vision, local I/O, paid calls, output publication, project publication, and capture. Parallel analyses bind an append-only project edit basis, so one sibling may publish while another is paused without authorizing structural or prior-evidence drift. Mutable edits join into one ordered recoverable project transaction. Rendering first freezes the complete project and edit documents into an immutable geometry-bound revision, resolves an exact tool, media, and recording-metadata-bound plan, and publishes video plus receipt through an output-specific lease and durable precommit. Landscape, square, and portrait branches therefore remain independent.
490
+
491
+ Every run is durable under `artifacts/slopcamera/private/workflow-runs/<run-id>/`. Inspect it with `runs list` and `runs show`; use `runs resume`, `runs approve`, or `runs cancel` when the bounded summary provides that next action. A normal resume reconstructs unfinished host operations from the persisted graph without evaluating the workflow bundle. Exact canonical analysis orphans and output-only render commits are adopted only through their run-bound recovery evidence. An interrupted arbitrary compute callback becomes `ambiguous-code` and requires an exact node-specific replay acknowledgement. Attached cancellation first aborts that callback's real signal, then force-retires an uncooperative worker after a bounded grace period. A paid request uses an exact request ID and durable dispatch journal; an unknown post-dispatch outcome is never submitted again automatically. Live recording actions reconcile against the same controller used by the desktop app and are never automatically replayed.
492
+
493
+ Custom code mode is trusted code, not a sandbox. Module top-level code and explicitly replayed compute callbacks run as the current user and can use ambient filesystem, process and network authority. Slopcamera keeps its own credentials and privileged handles out of the worker, but it cannot contain malicious repository code. Review custom source before `code check`, `code plan`, or `code run`.
494
+
495
+ ### Gateway media
496
+
497
+ `slopcamera ai models` reads Vercel AI Gateway's public live catalog rather than a checked model allowlist. It includes image-model endpoints, image-generating language models, video, speech, and transcription. The cache uses conditional requests, a canonical revision, and stale-last-good fallback; `models show` preserves raw capabilities and exposes common settings plus the non-conflicting provider-option vocabulary known to this release. Batch and streaming transcription operations are labeled separately; the batch command rejects streaming-only models before credential access or dispatch. A bounded JSON object supplied with `--provider-options` remains the forward-compatible escape hatch for new service-owned fields. Gateway `models` fallback configuration is deliberately rejected because every paid model must be independently catalog-validated and durably accounted. Provider-specific sample-count fields are also rejected; use `--count` with `--max-per-call` at least as large so one Slopcamera job maps to one AI SDK call.
498
+
499
+ Slopcamera reads Vercel AI Gateway credentials from `AI_GATEWAY_API_KEY`, falling back to the `VERCEL_OIDC_TOKEN` injected by `vercel env run`. It never persists, prints, forwards to subprocesses, or accepts either value through argv.
500
+
501
+ Every paid invocation validates its live model kind, prompt, options, and all local files before dispatch. Reference images/videos require `--allow-cloud-upload`; transcription audio requires the separate `--allow-cloud-audio-upload`. Consent is per invocation. Slopcamera resolves only each explicitly named physical file, bounds its bytes and media type, and records its SHA-256 without enumerating adjacent bundle files. The same image/video flags accept credential-free public HTTPS sources when the live catalog permits `url` or does not declare a source restriction; a catalog that explicitly lists only other source forms fails locally. Use the URL directly when its path has a recognized extension, or `<media-type>=<https-url>` when it does not. URLs with credentials, fragments, local hostnames, or private literal addresses fail locally. Remote bytes and intrinsic geometry remain provider-validated; durable state stores only a URL digest and declared media type, never the URL itself. Direct URL arguments remain visible to shell and process history, so use only references safe for that exposure.
502
+
503
+ Image generation exposes prompt/edit images, mask, count, batch size, dimensions, aspect ratio, and seed. Video exposes every AI SDK media input and common parameter: primary image, first/last frames, image/audio/video references, count, batch size, aspect ratio, resolution (including provider values such as `1080p`), duration, FPS, seed, and generated audio. Illegal precedence combinations fail locally: frames cannot accompany generic references, and a primary image cannot accompany a first frame. `--provider-options` accepts a bounded nested vocabulary spanning Google Vertex/Veo, Kling, Alibaba Wan, ByteDance Seedance, xAI Grok, Gateway routing, image-provider, speech, and transcription parameters; fields that can change model selection or duplicate a paid sample count are rejected in favor of the validated first-class flags. Those options can include BYOK credentials, webhook secrets, or similarly sensitive values: keep the source JSON gitignored and mode `0600`. Slopcamera refuses a group- or world-accessible options file, forwards the parsed object for that invocation, and persists only its SHA-256 and namespace list—never the raw option values.
504
+
505
+ Video is one long-lived Gateway SSE request; Gateway does not expose a resumable job/status API. Slopcamera writes a local pre-dispatch receipt, sets the AI SDK client's `maxRetries` to zero, and never resubmits an interrupted paid call. AI Gateway may still route or fail over that one request across multiple providers, so a single command can produce multiple provider attempts, and provider timeouts may still incur charges; receipts retain bounded generation/provider-attempt metadata when the SDK returns it, including on failures. An interrupted dispatched request remains visibly ambiguous. Retrying is always a new explicit command and may charge again. Successful media downloads reject private/local network targets, validate every redirect, share a per-request aggregate byte budget, and are preserved with privacy-safe warning hashes, catalog revision, normalized settings, input/output hashes, and explicit complete/partial/overproduced sample fulfillment. Slopcamera fully decodes self-describing generated media locally before emitting an exact project-add command. Failed decode keeps the paid bytes and a hash-only quarantine receipt but returns an error and emits no import command. Headerless `audio/pcm`, `audio/l16`, `audio/alaw`, `audio/basic`, and `audio/mulaw` speech remains saved and hashed but deliberately receives no project-add suggestion; convert it with explicit sample metadata first.
506
+
507
+ `slopcamera media audio` and `slopcamera media color` never contact the network. Audio uses one documented deterministic order—denoise, compression, volume, delay, then deterministic multi-tap reverb—while omitting unrequested stages. Color combines seven common presets with brightness, contrast, saturation, gamma, temperature, tint, and hue. Both use bounded typed controls, checked FFmpeg argv, a verified descriptor-pinned input, fresh no-replace output publication, SHA-256 receipts, and leave the source unchanged. A path swap or in-place input mutation before publication fails closed without exposing the derived output. Output publication and receipt publication are sequential rather than one atomic pair: a process crash between them can leave an output without a receipt, and the next run reports a conflict so an agent can inspect and remove that orphan explicitly.
508
+
509
+ Resolved render plans are stored by their full composition hash, including the selected display. Every successful recording or project render writes a strict receipt beside the video that points to the immutable plan and records the output path, byte count, and SHA-256. Failed encodes never relabel an older output, and a receipt-publication failure removes any stale receipt.
510
+
511
+ Structural project mutations publish `project.json` and the current edit plan as one recoverable generation. Immutable before/after evidence lives under `state/transactions/`; an interrupted mutating command recovers it while holding the project lease, while unlocked readers fail closed until that recovery occurs.
512
+
513
+ ### Overlay model
514
+
515
+ Overlay sources may be images, sanitized SVGs, GIFs, videos, or generated emoji. Animated sources have explicit source trim, loop/hide/freeze-end behavior, playback rate, volume, and mix/duck policy. Every overlay supports contain/cover/fill, normalized crop, anchor and pixel position, size, rotation, opacity, z-index, blend mode, rounded mask, entrance/exit motion, and repeatable transform/opacity keyframes. Playback stays continuous through project cuts and speed boundaries.
516
+
517
+ Diagrams, vectorization, generated media, and timeline composition share the
518
+ same application-operation registry and content-addressed artifact references.
519
+ The CLI therefore returns outputs that can be passed directly to media ingest
520
+ or overlay operations rather than copied through ambient temporary paths:
521
+
522
+ ```sh
523
+ slopcamera diagram init concepts/system-map.diagram.json
524
+ slopcamera diagram check concepts/system-map.diagram.json --strict
525
+ slopcamera diagram render concepts/system-map.diagram.json --scale 2
526
+ slopcamera image vectorize artwork/mark.png \
527
+ --output artwork/mark.svg --duotone '#111827,#f9fafb' --alpha-cutoff 8 --json
528
+ slopcamera html catalog
529
+ slopcamera html scaffold paper-shaders --output overlays/title.html
530
+ ```
531
+
532
+ Diagram rendering publishes light and dark SVG/PNG variants plus editable
533
+ `.tldr` source. Vectorization publishes an inert bounded SVG and a quality
534
+ receipt. Both bind the exact input bytes and publish by content hash under
535
+ `artifacts/slopcamera/generated/`; repeated equivalent work reuses the same
536
+ artifact. PNG outputs can feed `media.ingest`, while SVG outputs already match
537
+ the `media.overlay` artifact contract. This is the common interchange layer
538
+ for stills, diagrams, animated loops, generated imagery, and final video.
539
+
540
+ ### Deterministic HTML overlays
541
+
542
+ `workflow.media.htmlOverlay` turns ordinary HTML, CSS, SVG, Canvas, WebGL, or a
543
+ declared local image into a transparent alpha-video layer. Start from the
544
+ portable authoring package instead of hand-writing CDN tags:
545
+
546
+ ```ts
547
+ import { createHtmlOverlayScaffoldInput } from "@hraness/slopcamera/local/html-overlay";
548
+
549
+ const scaffold = createHtmlOverlayScaffoldInput("paper-shaders");
550
+ const title = workflow.media.htmlOverlay("chapter-title", {
551
+ canvas: { deviceScaleFactor: 1, height: 1080, width: 1920 },
552
+ ...scaffold,
553
+ parameters: { label: "A new shape" },
554
+ project,
555
+ range: { startUs: 0, endUs: 3_000_000 },
556
+ resources: [{
557
+ artifact: { path: "artwork/logo.png" },
558
+ mediaType: "image/png",
559
+ name: "logo",
560
+ urlPath: "images/logo.png",
561
+ }],
562
+ seed: 42,
563
+ timing: { durationUs: 3_000_000, fps: 30 },
564
+ });
565
+ ```
566
+
567
+ The seven scaffolds are `plain`, `motion`, `p5`, `two`, `paper-shaders`,
568
+ `three`, and `vgpu`. Use `plain` for native layout and SVG, `motion` for DOM/SVG
569
+ choreography, `p5` for immediate Canvas 2D sketches, `two` for retained vector
570
+ 2D scenes, Paper Shaders for parameterized textures, Three.js for retained 3D, and
571
+ [vgpu](https://vgpu.sh) for explicit WGSL and WebGPU passes. `slopcamera html catalog
572
+ --json` returns this selection model with exact active library versions. The
573
+ [creative toolkit guide](../../docs/html-overlay-creative-toolkit.md) classifies
574
+ the wider ecosystem without adding those tools to Slopcamera's executable allowlist.
575
+
576
+ The p5 starter uses instance-mode P2D, makes p5's mandatory startup draw empty,
577
+ disables its native loop, and awaits one manual redraw from each absolute Slopcamera
578
+ frame. The Two.js starter selects WebGL explicitly, leaves autostart disabled,
579
+ preallocates a bounded retained vector scene, and calls one manual render per
580
+ Slopcamera frame. Both clear to transparent, use keyed Slopcamera randomness, avoid system
581
+ fonts and remote assets, and release their resources on page exit. Their exact
582
+ browser modules, versions, byte lengths, licenses, and SHA-256 values are
583
+ allowlisted. Author code imports only the scaffold's bare specifier; the host
584
+ supplies the canonical private import map.
585
+
586
+ The vgpu starter compiles its shader before readiness, submits one pass from
587
+ each absolute Slopcamera frame, waits for GPU completion, and clears to transparent.
588
+ It fails closed when the selected browser runtime cannot acquire WebGPU; it does
589
+ not silently replace the effect with another renderer.
590
+
591
+ The Three.js starter defines the authoring contract.
592
+ It has explicit sRGB output and ACES tone mapping, no shadows or postprocessing,
593
+ automatic camera framing, reusable tracked GPU resources, shader precompilation,
594
+ context-loss failure, and cleanup. Its default ceiling is 64 draw calls and
595
+ 200,000 triangles per frame. Motion comes only from the absolute Slopcamera frame
596
+ clock. `orbitTurns`, `zoom`, and `explode` are bounded parameters. Use a 1x
597
+ `deviceScaleFactor` for full-length previews and raise it only for a selected
598
+ final render.
599
+
600
+ Reference-image code generation is deliberately staged. Generate or select one
601
+ image, inspect it, create the `three` scaffold, and let the agent replace only
602
+ its `createSubject()` function. Review the source and several preview angles
603
+ before execution. The final workflow binds the exact reference artifact even
604
+ when the image is not visible in the scene:
605
+
606
+ ```ts
607
+ import { createThreeReferenceScaffoldInput } from "@hraness/slopcamera/local/html-overlay";
608
+
609
+ const generated = workflow.gateway.image("reference", imageOptions);
610
+ const reference = generated.select("outputs").at(0);
611
+ const binding = createThreeReferenceScaffoldInput(
612
+ reference,
613
+ reference.select("mediaType"),
614
+ );
615
+ const scene = workflow.media.htmlOverlay("reviewed-three-scene", {
616
+ ...binding,
617
+ document: { path: "overlays/reviewed-scene.html" },
618
+ canvas: { deviceScaleFactor: 1, height: 1080, width: 1920 },
619
+ parameters: { explode: 0.35, orbitTurns: 1, zoom: 1 },
620
+ project,
621
+ range: { startUs: 0, endUs: 3_000_000 },
622
+ timing: { durationUs: 3_000_000, fps: 30 },
623
+ });
624
+ ```
625
+
626
+ The reference is a normal generated output with exact bytes, media type, path,
627
+ and SHA-256. HTML resource binding verifies those facts and rejects a declared
628
+ media type that disagrees with the generated artifact. Slopcamera never accepts
629
+ model-produced JavaScript as an executable operation input. Code Mode evaluates
630
+ only the local workflow and scene source that the agent or user reviewed.
631
+
632
+ For a texture that should be visible, load only the declared private asset and
633
+ settle it before frame zero:
634
+
635
+ ```js
636
+ const texture = new THREE.TextureLoader()
637
+ .loadAsync(SlopcameraOverlay.asset("reference-image"))
638
+ .then((loaded) => {
639
+ loaded.colorSpace = THREE.SRGBColorSpace;
640
+ return loaded;
641
+ });
642
+ SlopcameraOverlay.ready(texture);
643
+ ```
644
+
645
+ Reference-led image treatments remain generated image derivatives in the same
646
+ Code Mode graph. The metallic-logo recipe preserves the supplied mark as the
647
+ shape authority and varies only the named brand, background color, and metal
648
+ color:
649
+
650
+ ```ts
651
+ import { createMetallicLogoImageRequest } from "@hraness/slopcamera/local/code";
652
+
653
+ const metallic = workflow.gateway.image("metallic-logo",
654
+ createMetallicLogoImageRequest({
655
+ backgroundColor: "warm gray",
656
+ brandName: "Hraness",
657
+ model: input.imageModel,
658
+ objectColor: "brushed cobalt",
659
+ reference: input.logo,
660
+ }));
661
+ ```
662
+
663
+ The model stays explicit because image-reference support is a live provider
664
+ capability. For CLI use, save the output of `createMetallicLogoPrompt(...)` as
665
+ `metallic-logo-prompt.txt`, inspect the live model first, and run a complete
666
+ reference-led request:
667
+
668
+ ```sh
669
+ slopcamera ai models show <reference-capable-model-id>
670
+ slopcamera ai image generate \
671
+ --model <reference-capable-model-id> \
672
+ --prompt-file metallic-logo-prompt.txt \
673
+ --image reference-logo.png \
674
+ --aspect-ratio 1:1 \
675
+ --count 1 \
676
+ --allow-cloud-upload
677
+ ```
678
+
679
+ Treat the output as a candidate until its silhouette, negative space,
680
+ proportions, and any lettering match the reference.
681
+
682
+ Author documents use the frozen `SlopcameraOverlay` API:
683
+
684
+ - `onFrame(({ frame, timeMs, deltaMs, progress, width, height }) => …)` updates
685
+ the document from Slopcamera's absolute frame clock.
686
+ - `ready(promise)` holds frame zero for bounded asset or setup work, and
687
+ `trackAnimation(controls)` lets the host seek Motion or Web Animations.
688
+ - `asset(name)` returns the private URL of a declared resource;
689
+ `parameters`, `seed`, `random()`, and `randomFor(key)` provide immutable input
690
+ and reproducible variation.
691
+ - `width`, `height`, `fps`, and `durationMs` expose the exact render geometry.
692
+
693
+ Keep `html` and `body` transparent and let the compositor place the result.
694
+ Remote fetches, popups, child frames, workers, object URLs, and undeclared
695
+ resources fail closed. Declare images, fonts, JSON, audio, and other local
696
+ bytes in `resources` and resolve them with `asset(name)`. Browser time, timers,
697
+ animation frames, `Date`, performance time, and entropy are virtualized so a
698
+ given input renders the same frames. Every render receipt carries a SHA-256
699
+ Merkle root over the full injected runtime, authored document, import map,
700
+ locked modules, declared resources, authoring configuration, and exact Chrome
701
+ runtime tree—not only its launcher. The same Merkle root binds the exact
702
+ Playwright Core version plus launch flags, fixed environment, context, routing,
703
+ CSP, and transparent-screenshot policy. Production accepts only a directly
704
+ launched native executable inside a supported Google Chrome app signed by
705
+ Google's `EQHXZ8M8AV` team; PATH shims, shell wrappers, other Chromium
706
+ distributions, and malformed app bundles are rejected.
707
+
708
+ Slopcamera binds every sorted bundle path, entry kind, mode, file length and
709
+ hash, or internal symlink target. Abort-aware bounded reads copy the complete
710
+ signed app bundle into a fresh mode-0700 snapshot while source-before,
711
+ source-after, snapshot, and code-signature provenance checks bracket the copy.
712
+ The browser snapshot is never placed beneath the caller-selected module cache
713
+ or ambient `TMPDIR`. On macOS it is a unique direct child of validated physical,
714
+ root-owned, sticky `/private/tmp`; Slopcamera binds that anchor's exact stable
715
+ metadata and watches the unique child basename. The verified app tree is then
716
+ recursively user-immutable. After private mode-0700 `HOME` and `TMPDIR`
717
+ siblings are created, Chrome launches only from that snapshot with a minimal
718
+ fixed environment. The mutable outer container is bound by exact identity and
719
+ anchor events while the app tree itself remains recursively immutable. The
720
+ parent is watched recursively, and its exact
721
+ device/inode/ctime/mode/size identity plus the full app manifest and child path
722
+ identities are rechecked after launch and through shutdown. macOS may change
723
+ only the app root's first-launch metadata; bound parent identity and root rename
724
+ events independently prove that the pathname was never swapped, while
725
+ every child ctime remains enforced. Signature checks and snapshot copying are
726
+ bounded and cancellation-aware, and the app-tree flags are released before the
727
+ private snapshot is removed afterward. A strict mode-0600 lease is held open for
728
+ the render lifetime. On startup, a bounded scavenger preserves every ambiguous,
729
+ live, open, foreign, or changing tree. It accepts either an authenticated
730
+ released cleanup or a stale, same-host, dead-owner tree, then atomically moves
731
+ the closed, identity-stable tree into a one-use quarantine pathname and proves
732
+ the moved tree closed a second time before cleanup. Normal teardown
733
+ rechecks the complete runtime manifest and every direct child, then
734
+ atomically changes its held active lease to a released marker before removing
735
+ validated children; that marker is unlinked last, so an interrupted cleanup is
736
+ recoverable even while the desktop process remains alive. These gates prevent
737
+ deletion from colliding with a new render container or a swapped peer subtree.
738
+ The signed snapshot is prepared once per render request and shared by every
739
+ frame in that sequence; callers should submit a complete loop or overlay range
740
+ rather than issuing one render request per frame.
741
+ The injected Playwright launcher remains a trusted host adapter. Authored
742
+ documents use the `SlopcameraOverlay` API.
743
+
744
+ The prepared HTML result is the same overlay handle returned by image, SVG,
745
+ GIF, video, and emoji preparation, so it joins `edits.addOverlays` and one
746
+ recoverable `project.commitEdits` transaction. Set its range to one loop cycle
747
+ when authoring a reusable animated loop; ordinary video-overlay playback policy
748
+ can then loop, trim, hide, or freeze that immutable asset in later compositions.
749
+
750
+ The optional emoji provider reads ignored local outputs under `apps/desktop/.generated/emoji-pack/`. All non-emoji editing remains available without that pack.
751
+
752
+ ### Camera motion and face following
753
+
754
+ Project camera moves provide Ken Burns-style digital push-ins, pull-outs, and pans for any enabled video layer. Coordinates are normalized against the prepared video layer after its crop and fit:
755
+
756
+ ```sh
757
+ # Move from a centered 1x frame to the requested center and zoom.
758
+ slopcamera project edit <project> camera push \
759
+ --placement <id> --stream <id> --from 4s --to 6s \
760
+ --center 0.68,0.42 --start-zoom 1 --end-zoom 1.8 --easing ease-in-out
761
+
762
+ # Move between two explicit center-x,center-y,zoom poses.
763
+ slopcamera project edit <project> camera reframe \
764
+ --placement <id> --stream <id> --from 10s --to 14s \
765
+ --from-frame 0.5,0.5,1 --to-frame 0.67,0.45,2 --easing ease-in-out
766
+
767
+ # Author an arbitrary path; the first and last keyframes define its range.
768
+ slopcamera project edit <project> camera path \
769
+ --placement <id> --stream <id> \
770
+ --keyframe 20s,0.5,0.5,1 \
771
+ --keyframe 22s,0.68,0.4,1.5 \
772
+ --keyframe 25s,0.42,0.52,2
773
+
774
+ slopcamera project edit <project> camera show
775
+ slopcamera project edit <project> camera remove <camera-move-id>
776
+ ```
777
+
778
+ Zoom ranges from 1x through 10x, and each center must keep the viewport inside the prepared layer. Camera moves interpolate zoom in log space for symmetric push-ins and pull-outs. They are bound to the selected placement synchronization and prepared-layer geometry; changing either makes the move stale instead of silently retargeting it.
779
+
780
+ On macOS 15 or newer, the offline Apple Vision analyzer can detect and track multiple faces in one immutable project video stream:
781
+
782
+ ```sh
783
+ slopcamera analyze faces <project> --source <asset:video-stream> \
784
+ --backend vision --sample-fps 8 --min-confidence 0.6 \
785
+ --max-track-gap 500ms --max-faces 32
786
+
787
+ slopcamera faces list <project> <face-analysis-id> \
788
+ --at 12s --min-duration 750ms --min-confidence 0.7 --limit 20
789
+ ```
790
+
791
+ `faces list` uses asset time. Face analysis is local-only, and normalized bounding boxes are the only stored visual evidence. Track IDs mean geometry continuity within that one analysis; Slopcamera performs no face recognition or biometric identification and stores no names, embeddings, crops, or thumbnails.
792
+
793
+ Apply that evidence as an ordinary, deterministic camera move by choosing the largest currently visible face, every active face, or one or more explicit tracks:
794
+
795
+ ```sh
796
+ slopcamera project edit <project> camera follow-faces \
797
+ --placement <id> --analysis <face-analysis-id> --from 20s --to 35s \
798
+ --select largest
799
+
800
+ slopcamera project edit <project> camera follow-faces \
801
+ --placement <id> --analysis <face-analysis-id> --from 20s --to 35s \
802
+ --select all --framing group
803
+
804
+ slopcamera project edit <project> camera follow-faces \
805
+ --placement <id> --analysis <face-analysis-id> --from 20s --to 35s \
806
+ --track <face-track-id> --track <another-face-track-id> \
807
+ --require-all-selected --gap-policy hold
808
+ ```
809
+
810
+ `--select largest` reevaluates each analyzed frame after crop/fit mapping: visible box area wins, then confidence, then lexical track ID for a stable tie. `--framing tight|medium|wide|group` controls the space around visible faces. By default, multi-face framing continues with whichever selected faces remain visible. Add `--require-all-selected` with explicit `--track` values or `--select all` when one missing selected face should trigger `--gap-policy hold|fallback|fail`: briefly keep the last frame, return to the full prepared layer, or reject the edit. Use `--min-zoom` and `--max-zoom` to bound the crop, `--smoothing` for a 0–1 second response time, `--headroom` for a 0–1 top-padding ratio, and `--output-width`/`--output-height` to declare the even-pixel render dimensions used for framing. The defaults are 1920×1080, 1x–2.2x zoom, 0.75 seconds of smoothing, and 0.18 headroom.
811
+
812
+ For a normalized video-layer layout, face following records the declared output aspect ratio. Render planning rejects a different aspect ratio because it would change face framing; rerun `camera follow-faces` with the intended dimensions before switching, for example, between 16:9 and vertical output. The generated move also remains bound to the exact analysis file, analyzed media, selected tracks, placement sync, and prepared-layer geometry.
813
+
814
+ ### Analysis boundaries
815
+
816
+ - Audio alignment uses bounded 8 kHz envelopes, reports ambiguity and drift, and never mutates a placement until a candidate is explicitly or safely automatically accepted.
817
+ - Face analysis runs only in the local macOS Apple Vision helper and persists normalized boxes with geometry-continuity track IDs. Face-follow application resolves that evidence into an ordinary camera path; rendering never invokes the detector.
818
+ - Project inactivity analysis requires simultaneous freeze evidence from every enabled screen stream and, by default, silence from every enabled audio stream. It projects asset detections and reference-recording interactions through each placement's current sync map, writes an immutable sidecar, and applies only global project-time cuts or speed ranges with analysis provenance.
819
+ - Music analysis writes presence regions, tempo regions and changes, beat evidence, and key regions into a sidecar referenced by the project.
820
+ - Scene analysis follows PySceneDetect's scene-boundary ergonomics as a reference while keeping an owned FFmpeg-native detector and typed evidence. Planning is local by default. Execution uploads only selected, resized derived frames, never a raw video, directly to Vercel AI Gateway through the same environment credential as other paid media commands and requires `--allow-cloud-upload`. Exact duplicate frames are collapsed per scene, and completed descriptions are reused only when the input, sampled-frame hashes, model, prompt, and sampling version all match.
821
+ - Speech analysis runs a caller-selected local whisper.cpp model and requires word timestamps. Before `fillers apply` can create a global cut, every enabled audio stream must have a current integrity-checked music analysis, and every other audible placement-stream must have complete current speech/no-speech evidence. Music regions and words are mapped through accepted placement sync into project time. Missing coverage, stale evidence, music, or speech overlap fails closed. Editorial overrides use an ordinary manual project cut.
822
+
823
+ ## Development
824
+
825
+ Use Bun 1.3.14. Portable checks do not compile native capture:
826
+
827
+ ```sh
828
+ bun test apps/desktop
829
+ bun x tsc --noEmit -p apps/desktop/tsconfig.json
830
+ bun x eslint apps/desktop
831
+ bun run build:desktop
832
+ bun run test:cli:compiled:macos
833
+ bun run test:html-overlay
834
+ bun run benchmark:code-concurrency
835
+ ```
836
+
837
+ Native capture targets Apple Silicon macOS 15 or newer. It uses ScreenCaptureKit for every display and system audio, plus AVFoundation for independent webcam and microphone files.
838
+
839
+ ```sh
840
+ bun x native doctor --manifest apps/desktop/app.zon --strict
841
+ bun run apps/desktop/capture/build.ts
842
+ bun run apps/desktop/analysis/build.ts
843
+ bun run dev:desktop
844
+ bun run build:desktop:macos
845
+ bun run package:desktop:macos
846
+ bun run verify:html-overlay:macos
847
+ ```
848
+
849
+ `test:html-overlay` is portable and leaves the real-browser tests registered as
850
+ skipped. `test:html-overlay:browser:macos` runs the real Chrome frame suite,
851
+ including a declared PNG. `test:html-overlay:libraries:macos` additionally
852
+ downloads and verifies every exact Motion, p5.js, Two.js, Paper Shaders,
853
+ Three.js, and vgpu lock. The integrity-bound Chrome contract selects WebGPU's
854
+ SwiftShader fallback
855
+ adapter so identical browser receipts do not silently choose different GPUs.
856
+ `test:html-overlay:operation:macos` runs the complete Chrome → PNG frames →
857
+ FFmpeg qtrle/argb → project-ingest operation. The combined
858
+ `verify:html-overlay:macos` requires Google Chrome, FFmpeg, and FFprobe at the
859
+ paths reported by `slopcamera doctor`.
860
+
861
+ `build:cli` emits the current-host Bun bundle used by the portable workspace
862
+ build. `build:cli:macos` emits `dist/slopcamera`, a copied-binary-tested Apple Silicon macOS
863
+ CLI. It bundles the headless diagram renderer, the isolated VTracer worker, the
864
+ exact Sharp native addon, and libvips; the bootstrap expands native media assets
865
+ into a fresh private temporary runtime and removes them when the command exits.
866
+ The compiled smoke copies the executable away from the checkout and proves
867
+ diagram initialization/rendering plus PNG-to-SVG vectorization without
868
+ `node_modules`.
869
+
870
+ Screen recording, microphone, camera, Input Monitoring, and Accessibility are separate macOS permissions. A missing optional source becomes a typed diagnostic; strict-input mode fails before recording begins. Packaged local builds are ad hoc signed evidence until a release workflow adds Developer ID signing, notarization, and updates.
871
+
872
+ ### Real capture hardware smoke
873
+
874
+ The real hardware smoke is deliberately outside portable and ordinary macOS
875
+ checks. Without the exact confirmation below it is registered as skipped and
876
+ does not build or probe the helper, inspect permissions, or create artifact
877
+ directories:
878
+
879
+ ```sh
880
+ SLOPCAMERA_CAPTURE_HARDWARE_CONFIRM=record-local-displays-and-selected-inputs \
881
+ bun run test:capture:hardware:macos
882
+ ```
883
+
884
+ The default profile records every connected display twice, with a pause between
885
+ the two immutable segments. It leaves system audio, camera, microphone, and
886
+ typed text disabled. Enable selected inputs explicitly:
887
+
888
+ ```sh
889
+ SLOPCAMERA_CAPTURE_HARDWARE_CONFIRM=record-local-displays-and-selected-inputs \
890
+ SLOPCAMERA_CAPTURE_HARDWARE_SYSTEM_AUDIO=true \
891
+ SLOPCAMERA_CAPTURE_HARDWARE_CAMERA=true \
892
+ SLOPCAMERA_CAPTURE_HARDWARE_MICROPHONE=true \
893
+ SLOPCAMERA_CAPTURE_HARDWARE_MIN_DISPLAYS=2 \
894
+ bun run test:capture:hardware:macos
895
+ ```
896
+
897
+ Add `SLOPCAMERA_CAPTURE_HARDWARE_INTERACTIONS=true` for the owned interaction
898
+ fixture. The fixture activates its nonce-titled window, performs one fixed
899
+ public → secure → public exercise against its own fields, and remains open with
900
+ neutral focus until capture stops. It can post only the built-in `a`, `s`, and
901
+ `b` canaries to its own PID at verified coordinates inside its focused window;
902
+ it accepts no arbitrary text, key, coordinate, or target from the caller. Do
903
+ not type, click, or switch applications until the command exits because doing
904
+ so can disturb focus or fixture timing. The fixture-PID event tap excludes
905
+ clicks and keys delivered to other applications from the exact evidence gate.
906
+ The profile binds the fixture's native-clock receipt to exact ordered click/key
907
+ pairs, display identity, fixture process identity, public and secure focus
908
+ transitions, and one native `focused` window transition. With the default
909
+ typed-text opt-out, the stopped bundle must contain no `typing.input` event and
910
+ no key cadence from the secure phase.
911
+
912
+ Set `SLOPCAMERA_CAPTURE_HARDWARE_TYPED_TEXT=true` together with the interaction
913
+ profile to verify explicit typed-text capture. That profile accepts exactly the
914
+ public `a` and `b` canaries in metadata; a native focus-identity allowlist binds
915
+ text persistence to the fixture's nonce-derived field ID, PID, window ID, and
916
+ nonce title. Text from any other input remains unpersisted, and the secure `s`
917
+ canary must remain absent. Failed typed-text evidence is deleted regardless of
918
+ the artifact retention setting. Typed-text hardware verification is
919
+ unavailable without the owned fixture.
920
+
921
+ Before capture, the smoke performs the helper's read-only strict probe. Screen
922
+ Recording, Input Monitoring, Accessibility, and window metadata must already be
923
+ authorized; each selected optional input must also be authorized and present.
924
+ An explicitly requested run fails before `start` when a prerequisite is
925
+ missing, so it cannot open a surprise permission prompt. Grant permissions by
926
+ running Slopcamera interactively first. Strict capture also creates and disables
927
+ the listen-only input event tap before starting any media recorder, then waits
928
+ for the tap's run-loop thread to confirm that it is enabled. Metadata writes
929
+ display, focus, window, and cursor boundary snapshots only after that handshake
930
+ and before a recorder can emit its first sample. At pause or stop, the
931
+ user-visible clock freezes, every recorder drains, all metadata pollers are
932
+ cancelled and joined on one serial queue, and metadata takes a final boundary
933
+ snapshot; finalization latency therefore does not become blank footage.
934
+ Tap creation or activation failure aborts the strict segment instead of
935
+ silently losing clicks and keys. Window focus comes from the frontmost
936
+ application's actual Accessibility-focused window matched back to its
937
+ positioned Core Graphics record, not the first enumerated window owned by that
938
+ process.
939
+
940
+ The smoke writes to a unique directory below
941
+ `artifacts/slopcamera/recordings/.hardware-smoke/`, verifies that Git ignores the
942
+ directory, drives the real start/pause/resume/stop controller, probes every
943
+ finalized media stream with FFprobe, and validates verified `capture-sync-v1`
944
+ sample-clock measurements in the manifest. Controller-lifecycle and
945
+ container-length checks are supplemental diagnostics, not substitutes for
946
+ sample timing. It also re-hashes every physical media file, streams and
947
+ re-hashes every event file through the production event parser, checks its
948
+ declared record count and time interval, and requires real cursor, display
949
+ topology, positioned-window, focus, and exact pause/resume lifecycle events.
950
+ For both active segments, opening lifecycle and environment snapshots must
951
+ precede the earliest retained sample across every selected display, system
952
+ audio, camera, and microphone stream, while a closing cursor and lifecycle
953
+ marker must follow the latest retained sample across that same complete
954
+ envelope.
955
+ Any native dropped-event diagnostic fails the run. Typed-text opt-out and any
956
+ observed secure-focus interval are checked directly against the parsed input
957
+ events.
958
+
959
+ Failed evidence is retained by default and its absolute path is printed. Set
960
+ `SLOPCAMERA_CAPTURE_HARDWARE_KEEP_ARTIFACTS=never` to remove every run or `always`
961
+ to keep successful runs too. Optional-input values must be exactly `true` or
962
+ `false`; the minimum-display value is bounded from 1 through 16.
963
+
964
+ ## Direct
965
+
966
+ `bun run direct:slopcamera` opens the deterministic recorder and project-evidence lab without native capture, FFmpeg, whisper.cpp, Python, or cloud calls. It exposes compact fixtures for multi-angle placement, alignment, music, scene boundaries/descriptions, speech fillers, synchronized edits, and all overlay kinds. Permission, analyzer, and project worlds are fixture evidence, not claims about live native execution. `bun run verify:slopcamera:direct` drives every declared browser scenario and writes agent-readable evidence.