@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,1434 @@
1
+ import { z } from "zod";
2
+
3
+ export type DeepReadonly<T> =
4
+ T extends bigint | boolean | null | number | string | symbol | undefined
5
+ ? T
6
+ : T extends readonly (infer Item)[]
7
+ ? readonly DeepReadonly<Item>[]
8
+ : T extends object
9
+ ? { readonly [Key in keyof T]: DeepReadonly<T[Key]> }
10
+ : T;
11
+
12
+ export type ReadonlyInferred<Schema extends z.ZodType> = DeepReadonly<z.infer<Schema>>;
13
+
14
+ const OPAQUE_ID_SUFFIX = /^[a-z0-9][a-z0-9_-]{7,63}$/u;
15
+
16
+ function opaqueId<Prefix extends string>(prefix: Prefix) {
17
+ return z.string().superRefine((value, context) => {
18
+ if (!value.startsWith(prefix) || !OPAQUE_ID_SUFFIX.test(value.slice(prefix.length))) {
19
+ context.addIssue({
20
+ code: "custom",
21
+ message: `Expected an opaque ${prefix} identifier.`,
22
+ });
23
+ }
24
+ });
25
+ }
26
+
27
+ export const RecordingIdSchema = opaqueId("rec_").brand<"RecordingId">();
28
+ export const TrackIdSchema = opaqueId("track_").brand<"TrackId">();
29
+ export const SegmentIdSchema = opaqueId("segment_").brand<"SegmentId">();
30
+ export const EventStreamIdSchema = opaqueId("events_").brand<"EventStreamId">();
31
+
32
+ export const MicrosecondsSchema = z.number().int().safe().nonnegative();
33
+ export const PositiveMicrosecondsSchema = z.number().int().safe().positive();
34
+ export const SignedMicrosecondsSchema = z.number().int().safe();
35
+ export const SequenceSchema = z.number().int().safe().nonnegative();
36
+ export const Sha256Schema = z.string().regex(/^[a-f0-9]{64}$/u);
37
+ export const IsoTimestampSchema = z.string().datetime({ offset: true });
38
+
39
+ export const CAPTURE_SYNC_ONSET_FLOOR_US = 50_000;
40
+ export const CAPTURE_SYNC_DRIFT_FLOOR_US = 20_000;
41
+ export const CAPTURE_SYNC_DRIFT_PPM = 200;
42
+
43
+ export interface CaptureSyncPlacementInput {
44
+ readonly clockNativeStartUs: number;
45
+ readonly clockSourceEndUs: number;
46
+ readonly clockSourceStartUs: number;
47
+ readonly fileContainerOriginPtsUs: number;
48
+ readonly fileEndPtsUs: number;
49
+ readonly fileFirstPtsUs: number;
50
+ readonly helperNativeStartUs: number;
51
+ }
52
+
53
+ export interface CaptureSyncPlacement {
54
+ readonly endUs: number;
55
+ readonly fileRangeEndUs: number;
56
+ readonly fileRangeStartUs: number;
57
+ readonly rawEndUs: number;
58
+ readonly rawStartUs: number;
59
+ readonly startUs: number;
60
+ }
61
+
62
+ export function deriveCaptureSyncPlacement(
63
+ input: CaptureSyncPlacementInput,
64
+ ): CaptureSyncPlacement | null {
65
+ if (
66
+ Object.values(input).some(value => !Number.isSafeInteger(value))
67
+ || input.clockSourceStartUs < 0
68
+ || input.clockSourceEndUs <= input.clockSourceStartUs
69
+ ) {
70
+ return null;
71
+ }
72
+ const fileDurationUs = input.fileEndPtsUs - input.fileFirstPtsUs;
73
+ const rawStartUs = input.clockSourceStartUs
74
+ + input.helperNativeStartUs
75
+ - input.clockNativeStartUs;
76
+ const rawEndUs = rawStartUs + fileDurationUs;
77
+ const startUs = Math.max(input.clockSourceStartUs, rawStartUs);
78
+ const endUs = Math.min(input.clockSourceEndUs, rawEndUs);
79
+ const normalizedFileStartUs = input.fileFirstPtsUs
80
+ - input.fileContainerOriginPtsUs;
81
+ const fileRangeStartUs = normalizedFileStartUs + startUs - rawStartUs;
82
+ const fileRangeEndUs = fileRangeStartUs + endUs - startUs;
83
+ const values = [
84
+ fileDurationUs,
85
+ rawStartUs,
86
+ rawEndUs,
87
+ startUs,
88
+ endUs,
89
+ normalizedFileStartUs,
90
+ fileRangeStartUs,
91
+ fileRangeEndUs,
92
+ ];
93
+ if (
94
+ values.some(value => !Number.isSafeInteger(value))
95
+ || fileDurationUs <= 0
96
+ || startUs < 0
97
+ || endUs <= startUs
98
+ || fileRangeStartUs < 0
99
+ || fileRangeEndUs <= fileRangeStartUs
100
+ ) {
101
+ return null;
102
+ }
103
+ return {
104
+ endUs,
105
+ fileRangeEndUs,
106
+ fileRangeStartUs,
107
+ rawEndUs,
108
+ rawStartUs,
109
+ startUs,
110
+ };
111
+ }
112
+
113
+ export function deriveCaptureSyncSpanToleranceUs(
114
+ tickUs: number,
115
+ maximumSampleDurationUs: number,
116
+ ): number | null {
117
+ const toleranceUs = Math.max(1, tickUs, maximumSampleDurationUs);
118
+ return Number.isSafeInteger(toleranceUs) && toleranceUs > 0
119
+ ? toleranceUs
120
+ : null;
121
+ }
122
+
123
+ export interface CaptureSyncToleranceInput {
124
+ readonly referenceDurationUs: number;
125
+ readonly referenceEndUncertaintyUs: number;
126
+ readonly referenceFirstUncertaintyUs: number;
127
+ readonly referenceMaximumSampleDurationUs: number;
128
+ readonly subjectEndUncertaintyUs: number;
129
+ readonly subjectFirstUncertaintyUs: number;
130
+ readonly subjectMaximumSampleDurationUs: number;
131
+ }
132
+
133
+ export interface CaptureSyncTolerances {
134
+ readonly durationDriftUs: number;
135
+ readonly onsetSkewUs: number;
136
+ }
137
+
138
+ export function deriveCaptureSyncTolerances(
139
+ input: CaptureSyncToleranceInput,
140
+ ): CaptureSyncTolerances | null {
141
+ if (
142
+ Object.values(input).some(value => !Number.isSafeInteger(value) || value < 0)
143
+ || input.referenceDurationUs <= 0
144
+ || input.referenceMaximumSampleDurationUs <= 0
145
+ || input.subjectMaximumSampleDurationUs <= 0
146
+ ) {
147
+ return null;
148
+ }
149
+ const maximumSampleDurationUs = Math.max(
150
+ input.subjectMaximumSampleDurationUs,
151
+ input.referenceMaximumSampleDurationUs,
152
+ );
153
+ const onsetSkewUs = Math.max(
154
+ CAPTURE_SYNC_ONSET_FLOOR_US,
155
+ input.subjectFirstUncertaintyUs
156
+ + input.referenceFirstUncertaintyUs
157
+ + maximumSampleDurationUs,
158
+ );
159
+ const ppmToleranceUs = Number(
160
+ (
161
+ BigInt(input.referenceDurationUs) * BigInt(CAPTURE_SYNC_DRIFT_PPM)
162
+ + 999_999n
163
+ ) / 1_000_000n,
164
+ );
165
+ const durationDriftUs = Math.max(
166
+ CAPTURE_SYNC_DRIFT_FLOOR_US,
167
+ ppmToleranceUs,
168
+ input.subjectFirstUncertaintyUs
169
+ + input.subjectEndUncertaintyUs
170
+ + input.referenceFirstUncertaintyUs
171
+ + input.referenceEndUncertaintyUs
172
+ + 2 * maximumSampleDurationUs,
173
+ );
174
+ return Number.isSafeInteger(onsetSkewUs)
175
+ && Number.isSafeInteger(durationDriftUs)
176
+ && onsetSkewUs >= 0
177
+ && durationDriftUs >= 0
178
+ ? { durationDriftUs, onsetSkewUs }
179
+ : null;
180
+ }
181
+
182
+ export function deriveCaptureSyncDurationDriftPpm(
183
+ durationDriftUs: number,
184
+ referenceDurationUs: number,
185
+ ): number | null {
186
+ if (
187
+ !Number.isSafeInteger(durationDriftUs)
188
+ || !Number.isSafeInteger(referenceDurationUs)
189
+ || referenceDurationUs <= 0
190
+ ) {
191
+ return null;
192
+ }
193
+ const scaledMagnitude = BigInt(Math.abs(durationDriftUs)) * 1_000_000n;
194
+ const denominator = BigInt(referenceDurationUs);
195
+ const quotient = scaledMagnitude / denominator;
196
+ const remainder = scaledMagnitude % denominator;
197
+ const roundsAwayFromZero = durationDriftUs >= 0
198
+ ? remainder * 2n >= denominator
199
+ : remainder * 2n > denominator;
200
+ const magnitude = quotient + (roundsAwayFromZero ? 1n : 0n);
201
+ const result = Number(durationDriftUs < 0 ? -magnitude : magnitude);
202
+ return Number.isSafeInteger(result) ? result : null;
203
+ }
204
+
205
+ export function isSafeRepositoryRelativePath(value: string): boolean {
206
+ if (
207
+ value.length === 0
208
+ || value.length > 1024
209
+ || value.startsWith("/")
210
+ || value.startsWith("\\")
211
+ || /^[a-zA-Z]:/u.test(value)
212
+ || value.includes("\\")
213
+ || value.includes("\0")
214
+ || [...value].some((character) => {
215
+ const codePoint = character.codePointAt(0) ?? 0;
216
+ return codePoint <= 31 || codePoint === 127;
217
+ })
218
+ ) {
219
+ return false;
220
+ }
221
+ const parts = value.split("/");
222
+ return parts.every((part) => part.length > 0 && part !== "." && part !== "..");
223
+ }
224
+
225
+ export const RepositoryRelativePathSchema = z.string().refine(
226
+ isSafeRepositoryRelativePath,
227
+ "Use a normalized repository-relative path without empty, dot, or parent segments.",
228
+ );
229
+
230
+ export const PointSchema = z.strictObject({
231
+ x: z.number().finite(),
232
+ y: z.number().finite(),
233
+ });
234
+
235
+ export const RectSchema = PointSchema.extend({
236
+ height: z.number().finite().positive(),
237
+ width: z.number().finite().positive(),
238
+ }).strict();
239
+
240
+ export const PixelSizeSchema = z.strictObject({
241
+ height: z.number().int().safe().positive(),
242
+ width: z.number().int().safe().positive(),
243
+ });
244
+
245
+ export const PermissionStateSchema = z.enum([
246
+ "not-determined",
247
+ "authorized",
248
+ "denied",
249
+ "restricted",
250
+ "unavailable",
251
+ ]);
252
+
253
+ export const CapturePermissionsSchema = z.strictObject({
254
+ accessibility: PermissionStateSchema,
255
+ camera: PermissionStateSchema,
256
+ inputMonitoring: PermissionStateSchema,
257
+ microphone: PermissionStateSchema,
258
+ screenCapture: PermissionStateSchema,
259
+ systemAudio: PermissionStateSchema,
260
+ windowMetadata: PermissionStateSchema,
261
+ });
262
+
263
+ export const DisplaySourceSchema = z.strictObject({
264
+ bounds: RectSchema,
265
+ displayId: z.string().min(1).max(256),
266
+ isPrimary: z.boolean(),
267
+ label: z.string().min(1).max(512),
268
+ pixelSize: PixelSizeSchema,
269
+ refreshRateHz: z.number().finite().positive(),
270
+ scaleFactor: z.number().finite().positive(),
271
+ });
272
+
273
+ export const CameraSourceSchema = z.strictObject({
274
+ cameraId: z.string().min(1).max(256),
275
+ frameRate: z.number().finite().positive(),
276
+ label: z.string().min(1).max(512),
277
+ pixelSize: PixelSizeSchema,
278
+ position: z.enum(["front", "back", "external", "unspecified"]),
279
+ });
280
+
281
+ export const AudioSourceSchema = z.discriminatedUnion("kind", [
282
+ z.strictObject({
283
+ audioSourceId: z.string().min(1).max(256),
284
+ channels: z.number().int().safe().positive().max(64),
285
+ kind: z.literal("system"),
286
+ label: z.string().min(1).max(512),
287
+ sampleRateHz: z.number().int().safe().positive(),
288
+ }),
289
+ z.strictObject({
290
+ audioSourceId: z.string().min(1).max(256),
291
+ channels: z.number().int().safe().positive().max(64),
292
+ kind: z.literal("microphone"),
293
+ label: z.string().min(1).max(512),
294
+ sampleRateHz: z.number().int().safe().positive(),
295
+ }),
296
+ ]);
297
+
298
+ export const SourceInventorySchema = z.strictObject({
299
+ audio: z.array(AudioSourceSchema),
300
+ cameras: z.array(CameraSourceSchema),
301
+ displays: z.array(DisplaySourceSchema),
302
+ });
303
+
304
+ export const MAX_CAPTURE_INTERRUPTION_SEGMENTS = 128;
305
+ export const MAX_CAPTURE_INTERRUPTION_SOURCE_ID_BYTES = 256;
306
+
307
+ function utf8ByteLength(value: string): number {
308
+ return new TextEncoder().encode(value).byteLength;
309
+ }
310
+
311
+ const CaptureInterruptionSourceIdSchema = z.string().min(1).refine(
312
+ value =>
313
+ utf8ByteLength(value) <= MAX_CAPTURE_INTERRUPTION_SOURCE_ID_BYTES
314
+ && !value.includes("\0"),
315
+ `Expected a non-NUL source ID of at most ${MAX_CAPTURE_INTERRUPTION_SOURCE_ID_BYTES} UTF-8 bytes.`,
316
+ );
317
+
318
+ const CaptureInterruptionBaseShape = {
319
+ nativeTimeUs: MicrosecondsSchema,
320
+ recoverable: z.boolean(),
321
+ segmentIndex: z.number().int().safe().nonnegative()
322
+ .max(MAX_CAPTURE_INTERRUPTION_SEGMENTS - 1),
323
+ sourceId: CaptureInterruptionSourceIdSchema.nullable(),
324
+ sourceTimeUs: MicrosecondsSchema,
325
+ } as const;
326
+
327
+ export const CaptureInterruptionSchema = z.discriminatedUnion("source", [
328
+ z.strictObject({
329
+ ...CaptureInterruptionBaseShape,
330
+ code: z.enum([
331
+ "selected-display-disconnected",
332
+ "screen-stream-stopped",
333
+ "screen-recording-failed",
334
+ ]),
335
+ source: z.literal("screen"),
336
+ }),
337
+ z.strictObject({
338
+ ...CaptureInterruptionBaseShape,
339
+ code: z.literal("system-audio-track-missing"),
340
+ source: z.literal("system-audio"),
341
+ }),
342
+ z.strictObject({
343
+ ...CaptureInterruptionBaseShape,
344
+ code: z.enum([
345
+ "camera-device-disconnected",
346
+ "camera-session-interrupted",
347
+ "camera-runtime-error",
348
+ "camera-session-stopped",
349
+ "camera-recording-failed",
350
+ ]),
351
+ source: z.literal("camera"),
352
+ }),
353
+ z.strictObject({
354
+ ...CaptureInterruptionBaseShape,
355
+ code: z.enum([
356
+ "microphone-device-disconnected",
357
+ "microphone-session-interrupted",
358
+ "microphone-runtime-error",
359
+ "microphone-session-stopped",
360
+ "microphone-recording-failed",
361
+ ]),
362
+ source: z.literal("microphone"),
363
+ }),
364
+ ]);
365
+
366
+ export const PendingIntegritySchema = z.strictObject({
367
+ state: z.literal("pending"),
368
+ });
369
+
370
+ export const VerifiedIntegritySchema = z.strictObject({
371
+ bytes: z.number().int().safe().nonnegative(),
372
+ sha256: Sha256Schema,
373
+ state: z.literal("verified"),
374
+ });
375
+
376
+ export const FileIntegritySchema = z.discriminatedUnion("state", [
377
+ PendingIntegritySchema,
378
+ VerifiedIntegritySchema,
379
+ ]);
380
+
381
+ const LegacyMediaSegmentV1Schema = z.strictObject({
382
+ codec: z.string().min(1).max(128),
383
+ containerTrackIdentity: z.discriminatedUnion("kind", [
384
+ z.strictObject({ containerTrackId: z.string().min(1).max(256), kind: z.literal("verified") }),
385
+ z.strictObject({
386
+ diagnosticCode: z.string().min(1).max(128),
387
+ expectedRole: z.enum(["display-video", "camera-video", "system-audio", "microphone-audio"]),
388
+ kind: z.literal("provisional"),
389
+ }),
390
+ ]),
391
+ container: z.string().min(1).max(64),
392
+ endUs: PositiveMicrosecondsSchema,
393
+ integrity: FileIntegritySchema,
394
+ nativeEndUs: PositiveMicrosecondsSchema,
395
+ nativeStartUs: MicrosecondsSchema,
396
+ path: RepositoryRelativePathSchema,
397
+ segmentId: SegmentIdSchema,
398
+ startUs: MicrosecondsSchema,
399
+ streamIndex: z.number().int().safe().nonnegative(),
400
+ }).superRefine((segment, context) => {
401
+ if (segment.endUs <= segment.startUs) {
402
+ context.addIssue({ code: "custom", message: "Segment endUs must be greater than startUs." });
403
+ }
404
+ if (segment.nativeEndUs <= segment.nativeStartUs) {
405
+ context.addIssue({ code: "custom", message: "Segment nativeEndUs must be greater than nativeStartUs." });
406
+ }
407
+ });
408
+
409
+ const MediaFileRangeSchema = z.strictObject({
410
+ endUs: PositiveMicrosecondsSchema,
411
+ startUs: MicrosecondsSchema,
412
+ }).superRefine((range, context) => {
413
+ if (range.endUs <= range.startUs) {
414
+ context.addIssue({ code: "custom", message: "Media file range must have positive duration." });
415
+ }
416
+ });
417
+
418
+ const LegacyCaptureTimingSchema = z.strictObject({
419
+ kind: z.literal("legacy-estimate"),
420
+ nativeRange: z.strictObject({
421
+ endUs: PositiveMicrosecondsSchema,
422
+ startUs: MicrosecondsSchema,
423
+ }),
424
+ reason: z.literal("recording-manifest-v1-container-duration"),
425
+ }).superRefine((timing, context) => {
426
+ if (timing.nativeRange.endUs <= timing.nativeRange.startUs) {
427
+ context.addIssue({ code: "custom", message: "Legacy native timing range must have positive duration." });
428
+ }
429
+ });
430
+
431
+ export const CaptureSyncMeasurementSchema = z.strictObject({
432
+ captureSegmentIndex: z.number().int().safe().nonnegative().max(127),
433
+ durationDriftPpm: z.number().int().safe(),
434
+ durationDriftUs: SignedMicrosecondsSchema,
435
+ evidence: z.strictObject({
436
+ file: z.strictObject({
437
+ containerOriginPtsUs: SignedMicrosecondsSchema,
438
+ endPtsUs: SignedMicrosecondsSchema,
439
+ firstPtsUs: SignedMicrosecondsSchema,
440
+ spanToleranceUs: PositiveMicrosecondsSchema,
441
+ tickUs: PositiveMicrosecondsSchema,
442
+ }),
443
+ helper: z.strictObject({
444
+ bufferCount: z.number().int().safe().positive(),
445
+ clockAnchors: z.strictObject({
446
+ end: z.strictObject({
447
+ nativeTimeUs: MicrosecondsSchema,
448
+ ptsUs: SignedMicrosecondsSchema,
449
+ uncertaintyUs: MicrosecondsSchema,
450
+ }),
451
+ first: z.strictObject({
452
+ nativeTimeUs: MicrosecondsSchema,
453
+ ptsUs: SignedMicrosecondsSchema,
454
+ uncertaintyUs: MicrosecondsSchema,
455
+ }),
456
+ }),
457
+ containerDurationUs: PositiveMicrosecondsSchema,
458
+ presentation: z.strictObject({
459
+ endPtsUs: SignedMicrosecondsSchema,
460
+ firstPtsUs: SignedMicrosecondsSchema,
461
+ lastPtsUs: SignedMicrosecondsSchema,
462
+ maximumSampleDurationUs: PositiveMicrosecondsSchema,
463
+ }),
464
+ sampleCount: z.number().int().safe().positive(),
465
+ }),
466
+ }),
467
+ kind: z.literal("measured"),
468
+ nativeRange: z.strictObject({
469
+ endUs: PositiveMicrosecondsSchema,
470
+ startUs: MicrosecondsSchema,
471
+ }),
472
+ onsetSkewUs: SignedMicrosecondsSchema,
473
+ policy: z.literal("capture-sync-v1"),
474
+ presentation: z.strictObject({
475
+ endPtsUs: SignedMicrosecondsSchema,
476
+ firstPtsUs: SignedMicrosecondsSchema,
477
+ lastPtsUs: SignedMicrosecondsSchema,
478
+ }),
479
+ referenceTrackId: TrackIdSchema,
480
+ status: z.enum(["within-tolerance", "out-of-tolerance"]),
481
+ tolerance: z.strictObject({
482
+ durationDriftUs: MicrosecondsSchema,
483
+ onsetSkewUs: MicrosecondsSchema,
484
+ }),
485
+ }).superRefine((timing, context) => {
486
+ if (timing.nativeRange.endUs <= timing.nativeRange.startUs) {
487
+ context.addIssue({ code: "custom", message: "Measured native timing range must have positive duration." });
488
+ }
489
+ if (timing.presentation.lastPtsUs < timing.presentation.firstPtsUs) {
490
+ context.addIssue({ code: "custom", message: "Measured last PTS cannot precede first PTS." });
491
+ }
492
+ if (timing.presentation.endPtsUs <= timing.presentation.lastPtsUs) {
493
+ context.addIssue({ code: "custom", message: "Measured exclusive-end PTS must follow the last PTS." });
494
+ }
495
+ if (
496
+ timing.evidence.helper.presentation.firstPtsUs !== timing.presentation.firstPtsUs
497
+ || timing.evidence.helper.presentation.lastPtsUs !== timing.presentation.lastPtsUs
498
+ || timing.evidence.helper.presentation.endPtsUs !== timing.presentation.endPtsUs
499
+ ) {
500
+ context.addIssue({ code: "custom", message: "Capture sync summary PTS must match its raw timing evidence." });
501
+ }
502
+ if (
503
+ timing.evidence.helper.clockAnchors.first.nativeTimeUs !== timing.nativeRange.startUs
504
+ || timing.evidence.helper.clockAnchors.end.nativeTimeUs !== timing.nativeRange.endUs
505
+ || timing.evidence.helper.clockAnchors.first.ptsUs !== timing.evidence.helper.presentation.firstPtsUs
506
+ || timing.evidence.helper.clockAnchors.end.ptsUs !== timing.evidence.helper.presentation.endPtsUs
507
+ ) {
508
+ context.addIssue({ code: "custom", message: "Capture sync ranges must match their raw clock anchors." });
509
+ }
510
+ const presentationSpanUs = timing.evidence.helper.presentation.endPtsUs
511
+ - timing.evidence.helper.presentation.firstPtsUs;
512
+ const nativeSpanUs = timing.evidence.helper.clockAnchors.end.nativeTimeUs
513
+ - timing.evidence.helper.clockAnchors.first.nativeTimeUs;
514
+ const clockMappingToleranceUs = timing.evidence.helper.clockAnchors.first.uncertaintyUs
515
+ + timing.evidence.helper.clockAnchors.end.uncertaintyUs
516
+ + 2;
517
+ if (Math.abs(nativeSpanUs - presentationSpanUs) > clockMappingToleranceUs) {
518
+ context.addIssue({ code: "custom", message: "Capture native clock anchors exceed their recorded mapping uncertainty." });
519
+ }
520
+ if (
521
+ timing.evidence.helper.presentation.endPtsUs
522
+ - timing.evidence.helper.presentation.lastPtsUs
523
+ > timing.evidence.helper.presentation.maximumSampleDurationUs
524
+ ) {
525
+ context.addIssue({ code: "custom", message: "Capture sync final sample exceeds its recorded maximum duration." });
526
+ }
527
+ const helperSpanUs = timing.evidence.helper.presentation.endPtsUs
528
+ - timing.evidence.helper.presentation.firstPtsUs;
529
+ const fileSpanUs = timing.evidence.file.endPtsUs - timing.evidence.file.firstPtsUs;
530
+ const expectedSpanToleranceUs = deriveCaptureSyncSpanToleranceUs(
531
+ timing.evidence.file.tickUs,
532
+ timing.evidence.helper.presentation.maximumSampleDurationUs,
533
+ );
534
+ if (fileSpanUs <= 0) {
535
+ context.addIssue({ code: "custom", message: "Finalized file timing evidence must have positive duration." });
536
+ }
537
+ if (
538
+ expectedSpanToleranceUs === null
539
+ || timing.evidence.file.spanToleranceUs !== expectedSpanToleranceUs
540
+ ) {
541
+ context.addIssue({ code: "custom", message: "Finalized file span tolerance must match capture-sync-v1 policy." });
542
+ } else if (Math.abs(fileSpanUs - helperSpanUs) > expectedSpanToleranceUs) {
543
+ context.addIssue({ code: "custom", message: "Finalized file span exceeds its recorded helper tolerance." });
544
+ }
545
+ if (timing.evidence.file.firstPtsUs < timing.evidence.file.containerOriginPtsUs) {
546
+ context.addIssue({ code: "custom", message: "Finalized file PTS cannot precede its container origin." });
547
+ }
548
+ if (timing.evidence.helper.sampleCount < timing.evidence.helper.bufferCount) {
549
+ context.addIssue({ code: "custom", message: "Capture sample count cannot be smaller than buffer count." });
550
+ }
551
+ const outOfTolerance = Math.abs(timing.onsetSkewUs) > timing.tolerance.onsetSkewUs
552
+ || Math.abs(timing.durationDriftUs) > timing.tolerance.durationDriftUs;
553
+ if (outOfTolerance !== (timing.status === "out-of-tolerance")) {
554
+ context.addIssue({ code: "custom", message: "Capture sync status must match its explicit tolerances." });
555
+ }
556
+ });
557
+
558
+ export const MediaSegmentSchema = z.strictObject({
559
+ codec: z.string().min(1).max(128),
560
+ containerTrackIdentity: z.discriminatedUnion("kind", [
561
+ z.strictObject({ containerTrackId: z.string().min(1).max(256), kind: z.literal("verified") }),
562
+ z.strictObject({
563
+ diagnosticCode: z.string().min(1).max(128),
564
+ expectedRole: z.enum(["display-video", "camera-video", "system-audio", "microphone-audio"]),
565
+ kind: z.literal("provisional"),
566
+ }),
567
+ ]),
568
+ container: z.string().min(1).max(64),
569
+ endUs: PositiveMicrosecondsSchema,
570
+ fileRange: MediaFileRangeSchema,
571
+ integrity: FileIntegritySchema,
572
+ path: RepositoryRelativePathSchema,
573
+ segmentId: SegmentIdSchema,
574
+ startUs: MicrosecondsSchema,
575
+ streamIndex: z.number().int().safe().nonnegative(),
576
+ timing: z.discriminatedUnion("kind", [
577
+ LegacyCaptureTimingSchema,
578
+ CaptureSyncMeasurementSchema,
579
+ ]),
580
+ }).superRefine((segment, context) => {
581
+ if (segment.endUs <= segment.startUs) {
582
+ context.addIssue({ code: "custom", message: "Segment endUs must be greater than startUs." });
583
+ }
584
+ if (
585
+ segment.endUs - segment.startUs
586
+ !== segment.fileRange.endUs - segment.fileRange.startUs
587
+ ) {
588
+ context.addIssue({ code: "custom", message: "Media source and file ranges must have equal duration." });
589
+ }
590
+ });
591
+
592
+ const TrackBaseSchema = z.strictObject({
593
+ enabled: z.boolean(),
594
+ label: z.string().min(1).max(512),
595
+ segments: z.array(MediaSegmentSchema),
596
+ trackId: TrackIdSchema,
597
+ });
598
+
599
+ export const DisplayVideoTrackSchema = TrackBaseSchema.extend({
600
+ kind: z.literal("display-video"),
601
+ source: z.strictObject({ displayId: z.string().min(1).max(256) }),
602
+ }).strict();
603
+
604
+ export const CameraVideoTrackSchema = TrackBaseSchema.extend({
605
+ kind: z.literal("camera-video"),
606
+ source: z.strictObject({ cameraId: z.string().min(1).max(256) }),
607
+ }).strict();
608
+
609
+ export const SystemAudioTrackSchema = TrackBaseSchema.extend({
610
+ kind: z.literal("system-audio"),
611
+ source: z.strictObject({ audioSourceId: z.string().min(1).max(256) }),
612
+ }).strict();
613
+
614
+ export const MicrophoneAudioTrackSchema = TrackBaseSchema.extend({
615
+ kind: z.literal("microphone-audio"),
616
+ source: z.strictObject({ audioSourceId: z.string().min(1).max(256) }),
617
+ }).strict();
618
+
619
+ export const LogicalTrackSchema = z.discriminatedUnion("kind", [
620
+ DisplayVideoTrackSchema,
621
+ CameraVideoTrackSchema,
622
+ SystemAudioTrackSchema,
623
+ MicrophoneAudioTrackSchema,
624
+ ]);
625
+
626
+ export const EventKindSchema = z.enum([
627
+ "cursor.sample",
628
+ "mouse.click",
629
+ "key.activity",
630
+ "typing.input",
631
+ "focus.changed",
632
+ "window.snapshot",
633
+ "window.changed",
634
+ "display.topology",
635
+ "lifecycle.marker",
636
+ "diagnostic.dropped-events",
637
+ ]);
638
+
639
+ export const EventStreamReferenceSchema = z.strictObject({
640
+ endUs: MicrosecondsSchema,
641
+ eventKinds: z.array(EventKindSchema).min(1),
642
+ eventStreamId: EventStreamIdSchema,
643
+ integrity: FileIntegritySchema,
644
+ path: RepositoryRelativePathSchema,
645
+ recordCount: z.number().int().safe().nonnegative(),
646
+ startUs: MicrosecondsSchema,
647
+ }).superRefine((stream, context) => {
648
+ if (stream.endUs < stream.startUs) {
649
+ context.addIssue({ code: "custom", message: "Event stream endUs cannot precede startUs." });
650
+ }
651
+ if (new Set(stream.eventKinds).size !== stream.eventKinds.length) {
652
+ context.addIssue({ code: "custom", message: "Event stream kinds must be unique." });
653
+ }
654
+ });
655
+
656
+ export const RecordingDiagnosticSchema = z.strictObject({
657
+ code: z.string().min(1).max(128),
658
+ count: z.number().int().safe().positive(),
659
+ firstSourceTimeUs: MicrosecondsSchema.nullable(),
660
+ lastSourceTimeUs: MicrosecondsSchema.nullable(),
661
+ level: z.enum(["info", "warning", "error"]),
662
+ message: z.string().min(1).max(4096),
663
+ }).superRefine((diagnostic, context) => {
664
+ if ((diagnostic.firstSourceTimeUs === null) !== (diagnostic.lastSourceTimeUs === null)) {
665
+ context.addIssue({ code: "custom", message: "Diagnostic source-time bounds must both be null or both be present." });
666
+ } else if (
667
+ diagnostic.firstSourceTimeUs !== null
668
+ && diagnostic.lastSourceTimeUs !== null
669
+ && diagnostic.lastSourceTimeUs < diagnostic.firstSourceTimeUs
670
+ ) {
671
+ context.addIssue({ code: "custom", message: "Diagnostic lastSourceTimeUs cannot precede firstSourceTimeUs." });
672
+ }
673
+ });
674
+
675
+ export const RecordingLifecycleStateSchema = z.enum([
676
+ "preparing",
677
+ "recording",
678
+ "paused",
679
+ "stopped",
680
+ "failed",
681
+ ]);
682
+
683
+ function addDuplicateIssue(
684
+ values: readonly string[],
685
+ label: string,
686
+ context: z.core.$RefinementCtx<unknown>,
687
+ ): void {
688
+ if (new Set(values).size !== values.length) {
689
+ context.addIssue({ code: "custom", message: `${label} must be unique.` });
690
+ }
691
+ }
692
+
693
+ function validateOrderedSegments(
694
+ track: z.infer<typeof LogicalTrackSchema>,
695
+ context: z.core.$RefinementCtx<unknown>,
696
+ ): void {
697
+ let priorEnd = -1;
698
+ for (const segment of track.segments) {
699
+ if (segment.startUs < priorEnd) {
700
+ context.addIssue({
701
+ code: "custom",
702
+ message: `Track ${track.trackId} segments must be ordered and non-overlapping.`,
703
+ });
704
+ return;
705
+ }
706
+ priorEnd = segment.endUs;
707
+ }
708
+ }
709
+
710
+ const RecordingManifestBaseShape = {
711
+ capture: z.strictObject({
712
+ cursor: z.enum(["disabled", "metadata"]),
713
+ typedText: z.enum(["disabled", "enabled"]).default("disabled"),
714
+ windowMetadata: z.enum(["disabled", "bounds-only", "titles-and-bounds"]),
715
+ }),
716
+ coordinateSpace: z.strictObject({
717
+ kind: z.literal("global-display-points"),
718
+ origin: z.literal("top-left"),
719
+ xAxis: z.literal("right"),
720
+ yAxis: z.literal("down"),
721
+ }),
722
+ createdAt: IsoTimestampSchema,
723
+ diagnostics: z.array(RecordingDiagnosticSchema),
724
+ eventStreams: z.array(EventStreamReferenceSchema),
725
+ kind: z.union([
726
+ z.literal("slopcamera.recording-bundle"),
727
+ z.literal("studio.recording-bundle"),
728
+ ]),
729
+ permissions: CapturePermissionsSchema,
730
+ platform: z.strictObject({
731
+ architecture: z.string().min(1).max(128),
732
+ os: z.enum(["macos", "linux", "windows", "unknown"]),
733
+ osVersion: z.string().min(1).max(128),
734
+ }),
735
+ recordingId: RecordingIdSchema,
736
+ sources: SourceInventorySchema,
737
+ state: RecordingLifecycleStateSchema,
738
+ tool: z.strictObject({
739
+ captureVersion: z.string().min(1).max(128),
740
+ name: z.union([
741
+ z.literal("slopcamera"),
742
+ z.literal("studio"),
743
+ ]),
744
+ version: z.string().min(1).max(128),
745
+ }),
746
+ tracks: z.array(LogicalTrackSchema),
747
+ updatedAt: IsoTimestampSchema,
748
+ } as const;
749
+
750
+ const CaptureNativeClockSegmentSchema = z.strictObject({
751
+ index: z.number().int().safe().nonnegative().max(127),
752
+ nativeRange: z.strictObject({
753
+ endUs: PositiveMicrosecondsSchema,
754
+ startUs: MicrosecondsSchema,
755
+ }),
756
+ sourceRange: z.strictObject({
757
+ endUs: PositiveMicrosecondsSchema,
758
+ startUs: MicrosecondsSchema,
759
+ }),
760
+ }).superRefine((segment, context) => {
761
+ const nativeDurationUs = segment.nativeRange.endUs - segment.nativeRange.startUs;
762
+ const sourceDurationUs = segment.sourceRange.endUs - segment.sourceRange.startUs;
763
+ if (nativeDurationUs <= 0 || sourceDurationUs <= 0) {
764
+ context.addIssue({ code: "custom", message: "Capture native-clock ranges must have positive duration." });
765
+ } else if (nativeDurationUs !== sourceDurationUs) {
766
+ context.addIssue({ code: "custom", message: "Capture native and source ranges must have equal duration." });
767
+ }
768
+ });
769
+
770
+ const RecordingTimelineV1Schema = z.strictObject({
771
+ durationUs: MicrosecondsSchema,
772
+ timebase: z.literal("microseconds"),
773
+ });
774
+
775
+ const RecordingTimelineV2Schema = z.strictObject({
776
+ durationUs: MicrosecondsSchema,
777
+ nativeClock: z.strictObject({
778
+ kind: z.literal("mach-continuous-microseconds"),
779
+ segments: z.array(CaptureNativeClockSegmentSchema).max(128),
780
+ }),
781
+ timebase: z.literal("microseconds"),
782
+ }).superRefine((timeline, context) => {
783
+ let priorIndex = -1;
784
+ let priorNativeEndUs = -1;
785
+ let priorSourceEndUs = 0;
786
+ for (const segment of timeline.nativeClock.segments) {
787
+ if (segment.index <= priorIndex) {
788
+ context.addIssue({ code: "custom", message: "Capture native-clock segment indices must increase." });
789
+ return;
790
+ }
791
+ if (segment.sourceRange.startUs !== priorSourceEndUs) {
792
+ context.addIssue({ code: "custom", message: "Capture native-clock source ranges must be contiguous across pauses." });
793
+ return;
794
+ }
795
+ if (segment.nativeRange.startUs < priorNativeEndUs) {
796
+ context.addIssue({ code: "custom", message: "Capture native-clock ranges must be ordered and non-overlapping." });
797
+ return;
798
+ }
799
+ priorIndex = segment.index;
800
+ priorNativeEndUs = segment.nativeRange.endUs;
801
+ priorSourceEndUs = segment.sourceRange.endUs;
802
+ }
803
+ if (priorSourceEndUs > timeline.durationUs) {
804
+ context.addIssue({ code: "custom", message: "Capture native-clock ranges exceed the recording timeline." });
805
+ }
806
+ });
807
+
808
+ interface ValidatableRecordingManifest {
809
+ readonly createdAt: string;
810
+ readonly diagnostics: readonly z.infer<typeof RecordingDiagnosticSchema>[];
811
+ readonly eventStreams: readonly z.infer<typeof EventStreamReferenceSchema>[];
812
+ readonly kind: "slopcamera.recording-bundle" | "studio.recording-bundle";
813
+ readonly sources: z.infer<typeof SourceInventorySchema>;
814
+ readonly state: z.infer<typeof RecordingLifecycleStateSchema>;
815
+ readonly timeline: { readonly durationUs: number };
816
+ readonly tool: { readonly name: "slopcamera" | "studio" };
817
+ readonly tracks: readonly z.infer<typeof LogicalTrackSchema>[];
818
+ readonly updatedAt: string;
819
+ }
820
+
821
+ function validateRecordingManifest(
822
+ manifest: ValidatableRecordingManifest,
823
+ context: z.core.$RefinementCtx<unknown>,
824
+ ): void {
825
+ const canonicalIdentity = manifest.kind === "slopcamera.recording-bundle"
826
+ && manifest.tool.name === "slopcamera";
827
+ const legacyStudioIdentity = manifest.kind === "studio.recording-bundle"
828
+ && manifest.tool.name === "studio";
829
+ if (!canonicalIdentity && !legacyStudioIdentity) {
830
+ context.addIssue({
831
+ code: "custom",
832
+ message: "Recording bundle kind and tool name must use the same product identity.",
833
+ });
834
+ }
835
+ if (Date.parse(manifest.updatedAt) < Date.parse(manifest.createdAt)) {
836
+ context.addIssue({ code: "custom", message: "updatedAt cannot precede createdAt." });
837
+ }
838
+
839
+ addDuplicateIssue(manifest.tracks.map(({ trackId }) => trackId), "Track IDs", context);
840
+ addDuplicateIssue(manifest.sources.displays.map(({ displayId }) => displayId), "Display source IDs", context);
841
+ addDuplicateIssue(manifest.sources.cameras.map(({ cameraId }) => cameraId), "Camera source IDs", context);
842
+ addDuplicateIssue(manifest.sources.audio.map(({ audioSourceId }) => audioSourceId), "Audio source IDs", context);
843
+ addDuplicateIssue(
844
+ manifest.tracks.flatMap(({ segments }) => segments.map(({ segmentId }) => segmentId)),
845
+ "Segment IDs",
846
+ context,
847
+ );
848
+ addDuplicateIssue(
849
+ manifest.tracks.flatMap(({ segments }) => segments.map(({ path, streamIndex }) => `${path}\0${streamIndex}`)),
850
+ "Segment path and stream-index pairs",
851
+ context,
852
+ );
853
+ addDuplicateIssue(
854
+ manifest.eventStreams.map(({ eventStreamId }) => eventStreamId),
855
+ "Event stream IDs",
856
+ context,
857
+ );
858
+ addDuplicateIssue(
859
+ manifest.eventStreams.map(({ path }) => path),
860
+ "Event stream paths",
861
+ context,
862
+ );
863
+
864
+ const displayIds = new Set(manifest.sources.displays.map(({ displayId }) => displayId));
865
+ const cameraIds = new Set(manifest.sources.cameras.map(({ cameraId }) => cameraId));
866
+ const systemAudioIds = new Set(
867
+ manifest.sources.audio.filter(({ kind }) => kind === "system").map(({ audioSourceId }) => audioSourceId),
868
+ );
869
+ const microphoneIds = new Set(
870
+ manifest.sources.audio.filter(({ kind }) => kind === "microphone").map(({ audioSourceId }) => audioSourceId),
871
+ );
872
+
873
+ if (
874
+ manifest.sources.displays.length > 0
875
+ && manifest.sources.displays.filter(({ isPrimary }) => isPrimary).length !== 1
876
+ ) {
877
+ context.addIssue({ code: "custom", message: "Display inventory must identify exactly one primary display." });
878
+ }
879
+
880
+ const mediaPaths = new Set(manifest.tracks.flatMap(({ segments }) => segments.map(({ path }) => path)));
881
+ if (manifest.eventStreams.some(({ path }) => mediaPaths.has(path))) {
882
+ context.addIssue({ code: "custom", message: "Media segments and event streams must not share a file path." });
883
+ }
884
+ if (manifest.eventStreams.some(({ endUs }) => endUs > manifest.timeline.durationUs)) {
885
+ context.addIssue({ code: "custom", message: "Event streams cannot exceed the recording timeline." });
886
+ }
887
+ if (manifest.diagnostics.some(({ lastSourceTimeUs }) => (
888
+ lastSourceTimeUs !== null && lastSourceTimeUs > manifest.timeline.durationUs
889
+ ))) {
890
+ context.addIssue({ code: "custom", message: "Recording diagnostics cannot exceed the recording timeline." });
891
+ }
892
+ if (
893
+ manifest.state === "stopped"
894
+ && (
895
+ manifest.tracks.some(({ segments }) => segments.some(({ integrity }) => integrity.state !== "verified"))
896
+ || manifest.eventStreams.some(({ integrity }) => integrity.state !== "verified")
897
+ )
898
+ ) {
899
+ context.addIssue({ code: "custom", message: "Stopped recordings must have verified integrity for every referenced file." });
900
+ }
901
+
902
+ for (const track of manifest.tracks) {
903
+ validateOrderedSegments(track, context);
904
+ if (track.segments.some(({ endUs }) => endUs > manifest.timeline.durationUs)) {
905
+ context.addIssue({ code: "custom", message: `Track ${track.trackId} exceeds the recording timeline.` });
906
+ }
907
+ const sourceExists = track.kind === "display-video"
908
+ ? displayIds.has(track.source.displayId)
909
+ : track.kind === "camera-video"
910
+ ? cameraIds.has(track.source.cameraId)
911
+ : track.kind === "system-audio"
912
+ ? systemAudioIds.has(track.source.audioSourceId)
913
+ : microphoneIds.has(track.source.audioSourceId);
914
+ if (!sourceExists) {
915
+ context.addIssue({ code: "custom", message: `Track ${track.trackId} references an unknown source.` });
916
+ }
917
+ }
918
+ }
919
+
920
+ const NormalizedRecordingManifestV1Schema = z.strictObject({
921
+ ...RecordingManifestBaseShape,
922
+ interruptions: z.array(CaptureInterruptionSchema).max(0).default([]),
923
+ schemaVersion: z.literal(1),
924
+ timeline: RecordingTimelineV1Schema,
925
+ }).superRefine((manifest, context) => {
926
+ validateRecordingManifest(manifest, context);
927
+ if (manifest.tracks.some(track => track.segments.some(segment => segment.timing.kind !== "legacy-estimate"))) {
928
+ context.addIssue({ code: "custom", message: "Recording manifest v1 may contain only legacy-estimate timing." });
929
+ }
930
+ });
931
+
932
+ const MeasuredRecordingManifestShape = {
933
+ ...RecordingManifestBaseShape,
934
+ timeline: RecordingTimelineV2Schema,
935
+ } as const;
936
+
937
+ type ValidatableMeasuredRecordingManifest = z.infer<
938
+ z.ZodObject<typeof MeasuredRecordingManifestShape>
939
+ >;
940
+
941
+ function validateMeasuredRecordingManifest(
942
+ manifest: ValidatableMeasuredRecordingManifest,
943
+ context: z.core.$RefinementCtx<unknown>,
944
+ ): void {
945
+ validateRecordingManifest(manifest, context);
946
+ if (manifest.tracks.some(track => track.segments.some(segment => segment.timing.kind !== "measured"))) {
947
+ context.addIssue({ code: "custom", message: "Recording manifest v2 requires measured timing for every media segment." });
948
+ }
949
+ const clockSegments = new Map(
950
+ manifest.timeline.nativeClock.segments.map(segment => [segment.index, segment] as const),
951
+ );
952
+ for (const track of manifest.tracks) {
953
+ const captureSegmentIndices = track.segments.flatMap(segment => (
954
+ segment.timing.kind === "measured" ? [segment.timing.captureSegmentIndex] : []
955
+ ));
956
+ if (new Set(captureSegmentIndices).size !== captureSegmentIndices.length) {
957
+ context.addIssue({
958
+ code: "custom",
959
+ message: `Track ${track.trackId} must have at most one media segment per capture segment.`,
960
+ });
961
+ }
962
+ for (const segment of track.segments) {
963
+ if (segment.timing.kind !== "measured") continue;
964
+ const timing = segment.timing;
965
+ const clockSegment = clockSegments.get(timing.captureSegmentIndex);
966
+ if (clockSegment === undefined) {
967
+ context.addIssue({ code: "custom", message: "Measured timing references an unknown capture clock segment." });
968
+ } else {
969
+ const placement = deriveCaptureSyncPlacement({
970
+ clockNativeStartUs: clockSegment.nativeRange.startUs,
971
+ clockSourceEndUs: clockSegment.sourceRange.endUs,
972
+ clockSourceStartUs: clockSegment.sourceRange.startUs,
973
+ fileContainerOriginPtsUs: timing.evidence.file.containerOriginPtsUs,
974
+ fileEndPtsUs: timing.evidence.file.endPtsUs,
975
+ fileFirstPtsUs: timing.evidence.file.firstPtsUs,
976
+ helperNativeStartUs: timing.evidence.helper.clockAnchors.first.nativeTimeUs,
977
+ });
978
+ if (
979
+ placement === null
980
+ || segment.startUs !== placement.startUs
981
+ || segment.endUs !== placement.endUs
982
+ || segment.fileRange.startUs !== placement.fileRangeStartUs
983
+ || segment.fileRange.endUs !== placement.fileRangeEndUs
984
+ ) {
985
+ context.addIssue({
986
+ code: "custom",
987
+ message: "capture-timing-evidence-mismatch: media placement does not match raw clock and file evidence.",
988
+ });
989
+ }
990
+ }
991
+
992
+ const referenceTrack = manifest.tracks.find(
993
+ ({ trackId }) => trackId === timing.referenceTrackId,
994
+ );
995
+ if (referenceTrack === undefined) {
996
+ context.addIssue({ code: "custom", message: "Capture sync measurement references an unknown track." });
997
+ continue;
998
+ }
999
+ if (referenceTrack.kind !== "display-video") {
1000
+ context.addIssue({
1001
+ code: "custom",
1002
+ message: "Capture sync measurement must reference a display-video track.",
1003
+ });
1004
+ continue;
1005
+ }
1006
+ const referenceSegments = referenceTrack.segments.filter(candidate => (
1007
+ candidate.timing.kind === "measured"
1008
+ && candidate.timing.captureSegmentIndex === timing.captureSegmentIndex
1009
+ ));
1010
+ if (referenceSegments.length !== 1) {
1011
+ context.addIssue({
1012
+ code: "custom",
1013
+ message: "Capture sync reference track must have exactly one segment for the capture segment.",
1014
+ });
1015
+ continue;
1016
+ }
1017
+ const referenceTiming = referenceSegments[0]!.timing;
1018
+ if (referenceTiming.kind !== "measured") continue;
1019
+ const onsetSkewUs = timing.evidence.helper.clockAnchors.first.nativeTimeUs
1020
+ - referenceTiming.evidence.helper.clockAnchors.first.nativeTimeUs;
1021
+ const endSkewUs = timing.evidence.helper.clockAnchors.end.nativeTimeUs
1022
+ - referenceTiming.evidence.helper.clockAnchors.end.nativeTimeUs;
1023
+ const durationDriftUs = endSkewUs - onsetSkewUs;
1024
+ const referenceDurationUs = referenceTiming.evidence.helper.clockAnchors.end.nativeTimeUs
1025
+ - referenceTiming.evidence.helper.clockAnchors.first.nativeTimeUs;
1026
+ const durationDriftPpm = deriveCaptureSyncDurationDriftPpm(
1027
+ durationDriftUs,
1028
+ referenceDurationUs,
1029
+ );
1030
+ const tolerances = deriveCaptureSyncTolerances({
1031
+ referenceDurationUs,
1032
+ referenceEndUncertaintyUs: referenceTiming.evidence.helper.clockAnchors.end.uncertaintyUs,
1033
+ referenceFirstUncertaintyUs: referenceTiming.evidence.helper.clockAnchors.first.uncertaintyUs,
1034
+ referenceMaximumSampleDurationUs: referenceTiming.evidence.helper.presentation.maximumSampleDurationUs,
1035
+ subjectEndUncertaintyUs: timing.evidence.helper.clockAnchors.end.uncertaintyUs,
1036
+ subjectFirstUncertaintyUs: timing.evidence.helper.clockAnchors.first.uncertaintyUs,
1037
+ subjectMaximumSampleDurationUs: timing.evidence.helper.presentation.maximumSampleDurationUs,
1038
+ });
1039
+ if (
1040
+ durationDriftPpm === null
1041
+ || timing.onsetSkewUs !== onsetSkewUs
1042
+ || timing.durationDriftUs !== durationDriftUs
1043
+ || timing.durationDriftPpm !== durationDriftPpm
1044
+ ) {
1045
+ context.addIssue({
1046
+ code: "custom",
1047
+ message: "capture-timing-evidence-mismatch: derived synchronization does not match raw clock anchors.",
1048
+ });
1049
+ }
1050
+ if (
1051
+ tolerances === null
1052
+ || timing.tolerance.durationDriftUs !== tolerances.durationDriftUs
1053
+ || timing.tolerance.onsetSkewUs !== tolerances.onsetSkewUs
1054
+ ) {
1055
+ context.addIssue({
1056
+ code: "custom",
1057
+ message: "capture-timing-evidence-mismatch: synchronization tolerances do not match capture-sync-v1 policy.",
1058
+ });
1059
+ } else {
1060
+ const expectedStatus = Math.abs(onsetSkewUs) > tolerances.onsetSkewUs
1061
+ || Math.abs(durationDriftUs) > tolerances.durationDriftUs
1062
+ ? "out-of-tolerance"
1063
+ : "within-tolerance";
1064
+ if (timing.status !== expectedStatus) {
1065
+ context.addIssue({
1066
+ code: "custom",
1067
+ message: "capture-timing-evidence-mismatch: synchronization status does not match capture-sync-v1 policy.",
1068
+ });
1069
+ }
1070
+ }
1071
+ }
1072
+ }
1073
+ }
1074
+
1075
+ export const RecordingManifestV2Schema = z.strictObject({
1076
+ ...MeasuredRecordingManifestShape,
1077
+ interruptions: z.array(CaptureInterruptionSchema).max(0).default([]),
1078
+ schemaVersion: z.literal(2),
1079
+ }).superRefine(validateMeasuredRecordingManifest);
1080
+
1081
+ export const RecordingManifestV3Schema = z.strictObject({
1082
+ ...MeasuredRecordingManifestShape,
1083
+ interruptions: z.array(CaptureInterruptionSchema)
1084
+ .max(MAX_CAPTURE_INTERRUPTION_SEGMENTS),
1085
+ schemaVersion: z.literal(3),
1086
+ }).superRefine((manifest, context) => {
1087
+ validateMeasuredRecordingManifest(manifest, context);
1088
+
1089
+ const clockSegments = new Map(
1090
+ manifest.timeline.nativeClock.segments.map(segment => [segment.index, segment] as const),
1091
+ );
1092
+ const lastClockSegment = manifest.timeline.nativeClock.segments.at(-1);
1093
+ let priorInterruptionIndex = -1;
1094
+ let unmatchedFailureSeen = false;
1095
+ for (const interruption of manifest.interruptions) {
1096
+ if (interruption.segmentIndex <= priorInterruptionIndex) {
1097
+ context.addIssue({
1098
+ code: "custom",
1099
+ message: "Capture interruptions must be ordered with at most one interruption per segment.",
1100
+ });
1101
+ return;
1102
+ }
1103
+ priorInterruptionIndex = interruption.segmentIndex;
1104
+ const clockSegment = clockSegments.get(interruption.segmentIndex);
1105
+ if (clockSegment !== undefined) {
1106
+ if (
1107
+ !interruption.recoverable
1108
+ || interruption.nativeTimeUs !== clockSegment.nativeRange.endUs
1109
+ || interruption.sourceTimeUs !== clockSegment.sourceRange.endUs
1110
+ ) {
1111
+ context.addIssue({
1112
+ code: "custom",
1113
+ message: "A completed-segment interruption must be recoverable and match its capture clock end anchors.",
1114
+ });
1115
+ }
1116
+ continue;
1117
+ }
1118
+
1119
+ const expectedPreparedIndex = (lastClockSegment?.index ?? -1) + 1;
1120
+ const persistedSourceFrontierUs =
1121
+ lastClockSegment?.sourceRange.endUs ?? 0;
1122
+ const persistedNativeFrontierUs =
1123
+ lastClockSegment?.nativeRange.endUs ?? 0;
1124
+ if (
1125
+ unmatchedFailureSeen
1126
+ || manifest.state !== "failed"
1127
+ || interruption.segmentIndex !== expectedPreparedIndex
1128
+ || interruption.sourceTimeUs !== persistedSourceFrontierUs
1129
+ || interruption.nativeTimeUs < persistedNativeFrontierUs
1130
+ || interruption.recoverable
1131
+ || manifest.timeline.durationUs !== persistedSourceFrontierUs
1132
+ ) {
1133
+ context.addIssue({
1134
+ code: "custom",
1135
+ message: "Only one nonrecoverable failed prepared-start interruption may be anchored at the persisted capture frontier.",
1136
+ });
1137
+ }
1138
+ unmatchedFailureSeen = true;
1139
+ }
1140
+ });
1141
+
1142
+ function unknownArray(value: unknown): readonly unknown[] | null {
1143
+ return Array.isArray(value) ? value as readonly unknown[] : null;
1144
+ }
1145
+
1146
+ function normalizeLegacyRecordingManifest(input: unknown): unknown {
1147
+ if (typeof input !== "object" || input === null || Array.isArray(input)) return input;
1148
+ const manifest = input as Readonly<Record<string, unknown>>;
1149
+ const rawTracks = unknownArray(manifest.tracks);
1150
+ if (manifest.schemaVersion !== 1 || rawTracks === null) return input;
1151
+ let normalizedLegacySegment = false;
1152
+ const tracks = rawTracks.map(rawTrack => {
1153
+ if (typeof rawTrack !== "object" || rawTrack === null || Array.isArray(rawTrack)) return rawTrack;
1154
+ const track = rawTrack as Readonly<Record<string, unknown>>;
1155
+ const rawSegments = unknownArray(track.segments);
1156
+ if (rawSegments === null) return rawTrack;
1157
+ const segments = rawSegments.map(rawSegment => {
1158
+ if (typeof rawSegment !== "object" || rawSegment === null || Array.isArray(rawSegment)) return rawSegment;
1159
+ const segment = rawSegment as Readonly<Record<string, unknown>>;
1160
+ if (segment.fileRange !== undefined || segment.timing !== undefined) {
1161
+ if (
1162
+ typeof segment.timing === "object"
1163
+ && segment.timing !== null
1164
+ && !Array.isArray(segment.timing)
1165
+ && (segment.timing as Readonly<Record<string, unknown>>).kind === "legacy-estimate"
1166
+ ) {
1167
+ normalizedLegacySegment = true;
1168
+ }
1169
+ return rawSegment;
1170
+ }
1171
+ const parsed = LegacyMediaSegmentV1Schema.safeParse(rawSegment);
1172
+ if (!parsed.success) return rawSegment;
1173
+ normalizedLegacySegment = true;
1174
+ const legacy = parsed.data;
1175
+ return {
1176
+ codec: legacy.codec,
1177
+ container: legacy.container,
1178
+ containerTrackIdentity: legacy.containerTrackIdentity,
1179
+ endUs: legacy.endUs,
1180
+ fileRange: { endUs: legacy.endUs - legacy.startUs, startUs: 0 },
1181
+ integrity: legacy.integrity,
1182
+ path: legacy.path,
1183
+ segmentId: legacy.segmentId,
1184
+ startUs: legacy.startUs,
1185
+ streamIndex: legacy.streamIndex,
1186
+ timing: {
1187
+ kind: "legacy-estimate",
1188
+ nativeRange: { endUs: legacy.nativeEndUs, startUs: legacy.nativeStartUs },
1189
+ reason: "recording-manifest-v1-container-duration",
1190
+ },
1191
+ };
1192
+ });
1193
+ return { ...track, segments };
1194
+ });
1195
+ const diagnostics = unknownArray(manifest.diagnostics);
1196
+ if (diagnostics === null) return { ...manifest, tracks };
1197
+ const hasLegacyDiagnostic = diagnostics.some(diagnostic => (
1198
+ typeof diagnostic === "object"
1199
+ && diagnostic !== null
1200
+ && !Array.isArray(diagnostic)
1201
+ && (diagnostic as Readonly<Record<string, unknown>>).code === "legacy-capture-timing"
1202
+ ));
1203
+ return {
1204
+ ...manifest,
1205
+ diagnostics: normalizedLegacySegment && !hasLegacyDiagnostic
1206
+ ? [...diagnostics, {
1207
+ code: "legacy-capture-timing",
1208
+ count: 1,
1209
+ firstSourceTimeUs: null,
1210
+ lastSourceTimeUs: null,
1211
+ level: "warning",
1212
+ message: "Recording manifest v1 has estimated container timing; per-track capture synchronization was not measured.",
1213
+ }]
1214
+ : diagnostics,
1215
+ tracks,
1216
+ };
1217
+ }
1218
+
1219
+ export const RecordingManifestSchema = z.preprocess(
1220
+ normalizeLegacyRecordingManifest,
1221
+ z.discriminatedUnion("schemaVersion", [
1222
+ NormalizedRecordingManifestV1Schema,
1223
+ RecordingManifestV2Schema,
1224
+ RecordingManifestV3Schema,
1225
+ ]),
1226
+ );
1227
+
1228
+ /** @deprecated Use RecordingManifestSchema. Retained as a source-compatible reader alias. */
1229
+ export const RecordingManifestV1Schema = RecordingManifestSchema;
1230
+
1231
+ const EventBaseShape = {
1232
+ nativeTimeUs: MicrosecondsSchema,
1233
+ sequence: SequenceSchema,
1234
+ sourceTimeUs: MicrosecondsSchema,
1235
+ } as const;
1236
+
1237
+ export const CursorSampleEventSchema = z.strictObject({
1238
+ ...EventBaseShape,
1239
+ displayId: z.string().min(1).max(256),
1240
+ position: PointSchema,
1241
+ type: z.literal("cursor.sample"),
1242
+ visible: z.boolean(),
1243
+ });
1244
+
1245
+ export const MouseClickEventSchema = z.strictObject({
1246
+ ...EventBaseShape,
1247
+ button: z.enum(["left", "right", "middle", "other"]),
1248
+ clickCount: z.number().int().safe().positive().max(16),
1249
+ displayId: z.string().min(1).max(256),
1250
+ phase: z.enum(["down", "up"]),
1251
+ position: PointSchema,
1252
+ type: z.literal("mouse.click"),
1253
+ });
1254
+
1255
+ const ModifierSchema = z.enum(["command", "control", "option", "shift", "caps-lock", "function"]);
1256
+
1257
+ export const KeyActivityEventSchema = z.strictObject({
1258
+ ...EventBaseShape,
1259
+ activity: z.discriminatedUnion("kind", [
1260
+ z.strictObject({
1261
+ kind: z.literal("shortcut"),
1262
+ keyCode: z.string().min(1).max(128),
1263
+ modifiers: z.array(ModifierSchema).min(1),
1264
+ phase: z.enum(["down", "up"]),
1265
+ repeat: z.boolean(),
1266
+ }),
1267
+ z.strictObject({
1268
+ control: z.enum(["arrow-up", "arrow-down", "arrow-left", "arrow-right", "escape", "tab", "enter", "delete"]),
1269
+ kind: z.literal("control"),
1270
+ modifiers: z.array(ModifierSchema),
1271
+ phase: z.enum(["down", "up"]),
1272
+ repeat: z.boolean(),
1273
+ }),
1274
+ z.strictObject({
1275
+ kind: z.literal("printable"),
1276
+ modifiers: z.array(ModifierSchema),
1277
+ phase: z.enum(["down", "up"]),
1278
+ repeat: z.boolean(),
1279
+ token: z.literal("[PRINTABLE]"),
1280
+ }),
1281
+ ]),
1282
+ type: z.literal("key.activity"),
1283
+ });
1284
+
1285
+ const PublicTypingPayloadSchema = z.strictObject({
1286
+ action: z.enum(["insert", "delete-backward", "delete-forward", "replace"]),
1287
+ bounds: RectSchema,
1288
+ fieldId: z.string().min(1).max(512),
1289
+ secure: z.literal(false),
1290
+ text: z.string().max(4096),
1291
+ windowId: z.string().min(1).max(256),
1292
+ });
1293
+
1294
+ export const TypingInputEventSchema = z.strictObject({
1295
+ ...EventBaseShape,
1296
+ input: PublicTypingPayloadSchema,
1297
+ type: z.literal("typing.input"),
1298
+ });
1299
+
1300
+ export const FocusTargetSchema = z.discriminatedUnion("kind", [
1301
+ z.strictObject({ kind: z.literal("none") }),
1302
+ z.strictObject({
1303
+ bounds: RectSchema,
1304
+ fieldId: z.string().min(1).max(512),
1305
+ kind: z.literal("public-input"),
1306
+ processId: z.number().int().positive().max(2_147_483_647).optional(),
1307
+ role: z.string().min(1).max(128),
1308
+ windowId: z.string().min(1).max(256),
1309
+ }),
1310
+ z.strictObject({
1311
+ bounds: RectSchema,
1312
+ fieldId: z.literal("[REDACTED]"),
1313
+ kind: z.literal("secure-input"),
1314
+ processId: z.number().int().positive().max(2_147_483_647).optional(),
1315
+ redacted: z.literal(true),
1316
+ role: z.literal("secure-text-field"),
1317
+ windowId: z.string().min(1).max(256),
1318
+ }),
1319
+ ]);
1320
+
1321
+ export const FocusChangedEventSchema = z.strictObject({
1322
+ ...EventBaseShape,
1323
+ target: FocusTargetSchema,
1324
+ type: z.literal("focus.changed"),
1325
+ });
1326
+
1327
+ export const WindowTitleSchema = z.discriminatedUnion("state", [
1328
+ z.strictObject({ state: z.literal("available"), value: z.string().max(2048) }),
1329
+ z.strictObject({ reason: z.enum(["permission", "secure", "unavailable"]), state: z.literal("redacted") }),
1330
+ ]);
1331
+
1332
+ export const WindowRecordSchema = z.strictObject({
1333
+ applicationBundleId: z.string().min(1).max(512),
1334
+ applicationName: z.string().min(1).max(512),
1335
+ bounds: RectSchema,
1336
+ displayId: z.string().min(1).max(256),
1337
+ isFocused: z.boolean(),
1338
+ layer: z.number().int().safe(),
1339
+ title: WindowTitleSchema,
1340
+ windowId: z.string().min(1).max(256),
1341
+ });
1342
+
1343
+ export const WindowSnapshotEventSchema = z.strictObject({
1344
+ ...EventBaseShape,
1345
+ type: z.literal("window.snapshot"),
1346
+ windows: z.array(WindowRecordSchema),
1347
+ });
1348
+
1349
+ export const WindowChangedEventSchema = z.strictObject({
1350
+ ...EventBaseShape,
1351
+ change: z.discriminatedUnion("kind", [
1352
+ z.strictObject({ kind: z.enum(["created", "updated", "focused"]), window: WindowRecordSchema }),
1353
+ z.strictObject({ kind: z.literal("destroyed"), windowId: z.string().min(1).max(256) }),
1354
+ ]),
1355
+ type: z.literal("window.changed"),
1356
+ });
1357
+
1358
+ export const DisplayTopologyEventSchema = z.strictObject({
1359
+ ...EventBaseShape,
1360
+ displays: z.array(DisplaySourceSchema).min(1),
1361
+ type: z.literal("display.topology"),
1362
+ });
1363
+
1364
+ export const LifecycleMarkerEventSchema = z.strictObject({
1365
+ ...EventBaseShape,
1366
+ marker: z.enum([
1367
+ "capture-requested",
1368
+ "recording-started",
1369
+ "pause-requested",
1370
+ "paused",
1371
+ "resume-requested",
1372
+ "resumed",
1373
+ "stop-requested",
1374
+ "stopped",
1375
+ "segment-opened",
1376
+ "segment-closed",
1377
+ "failed",
1378
+ ]),
1379
+ segmentId: SegmentIdSchema.nullable(),
1380
+ type: z.literal("lifecycle.marker"),
1381
+ });
1382
+
1383
+ export const DroppedEventsDiagnosticSchema = z.strictObject({
1384
+ ...EventBaseShape,
1385
+ category: z.enum(["cursor", "mouse", "keyboard", "typing", "window", "display", "lifecycle"]),
1386
+ droppedCount: z.number().int().safe().positive(),
1387
+ firstDroppedNativeTimeUs: MicrosecondsSchema,
1388
+ lastDroppedNativeTimeUs: MicrosecondsSchema,
1389
+ reason: z.string().min(1).max(1024),
1390
+ type: z.literal("diagnostic.dropped-events"),
1391
+ });
1392
+
1393
+ export const RecordingEventV1Schema = z.discriminatedUnion("type", [
1394
+ CursorSampleEventSchema,
1395
+ MouseClickEventSchema,
1396
+ KeyActivityEventSchema,
1397
+ TypingInputEventSchema,
1398
+ FocusChangedEventSchema,
1399
+ WindowSnapshotEventSchema,
1400
+ WindowChangedEventSchema,
1401
+ DisplayTopologyEventSchema,
1402
+ LifecycleMarkerEventSchema,
1403
+ DroppedEventsDiagnosticSchema,
1404
+ ]);
1405
+
1406
+ export type RecordingId = z.infer<typeof RecordingIdSchema>;
1407
+ export type TrackId = z.infer<typeof TrackIdSchema>;
1408
+ export type SegmentId = z.infer<typeof SegmentIdSchema>;
1409
+ export type Rect = ReadonlyInferred<typeof RectSchema>;
1410
+ export type Point = ReadonlyInferred<typeof PointSchema>;
1411
+ export type DisplaySource = ReadonlyInferred<typeof DisplaySourceSchema>;
1412
+ export type SourceInventory = ReadonlyInferred<typeof SourceInventorySchema>;
1413
+ export type CapturePermissions = ReadonlyInferred<typeof CapturePermissionsSchema>;
1414
+ export type CaptureInterruption = ReadonlyInferred<typeof CaptureInterruptionSchema>;
1415
+ export type RecordingManifestV1 = ReadonlyInferred<typeof RecordingManifestV1Schema>;
1416
+ export type RecordingManifestV2 = ReadonlyInferred<typeof RecordingManifestV2Schema>;
1417
+ export type RecordingManifestV3 = ReadonlyInferred<typeof RecordingManifestV3Schema>;
1418
+ export type RecordingManifest = ReadonlyInferred<typeof RecordingManifestSchema>;
1419
+ export type RecordingEventV1 = ReadonlyInferred<typeof RecordingEventV1Schema>;
1420
+ export type CursorSampleEvent = ReadonlyInferred<typeof CursorSampleEventSchema>;
1421
+ export type TypingInputEvent = ReadonlyInferred<typeof TypingInputEventSchema>;
1422
+ export type WindowRecord = ReadonlyInferred<typeof WindowRecordSchema>;
1423
+
1424
+ export function parseRecordingManifestV1(input: unknown): RecordingManifestV1 {
1425
+ return RecordingManifestV1Schema.parse(input);
1426
+ }
1427
+
1428
+ export function parseRecordingManifest(input: unknown): RecordingManifest {
1429
+ return RecordingManifestSchema.parse(input);
1430
+ }
1431
+
1432
+ export function parseRecordingEventV1(input: unknown): RecordingEventV1 {
1433
+ return RecordingEventV1Schema.parse(input);
1434
+ }