@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,288 @@
1
+ import { join, resolve } from "node:path";
2
+ import { ZodError } from "zod";
3
+
4
+ import type { ApplicationContext } from "../application/context";
5
+ import { DIRECTING_LIMITS, directingRequestId, type DirectingAttempt, type DirectingRecipe, type DirectingState } from "../application/directing-contract";
6
+ import {
7
+ activeDirectingSelections, attachDirectingEndpoint, buildDirectingTimeline,
8
+ completeDirectingAttempt, createDirectingState, directingRecipeSha256,
9
+ parseDirectingRecipe, parseDirectingState, reserveDirectingAttempt,
10
+ resolveDirectingShot, reviewDirectingAttempt, reviseDirectingRecipe,
11
+ settleDirectingAttempt, totalDirectingReservedMicroUsd,
12
+ } from "../application/directing-plan";
13
+ import {
14
+ dispatchGatewayOperation, GatewayVideoOperationResultSchema,
15
+ prepareGatewayOperation, reconcileGatewayOperation,
16
+ type GatewayPortRequest,
17
+ } from "../application/gateway-port";
18
+ import { canonicalJson, canonicalJsonSha256 } from "../core/canonical-json";
19
+ import { createNodeBundleFileSystem } from "../core/storage";
20
+ import type { DirectingCommand } from "./args";
21
+ import type { createDirectingBlobSession } from "./directing-blob";
22
+ import { assembleDirectingClips, extractDirectingEndpoint, importDirectingAnchor } from "./directing-media";
23
+ import { directingInputTransport, parseDirectingUsd, quoteDirectingShot } from "./directing-quote";
24
+ import { CliError } from "./errors";
25
+ import { GatewayMediaExecutionError } from "./gateway-media-service";
26
+ import { GatewayCredentialError } from "./gateway-credential";
27
+ import type { GatewayMediaCatalogView } from "./gateway-media-catalog";
28
+ import { withMutationLock } from "./mutation-lock";
29
+ import { ensurePhysicalPrivateDirectoryWithin, ensurePrivateDirectory } from "./paths";
30
+ import { publishSpatialSource, readSpatialJson } from "./spatial-scene-service";
31
+
32
+ export interface DirectingServiceAdapters {
33
+ readonly catalog: { get(input: { forceRefresh: boolean; freshness: "require-fresh"; signal: AbortSignal }): Promise<GatewayMediaCatalogView> };
34
+ readonly signal?: AbortSignal;
35
+ readonly createReferenceHosting?: (directingId: string, attemptId: string, signal: AbortSignal) => ReturnType<typeof createDirectingBlobSession>;
36
+ readonly media?: {
37
+ readonly anchor: typeof importDirectingAnchor;
38
+ readonly endpoint: typeof extractDirectingEndpoint;
39
+ readonly assemble: typeof assembleDirectingClips;
40
+ };
41
+ }
42
+
43
+ const STATE_FILE = "state.json";
44
+ const BUDGET_NOTICE = "USD amounts are retained catalog estimates, not settled invoices or a provider-enforced spending cap. Every dispatched or ambiguous take keeps its reservation. Gateway may make multiple provider attempts; client retries are disabled.";
45
+
46
+ function aborted(signal: AbortSignal): void {
47
+ if (signal.aborted) throw new CliError("cancelled", "Directing command interrupted; inspect or resume the retained take before continuing.");
48
+ }
49
+ function currentRecipe(state: DirectingState): DirectingRecipe {
50
+ return state.recipes.find(value => value.sha256 === state.activeRecipeSha256)!.recipe;
51
+ }
52
+ function snapshot(state: DirectingState) {
53
+ const active = activeDirectingSelections(state), reservedMicroUsd = totalDirectingReservedMicroUsd(state);
54
+ return {
55
+ id: state.id, recipeSha256: state.activeRecipeSha256,
56
+ budget: { maximumMicroUsd: state.budgetMicroUsd, reservedMicroUsd, remainingMicroUsd: state.budgetMicroUsd - reservedMicroUsd, notice: BUDGET_NOTICE },
57
+ shots: currentRecipe(state).shots.map(shot => ({
58
+ id: shot.id, prompt: shot.prompt, model: shot.model,
59
+ selectedAttempt: Object.hasOwn(state.selections, shot.id) ? state.selections[shot.id] : null,
60
+ selectionStatus: Object.hasOwn(active, shot.id) ? "accepted" : Object.hasOwn(state.selections, shot.id) ? "stale" : "unselected",
61
+ })),
62
+ attempts: state.attempts.map(attempt => ({
63
+ id: attempt.id, shotId: attempt.shotId, state: attempt.state,
64
+ reservedMicroUsd: attempt.state === "not-dispatched" ? 0 : attempt.quote.costMicroUsd,
65
+ requestId: attempt.requestId, dependencies: attempt.dependencies,
66
+ ...(attempt.state === "completed" ? { outputs: attempt.result.outputs, receipt: attempt.result.receipt, endpoint: attempt.endpoint ?? null, review: attempt.review ?? null } : {}),
67
+ })),
68
+ nextCommands: [`slopcamera direct inspect ${state.id} --json`, `slopcamera direct assemble ${state.id} --json`],
69
+ };
70
+ }
71
+
72
+ async function directoryFor(application: ApplicationContext, id: string): Promise<string> {
73
+ if (!/^direct_[a-z][a-z0-9_-]{0,63}$/u.test(id)) throw new CliError("usage", "Expected the exact direct_<id> identifier.");
74
+ await ensurePrivateDirectory(application.paths.privateRoot);
75
+ const root = await ensurePhysicalPrivateDirectoryWithin(application.paths.privateRoot, "directing");
76
+ return await ensurePhysicalPrivateDirectoryWithin(root, id);
77
+ }
78
+ async function readState(directory: string): Promise<DirectingState> {
79
+ return parseDirectingState(await readSpatialJson(join(directory, STATE_FILE), DIRECTING_LIMITS.stateBytes));
80
+ }
81
+
82
+ async function executeDirectingCommandBody(
83
+ application: ApplicationContext,
84
+ command: DirectingCommand,
85
+ adapters: DirectingServiceAdapters,
86
+ ): Promise<unknown> {
87
+ const signal = adapters.signal ?? new AbortController().signal;
88
+ const media = adapters.media ?? { anchor: importDirectingAnchor, endpoint: extractDirectingEndpoint, assemble: assembleDirectingClips };
89
+ const recipeAt = async (path: string) => parseDirectingRecipe(await readSpatialJson(resolve(application.paths.repositoryRoot, path), 8 * 1024 * 1024));
90
+ aborted(signal);
91
+ if (command.action === "init") {
92
+ const recipe = parseDirectingRecipe({
93
+ kind: "slopcamera.directing-recipe", schemaVersion: 1, id: "direct_film", title: "Untitled film",
94
+ shots: [{ id: "opening", model: "minimax/minimax-h3-max", prompt: "Replace this with the shot you want to direct.", durationSeconds: 5, resolution: "480p", aspectRatio: "16:9", fps: 24 }],
95
+ });
96
+ const path = resolve(application.paths.repositoryRoot, command.path);
97
+ await publishSpatialSource(path, recipe, async () => aborted(signal));
98
+ return { path, recipeSha256: directingRecipeSha256(recipe), nextCommand: `slopcamera direct plan ${JSON.stringify(command.path)} --json` };
99
+ }
100
+ if (command.action === "anchor") return await media.anchor(application, command.input, signal);
101
+ if (command.action === "plan") {
102
+ const recipe = await recipeAt(command.recipe);
103
+ const catalog = await adapters.catalog.get({ forceRefresh: true, freshness: "require-fresh", signal });
104
+ const shots = recipe.shots.map(shot => ({ shotId: shot.id, quote: quoteDirectingShot(catalog, shot, application.clock.now()), inputTransport: directingInputTransport(catalog, shot), continuity: shot.firstFrame?.kind === "shot-end" ? { requiresAcceptedShot: shot.firstFrame.shotId } : null }));
105
+ return { id: recipe.id, recipeSha256: directingRecipeSha256(recipe), shots, firstPassMicroUsd: shots.reduce((sum, shot) => sum + shot.quote.costMicroUsd, 0), notice: BUDGET_NOTICE };
106
+ }
107
+ if (command.action === "start") {
108
+ const recipe = await recipeAt(command.recipe);
109
+ const directory = await directoryFor(application, recipe.id);
110
+ return await withMutationLock(directory, { command: "direct start", label: `Directing ${recipe.id}` }, async lease => {
111
+ const state = createDirectingState(recipe, parseDirectingUsd(command.budgetUsd));
112
+ await lease.assertOwned();
113
+ const created = await createNodeBundleFileSystem(directory).writeTextNoReplace?.(STATE_FILE, `${canonicalJson(state)}\n`, async () => { aborted(signal); await lease.assertOwned(); });
114
+ if (created !== "created") throw new CliError("conflict", "This directing ID already has a retained budget. Inspect it or revise its recipe; starting again cannot reset spending.");
115
+ return snapshot(state);
116
+ });
117
+ }
118
+ const directory = await directoryFor(application, command.id);
119
+ if (command.action === "inspect") return snapshot(await readState(directory));
120
+ return await withMutationLock(directory, { command: `direct ${command.action}`, label: `Directing ${command.id}` }, async lease => {
121
+ let state = await readState(directory);
122
+ if (state.id !== command.id) throw new CliError("conflict", "The directing directory and retained identity differ.");
123
+ const save = async (next: DirectingState): Promise<void> => {
124
+ await lease.assertOwned();
125
+ const parsed = parseDirectingState(next);
126
+ await createNodeBundleFileSystem(directory).writeTextAtomicGuarded!(STATE_FILE, `${canonicalJson(parsed)}\n`, () => lease.assertOwned());
127
+ state = parsed;
128
+ };
129
+ const findAttempt = (id: string): DirectingAttempt => {
130
+ const value = state.attempts.find(attempt => attempt.id === id);
131
+ if (value === undefined) throw new CliError("not-found", "No retained take has this exact ID.");
132
+ return value;
133
+ };
134
+ const finishEndpoint = async (attemptId: string): Promise<void> => {
135
+ const attempt = findAttempt(attemptId);
136
+ if (attempt.state !== "completed") return;
137
+ // Reconciliation verifies the authoritative receipt and video even on reuse.
138
+ const reconciled = await reconcileGatewayOperation(application, { request: attempt.request, requestId: attempt.requestId, signal });
139
+ if (reconciled.status !== "completed") throw new CliError("conflict", "Completed directing media no longer matches its authoritative Gateway receipt.");
140
+ completeDirectingAttempt(state, attemptId, GatewayVideoOperationResultSchema.parse(reconciled.result));
141
+ const endpoint = await media.endpoint(application, attempt.result.outputs[0]!, "last", signal);
142
+ const next = attachDirectingEndpoint(state, attemptId, endpoint);
143
+ if (attempt.endpoint === undefined) await save(next);
144
+ };
145
+ const reconcile = async (attemptId: string): Promise<void> => {
146
+ const attempt = findAttempt(attemptId);
147
+ const result = await reconcileGatewayOperation(application, { request: attempt.request, requestId: attempt.requestId, signal });
148
+ if (result.status === "completed") {
149
+ await save(completeDirectingAttempt(state, attemptId, GatewayVideoOperationResultSchema.parse(result.result)));
150
+ await finishEndpoint(attemptId);
151
+ } else if (attempt.state === "completed") {
152
+ throw new CliError("conflict", "Retained completion no longer verifies; no budget was released.");
153
+ } else if (result.status === "not-dispatched" && attempt.state === "not-dispatched") {
154
+ // Only a previously retained, proven non-dispatch can stay released.
155
+ // A missing journal after restart cannot prove a reserved take was never sent.
156
+ return;
157
+ } else {
158
+ await save(settleDirectingAttempt(state, attemptId, "ambiguous", result.status));
159
+ throw new CliError("ambiguous", "This take may have been charged. Its reservation remains held; resume only checks retained local receipts and never resubmits a provider call.");
160
+ }
161
+ };
162
+ if (command.action === "cleanup") {
163
+ findAttempt(command.attempt);
164
+ if (adapters.createReferenceHosting === undefined) throw new CliError("unavailable", "Reference hosting is not configured.");
165
+ return await (await adapters.createReferenceHosting(state.id, command.attempt, signal)).cleanup();
166
+ }
167
+ if (command.action === "revise") {
168
+ await save(reviseDirectingRecipe(state, await recipeAt(command.recipe)));
169
+ } else if (command.action === "resume") {
170
+ await reconcile(command.attempt);
171
+ } else if (command.action === "review") {
172
+ if (command.decision === "accepted") await finishEndpoint(command.attempt);
173
+ await save(reviewDirectingAttempt(state, command.attempt, command.decision, command.note));
174
+ } else if (command.action === "assemble") {
175
+ const clips = buildDirectingTimeline(state);
176
+ for (const clip of clips) await finishEndpoint(clip.attemptId);
177
+ aborted(signal);
178
+ await lease.assertOwned();
179
+ const assembled = await media.assemble(application, { id: state.id, title: currentRecipe(state).title, clips: clips.map(({ shotId, attemptId, source, durationUs }) => ({ shotId, attemptId, source, durationUs })), recipeSha256: state.activeRecipeSha256 }, signal);
180
+ return { ...assembled, nextCommand: `slopcamera project render run ${assembled.projectId} --width 1280 --height 720 --fps 24 --output renders/directed-film.mp4 --json` };
181
+ } else if (command.action === "generate") {
182
+ const prior = state.attempts.find(attempt => attempt.id === command.attempt);
183
+ if (prior !== undefined) {
184
+ const resolved = resolveDirectingShot(state, command.shot);
185
+ if (prior.shotId !== command.shot || prior.shotSha256 !== resolved.shotSha256) throw new CliError("conflict", "This take ID is already bound to different shot input. Choose a new take ID for a deliberate new request.");
186
+ await reconcile(command.attempt);
187
+ return snapshot(state);
188
+ }
189
+ const dependencies = resolveDirectingShot(state, command.shot).dependencies;
190
+ for (const dependency of dependencies) await finishEndpoint(dependency.attemptId);
191
+ const resolved = resolveDirectingShot(state, command.shot), shot = resolved.shot;
192
+ if ((resolved.firstFrame !== undefined || resolved.lastFrame !== undefined) && !command.allowCloudUpload) throw new CliError("authorization-required", "This take uploads its exact retained image references. Supply --allow-cloud-upload for this request.");
193
+ const catalog = await adapters.catalog.get({ forceRefresh: true, freshness: "require-fresh", signal });
194
+ const quote = quoteDirectingShot(catalog, shot, application.clock.now());
195
+ const needsHosting = directingInputTransport(catalog, shot) === "url";
196
+ if (needsHosting && (!command.allowReferenceHosting || adapters.createReferenceHosting === undefined)) throw new CliError("authorization-required", "This model requires image URLs. Configure a private Vercel Blob store and supply --allow-reference-hosting for expiring access to these exact reference frames; --allow-cloud-upload is also required.");
197
+ if (quote.costMicroUsd > state.budgetMicroUsd - totalDirectingReservedMicroUsd(state)) throw new CliError("authorization-required", "This take exceeds the remaining directing budget. No paid request was dispatched.");
198
+ const request = await prepareGatewayOperation(application, {
199
+ signal,
200
+ request: { operation: "video", request: {
201
+ model: shot.model, prompt: shot.prompt, durationSeconds: shot.durationSeconds,
202
+ resolution: shot.resolution, aspectRatio: shot.aspectRatio, n: 1, maxVideosPerCall: 1,
203
+ timeoutMs: 10 * 60_000,
204
+ ...(shot.fps === undefined ? {} : { fps: shot.fps }),
205
+ ...(shot.seed === undefined ? {} : { seed: shot.seed }),
206
+ ...(resolved.firstFrame === undefined ? {} : { frames: [
207
+ { frameType: "first_frame" as const, source: resolved.firstFrame },
208
+ ...(resolved.lastFrame === undefined ? [] : [{ frameType: "last_frame" as const, source: resolved.lastFrame }]),
209
+ ] }),
210
+ } },
211
+ });
212
+ const requestId = directingRequestId({ id: state.id, attemptId: command.attempt, recipeSha256: state.activeRecipeSha256, shotSha256: resolved.shotSha256, request });
213
+ await save(reserveDirectingAttempt(state, {
214
+ id: command.attempt, recipeSha256: state.activeRecipeSha256, shotId: shot.id,
215
+ shotSha256: resolved.shotSha256, requestId, request, quote, state: "reserved", dependencies: resolved.dependencies,
216
+ }));
217
+ let hosting: Awaited<ReturnType<typeof createDirectingBlobSession>> | undefined;
218
+ const generation = await (async () => {
219
+ try {
220
+ hosting = needsHosting ? await adapters.createReferenceHosting!(state.id, command.attempt, signal) : undefined;
221
+ aborted(signal);
222
+ const result = GatewayVideoOperationResultSchema.parse(await dispatchGatewayOperation(application, {
223
+ request: request as GatewayPortRequest, requestId, signal,
224
+ ...(hosting === undefined ? {} : { resolveSourceUrl: hosting.resolveSourceUrl }),
225
+ beforeDispatch: async () => {
226
+ aborted(signal);
227
+ await lease.assertOwned();
228
+ const current = await readState(directory);
229
+ if (canonicalJsonSha256(current) !== canonicalJsonSha256(state)) throw new CliError("conflict", "The directing reservation changed before dispatch.");
230
+ quoteDirectingShot(catalog, shot, application.clock.now());
231
+ },
232
+ beforePublication: async () => { aborted(signal); await lease.assertOwned(); },
233
+ }));
234
+ await save(completeDirectingAttempt(state, command.attempt, result));
235
+ } catch (error) {
236
+ // Use an uncancelled, local-only read to retain charge ambiguity on abort.
237
+ const attempt = findAttempt(command.attempt);
238
+ const recovered = await reconcileGatewayOperation(application, { request: attempt.request, requestId, signal: new AbortController().signal }).catch(() => undefined);
239
+ if (recovered?.status === "completed") {
240
+ await save(completeDirectingAttempt(state, command.attempt, GatewayVideoOperationResultSchema.parse(recovered.result)));
241
+ } else {
242
+ const undispatched = recovered?.status === "not-dispatched";
243
+ const reason = error instanceof GatewayMediaExecutionError || error instanceof GatewayCredentialError || error instanceof CliError ? error.code : "pre-dispatch-failure";
244
+ await save(settleDirectingAttempt(state, command.attempt, undispatched ? "not-dispatched" : "ambiguous", undispatched ? reason : "unresolved-dispatch"));
245
+ throw new CliError(undispatched ? "unavailable" : "ambiguous", undispatched ? `The take failed before dispatch (${reason}); its reservation was released. Inspect model access and use a new take ID for a deliberate retry.` : "The take may have been charged. Its reservation remains held. Resume can recover completed local receipts; it never resubmits the provider call.", hosting === undefined ? undefined : { referenceHostingReceipt: hosting.receiptPath, cleanupCommand: `slopcamera direct cleanup ${state.id} --attempt ${command.attempt} --json` });
246
+ }
247
+ }
248
+ })().then(() => ({ ok: true as const }), (error: unknown) => ({ ok: false as const, error }));
249
+ let referenceHosting: { receiptPath: string; cleanupRequired: boolean; cleanupCommand: string; receipt?: Awaited<ReturnType<NonNullable<typeof hosting>["inspect"]>> } | undefined;
250
+ if (hosting !== undefined) {
251
+ const retained = findAttempt(command.attempt);
252
+ let receipt: Awaited<ReturnType<typeof hosting.inspect>> | undefined;
253
+ // An ambiguous remote job may still read its reference after the client stops.
254
+ try {
255
+ receipt = retained.state === "completed" || retained.state === "not-dispatched"
256
+ ? await hosting.cleanup() : await hosting.inspect();
257
+ } catch { /* Retain a recovery command even when the cleanup ledger cannot be read. */ }
258
+ referenceHosting = {
259
+ receiptPath: hosting.receiptPath,
260
+ cleanupRequired: receipt === undefined || receipt.entries.some(entry => entry.cleanup !== "deleted"),
261
+ cleanupCommand: `slopcamera direct cleanup ${state.id} --attempt ${command.attempt} --json`,
262
+ ...(receipt === undefined ? {} : { receipt }),
263
+ };
264
+ }
265
+ const withHostingEvidence = (error: unknown): unknown => {
266
+ if (referenceHosting === undefined) return error;
267
+ const known = error instanceof CliError;
268
+ return new CliError(known ? error.code : "internal", known ? error.message : "Local directing completion failed; inspect the retained take before retrying.", { referenceHosting });
269
+ };
270
+ if (!generation.ok) throw withHostingEvidence(generation.error);
271
+ try { await finishEndpoint(command.attempt); }
272
+ catch (error) { throw withHostingEvidence(error); }
273
+ return { ...snapshot(state), ...(referenceHosting === undefined ? {} : { referenceHosting }) };
274
+ }
275
+ return snapshot(state);
276
+ });
277
+ }
278
+
279
+ /** Keep invalid authored data and stale selections distinct from internal faults. */
280
+ export async function executeDirectingCommand(application: ApplicationContext, command: DirectingCommand, adapters: DirectingServiceAdapters): Promise<unknown> {
281
+ try { return await executeDirectingCommandBody(application, command, adapters); }
282
+ catch (error) {
283
+ if (error instanceof ZodError) throw new CliError("invalid-data", "Directing data does not match the recipe or retained-state contract.", { issues: error.issues.slice(0, 8).map(issue => ({ path: issue.path, message: issue.message })) });
284
+ if (error instanceof RangeError) throw new CliError("conflict", error.message);
285
+ if (error instanceof SyntaxError) throw new CliError("invalid-data", "Directing input must be valid bounded JSON.");
286
+ throw error;
287
+ }
288
+ }