@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,171 @@
1
+ import { z } from "zod";
2
+
3
+ import {
4
+ HtmlOverlayLibrarySelectionSchema,
5
+ type HtmlOverlayLibrarySelection,
6
+ } from "./libraries";
7
+
8
+ export const HTML_OVERLAY_SCAFFOLD_KINDS = Object.freeze([
9
+ "plain",
10
+ "motion",
11
+ "p5",
12
+ "two",
13
+ "paper-shaders",
14
+ "three",
15
+ "vgpu",
16
+ ] as const);
17
+
18
+ export const HtmlOverlayScaffoldKindSchema = z.enum(HTML_OVERLAY_SCAFFOLD_KINDS);
19
+ export type HtmlOverlayScaffoldKind = typeof HTML_OVERLAY_SCAFFOLD_KINDS[number];
20
+
21
+ export const HTML_OVERLAY_SCAFFOLD_PRIMARY_JOBS = Object.freeze([
22
+ "dom-layout",
23
+ "dom-motion",
24
+ "immediate-2d",
25
+ "retained-2d",
26
+ "shader-texture",
27
+ "scene-3d",
28
+ "gpu-pipeline",
29
+ ] as const);
30
+ export const HtmlOverlayScaffoldPrimaryJobSchema = z.enum(
31
+ HTML_OVERLAY_SCAFFOLD_PRIMARY_JOBS,
32
+ );
33
+ export type HtmlOverlayScaffoldPrimaryJob =
34
+ typeof HTML_OVERLAY_SCAFFOLD_PRIMARY_JOBS[number];
35
+
36
+ export const HTML_OVERLAY_SCAFFOLD_SUBSTRATES = Object.freeze([
37
+ "dom",
38
+ "canvas-2d",
39
+ "webgl",
40
+ "webgl-2",
41
+ "webgpu",
42
+ ] as const);
43
+ export const HtmlOverlayScaffoldSubstrateSchema = z.enum(
44
+ HTML_OVERLAY_SCAFFOLD_SUBSTRATES,
45
+ );
46
+ export type HtmlOverlayScaffoldSubstrate =
47
+ typeof HTML_OVERLAY_SCAFFOLD_SUBSTRATES[number];
48
+
49
+ export const HTML_OVERLAY_SCAFFOLD_CLOCK_INTEGRATIONS = Object.freeze([
50
+ "absolute-frame",
51
+ "seeked-animation",
52
+ ] as const);
53
+ export const HtmlOverlayScaffoldClockIntegrationSchema = z.enum(
54
+ HTML_OVERLAY_SCAFFOLD_CLOCK_INTEGRATIONS,
55
+ );
56
+ export type HtmlOverlayScaffoldClockIntegration =
57
+ typeof HTML_OVERLAY_SCAFFOLD_CLOCK_INTEGRATIONS[number];
58
+
59
+ export const HtmlOverlayScaffoldProfileSchema = z.strictObject({
60
+ bestFor: z.string().min(1).max(240),
61
+ clockIntegration: HtmlOverlayScaffoldClockIntegrationSchema,
62
+ kind: HtmlOverlayScaffoldKindSchema,
63
+ libraries: HtmlOverlayLibrarySelectionSchema,
64
+ primaryJob: HtmlOverlayScaffoldPrimaryJobSchema,
65
+ substrate: HtmlOverlayScaffoldSubstrateSchema,
66
+ summary: z.string().min(1).max(160),
67
+ });
68
+
69
+ type ParsedHtmlOverlayScaffoldProfile = z.infer<
70
+ typeof HtmlOverlayScaffoldProfileSchema
71
+ >;
72
+ export type HtmlOverlayScaffoldProfile = Readonly<
73
+ Omit<ParsedHtmlOverlayScaffoldProfile, "libraries">
74
+ & { readonly libraries: HtmlOverlayLibrarySelection }
75
+ >;
76
+
77
+ function frozenProfile(
78
+ input: z.input<typeof HtmlOverlayScaffoldProfileSchema>,
79
+ ): HtmlOverlayScaffoldProfile {
80
+ const parsed = HtmlOverlayScaffoldProfileSchema.parse(input);
81
+ return Object.freeze({
82
+ ...parsed,
83
+ libraries: Object.freeze([...parsed.libraries]),
84
+ });
85
+ }
86
+
87
+ /**
88
+ * Supported authoring profiles in stable recommendation order. This registry is
89
+ * advisory metadata, not persisted render state; exact executable provenance
90
+ * remains owned by the library-lock registry.
91
+ */
92
+ const HTML_OVERLAY_SCAFFOLD_PROFILE_BY_KIND = Object.freeze({
93
+ plain: frozenProfile({
94
+ bestFor: "Semantic layout, typography, SVG, and lightweight native Canvas work.",
95
+ clockIntegration: "absolute-frame",
96
+ kind: "plain",
97
+ libraries: [],
98
+ primaryJob: "dom-layout",
99
+ substrate: "dom",
100
+ summary: "Native document composition without a browser-library dependency.",
101
+ }),
102
+ motion: frozenProfile({
103
+ bestFor: "Titles, cards, lower thirds, and interface-like choreography.",
104
+ clockIntegration: "seeked-animation",
105
+ kind: "motion",
106
+ libraries: ["motion"],
107
+ primaryJob: "dom-motion",
108
+ substrate: "dom",
109
+ summary: "Seekable DOM and SVG choreography with Motion.",
110
+ }),
111
+ p5: frozenProfile({
112
+ bestFor: "Generative drawing, procedural illustration, and sketch-led art.",
113
+ clockIntegration: "absolute-frame",
114
+ kind: "p5",
115
+ libraries: ["p5"],
116
+ primaryJob: "immediate-2d",
117
+ substrate: "canvas-2d",
118
+ summary: "Immediate-mode Canvas 2D sketches with manual redraw.",
119
+ }),
120
+ two: frozenProfile({
121
+ bestFor: "Retained vector shapes, particles, and many-object 2D compositions.",
122
+ clockIntegration: "absolute-frame",
123
+ kind: "two",
124
+ libraries: ["two.js"],
125
+ primaryJob: "retained-2d",
126
+ substrate: "webgl",
127
+ summary: "Retained vector 2D scenes rendered through Two.js WebGL.",
128
+ }),
129
+ "paper-shaders": frozenProfile({
130
+ bestFor: "Mesh gradients, grain, distortion, and polished shader treatments.",
131
+ clockIntegration: "absolute-frame",
132
+ kind: "paper-shaders",
133
+ libraries: ["@paper-design/shaders"],
134
+ primaryJob: "shader-texture",
135
+ substrate: "webgl",
136
+ summary: "Declarative transparent shader textures and gradients.",
137
+ }),
138
+ three: frozenProfile({
139
+ bestFor: "Lit 3D subjects, spatial scenes, materials, and camera work.",
140
+ clockIntegration: "absolute-frame",
141
+ kind: "three",
142
+ libraries: ["three"],
143
+ primaryJob: "scene-3d",
144
+ substrate: "webgl-2",
145
+ summary: "Retained 3D scenes, materials, cameras, and custom shaders.",
146
+ }),
147
+ vgpu: frozenProfile({
148
+ bestFor: "Reviewed fullscreen WGSL effects and bounded multipass GPU work.",
149
+ clockIntegration: "absolute-frame",
150
+ kind: "vgpu",
151
+ libraries: ["vgpu"],
152
+ primaryJob: "gpu-pipeline",
153
+ substrate: "webgpu",
154
+ summary: "Explicit WGSL and WebGPU effects with pass-level control.",
155
+ }),
156
+ } satisfies Readonly<
157
+ Record<HtmlOverlayScaffoldKind, HtmlOverlayScaffoldProfile>
158
+ >);
159
+
160
+ export const HTML_OVERLAY_SCAFFOLD_PROFILES = Object.freeze(
161
+ HTML_OVERLAY_SCAFFOLD_KINDS.map(
162
+ kind => HTML_OVERLAY_SCAFFOLD_PROFILE_BY_KIND[kind],
163
+ ),
164
+ );
165
+
166
+ export function getHtmlOverlayScaffoldProfile(
167
+ kind: HtmlOverlayScaffoldKind,
168
+ ): HtmlOverlayScaffoldProfile {
169
+ const parsed = HtmlOverlayScaffoldKindSchema.parse(kind);
170
+ return HTML_OVERLAY_SCAFFOLD_PROFILE_BY_KIND[parsed];
171
+ }
@@ -0,0 +1,372 @@
1
+ import { z } from "zod";
2
+
3
+ import { canonicalJson } from "../core/canonical-json";
4
+ import { HtmlOverlayLibrarySelectionSchema } from "./libraries";
5
+
6
+ export const HTML_OVERLAY_SCHEMA_VERSION = 1 as const;
7
+ export const HTML_OVERLAY_MAX_HTML_BYTES = 1024 * 1024;
8
+ export const HTML_OVERLAY_MAX_PARAMETER_BYTES = 64 * 1024;
9
+ export const HTML_OVERLAY_MAX_PARAMETER_DEPTH = 8;
10
+ export const HTML_OVERLAY_MAX_PARAMETER_NODES = 2_048;
11
+ export const HTML_OVERLAY_MAX_RESOURCES = 64;
12
+ export const HTML_OVERLAY_MAX_RESOURCE_BYTES = 128 * 1024 * 1024;
13
+ export const HTML_OVERLAY_MAX_TOTAL_RESOURCE_BYTES = 256 * 1024 * 1024;
14
+ export const HTML_OVERLAY_MAX_DURATION_US = 3_600_000_000;
15
+ export const HTML_OVERLAY_MAX_FRAMES = 216_000;
16
+ export const HTML_OVERLAY_MAX_DEVICE_PIXELS_PER_FRAME = 33_554_432;
17
+ export const HTML_OVERLAY_MAX_TOTAL_PIXEL_SAMPLES = 300_000_000_000;
18
+
19
+ const textEncoder = new TextEncoder();
20
+ const Sha256Schema = z.string().regex(/^[a-f0-9]{64}$/u);
21
+ const ResourceNameSchema = z.string()
22
+ .min(1)
23
+ .max(64)
24
+ .regex(/^[a-z][a-z0-9]*(?:[-_.][a-z0-9]+)*$/u);
25
+ const ResourceUrlPathSchema = z.string()
26
+ .min(1)
27
+ .max(512)
28
+ .refine((path) => (
29
+ !path.startsWith("/")
30
+ && !path.includes("\\")
31
+ && !path.includes("\0")
32
+ && !path.includes("?")
33
+ && !path.includes("#")
34
+ && !path.includes("%")
35
+ && path.split("/").every(segment => (
36
+ /^[A-Za-z0-9][A-Za-z0-9._~@+-]{0,127}$/u.test(segment)
37
+ && segment !== "."
38
+ && segment !== ".."
39
+ ))
40
+ ), "Expected an unescaped relative URL path without dot segments, query, or fragment.");
41
+ const MediaTypeSchema = z.string()
42
+ .min(3)
43
+ .max(128)
44
+ .regex(/^[a-z0-9][a-z0-9!#$&^_.+-]*\/[a-z0-9][a-z0-9!#$&^_.+-]*$/u);
45
+ const Uint32Schema = z.number().int().safe().min(0).max(0xffff_ffff);
46
+
47
+ function compareAscii(left: string, right: string): number {
48
+ return left < right ? -1 : left > right ? 1 : 0;
49
+ }
50
+
51
+ export const HtmlOverlayCanvasSchema = z.strictObject({
52
+ deviceScaleFactor: z.number().finite().min(0.5).max(4),
53
+ height: z.number().int().safe().min(1).max(8_192),
54
+ width: z.number().int().safe().min(1).max(8_192),
55
+ }).superRefine((canvas, context) => {
56
+ const pixels = canvas.width * canvas.height * canvas.deviceScaleFactor ** 2;
57
+ if (pixels > HTML_OVERLAY_MAX_DEVICE_PIXELS_PER_FRAME) {
58
+ context.addIssue({
59
+ code: "custom",
60
+ message: `HTML overlay canvas exceeds ${HTML_OVERLAY_MAX_DEVICE_PIXELS_PER_FRAME} device pixels.`,
61
+ });
62
+ }
63
+ });
64
+ export type HtmlOverlayCanvas = Readonly<z.infer<typeof HtmlOverlayCanvasSchema>>;
65
+
66
+ export const HtmlOverlayTimingSchema = z.strictObject({
67
+ durationUs: z.number().int().safe().min(1).max(HTML_OVERLAY_MAX_DURATION_US),
68
+ fps: z.number().int().safe().min(1).max(120),
69
+ });
70
+ export type HtmlOverlayTiming = Readonly<z.infer<typeof HtmlOverlayTimingSchema>>;
71
+
72
+ export type HtmlOverlayParameterValue =
73
+ | boolean
74
+ | null
75
+ | number
76
+ | string
77
+ | readonly HtmlOverlayParameterValue[]
78
+ | { readonly [key: string]: HtmlOverlayParameterValue };
79
+ export type HtmlOverlayParameters = Readonly<Record<string, HtmlOverlayParameterValue>>;
80
+
81
+ const ParameterKeySchema = z.string()
82
+ .min(1)
83
+ .max(128)
84
+ .refine(key => key !== "__proto__", "The reserved __proto__ parameter key is not allowed.");
85
+
86
+ function createParameterValueSchema(depth: number): z.ZodType<HtmlOverlayParameterValue> {
87
+ const scalar = z.union([
88
+ z.null(),
89
+ z.boolean(),
90
+ z.number().finite().overwrite(value => Object.is(value, -0) ? 0 : value),
91
+ z.string().max(4_096),
92
+ ]);
93
+ if (depth >= HTML_OVERLAY_MAX_PARAMETER_DEPTH) return scalar;
94
+ const child = createParameterValueSchema(depth + 1);
95
+ const object = z.record(ParameterKeySchema, child).superRefine((value, context) => {
96
+ if (Object.keys(value).length > 64) {
97
+ context.addIssue({ code: "custom", message: "HTML overlay parameter objects may contain at most 64 keys." });
98
+ }
99
+ });
100
+ return z.union([
101
+ scalar,
102
+ z.array(child).max(128),
103
+ object,
104
+ ]);
105
+ }
106
+
107
+ const ParameterValueSchema = createParameterValueSchema(0);
108
+
109
+ const HtmlOverlayParametersStructureSchema = z
110
+ .record(ParameterKeySchema, ParameterValueSchema)
111
+ .superRefine((parameters, context) => {
112
+ if (Object.keys(parameters).length > 64) {
113
+ context.addIssue({ code: "custom", message: "HTML overlay parameters may contain at most 64 top-level keys." });
114
+ }
115
+ if (textEncoder.encode(canonicalJson(parameters)).byteLength > HTML_OVERLAY_MAX_PARAMETER_BYTES) {
116
+ context.addIssue({
117
+ code: "custom",
118
+ message: `HTML overlay parameters exceed ${HTML_OVERLAY_MAX_PARAMETER_BYTES} UTF-8 bytes.`,
119
+ });
120
+ }
121
+ const stack: HtmlOverlayParameterValue[] = Object.values(parameters);
122
+ let nodes = 0;
123
+ while (stack.length > 0) {
124
+ const value = stack.pop();
125
+ if (value === undefined) continue;
126
+ nodes += 1;
127
+ if (nodes > HTML_OVERLAY_MAX_PARAMETER_NODES) {
128
+ context.addIssue({
129
+ code: "custom",
130
+ message: `HTML overlay parameters exceed ${HTML_OVERLAY_MAX_PARAMETER_NODES} values.`,
131
+ });
132
+ break;
133
+ }
134
+ if (Array.isArray(value)) {
135
+ stack.push(...(value as readonly HtmlOverlayParameterValue[]));
136
+ } else if (value !== null && typeof value === "object") {
137
+ const record = value as Readonly<Record<string, HtmlOverlayParameterValue>>;
138
+ stack.push(...Object.values(record));
139
+ }
140
+ }
141
+ });
142
+
143
+ const HtmlOverlayParametersPreflightSchema = z.unknown().superRefine((input, context) => {
144
+ try {
145
+ if (
146
+ input === null
147
+ || typeof input !== "object"
148
+ || Array.isArray(input)
149
+ || (
150
+ Object.getPrototypeOf(input) !== Object.prototype
151
+ && Object.getPrototypeOf(input) !== null
152
+ )
153
+ ) {
154
+ context.addIssue({ code: "custom", message: "HTML overlay parameters must be a plain object." });
155
+ return;
156
+ }
157
+ const seen = new WeakSet<object>();
158
+ const stack: Array<{ readonly depth: number; readonly value: unknown }> = [{
159
+ depth: 0,
160
+ value: input,
161
+ }];
162
+ let nodes = 0;
163
+ while (stack.length > 0) {
164
+ const entry = stack.pop();
165
+ if (entry === undefined) break;
166
+ nodes += 1;
167
+ if (nodes > HTML_OVERLAY_MAX_PARAMETER_NODES) {
168
+ context.addIssue({
169
+ code: "custom",
170
+ message: `HTML overlay parameters exceed ${HTML_OVERLAY_MAX_PARAMETER_NODES} values.`,
171
+ });
172
+ return;
173
+ }
174
+ if (entry.depth > HTML_OVERLAY_MAX_PARAMETER_DEPTH + 1) {
175
+ context.addIssue({
176
+ code: "custom",
177
+ message: `HTML overlay parameters exceed depth ${HTML_OVERLAY_MAX_PARAMETER_DEPTH}.`,
178
+ });
179
+ return;
180
+ }
181
+ if (entry.value === null || typeof entry.value !== "object") continue;
182
+ if (seen.has(entry.value)) {
183
+ context.addIssue({ code: "custom", message: "HTML overlay parameters must not contain cycles or aliases." });
184
+ return;
185
+ }
186
+ seen.add(entry.value);
187
+ const prototype: unknown = Object.getPrototypeOf(entry.value);
188
+ if (Array.isArray(entry.value)) {
189
+ if (
190
+ prototype !== Array.prototype
191
+ || Reflect.ownKeys(entry.value).some(key => (
192
+ typeof key !== "string"
193
+ || (key !== "length" && !/^(?:0|[1-9][0-9]*)$/u.test(key))
194
+ ))
195
+ || Object.keys(entry.value).length !== entry.value.length
196
+ ) {
197
+ context.addIssue({ code: "custom", message: "HTML overlay parameter arrays must be dense plain arrays." });
198
+ return;
199
+ }
200
+ for (const item of entry.value) {
201
+ stack.push({ depth: entry.depth + 1, value: item });
202
+ }
203
+ continue;
204
+ }
205
+ if (prototype !== Object.prototype && prototype !== null) {
206
+ context.addIssue({ code: "custom", message: "HTML overlay parameter values must be plain JSON objects." });
207
+ return;
208
+ }
209
+ if (Object.hasOwn(entry.value, "__proto__")) {
210
+ context.addIssue({ code: "custom", message: "The reserved __proto__ parameter key is not allowed." });
211
+ return;
212
+ }
213
+ const ownKeys = Reflect.ownKeys(entry.value);
214
+ if (ownKeys.some(key => typeof key !== "string")) {
215
+ context.addIssue({ code: "custom", message: "HTML overlay parameter objects must not contain symbol keys." });
216
+ return;
217
+ }
218
+ const descriptors = Object.getOwnPropertyDescriptors(entry.value);
219
+ for (const [key, descriptor] of Object.entries(descriptors)) {
220
+ if (!("value" in descriptor)) {
221
+ context.addIssue({ code: "custom", message: "HTML overlay parameters must not contain accessors." });
222
+ return;
223
+ }
224
+ if (key.length === 0 || key.length > 128) {
225
+ context.addIssue({ code: "custom", message: "HTML overlay parameter keys must contain 1–128 characters." });
226
+ return;
227
+ }
228
+ stack.push({ depth: entry.depth + 1, value: descriptor.value });
229
+ }
230
+ }
231
+ } catch {
232
+ context.addIssue({ code: "custom", message: "HTML overlay parameters could not be inspected safely." });
233
+ }
234
+ });
235
+
236
+ export const HtmlOverlayParametersSchema: z.ZodType<HtmlOverlayParameters> =
237
+ HtmlOverlayParametersPreflightSchema.pipe(HtmlOverlayParametersStructureSchema);
238
+
239
+ export const HtmlOverlayDeclaredResourceSchema = z.strictObject({
240
+ bytes: z.number().int().safe().min(0).max(HTML_OVERLAY_MAX_RESOURCE_BYTES),
241
+ mediaType: MediaTypeSchema,
242
+ name: ResourceNameSchema,
243
+ sha256: Sha256Schema,
244
+ /** Explicit read-only browser fetch; absence preserves the historical CSP. */
245
+ transport: z.literal("fetch").optional(),
246
+ urlPath: ResourceUrlPathSchema,
247
+ });
248
+ export type HtmlOverlayDeclaredResource = Readonly<z.infer<typeof HtmlOverlayDeclaredResourceSchema>>;
249
+
250
+ export const HtmlOverlayDeclaredResourcesSchema = z.array(HtmlOverlayDeclaredResourceSchema)
251
+ .max(HTML_OVERLAY_MAX_RESOURCES)
252
+ .superRefine((resources, context) => {
253
+ if (new Set(resources.map(resource => resource.name)).size !== resources.length) {
254
+ context.addIssue({ code: "custom", message: "HTML overlay resource names must be unique." });
255
+ }
256
+ if (new Set(resources.map(resource => resource.urlPath)).size !== resources.length) {
257
+ context.addIssue({ code: "custom", message: "HTML overlay resource URL paths must be unique." });
258
+ }
259
+ const totalBytes = resources.reduce((total, resource) => total + resource.bytes, 0);
260
+ if (totalBytes > HTML_OVERLAY_MAX_TOTAL_RESOURCE_BYTES) {
261
+ context.addIssue({
262
+ code: "custom",
263
+ message: `HTML overlay resources exceed ${HTML_OVERLAY_MAX_TOTAL_RESOURCE_BYTES} total bytes.`,
264
+ });
265
+ }
266
+ })
267
+ .overwrite(resources => [...resources].sort((left, right) => compareAscii(left.name, right.name)));
268
+ export type HtmlOverlayDeclaredResources = Readonly<z.infer<typeof HtmlOverlayDeclaredResourcesSchema>>;
269
+
270
+ const HtmlDocumentSchema = z.string()
271
+ .min(1)
272
+ .max(HTML_OVERLAY_MAX_HTML_BYTES)
273
+ .refine(html => !html.includes("\0"), "HTML overlay documents must not contain NUL.")
274
+ .refine(
275
+ html => textEncoder.encode(html).byteLength <= HTML_OVERLAY_MAX_HTML_BYTES,
276
+ `HTML overlay documents may not exceed ${HTML_OVERLAY_MAX_HTML_BYTES} UTF-8 bytes.`,
277
+ );
278
+
279
+ export const HtmlOverlayInlineDocumentSchema = z.strictObject({
280
+ html: HtmlDocumentSchema,
281
+ });
282
+ export type HtmlOverlayInlineDocument = Readonly<
283
+ z.infer<typeof HtmlOverlayInlineDocumentSchema>
284
+ >;
285
+
286
+ export function htmlOverlayFrameCount(timing: HtmlOverlayTiming): number {
287
+ const parsed = HtmlOverlayTimingSchema.parse(timing);
288
+ return Math.ceil((parsed.durationUs * parsed.fps) / 1_000_000);
289
+ }
290
+
291
+ export const HtmlOverlayAuthoringInputSchema = z.strictObject({
292
+ canvas: HtmlOverlayCanvasSchema,
293
+ html: HtmlDocumentSchema,
294
+ // Studio v1 authoring inputs remain readable, but every parsed/new value is
295
+ // normalized to the canonical Slopcamera identity before hashing or render.
296
+ kind: z.union([
297
+ z.literal("slopcamera.html-overlay"),
298
+ z.literal("studio.html-overlay"),
299
+ ]).overwrite(() => "slopcamera.html-overlay" as const),
300
+ libraries: HtmlOverlayLibrarySelectionSchema.default([]),
301
+ parameters: HtmlOverlayParametersSchema.default({}),
302
+ resources: HtmlOverlayDeclaredResourcesSchema.default([]),
303
+ schemaVersion: z.literal(HTML_OVERLAY_SCHEMA_VERSION),
304
+ seed: Uint32Schema,
305
+ timing: HtmlOverlayTimingSchema,
306
+ }).superRefine((input, context) => {
307
+ const frames = htmlOverlayFrameCount(input.timing);
308
+ if (frames > HTML_OVERLAY_MAX_FRAMES) {
309
+ context.addIssue({
310
+ code: "custom",
311
+ message: `HTML overlay render exceeds ${HTML_OVERLAY_MAX_FRAMES} frames.`,
312
+ });
313
+ }
314
+ const pixels = input.canvas.width
315
+ * input.canvas.height
316
+ * input.canvas.deviceScaleFactor ** 2
317
+ * frames;
318
+ if (pixels > HTML_OVERLAY_MAX_TOTAL_PIXEL_SAMPLES) {
319
+ context.addIssue({
320
+ code: "custom",
321
+ message: `HTML overlay render exceeds ${HTML_OVERLAY_MAX_TOTAL_PIXEL_SAMPLES} total pixel samples.`,
322
+ });
323
+ }
324
+ });
325
+ export type HtmlOverlayAuthoringInput = Readonly<z.infer<typeof HtmlOverlayAuthoringInputSchema>>;
326
+
327
+ export const HtmlOverlayRuntimeFrameSchema = z.strictObject({
328
+ deltaMs: z.number().finite().nonnegative(),
329
+ frame: z.number().int().safe().nonnegative(),
330
+ height: z.number().int().safe().positive(),
331
+ progress: z.number().finite().min(0).max(1),
332
+ timeMs: z.number().finite().nonnegative(),
333
+ width: z.number().int().safe().positive(),
334
+ });
335
+ export type HtmlOverlayRuntimeFrame = Readonly<z.infer<typeof HtmlOverlayRuntimeFrameSchema>>;
336
+
337
+ export function createHtmlOverlayRuntimeFrame(
338
+ frame: number,
339
+ canvas: HtmlOverlayCanvas,
340
+ timing: HtmlOverlayTiming,
341
+ ): HtmlOverlayRuntimeFrame {
342
+ const parsedCanvas = HtmlOverlayCanvasSchema.parse(canvas);
343
+ const parsedTiming = HtmlOverlayTimingSchema.parse(timing);
344
+ if (!Number.isSafeInteger(frame) || frame < 0 || frame >= htmlOverlayFrameCount(parsedTiming)) {
345
+ throw new RangeError(`HTML overlay frame ${String(frame)} is outside the render range.`);
346
+ }
347
+ const timeMs = (frame * 1_000) / parsedTiming.fps;
348
+ const durationMs = parsedTiming.durationUs / 1_000;
349
+ return Object.freeze({
350
+ deltaMs: frame === 0 ? 0 : 1_000 / parsedTiming.fps,
351
+ frame,
352
+ height: parsedCanvas.height,
353
+ progress: Math.min(1, timeMs / durationMs),
354
+ timeMs,
355
+ width: parsedCanvas.width,
356
+ });
357
+ }
358
+
359
+ export function parseHtmlOverlayRuntimeFrame(
360
+ value: unknown,
361
+ canvas: HtmlOverlayCanvas,
362
+ timing: HtmlOverlayTiming,
363
+ ): HtmlOverlayRuntimeFrame {
364
+ const parsed = HtmlOverlayRuntimeFrameSchema.parse(value);
365
+ const expected = createHtmlOverlayRuntimeFrame(parsed.frame, canvas, timing);
366
+ for (const key of ["deltaMs", "frame", "height", "progress", "timeMs", "width"] as const) {
367
+ if (!Object.is(parsed[key], expected[key])) {
368
+ throw new RangeError(`HTML overlay frame field ${key} does not match the absolute render clock.`);
369
+ }
370
+ }
371
+ return expected;
372
+ }
@@ -0,0 +1,77 @@
1
+ import { z } from "zod";
2
+
3
+ /** Absence selects the historical software contract without changing its bytes. */
4
+ export const HtmlOverlayExecutionProfileSchema = z.enum([
5
+ "three-webgl2-hardware-v1",
6
+ "three-spark-webgl2-hardware-v1",
7
+ ]);
8
+ export type HtmlOverlayExecutionProfile = z.infer<typeof HtmlOverlayExecutionProfileSchema>;
9
+
10
+ const description = z.string().min(1).max(1_024);
11
+ const optionalDescription = z.string().max(1_024);
12
+ const dimension = z.number().int().positive().max(1_048_576);
13
+ export const HtmlOverlayWebGlContextEvidenceSchema = z.strictObject({
14
+ vendor: description, renderer: description, version: description.regex(/^WebGL 2\.0(?:\s|$)/u), shadingLanguageVersion: description,
15
+ unmaskedVendor: description, unmaskedRenderer: description,
16
+ maxTextureSize: dimension, maxRenderbufferSize: dimension,
17
+ maxViewportDimensions: z.tuple([dimension, dimension]),
18
+ halfFloatColorBuffer: z.literal(true),
19
+ });
20
+ export const HtmlOverlayBrowserGpuEvidenceSchema = z.strictObject({
21
+ devices: z.array(z.strictObject({
22
+ vendorId: z.number().int().min(0).max(0xffff_ffff), deviceId: z.number().int().min(0).max(0xffff_ffff),
23
+ vendorString: optionalDescription, deviceString: description,
24
+ driverVendor: optionalDescription, driverVersion: optionalDescription,
25
+ })).min(1).max(8),
26
+ glVendor: description, glRenderer: description, glVersion: description,
27
+ webgl: z.literal("enabled"), webgl2: z.literal("enabled").optional(),
28
+ });
29
+ const softwareRenderer = /swiftshader|llvmpipe|softpipe|software|microsoft basic render|lavapipe/iu;
30
+ const metalRenderer = /^ANGLE \(([^,()]+), ANGLE Metal Renderer: ([^,()]+), .+\)$/u;
31
+ function metalDeviceIdentity(renderer: string): string | undefined {
32
+ const match = metalRenderer.exec(renderer);
33
+ if (match === null || match[1]!.trim().length === 0 || match[2]!.trim().length === 0) return undefined;
34
+ // WebGL intentionally redacts the version suffix that CDP exposes. Preserve
35
+ // both raw observations; match the exact vendor/model with a Metal backend.
36
+ return JSON.stringify([match[1]!.trim(), match[2]!.trim()]);
37
+ }
38
+
39
+ /** Host observations, not authored assertions or a promise of cross-driver pixel identity. */
40
+ export const HtmlOverlayGpuEvidenceSchema = z.strictObject({
41
+ kind: z.literal("slopcamera.html-overlay-gpu-evidence"), schemaVersion: z.literal(1),
42
+ executionProfile: HtmlOverlayExecutionProfileSchema,
43
+ api: z.literal("webgl2"), backend: z.literal("angle-metal"),
44
+ platform: z.literal("darwin"), architecture: z.enum(["arm64", "x64"]), osRelease: description,
45
+ context: HtmlOverlayWebGlContextEvidenceSchema,
46
+ browserGpu: HtmlOverlayBrowserGpuEvidenceSchema,
47
+ }).superRefine((evidence, context) => {
48
+ const active = evidence.context.unmaskedRenderer;
49
+ const metal = metalDeviceIdentity(active);
50
+ const descriptions = [active, evidence.context.unmaskedVendor, evidence.browserGpu.glRenderer,
51
+ ...evidence.browserGpu.devices.flatMap(device => [device.deviceString, device.vendorString])];
52
+ if (metal === undefined
53
+ || softwareRenderer.test(descriptions.join("\n"))
54
+ || metalDeviceIdentity(evidence.browserGpu.glRenderer) !== metal
55
+ || !evidence.browserGpu.devices.some(device => metalDeviceIdentity(device.deviceString) === metal)) {
56
+ context.addIssue({ code: "custom", message: "Hardware rendering requires matching active WebGL2 and browser ANGLE Metal device evidence; software or unknown fallback is unsupported." });
57
+ }
58
+ });
59
+ export type HtmlOverlayGpuEvidence = z.infer<typeof HtmlOverlayGpuEvidenceSchema>;
60
+
61
+ export function parseHtmlOverlayGpuEvidence(input: unknown): HtmlOverlayGpuEvidence {
62
+ return HtmlOverlayGpuEvidenceSchema.parse(input);
63
+ }
64
+
65
+ /** Shared by production, projection verification and recovery without starting a GPU. */
66
+ export function assertHtmlOverlayGpuEvidenceProfile(
67
+ profile: HtmlOverlayExecutionProfile | undefined,
68
+ input: unknown,
69
+ ): HtmlOverlayGpuEvidence | undefined {
70
+ if (profile === undefined) {
71
+ if (input !== undefined) throw new Error("Legacy software rendering must not claim hardware evidence.");
72
+ return undefined;
73
+ }
74
+ const evidence = parseHtmlOverlayGpuEvidence(input);
75
+ if (evidence.executionProfile !== profile) throw new Error("GPU evidence differs from the requested execution profile.");
76
+ return evidence;
77
+ }