@mevdragon/vidfarm-devcli 0.14.0 → 0.16.0

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 (427) hide show
  1. package/.agents/skills/embedded-captions/CATALOG.md +93 -0
  2. package/.agents/skills/embedded-captions/SKILL.md +286 -0
  3. package/.agents/skills/embedded-captions/assets/brand/CDPR-fankit-terms.txt +35 -0
  4. package/.agents/skills/embedded-captions/assets/brand/cyberpunk-widths.json +115 -0
  5. package/.agents/skills/embedded-captions/assets/fonts/char-widths.json +2211 -0
  6. package/.agents/skills/embedded-captions/assets/strokefonts/HersheyScript1.svg +242 -0
  7. package/.agents/skills/embedded-captions/assets/strokefonts/HersheyScriptMed.svg +242 -0
  8. package/.agents/skills/embedded-captions/dna/README.md +148 -0
  9. package/.agents/skills/embedded-captions/dna/chrome.json +68 -0
  10. package/.agents/skills/embedded-captions/dna/cream.json +69 -0
  11. package/.agents/skills/embedded-captions/dna/documentary.json +62 -0
  12. package/.agents/skills/embedded-captions/dna/editorial.json +70 -0
  13. package/.agents/skills/embedded-captions/dna/glitch.json +82 -0
  14. package/.agents/skills/embedded-captions/dna/ink.json +65 -0
  15. package/.agents/skills/embedded-captions/dna/keynote.json +62 -0
  16. package/.agents/skills/embedded-captions/dna/loud.json +75 -0
  17. package/.agents/skills/embedded-captions/dna/neon.json +58 -0
  18. package/.agents/skills/embedded-captions/dna/velocity.json +89 -0
  19. package/.agents/skills/embedded-captions/modes/cinematic/README.md +48 -0
  20. package/.agents/skills/embedded-captions/modes/cinematic/_archive/champion/spec.md +98 -0
  21. package/.agents/skills/embedded-captions/modes/cinematic/_archive/champion/template.html +188 -0
  22. package/.agents/skills/embedded-captions/modes/cinematic/_archive/memory-wall/spec.md +134 -0
  23. package/.agents/skills/embedded-captions/modes/cinematic/_archive/memory-wall/template.html +179 -0
  24. package/.agents/skills/embedded-captions/modes/cinematic/_archive/portrait-header/spec.md +81 -0
  25. package/.agents/skills/embedded-captions/modes/cinematic/_archive/portrait-header/template.html +170 -0
  26. package/.agents/skills/embedded-captions/modes/cinematic/cinematic-cream/spec.md +16 -0
  27. package/.agents/skills/embedded-captions/modes/cinematic/cinematic-cream/template.html +226 -0
  28. package/.agents/skills/embedded-captions/modes/cinematic/engine.html +355 -0
  29. package/.agents/skills/embedded-captions/modes/standard/_anatomy.md +233 -0
  30. package/.agents/skills/embedded-captions/modes/standard/_motion.md +192 -0
  31. package/.agents/skills/embedded-captions/modes/standard/fonts/build-fonts-css.cjs +97 -0
  32. package/.agents/skills/embedded-captions/references/aesthetic-principles.md +168 -0
  33. package/.agents/skills/embedded-captions/references/anti-patterns.md +188 -0
  34. package/.agents/skills/embedded-captions/references/bespoke-vs-presets.md +178 -0
  35. package/.agents/skills/embedded-captions/references/caption-grouping.md +130 -0
  36. package/.agents/skills/embedded-captions/references/composition-craft.md +522 -0
  37. package/.agents/skills/embedded-captions/references/direction-catalog.md +138 -0
  38. package/.agents/skills/embedded-captions/references/example-renders/champion.html +371 -0
  39. package/.agents/skills/embedded-captions/references/example-renders/memory-wall.html +334 -0
  40. package/.agents/skills/embedded-captions/references/failure-modes.md +145 -0
  41. package/.agents/skills/embedded-captions/references/layout-heuristics.md +238 -0
  42. package/.agents/skills/embedded-captions/references/motion-vocabulary.md +148 -0
  43. package/.agents/skills/embedded-captions/references/rail.md +68 -0
  44. package/.agents/skills/embedded-captions/references/reference-bar.md +47 -0
  45. package/.agents/skills/embedded-captions/references/scene-types.md +94 -0
  46. package/.agents/skills/embedded-captions/references/test-set.md +66 -0
  47. package/.agents/skills/embedded-captions/references/typographic-moves.md +266 -0
  48. package/.agents/skills/embedded-captions/references/typography-presets.md +63 -0
  49. package/.agents/skills/embedded-captions/scripts/audio-envelope.cjs +95 -0
  50. package/.agents/skills/embedded-captions/scripts/check-occlusion.cjs +250 -0
  51. package/.agents/skills/embedded-captions/scripts/check-overflow.cjs +194 -0
  52. package/.agents/skills/embedded-captions/scripts/check-rail-climax.cjs +233 -0
  53. package/.agents/skills/embedded-captions/scripts/check-timing.cjs +173 -0
  54. package/.agents/skills/embedded-captions/scripts/fill-timings.cjs +124 -0
  55. package/.agents/skills/embedded-captions/scripts/fit-fonts.cjs +158 -0
  56. package/.agents/skills/embedded-captions/scripts/gen-stroke-path.py +46 -0
  57. package/.agents/skills/embedded-captions/scripts/inject-fonts.cjs +169 -0
  58. package/.agents/skills/embedded-captions/scripts/lib-dna.cjs +201 -0
  59. package/.agents/skills/embedded-captions/scripts/make-cinematic.cjs +1205 -0
  60. package/.agents/skills/embedded-captions/scripts/make-composition.cjs +404 -0
  61. package/.agents/skills/embedded-captions/scripts/make-theme.cjs +8781 -0
  62. package/.agents/skills/embedded-captions/scripts/matte.cjs +294 -0
  63. package/.agents/skills/embedded-captions/scripts/measure-layout.cjs +293 -0
  64. package/.agents/skills/embedded-captions/scripts/prepare.sh +39 -0
  65. package/.agents/skills/embedded-captions/scripts/preview-frames.cjs +268 -0
  66. package/.agents/skills/embedded-captions/scripts/render-and-composite.sh +509 -0
  67. package/.agents/skills/embedded-captions/scripts/render-theme.sh +34 -0
  68. package/.agents/skills/embedded-captions/scripts/safe-zones.cjs +813 -0
  69. package/.agents/skills/embedded-captions/scripts/transcribe.cjs +349 -0
  70. package/.agents/skills/embedded-captions/themes/PORTING.md +49 -0
  71. package/.agents/skills/embedded-captions/themes/README.md +244 -0
  72. package/.agents/skills/embedded-captions/themes/anchor.json +27 -0
  73. package/.agents/skills/embedded-captions/themes/arcade.json +51 -0
  74. package/.agents/skills/embedded-captions/themes/aurora.json +41 -0
  75. package/.agents/skills/embedded-captions/themes/biolume.json +35 -0
  76. package/.agents/skills/embedded-captions/themes/brush.json +74 -0
  77. package/.agents/skills/embedded-captions/themes/chalkboard.json +52 -0
  78. package/.agents/skills/embedded-captions/themes/dossier.json +56 -0
  79. package/.agents/skills/embedded-captions/themes/graffiti.json +62 -0
  80. package/.agents/skills/embedded-captions/themes/hologram.json +41 -0
  81. package/.agents/skills/embedded-captions/themes/inkwater.json +43 -0
  82. package/.agents/skills/embedded-captions/themes/laser.json +46 -0
  83. package/.agents/skills/embedded-captions/themes/lastpage.json +33 -0
  84. package/.agents/skills/embedded-captions/themes/neonsign.json +53 -0
  85. package/.agents/skills/embedded-captions/themes/nightcity.json +56 -0
  86. package/.agents/skills/embedded-captions/themes/ordnance.json +54 -0
  87. package/.agents/skills/embedded-captions/themes/papercut.json +37 -0
  88. package/.agents/skills/embedded-captions/themes/popup.json +46 -0
  89. package/.agents/skills/embedded-captions/themes/ransom.json +62 -0
  90. package/.agents/skills/embedded-captions/themes/scoreboard.json +54 -0
  91. package/.agents/skills/embedded-captions/themes/spectrum.json +46 -0
  92. package/.agents/skills/embedded-captions/themes/stardust.json +29 -0
  93. package/.agents/skills/embedded-captions/themes/stomp.json +43 -0
  94. package/.agents/skills/embedded-captions/themes/terminal.json +49 -0
  95. package/.agents/skills/embedded-captions/themes/thunder.json +44 -0
  96. package/.agents/skills/embedded-captions/themes/transit.json +44 -0
  97. package/.agents/skills/embedded-captions/themes/vhs.json +47 -0
  98. package/.agents/skills/faceless-explainer/SKILL.md +209 -0
  99. package/.agents/skills/faceless-explainer/references/cut-catalog.md +215 -0
  100. package/.agents/skills/faceless-explainer/references/motion-language.md +156 -0
  101. package/.agents/skills/faceless-explainer/references/story-design.md +248 -0
  102. package/.agents/skills/faceless-explainer/references/visual-design.md +146 -0
  103. package/.agents/skills/faceless-explainer/scripts/assemble-index.mjs +570 -0
  104. package/.agents/skills/faceless-explainer/scripts/audio.mjs +260 -0
  105. package/.agents/skills/faceless-explainer/scripts/build-frame.mjs +536 -0
  106. package/.agents/skills/faceless-explainer/scripts/captions.mjs +508 -0
  107. package/.agents/skills/faceless-explainer/scripts/lib/assets.mjs +55 -0
  108. package/.agents/skills/faceless-explainer/scripts/lib/dimensions.mjs +45 -0
  109. package/.agents/skills/faceless-explainer/scripts/lib/storyboard.mjs +249 -0
  110. package/.agents/skills/faceless-explainer/scripts/lib/tokens.mjs +204 -0
  111. package/.agents/skills/faceless-explainer/scripts/lib/transition-registry.mjs +38 -0
  112. package/.agents/skills/faceless-explainer/scripts/lib/transitions.json +71 -0
  113. package/.agents/skills/faceless-explainer/scripts/transitions.mjs +320 -0
  114. package/.agents/skills/faceless-explainer/sub-agents/frame-worker.md +75 -0
  115. package/.agents/skills/flockposter/LICENSE +17 -0
  116. package/.agents/skills/flockposter/README.md +72 -0
  117. package/.agents/skills/flockposter/SKILL.md +562 -0
  118. package/.agents/skills/flockposter/examples/cli-instagram-reel.sh +21 -0
  119. package/.agents/skills/flockposter/examples/cli-multi-platform.json +69 -0
  120. package/.agents/skills/flockposter/examples/cli-tiktok-upload-only.sh +22 -0
  121. package/.agents/skills/flockposter/examples/cli-x-thread.sh +17 -0
  122. package/.agents/skills/flockposter/examples/cli-youtube-short.sh +21 -0
  123. package/.agents/skills/flockposter/examples/public-api-instagram-reel.json +28 -0
  124. package/.agents/skills/general-video/SKILL.md +143 -0
  125. package/.agents/skills/hyperframes/SKILL.md +160 -0
  126. package/.agents/skills/hyperframes-animation/SKILL.md +84 -0
  127. package/.agents/skills/hyperframes-animation/adapters/animate-text.md +64 -0
  128. package/.agents/skills/hyperframes-animation/adapters/animejs.md +114 -0
  129. package/.agents/skills/hyperframes-animation/adapters/css-animations.md +143 -0
  130. package/.agents/skills/hyperframes-animation/adapters/gsap-easing-and-stagger.md +118 -0
  131. package/.agents/skills/hyperframes-animation/adapters/gsap-timeline-and-labels.md +96 -0
  132. package/.agents/skills/hyperframes-animation/adapters/gsap-transforms-and-perf.md +96 -0
  133. package/.agents/skills/hyperframes-animation/adapters/gsap.md +105 -0
  134. package/.agents/skills/hyperframes-animation/adapters/html-in-canvas-patterns.md +507 -0
  135. package/.agents/skills/hyperframes-animation/adapters/lottie.md +117 -0
  136. package/.agents/skills/hyperframes-animation/adapters/three.md +131 -0
  137. package/.agents/skills/hyperframes-animation/adapters/typegpu.md +178 -0
  138. package/.agents/skills/hyperframes-animation/adapters/waapi.md +101 -0
  139. package/.agents/skills/hyperframes-animation/blueprints/comparison-split.md +27 -0
  140. package/.agents/skills/hyperframes-animation/blueprints/constellation-hub.md +44 -0
  141. package/.agents/skills/hyperframes-animation/blueprints/cta-morph-press.md +28 -0
  142. package/.agents/skills/hyperframes-animation/blueprints/cursor-ui-demo.md +57 -0
  143. package/.agents/skills/hyperframes-animation/blueprints/dataviz-countup.md +46 -0
  144. package/.agents/skills/hyperframes-animation/blueprints/device-surface-showcase.md +53 -0
  145. package/.agents/skills/hyperframes-animation/blueprints/grid-card-assemble.md +66 -0
  146. package/.agents/skills/hyperframes-animation/blueprints/kinetic-type-beats.md +78 -0
  147. package/.agents/skills/hyperframes-animation/blueprints/logo-assemble-lockup.md +69 -0
  148. package/.agents/skills/hyperframes-animation/blueprints/overwhelm-surround.md +28 -0
  149. package/.agents/skills/hyperframes-animation/blueprints/spatial-pan-stations.md +37 -0
  150. package/.agents/skills/hyperframes-animation/blueprints/ticker-takeover.md +29 -0
  151. package/.agents/skills/hyperframes-animation/blueprints/titlecard-reveal.md +42 -0
  152. package/.agents/skills/hyperframes-animation/blueprints/typewriter-reveal.md +51 -0
  153. package/.agents/skills/hyperframes-animation/blueprints/video-text-pivot.md +30 -0
  154. package/.agents/skills/hyperframes-animation/blueprints-index.md +146 -0
  155. package/.agents/skills/hyperframes-animation/examples/assets/avatars/02.avif +0 -0
  156. package/.agents/skills/hyperframes-animation/examples/assets/brands/github.avif +0 -0
  157. package/.agents/skills/hyperframes-animation/examples/assets/brands/nvidia.avif +0 -0
  158. package/.agents/skills/hyperframes-animation/examples/assets/brands/visa.avif +0 -0
  159. package/.agents/skills/hyperframes-animation/examples/assets/brands/zoominfo.avif +0 -0
  160. package/.agents/skills/hyperframes-animation/examples/brand-reveal-assemble-zoom.html +382 -0
  161. package/.agents/skills/hyperframes-animation/examples/comparison-split-cards.html +649 -0
  162. package/.agents/skills/hyperframes-animation/examples/concept-demo-decode-pan.html +520 -0
  163. package/.agents/skills/hyperframes-animation/examples/cta-morph-press.html +468 -0
  164. package/.agents/skills/hyperframes-animation/examples/cta-orbit-collapse.html +1298 -0
  165. package/.agents/skills/hyperframes-animation/examples/demo-page-scroll-spotlight.html +759 -0
  166. package/.agents/skills/hyperframes-animation/examples/hook-counter-burst.html +729 -0
  167. package/.agents/skills/hyperframes-animation/examples/messaging-multi-phrase.html +352 -0
  168. package/.agents/skills/hyperframes-animation/examples/metric-video-text-pivot.html +779 -0
  169. package/.agents/skills/hyperframes-animation/examples/problem-mockup-overwhelm.html +1374 -0
  170. package/.agents/skills/hyperframes-animation/examples/proof-logo-chain.html +861 -0
  171. package/.agents/skills/hyperframes-animation/examples/takeover-ticker-displace.html +347 -0
  172. package/.agents/skills/hyperframes-animation/examples/workflow-approve-press.html +606 -0
  173. package/.agents/skills/hyperframes-animation/rules/3d-page-scroll.md +227 -0
  174. package/.agents/skills/hyperframes-animation/rules/3d-text-depth-layers.md +297 -0
  175. package/.agents/skills/hyperframes-animation/rules/ai-tracking-box.md +382 -0
  176. package/.agents/skills/hyperframes-animation/rules/ambient-glow-bloom.md +305 -0
  177. package/.agents/skills/hyperframes-animation/rules/asr-keyword-glow.md +286 -0
  178. package/.agents/skills/hyperframes-animation/rules/avatar-cloud-network.md +371 -0
  179. package/.agents/skills/hyperframes-animation/rules/camera-cursor-tracking.md +246 -0
  180. package/.agents/skills/hyperframes-animation/rules/card-morph-anchor.md +267 -0
  181. package/.agents/skills/hyperframes-animation/rules/center-outward-expansion.md +227 -0
  182. package/.agents/skills/hyperframes-animation/rules/context-sensitive-cursor.md +257 -0
  183. package/.agents/skills/hyperframes-animation/rules/coordinate-target-zoom.md +332 -0
  184. package/.agents/skills/hyperframes-animation/rules/counting-dynamic-scale.md +283 -0
  185. package/.agents/skills/hyperframes-animation/rules/css-marker-patterns.md +373 -0
  186. package/.agents/skills/hyperframes-animation/rules/cursor-click-ripple.md +262 -0
  187. package/.agents/skills/hyperframes-animation/rules/depth-of-field-blur.md +313 -0
  188. package/.agents/skills/hyperframes-animation/rules/depth-scatter-assemble.md +303 -0
  189. package/.agents/skills/hyperframes-animation/rules/discrete-text-sequence.md +273 -0
  190. package/.agents/skills/hyperframes-animation/rules/dynamic-content-sequencing.md +307 -0
  191. package/.agents/skills/hyperframes-animation/rules/gsap-effects.md +299 -0
  192. package/.agents/skills/hyperframes-animation/rules/hacker-flip-3d.md +223 -0
  193. package/.agents/skills/hyperframes-animation/rules/kinetic-beat-slam.md +183 -0
  194. package/.agents/skills/hyperframes-animation/rules/motion-blur-streak.md +328 -0
  195. package/.agents/skills/hyperframes-animation/rules/multi-phase-camera.md +273 -0
  196. package/.agents/skills/hyperframes-animation/rules/orbit-3d-entry.md +301 -0
  197. package/.agents/skills/hyperframes-animation/rules/physics-press-reaction.md +350 -0
  198. package/.agents/skills/hyperframes-animation/rules/press-release-spring.md +296 -0
  199. package/.agents/skills/hyperframes-animation/rules/reactive-displacement.md +277 -0
  200. package/.agents/skills/hyperframes-animation/rules/scale-swap-transition.md +298 -0
  201. package/.agents/skills/hyperframes-animation/rules/sine-wave-loop.md +278 -0
  202. package/.agents/skills/hyperframes-animation/rules/split-tilt-cards.md +277 -0
  203. package/.agents/skills/hyperframes-animation/rules/spring-pop-entrance.md +273 -0
  204. package/.agents/skills/hyperframes-animation/rules/stat-bars-and-fills.md +156 -0
  205. package/.agents/skills/hyperframes-animation/rules/svg-icon-enrichment.md +329 -0
  206. package/.agents/skills/hyperframes-animation/rules/svg-path-draw.md +274 -0
  207. package/.agents/skills/hyperframes-animation/rules/vertical-spring-ticker.md +239 -0
  208. package/.agents/skills/hyperframes-animation/rules/viewport-change.md +349 -0
  209. package/.agents/skills/hyperframes-animation/rules-index.md +86 -0
  210. package/.agents/skills/hyperframes-animation/scripts/animation-map.mjs +606 -0
  211. package/.agents/skills/hyperframes-animation/scripts/package-loader.mjs +288 -0
  212. package/.agents/skills/hyperframes-animation/scripts/package-loader.test.mjs +62 -0
  213. package/.agents/skills/hyperframes-animation/techniques.md +507 -0
  214. package/.agents/skills/hyperframes-animation/transitions/TRANSITION-REGISTRY.md +167 -0
  215. package/.agents/skills/hyperframes-animation/transitions/catalog.md +127 -0
  216. package/.agents/skills/hyperframes-animation/transitions/css-3d.md +12 -0
  217. package/.agents/skills/hyperframes-animation/transitions/css-blur.md +51 -0
  218. package/.agents/skills/hyperframes-animation/transitions/css-cover.md +43 -0
  219. package/.agents/skills/hyperframes-animation/transitions/css-destruction.md +95 -0
  220. package/.agents/skills/hyperframes-animation/transitions/css-dissolve.md +66 -0
  221. package/.agents/skills/hyperframes-animation/transitions/css-distortion.md +45 -0
  222. package/.agents/skills/hyperframes-animation/transitions/css-grid.md +10 -0
  223. package/.agents/skills/hyperframes-animation/transitions/css-light.md +49 -0
  224. package/.agents/skills/hyperframes-animation/transitions/css-mechanical.md +30 -0
  225. package/.agents/skills/hyperframes-animation/transitions/css-other.md +25 -0
  226. package/.agents/skills/hyperframes-animation/transitions/css-push.md +41 -0
  227. package/.agents/skills/hyperframes-animation/transitions/css-radial.md +37 -0
  228. package/.agents/skills/hyperframes-animation/transitions/css-scale.md +24 -0
  229. package/.agents/skills/hyperframes-animation/transitions/overview.md +153 -0
  230. package/.agents/skills/hyperframes-cli/SKILL.md +113 -0
  231. package/.agents/skills/hyperframes-cli/references/doctor-browser.md +45 -0
  232. package/.agents/skills/hyperframes-cli/references/init-and-scaffold.md +55 -0
  233. package/.agents/skills/hyperframes-cli/references/lambda.md +132 -0
  234. package/.agents/skills/hyperframes-cli/references/lint-validate-inspect.md +121 -0
  235. package/.agents/skills/hyperframes-cli/references/preview-render.md +149 -0
  236. package/.agents/skills/hyperframes-cli/references/upgrade-info-misc.md +75 -0
  237. package/.agents/skills/hyperframes-core/SKILL.md +78 -0
  238. package/.agents/skills/hyperframes-core/references/composition-patterns.md +263 -0
  239. package/.agents/skills/hyperframes-core/references/data-attributes.md +70 -0
  240. package/.agents/skills/hyperframes-core/references/determinism-rules.md +68 -0
  241. package/.agents/skills/hyperframes-core/references/full-screen-motion.md +62 -0
  242. package/.agents/skills/hyperframes-core/references/minimal-composition.md +66 -0
  243. package/.agents/skills/hyperframes-core/references/script-format.md +49 -0
  244. package/.agents/skills/hyperframes-core/references/storyboard-format.md +95 -0
  245. package/.agents/skills/hyperframes-core/references/sub-compositions.md +237 -0
  246. package/.agents/skills/hyperframes-core/references/subagent-dispatch.md +41 -0
  247. package/.agents/skills/hyperframes-core/references/tailwind.md +125 -0
  248. package/.agents/skills/hyperframes-core/references/tracks-and-clips.md +76 -0
  249. package/.agents/skills/hyperframes-core/references/variables-and-media.md +90 -0
  250. package/.agents/skills/hyperframes-creative/SKILL.md +70 -0
  251. package/.agents/skills/hyperframes-creative/frame-presets/biennale-yellow/FRAME.md +289 -0
  252. package/.agents/skills/hyperframes-creative/frame-presets/biennale-yellow/caption-skin.html +221 -0
  253. package/.agents/skills/hyperframes-creative/frame-presets/biennale-yellow/frame-showcase.html +1214 -0
  254. package/.agents/skills/hyperframes-creative/frame-presets/blockframe/FRAME.md +275 -0
  255. package/.agents/skills/hyperframes-creative/frame-presets/blockframe/caption-skin.html +224 -0
  256. package/.agents/skills/hyperframes-creative/frame-presets/blockframe/frame-showcase.html +1347 -0
  257. package/.agents/skills/hyperframes-creative/frame-presets/blue-professional/FRAME.md +307 -0
  258. package/.agents/skills/hyperframes-creative/frame-presets/blue-professional/caption-skin.html +223 -0
  259. package/.agents/skills/hyperframes-creative/frame-presets/blue-professional/frame-showcase.html +1372 -0
  260. package/.agents/skills/hyperframes-creative/frame-presets/bold-poster/FRAME.md +275 -0
  261. package/.agents/skills/hyperframes-creative/frame-presets/bold-poster/caption-skin.html +230 -0
  262. package/.agents/skills/hyperframes-creative/frame-presets/bold-poster/frame-showcase.html +1140 -0
  263. package/.agents/skills/hyperframes-creative/frame-presets/broadside/FRAME.md +284 -0
  264. package/.agents/skills/hyperframes-creative/frame-presets/broadside/caption-skin.html +225 -0
  265. package/.agents/skills/hyperframes-creative/frame-presets/broadside/frame-showcase.html +1166 -0
  266. package/.agents/skills/hyperframes-creative/frame-presets/capsule/FRAME.md +284 -0
  267. package/.agents/skills/hyperframes-creative/frame-presets/capsule/caption-skin.html +224 -0
  268. package/.agents/skills/hyperframes-creative/frame-presets/capsule/frame-showcase.html +1465 -0
  269. package/.agents/skills/hyperframes-creative/frame-presets/cartesian/FRAME.md +278 -0
  270. package/.agents/skills/hyperframes-creative/frame-presets/cartesian/caption-skin.html +222 -0
  271. package/.agents/skills/hyperframes-creative/frame-presets/cartesian/frame-showcase.html +1263 -0
  272. package/.agents/skills/hyperframes-creative/frame-presets/claude/FRAME.md +277 -0
  273. package/.agents/skills/hyperframes-creative/frame-presets/claude/caption-skin.html +224 -0
  274. package/.agents/skills/hyperframes-creative/frame-presets/claude/frame-showcase.html +1439 -0
  275. package/.agents/skills/hyperframes-creative/frame-presets/cobalt-grid/FRAME.md +265 -0
  276. package/.agents/skills/hyperframes-creative/frame-presets/cobalt-grid/caption-skin.html +238 -0
  277. package/.agents/skills/hyperframes-creative/frame-presets/cobalt-grid/frame-showcase.html +1468 -0
  278. package/.agents/skills/hyperframes-creative/frame-presets/coral/FRAME.md +314 -0
  279. package/.agents/skills/hyperframes-creative/frame-presets/coral/caption-skin.html +226 -0
  280. package/.agents/skills/hyperframes-creative/frame-presets/coral/frame-showcase.html +1268 -0
  281. package/.agents/skills/hyperframes-creative/frame-presets/creative-mode/FRAME.md +333 -0
  282. package/.agents/skills/hyperframes-creative/frame-presets/creative-mode/caption-skin.html +227 -0
  283. package/.agents/skills/hyperframes-creative/frame-presets/creative-mode/frame-showcase.html +1330 -0
  284. package/.agents/skills/hyperframes-creative/frame-presets/daisy-days/FRAME.md +274 -0
  285. package/.agents/skills/hyperframes-creative/frame-presets/daisy-days/caption-skin.html +230 -0
  286. package/.agents/skills/hyperframes-creative/frame-presets/daisy-days/frame-showcase.html +1444 -0
  287. package/.agents/skills/hyperframes-creative/frame-presets/editorial-forest/FRAME.md +265 -0
  288. package/.agents/skills/hyperframes-creative/frame-presets/editorial-forest/caption-skin.html +223 -0
  289. package/.agents/skills/hyperframes-creative/frame-presets/editorial-forest/frame-showcase.html +1273 -0
  290. package/.agents/skills/hyperframes-creative/palettes/bold-energetic.md +14 -0
  291. package/.agents/skills/hyperframes-creative/palettes/clean-corporate.md +14 -0
  292. package/.agents/skills/hyperframes-creative/palettes/dark-premium.md +14 -0
  293. package/.agents/skills/hyperframes-creative/palettes/jewel-rich.md +14 -0
  294. package/.agents/skills/hyperframes-creative/palettes/monochrome.md +14 -0
  295. package/.agents/skills/hyperframes-creative/palettes/nature-earth.md +14 -0
  296. package/.agents/skills/hyperframes-creative/palettes/neon-electric.md +14 -0
  297. package/.agents/skills/hyperframes-creative/palettes/pastel-soft.md +14 -0
  298. package/.agents/skills/hyperframes-creative/palettes/warm-editorial.md +14 -0
  299. package/.agents/skills/hyperframes-creative/references/audio-reactive.md +76 -0
  300. package/.agents/skills/hyperframes-creative/references/beat-direction.md +164 -0
  301. package/.agents/skills/hyperframes-creative/references/composition-patterns.md +199 -0
  302. package/.agents/skills/hyperframes-creative/references/data-in-motion.md +19 -0
  303. package/.agents/skills/hyperframes-creative/references/design-adherence.md +19 -0
  304. package/.agents/skills/hyperframes-creative/references/design-picker.md +123 -0
  305. package/.agents/skills/hyperframes-creative/references/design-spec.md +55 -0
  306. package/.agents/skills/hyperframes-creative/references/house-style.md +73 -0
  307. package/.agents/skills/hyperframes-creative/references/motion-principles.md +150 -0
  308. package/.agents/skills/hyperframes-creative/references/narration.md +92 -0
  309. package/.agents/skills/hyperframes-creative/references/prompt-expansion.md +68 -0
  310. package/.agents/skills/hyperframes-creative/references/typography.md +218 -0
  311. package/.agents/skills/hyperframes-creative/references/video-composition.md +63 -0
  312. package/.agents/skills/hyperframes-creative/references/visual-styles.md +457 -0
  313. package/.agents/skills/hyperframes-creative/scripts/contrast-report.mjs +353 -0
  314. package/.agents/skills/hyperframes-creative/scripts/extract-audio-data.py +188 -0
  315. package/.agents/skills/hyperframes-creative/scripts/package-loader.mjs +288 -0
  316. package/.agents/skills/hyperframes-creative/scripts/package-loader.test.mjs +62 -0
  317. package/.agents/skills/hyperframes-creative/templates/design-picker.html +1432 -0
  318. package/.agents/skills/hyperframes-keyframes/SKILL.md +237 -0
  319. package/.agents/skills/hyperframes-keyframes/agents/openai.yaml +4 -0
  320. package/.agents/skills/hyperframes-keyframes/references/keyframe-patterns.md +106 -0
  321. package/.agents/skills/motion-graphics/SKILL.md +172 -0
  322. package/.agents/skills/motion-graphics/agents/builder.md +40 -0
  323. package/.agents/skills/motion-graphics/agents/director.md +53 -0
  324. package/.agents/skills/motion-graphics/agents/finalize.md +17 -0
  325. package/.agents/skills/motion-graphics/catalog-map.md +40 -0
  326. package/.agents/skills/motion-graphics/categories/asset-fusion/module.md +37 -0
  327. package/.agents/skills/motion-graphics/categories/charts/module.md +21 -0
  328. package/.agents/skills/motion-graphics/categories/kinetic-type/module.md +19 -0
  329. package/.agents/skills/motion-graphics/categories/logo-reveal/module.md +17 -0
  330. package/.agents/skills/motion-graphics/categories/lower-thirds/module.md +16 -0
  331. package/.agents/skills/motion-graphics/categories/maps/bake-basemap.mjs +273 -0
  332. package/.agents/skills/motion-graphics/categories/maps/module.md +61 -0
  333. package/.agents/skills/motion-graphics/categories/news/module.md +56 -0
  334. package/.agents/skills/motion-graphics/categories/stat/module.md +21 -0
  335. package/.agents/skills/motion-graphics/categories/tweet/module.md +16 -0
  336. package/.agents/skills/motion-graphics/categories/webpage/module.md +21 -0
  337. package/.agents/skills/motion-graphics/grounding/PROTOCOL.md +64 -0
  338. package/.agents/skills/motion-graphics/grounding/locate.mjs +227 -0
  339. package/.agents/skills/motion-graphics/phases/source/guide.md +21 -0
  340. package/.agents/skills/motion-graphics/references/builder-contract.md +38 -0
  341. package/.agents/skills/motion-graphics/references/motion-vocabulary.md +43 -0
  342. package/.agents/skills/motion-graphics/references/shot-plan-ir.md +54 -0
  343. package/.agents/skills/motion-graphics/samples/asset-fusion/_ref-circle-highlight.html +306 -0
  344. package/.agents/skills/product-launch-video/SKILL.md +208 -0
  345. package/.agents/skills/product-launch-video/references/cut-catalog.md +220 -0
  346. package/.agents/skills/product-launch-video/references/motion-language.md +156 -0
  347. package/.agents/skills/product-launch-video/references/story-design.md +373 -0
  348. package/.agents/skills/product-launch-video/references/visual-design.md +126 -0
  349. package/.agents/skills/product-launch-video/scripts/assemble-index.mjs +570 -0
  350. package/.agents/skills/product-launch-video/scripts/audio.mjs +260 -0
  351. package/.agents/skills/product-launch-video/scripts/build-frame.mjs +536 -0
  352. package/.agents/skills/product-launch-video/scripts/captions.mjs +508 -0
  353. package/.agents/skills/product-launch-video/scripts/lib/assets.mjs +55 -0
  354. package/.agents/skills/product-launch-video/scripts/lib/dimensions.mjs +45 -0
  355. package/.agents/skills/product-launch-video/scripts/lib/pad-frame-duration.mjs +36 -0
  356. package/.agents/skills/product-launch-video/scripts/lib/pad-frame-duration.test.mjs +76 -0
  357. package/.agents/skills/product-launch-video/scripts/lib/storyboard.mjs +249 -0
  358. package/.agents/skills/product-launch-video/scripts/lib/tokens.mjs +204 -0
  359. package/.agents/skills/product-launch-video/scripts/lib/transition-registry.mjs +38 -0
  360. package/.agents/skills/product-launch-video/scripts/lib/transitions.json +71 -0
  361. package/.agents/skills/product-launch-video/scripts/stage-assets.mjs +39 -0
  362. package/.agents/skills/product-launch-video/scripts/transitions.mjs +327 -0
  363. package/.agents/skills/product-launch-video/sub-agents/frame-worker.md +75 -0
  364. package/.agents/skills/slideshow/SKILL.md +550 -0
  365. package/.agents/skills/slideshow/references/standalone-harness.md +1020 -0
  366. package/.agents/skills/talking-head-recut/NOTICE.md +39 -0
  367. package/.agents/skills/talking-head-recut/SKILL.md +1195 -0
  368. package/.agents/skills/talking-head-recut/assets/vendor/gsap.min.js +10 -0
  369. package/.agents/skills/talking-head-recut/references/DESIGN_INDEX.md +145 -0
  370. package/.agents/skills/talking-head-recut/references/frames/clean.html +92 -0
  371. package/.agents/skills/talking-head-recut/references/frames/hairline.html +171 -0
  372. package/.agents/skills/talking-head-recut/references/frames/polaroid.html +131 -0
  373. package/.agents/skills/talking-head-recut/references/layouts/overlay.html +164 -0
  374. package/.agents/skills/talking-head-recut/references/layouts/pip.html +143 -0
  375. package/.agents/skills/talking-head-recut/references/layouts/split.html +121 -0
  376. package/.agents/skills/talking-head-recut/references/layouts/stack.html +109 -0
  377. package/.agents/skills/talking-head-recut/references/styles/academic.html +172 -0
  378. package/.agents/skills/talking-head-recut/references/styles/audit.html +170 -0
  379. package/.agents/skills/talking-head-recut/references/styles/editorial.html +189 -0
  380. package/.agents/skills/talking-head-recut/references/styles/geom.html +181 -0
  381. package/.agents/skills/talking-head-recut/references/styles/minimal.html +130 -0
  382. package/.agents/skills/talking-head-recut/references/styles/spotlight.html +142 -0
  383. package/.agents/skills/talking-head-recut/references/styles/swiss.html +188 -0
  384. package/.agents/skills/talking-head-recut/references/styles/terminal.html +196 -0
  385. package/.agents/skills/talking-head-recut/references/styles/whiteboard.html +170 -0
  386. package/.agents/skills/talking-head-recut/references/styles/xhs.html +206 -0
  387. package/.agents/skills/vidfarm-media/SKILL.md +85 -0
  388. package/.agents/skills/vidfarm-media/references/tts.md +54 -0
  389. package/.agents/skills/vidfarm-media/scripts/audio.mjs +628 -0
  390. package/.agents/skills/vidfarm-media/scripts/wait-bgm.mjs +31 -0
  391. package/.agents/skills/website-to-video/SKILL.md +145 -0
  392. package/.agents/skills/website-to-video/assets/sfx/CREDITS.md +35 -0
  393. package/.agents/skills/website-to-video/assets/sfx/manifest.json +97 -0
  394. package/.agents/skills/website-to-video/references/beat-builder-guide.md +263 -0
  395. package/.agents/skills/website-to-video/references/capabilities.md +713 -0
  396. package/.agents/skills/website-to-video/references/step-0-capture.md +55 -0
  397. package/.agents/skills/website-to-video/references/step-1-design.md +333 -0
  398. package/.agents/skills/website-to-video/references/step-2-brief.md +178 -0
  399. package/.agents/skills/website-to-video/references/step-3-storyboard.md +572 -0
  400. package/.agents/skills/website-to-video/references/step-4-vo.md +225 -0
  401. package/.agents/skills/website-to-video/references/step-5-build.md +483 -0
  402. package/.agents/skills/website-to-video/references/step-6-validate.md +341 -0
  403. package/.agents/skills/website-to-video/scripts/w2h-verify.mjs +759 -0
  404. package/SKILL.director.md +37 -0
  405. package/SKILL.platform.md +6 -1
  406. package/demo/dist/app.css +1 -1
  407. package/demo/dist/app.js +369 -85
  408. package/dist/src/app.js +630 -140
  409. package/dist/src/cli.js +529 -12
  410. package/dist/src/composition-runtime.js +262 -3
  411. package/dist/src/config.js +13 -0
  412. package/dist/src/devcli/doctor.js +192 -0
  413. package/dist/src/devcli/hyperframes-cli.js +118 -0
  414. package/dist/src/devcli/skills.js +476 -0
  415. package/dist/src/devcli/stills.js +249 -0
  416. package/dist/src/editor-chat.js +256 -0
  417. package/dist/src/frontend/homepage-client.js +50 -1
  418. package/dist/src/frontend/homepage-shared.js +197 -0
  419. package/dist/src/frontend/homepage-store.js +10 -1
  420. package/dist/src/frontend/homepage-view.js +43 -5
  421. package/dist/src/homepage.js +51 -18
  422. package/dist/src/hyperframes/composition.js +5 -5
  423. package/dist/src/services/composition-lint.js +199 -0
  424. package/dist/src/services/hyperframes.js +67 -13
  425. package/dist/src/services/serverless-records.js +9 -0
  426. package/package.json +2 -1
  427. package/public/assets/homepage-client-app.js +23 -23
@@ -0,0 +1,759 @@
1
+ #!/usr/bin/env node
2
+ // w2h-verify.mjs — verification report for a website-to-video project.
3
+ //
4
+ // Computes quality signals the agent cannot fudge. Each check is designed to
5
+ // catch a specific failure mode observed across three real agent debriefs.
6
+ // Result becomes the Step 6 deliverable — paste verbatim into the final
7
+ // user-facing summary so the user sees exactly what shipped.
8
+ //
9
+ // Pure file analysis. No shell spawns. Run lint + inspect separately and
10
+ // paste alongside.
11
+ //
12
+ // Usage:
13
+ // node skills/website-to-video/scripts/w2h-verify.mjs <project-dir>
14
+ //
15
+ // Exit codes:
16
+ // 0 = all gates pass
17
+ // 1 = one or more gates failed
18
+ // 2 = script error (project-dir missing, etc.)
19
+
20
+ import { readFile, readdir } from "node:fs/promises";
21
+ import { join, resolve } from "node:path";
22
+ import { existsSync } from "node:fs";
23
+
24
+ const PROJECT_DIR = resolve(process.argv[2] || ".");
25
+
26
+ // Thresholds — change here, not by interpretation.
27
+ const HEADLINE_MIN_PX = 80; // 80px floor for primary headline at 1920×1080
28
+ const TIMELINE_COVERAGE_MIN = 0.7; // max GSAP event position must reach ≥70% of beat duration
29
+ const SFX_DRIFT_TOLERANCE_S = 0.1; // 3 frames at 30fps; matches step-5 evidence rule + step-6 playback floor
30
+ const BEAT_DURATION_DRIFT_TOLERANCE_S = 0.5;
31
+
32
+ const SHADER_NAMES = [
33
+ "cross-warp-morph",
34
+ "cross-warp",
35
+ "cinematic-zoom",
36
+ "gravitational-lens",
37
+ "glitch",
38
+ "light-leak",
39
+ "flash-through-white",
40
+ "whip-pan",
41
+ "domain-warp",
42
+ "thermal-bloom",
43
+ "swirl",
44
+ "ridged-noise",
45
+ "sdf-reveal",
46
+ "chromatic-aberration",
47
+ "ripple",
48
+ ];
49
+
50
+ // ─── Main ────────────────────────────────────────────────────────────────────
51
+
52
+ async function main() {
53
+ if (!existsSync(PROJECT_DIR)) {
54
+ console.error(`✗ Project directory not found: ${PROJECT_DIR}`);
55
+ process.exit(2);
56
+ }
57
+
58
+ const results = [];
59
+ results.push(await checkRequiredArtifacts());
60
+ results.push(await checkBrandVisualsUsed());
61
+ results.push(await checkPerBeatHeadlineSize());
62
+ results.push(await checkPerBeatTimelineCoverage());
63
+ results.push(await checkShaderTransitionsConsistency());
64
+ results.push(await checkSfxTimestampConsistency());
65
+ results.push(await checkBeatDurationConsistency());
66
+ results.push(await checkMp4Exists());
67
+
68
+ printReport(results);
69
+
70
+ const anyFail = results.some((r) => r.status === "FAIL");
71
+ process.exit(anyFail ? 1 : 0);
72
+ }
73
+
74
+ // ─── Checks ──────────────────────────────────────────────────────────────────
75
+
76
+ async function checkRequiredArtifacts() {
77
+ const required = ["STORYBOARD.md", "DESIGN.md", "SCRIPT.md", "index.html"];
78
+ const missing = required.filter((f) => !existsSync(join(PROJECT_DIR, f)));
79
+ if (missing.length === 0) {
80
+ return { name: "Required artifacts", status: "PASS", detail: required.join(", ") };
81
+ }
82
+ return {
83
+ name: "Required artifacts",
84
+ status: "FAIL",
85
+ detail: `missing: ${missing.join(", ")}`,
86
+ };
87
+ }
88
+
89
+ // Catches the biggest failure mode: agent uses only the logo and rebuilds
90
+ // every "hero illustration" from CSS, ignoring the brand's actual visual identity.
91
+ async function checkBrandVisualsUsed() {
92
+ const compositions = await readBeatCompositions();
93
+ if (compositions.length === 0) {
94
+ return { name: "Brand visuals used", status: "INFO", detail: "no beat compositions found" };
95
+ }
96
+
97
+ // A "brand visual" is anything captured under capture/assets/ that ISN'T:
98
+ // - a font file
99
+ // - a logo file (filename contains "logo")
100
+ // - a favicon / apple-touch-icon
101
+ // i.e., hero-*.jpg, image-*.png, illustrations, photographs, svgs/<icons>.svg
102
+ const brandRegex =
103
+ /capture\/assets\/(?!fonts\/)(?:svgs\/)?(?!.*(?:logo|favicon|apple-touch-icon))[\w-]+\.(?:jpg|jpeg|png|svg|webp|gif)/gi;
104
+ const beatsUsingBrand = [];
105
+ for (const beat of compositions) {
106
+ const matches = beat.content.match(brandRegex) || [];
107
+ if (matches.length > 0) {
108
+ beatsUsingBrand.push({ beat: beat.name, count: new Set(matches).size });
109
+ }
110
+ }
111
+
112
+ const pass = beatsUsingBrand.length >= 1;
113
+ if (pass) {
114
+ return {
115
+ name: "Brand visuals used",
116
+ status: "PASS",
117
+ detail: `${beatsUsingBrand.length}/${compositions.length} beats reference a hero/image/svg captured asset`,
118
+ extra:
119
+ beatsUsingBrand.length === 1
120
+ ? "Only 1 beat uses a captured visual — consider whether the brand's hero illustrations or signature graphics fit other beats too."
121
+ : null,
122
+ };
123
+ }
124
+ return {
125
+ name: "Brand visuals used",
126
+ status: "FAIL",
127
+ detail: `0/${compositions.length} beats reference any hero-*/image-*/svgs/ captured asset (logo doesn't count)`,
128
+ extra:
129
+ "Open capture/assets/contact-sheet-*.jpg and capture/assets/svgs/contact-sheet-*.jpg. The brand's actual visuals are sitting there. Rebuilding them in CSS erases what makes the brand recognizable.",
130
+ };
131
+ }
132
+
133
+ // Catches "headlines too small to read" — inspect typically catches the
134
+ // overflow afterward, but this catches the cause earlier.
135
+ async function checkPerBeatHeadlineSize() {
136
+ const compositions = await readBeatCompositions();
137
+ if (compositions.length === 0) {
138
+ return { name: "Headline font-size", status: "INFO", detail: "no beat compositions found" };
139
+ }
140
+
141
+ // Only flag beats where the LARGEST font-size is in the "aspiring headline
142
+ // but too small" range (40–<80px). Below 40px = the beat has no headline by
143
+ // design (UI labels, code text, decorative). ≥80px = proper headline.
144
+ // This skips legitimate non-headline beats (terminal beats, SVG-only beats,
145
+ // pure-image beats) without losing the real "headline too small" signal.
146
+ const HEADLINE_FLOOR_FOR_CHECK = 40;
147
+ const offenders = [];
148
+ const skipped = [];
149
+ for (const beat of compositions) {
150
+ const sizes = [...beat.content.matchAll(/font-size:\s*(\d+(?:\.\d+)?)px/g)].map((m) =>
151
+ parseFloat(m[1]),
152
+ );
153
+ if (sizes.length === 0) {
154
+ skipped.push({ beat: beat.name, reason: "no font-size declared" });
155
+ continue;
156
+ }
157
+ const max = Math.max(...sizes);
158
+ if (max < HEADLINE_FLOOR_FOR_CHECK) {
159
+ skipped.push({ beat: beat.name, reason: `largest font is ${max}px — no headline by design` });
160
+ continue;
161
+ }
162
+ if (max < HEADLINE_MIN_PX) {
163
+ offenders.push({ beat: beat.name, maxSize: max });
164
+ }
165
+ }
166
+
167
+ const pass = offenders.length === 0;
168
+ const checked = compositions.length - skipped.length;
169
+ return {
170
+ name: "Headline font-size",
171
+ status: pass ? "PASS" : "FAIL",
172
+ detail: pass
173
+ ? `${checked}/${compositions.length} beats with a headline-sized text element, all ≥${HEADLINE_MIN_PX}px`
174
+ : `${offenders.length} beat(s) with headline-sized text below ${HEADLINE_MIN_PX}px floor`,
175
+ extra: pass
176
+ ? null
177
+ : [
178
+ ...offenders.map((o) => `${o.beat}: largest font-size is ${o.maxSize}px`),
179
+ ...(skipped.length > 0
180
+ ? [
181
+ `(skipped ${skipped.length} beat(s) with no headline-sized text: ${skipped.map((s) => s.beat).join(", ")})`,
182
+ ]
183
+ : []),
184
+ ].join("\n "),
185
+ };
186
+ }
187
+
188
+ // Catches "webpage not shot" failures — entrance tweens in the first second
189
+ // then nothing. Snapshots look fine (static end state) but motion is dead.
190
+ async function checkPerBeatTimelineCoverage() {
191
+ const compositions = await readBeatCompositions();
192
+ const beatDurations = await readBeatDurationsFromIndex();
193
+ if (compositions.length === 0) {
194
+ return { name: "Timeline coverage", status: "INFO", detail: "no beat compositions found" };
195
+ }
196
+
197
+ const offenders = [];
198
+ const skipped = [];
199
+ // Pattern detectors: beats that use these idioms have events at positions
200
+ // the static parser can't read (loop iterators, variable arithmetic).
201
+ // Don't flag them as "webpage not shot" — they have events the parser
202
+ // simply can't see. Note: single-tween yoyo/repeat is NOT enough to skip
203
+ // — it only oscillates one element, not the whole beat.
204
+ const dynamicPatterns = [
205
+ {
206
+ name: "forEach with tweens",
207
+ re: /\.forEach\s*\([^{]*\{[\s\S]{0,2000}?\btl\.(?:to|set|fromTo|from)\(/,
208
+ },
209
+ {
210
+ name: "for-loop with tweens",
211
+ re: /\bfor\s*\([^)]*\)\s*\{[\s\S]{0,2000}?\btl\.(?:to|set|fromTo|from)\(/,
212
+ },
213
+ ];
214
+
215
+ for (const beat of compositions) {
216
+ const beatId = beat.name.replace(/\.html$/, "");
217
+ const dur = beatDurations[beatId] ?? beatDurations[beat.name];
218
+ if (!dur) {
219
+ skipped.push({ beat: beat.name, reason: "no data-duration in index.html" });
220
+ continue;
221
+ }
222
+
223
+ // Check for dynamic patterns first — if present, coverage cannot be
224
+ // statically determined; treat as informational, not a failure.
225
+ const matchedDynamic = dynamicPatterns.find((p) => p.re.test(beat.content));
226
+ if (matchedDynamic) {
227
+ skipped.push({
228
+ beat: beat.name,
229
+ reason: `dynamic event pattern detected (${matchedDynamic.name}) — coverage not statically measurable`,
230
+ });
231
+ continue;
232
+ }
233
+
234
+ // Long-duration tween check: if there's a tween with duration ≥ 70% of
235
+ // beat duration, that single tween covers the whole beat — likely a
236
+ // camera dolly, breathing animation, or persistent motion. Skip the
237
+ // position-based coverage check.
238
+ const durationRe = /\btl\.(?:to|set|fromTo|from)\([\s\S]{0,500}?duration:\s*([0-9.]+)/g;
239
+ let dm;
240
+ let hasLongTween = false;
241
+ let longTweenDur = 0;
242
+ while ((dm = durationRe.exec(beat.content)) !== null) {
243
+ const d = parseFloat(dm[1]);
244
+ if (d >= dur * TIMELINE_COVERAGE_MIN) {
245
+ hasLongTween = true;
246
+ longTweenDur = d;
247
+ break;
248
+ }
249
+ }
250
+ if (hasLongTween) {
251
+ skipped.push({
252
+ beat: beat.name,
253
+ reason: `long-duration tween covers ${longTweenDur.toFixed(2)}s of ${dur.toFixed(2)}s beat — full coverage via persistent motion`,
254
+ });
255
+ continue;
256
+ }
257
+
258
+ // Extract GSAP event positions for static cases.
259
+ // Use balanced-paren scanning so multi-line calls and rgba(...) values
260
+ // inside option objects don't false-match.
261
+ const positions = extractTopLevelPositionArgs(beat.content);
262
+ if (positions.length === 0) {
263
+ offenders.push({ beat: beat.name, reason: "no GSAP events with explicit position found" });
264
+ continue;
265
+ }
266
+
267
+ const maxPos = Math.max(...positions);
268
+ const coverage = maxPos / dur;
269
+ if (coverage < TIMELINE_COVERAGE_MIN) {
270
+ offenders.push({
271
+ beat: beat.name,
272
+ reason: `static events span 0–${maxPos.toFixed(2)}s of ${dur.toFixed(2)}s beat (${Math.round(coverage * 100)}%)`,
273
+ });
274
+ }
275
+ }
276
+
277
+ const pass = offenders.length === 0;
278
+ const checked = compositions.length - skipped.length;
279
+ return {
280
+ name: "Timeline coverage",
281
+ status: pass ? "PASS" : "FAIL",
282
+ detail: pass
283
+ ? `${checked}/${compositions.length} statically-measurable beats span ≥${Math.round(TIMELINE_COVERAGE_MIN * 100)}% of duration`
284
+ : `${offenders.length} beat(s) below ${Math.round(TIMELINE_COVERAGE_MIN * 100)}% static coverage — likely "webpage not shot" failures`,
285
+ extra:
286
+ [
287
+ ...offenders.map((o) => `${o.beat}: ${o.reason}`),
288
+ ...(skipped.length > 0 ? skipped.map((s) => `(skipped ${s.beat}: ${s.reason})`) : []),
289
+ ].join("\n ") || null,
290
+ };
291
+ }
292
+
293
+ async function checkShaderTransitionsConsistency() {
294
+ const storyboardPath = join(PROJECT_DIR, "STORYBOARD.md");
295
+ const indexPath = join(PROJECT_DIR, "index.html");
296
+ if (!existsSync(storyboardPath) || !existsSync(indexPath)) {
297
+ return {
298
+ name: "Shader transitions",
299
+ status: "INFO",
300
+ detail: "STORYBOARD.md or index.html missing — cannot check",
301
+ };
302
+ }
303
+
304
+ const storyboard = await readFile(storyboardPath, "utf-8");
305
+ const index = await readFile(indexPath, "utf-8");
306
+
307
+ // For each shader name, count it as "declared" only if it appears in a
308
+ // transition-use context — NOT in an inventory list (3+ names on one line)
309
+ // and NOT exclusively as part of an SFX filename (sfx/glitch-1.mp3).
310
+ const sbLines = storyboard.split("\n");
311
+ // Longest-name matching to avoid substring double-counting.
312
+ const sortedNames = [...SHADER_NAMES].sort((a, b) => b.length - a.length);
313
+ const seen = new Set();
314
+ const declared = [];
315
+ for (const name of sortedNames) {
316
+ let foundInUseContext = false;
317
+ for (const line of sbLines) {
318
+ if (seen.has(name)) break;
319
+ if (!line.includes(name)) continue;
320
+ // Skip inventory listing lines (3+ shader names on one line).
321
+ const namesOnLine = SHADER_NAMES.filter((n) => line.includes(n)).length;
322
+ if (namesOnLine >= 3) continue;
323
+ // Skip lines where the shader name only appears in SFX filename context.
324
+ const sfxContext = line.includes(`sfx/${name}`) || line.includes(`sfx-${name}`);
325
+ // Count this name if it appears in a non-SFX, non-inventory line.
326
+ if (!sfxContext) {
327
+ foundInUseContext = true;
328
+ break;
329
+ }
330
+ }
331
+ if (foundInUseContext) {
332
+ declared.push(name);
333
+ seen.add(name);
334
+ }
335
+ }
336
+ if (declared.length === 0) {
337
+ return {
338
+ name: "Shader transitions",
339
+ status: "PASS",
340
+ detail: "STORYBOARD declared none — no shader transitions expected",
341
+ };
342
+ }
343
+
344
+ // A shader is "present" only if HyperShader runtime is in index.html AND the
345
+ // shader name appears in a line that is NOT an SFX reference.
346
+ const hasHyperShader = /HyperShader\s*[(.]/.test(index);
347
+ const indexLines = index.split("\n");
348
+ const present = !hasHyperShader
349
+ ? []
350
+ : declared.filter((name) =>
351
+ indexLines.some((line) => {
352
+ if (!line.includes(name)) return false;
353
+ if (line.includes(`sfx/${name}`) || line.includes(`sfx-${name}`)) return false;
354
+ return true;
355
+ }),
356
+ );
357
+ const missing = declared.filter((name) => !present.includes(name));
358
+ const pass = missing.length === 0;
359
+
360
+ return {
361
+ name: "Shader transitions",
362
+ status: pass ? "PASS" : "FAIL",
363
+ detail: `STORYBOARD declared ${declared.length}, ${present.length} present in index.html, ${missing.length} missing`,
364
+ extra: pass
365
+ ? null
366
+ : `Missing from build: ${missing.join(", ")}. STORYBOARD.md and index.html disagree — either re-add the transitions or update STORYBOARD.md.`,
367
+ };
368
+ }
369
+
370
+ async function checkSfxTimestampConsistency() {
371
+ const storyboardPath = join(PROJECT_DIR, "STORYBOARD.md");
372
+ const indexPath = join(PROJECT_DIR, "index.html");
373
+ if (!existsSync(storyboardPath) || !existsSync(indexPath)) {
374
+ return {
375
+ name: "SFX timestamps",
376
+ status: "INFO",
377
+ detail: "STORYBOARD.md or index.html missing",
378
+ };
379
+ }
380
+
381
+ const storyboard = await readFile(storyboardPath, "utf-8");
382
+ const index = await readFile(indexPath, "utf-8");
383
+
384
+ const sfxRefs = [];
385
+ for (const line of storyboard.split("\n")) {
386
+ const fileMatch = line.match(/sfx\/([\w-]+\.mp3)/);
387
+ // Require trailing `s` so we capture the time column, not the volume column.
388
+ const timeMatch = line.match(/\|\s*(\d+(?:\.\d+)?)s\b/);
389
+ if (fileMatch && timeMatch) {
390
+ sfxRefs.push({ file: fileMatch[1], storyboardT: parseFloat(timeMatch[1]) });
391
+ }
392
+ }
393
+
394
+ if (sfxRefs.length === 0) {
395
+ return {
396
+ name: "SFX timestamps",
397
+ status: "INFO",
398
+ detail: "No SFX entries detected in STORYBOARD.md",
399
+ };
400
+ }
401
+
402
+ // Collect ALL audio tags per file (multi-timestamp SFX like click.mp3 have
403
+ // 3 tags). Use a two-step extraction so we don't depend on src= and
404
+ // data-start= attribute ordering — the documented canonical pattern in
405
+ // capabilities.md puts src= LAST in the tag, which an order-dependent
406
+ // regex would miss → false MISSING reports.
407
+ const indexSfx = new Map();
408
+ const audioTagRegex = /<audio[^>]*?>/g;
409
+ let tagMatch;
410
+ while ((tagMatch = audioTagRegex.exec(index)) !== null) {
411
+ const tag = tagMatch[0];
412
+ const srcMatch = tag.match(/src=["'](?:[^"']*\/)?sfx\/([\w-]+\.mp3)["']/);
413
+ const dsMatch = tag.match(/data-start=["']([0-9.]+)["']/);
414
+ if (!srcMatch || !dsMatch) continue;
415
+ const file = srcMatch[1];
416
+ const t = parseFloat(dsMatch[1]);
417
+ if (!indexSfx.has(file)) indexSfx.set(file, []);
418
+ indexSfx.get(file).push(t);
419
+ }
420
+
421
+ const drifts = [];
422
+ const missing = [];
423
+ for (const ref of sfxRefs) {
424
+ if (!indexSfx.has(ref.file)) {
425
+ missing.push(ref.file);
426
+ continue;
427
+ }
428
+ const indexTs = indexSfx.get(ref.file);
429
+ const closest = indexTs.reduce((best, t) =>
430
+ Math.abs(t - ref.storyboardT) < Math.abs(best - ref.storyboardT) ? t : best,
431
+ );
432
+ const drift = Math.abs(closest - ref.storyboardT);
433
+ if (drift > SFX_DRIFT_TOLERANCE_S) {
434
+ drifts.push({ file: ref.file, storyboardT: ref.storyboardT, indexT: closest, drift });
435
+ }
436
+ }
437
+
438
+ const indexCount = [...indexSfx.values()].reduce((sum, arr) => sum + arr.length, 0);
439
+ const pass = missing.length === 0 && drifts.length === 0;
440
+ return {
441
+ name: "SFX timestamps",
442
+ status: pass ? "PASS" : "FAIL",
443
+ detail: `${sfxRefs.length} SFX in STORYBOARD · ${indexCount} in index.html · ${missing.length} missing · ${drifts.length} drifted >${SFX_DRIFT_TOLERANCE_S}s`,
444
+ extra: pass
445
+ ? null
446
+ : [
447
+ ...missing.map((f) => `MISSING in index.html: ${f}`),
448
+ ...drifts.map(
449
+ (d) =>
450
+ `DRIFT: ${d.file} storyboard=${d.storyboardT}s closest index=${d.indexT}s drift=${d.drift.toFixed(2)}s`,
451
+ ),
452
+ ].join("\n "),
453
+ };
454
+ }
455
+
456
+ // Catches storyboard staleness on beat timings — agent shipped with different
457
+ // beat durations than the storyboard documented, leaving the spec lying.
458
+ async function checkBeatDurationConsistency() {
459
+ const storyboardPath = join(PROJECT_DIR, "STORYBOARD.md");
460
+ if (!existsSync(storyboardPath)) {
461
+ return { name: "Beat durations", status: "INFO", detail: "STORYBOARD.md missing" };
462
+ }
463
+
464
+ const storyboard = await readFile(storyboardPath, "utf-8");
465
+ const indexDurations = await readBeatDurationsFromIndex();
466
+ // Filter to only numbered beats (beat-1, beat-2, ...). Skip "main" / root
467
+ // composition and any non-numbered placeholders.
468
+ const buildBeatIds = Object.keys(indexDurations).filter((id) => /^beat-\d+/i.test(id));
469
+ if (buildBeatIds.length === 0) {
470
+ return {
471
+ name: "Beat durations",
472
+ status: "INFO",
473
+ detail: "no numbered beat data-duration in index.html",
474
+ };
475
+ }
476
+
477
+ // Parse storyboard beat durations. The expected pattern is a timing-table row:
478
+ // | B4 — MetaBrain | 16.600 – 21.000s | ... |
479
+ // We extract start–end and compute duration = end - start. Falls back to a
480
+ // direct duration mention ("duration: X.Xs") if the range format isn't found.
481
+ // A beat with no parseable duration is skipped — we don't flag missing rows.
482
+ const drifts = [];
483
+ const unparseable = [];
484
+ for (const beatId of buildBeatIds) {
485
+ const num = beatId.match(/beat-(\d+)/i)?.[1];
486
+ if (!num) continue;
487
+ let storyT = null;
488
+
489
+ // Strategy 1: standalone beat row "B4 — Name | 16.600 – 21.000s |".
490
+ // Require `B${num}` to be followed by a non-digit-non-dot char so "B3.1"
491
+ // doesn't false-match for B3.
492
+ const rangeRe = new RegExp(
493
+ `\\bB${num}(?![\\.\\d])[^\\n|]*\\|\\s*(\\d+(?:\\.\\d+)?)s?\\s*[–-]\\s*(\\d+(?:\\.\\d+)?)s`,
494
+ "i",
495
+ );
496
+ const rm = storyboard.match(rangeRe);
497
+ if (rm) {
498
+ storyT = parseFloat(rm[2]) - parseFloat(rm[1]);
499
+ } else {
500
+ // Strategy 2: sum sub-beats "B${num}.X — ... | start – end s |".
501
+ // Useful when a beat is broken into sub-rows (B3.1, B3.2, ...) instead
502
+ // of having a standalone row.
503
+ const subRe = new RegExp(
504
+ `\\bB${num}\\.\\d+\\b[^\\n|]*\\|\\s*(\\d+(?:\\.\\d+)?)s?\\s*[–-]\\s*(\\d+(?:\\.\\d+)?)s`,
505
+ "gi",
506
+ );
507
+ let sum = 0;
508
+ let count = 0;
509
+ let mm;
510
+ while ((mm = subRe.exec(storyboard)) !== null) {
511
+ sum += parseFloat(mm[2]) - parseFloat(mm[1]);
512
+ count++;
513
+ }
514
+ if (count > 0) storyT = sum;
515
+ }
516
+
517
+ if (storyT === null) {
518
+ // Strategy 3: bare-number timing table — "| 1 | 0.00s | 5.20s | 5.20s |"
519
+ // (Beat | Start | End | Duration). The duration column is the 4th cell,
520
+ // OR derive from end - start (columns 2 and 3). Match a row that starts
521
+ // with `| <num> |` and has at least 2 time cells.
522
+ // Allow optional leading `>` (blockquote) before the pipe.
523
+ const tableRe = new RegExp(
524
+ `^\\s*>?\\s*\\|\\s*${num}\\s*\\|\\s*(\\d+(?:\\.\\d+)?)s?\\s*\\|\\s*(\\d+(?:\\.\\d+)?)s`,
525
+ "im",
526
+ );
527
+ const tm = storyboard.match(tableRe);
528
+ if (tm) {
529
+ const start = parseFloat(tm[1]);
530
+ const end = parseFloat(tm[2]);
531
+ storyT = end - start;
532
+ }
533
+ }
534
+ // Note: removed the previous "duration: X.Xs near beat label" fallback —
535
+ // it false-matched non-beat durations (e.g., "shader runs — duration 0.7s"
536
+ // near a "Beat 1" mention). If a storyboard's timing format isn't a clean
537
+ // range or table row, the beat is reported as unparseable rather than
538
+ // guessed at.
539
+
540
+ if (storyT === null) {
541
+ unparseable.push(beatId);
542
+ continue;
543
+ }
544
+ const buildT = indexDurations[beatId];
545
+ const drift = Math.abs(storyT - buildT);
546
+ if (drift > BEAT_DURATION_DRIFT_TOLERANCE_S) {
547
+ drifts.push({ beat: beatId, storyboardDuration: storyT, buildDuration: buildT, drift });
548
+ }
549
+ }
550
+
551
+ const parseable = buildBeatIds.length - unparseable.length;
552
+ if (drifts.length === 0) {
553
+ return {
554
+ name: "Beat durations",
555
+ status: "PASS",
556
+ detail: `${parseable}/${buildBeatIds.length} beats parseable, storyboard durations match within ±${BEAT_DURATION_DRIFT_TOLERANCE_S}s`,
557
+ extra:
558
+ unparseable.length > 0
559
+ ? `(skipped: ${unparseable.join(", ")} — could not find duration in STORYBOARD.md)`
560
+ : null,
561
+ };
562
+ }
563
+ return {
564
+ name: "Beat durations",
565
+ status: "FAIL",
566
+ detail: `${drifts.length} beat(s) drift between STORYBOARD.md and index.html > ${BEAT_DURATION_DRIFT_TOLERANCE_S}s`,
567
+ extra: [
568
+ ...drifts.map(
569
+ (d) =>
570
+ `${d.beat}: storyboard=${d.storyboardDuration.toFixed(2)}s build=${d.buildDuration}s drift=${d.drift.toFixed(2)}s`,
571
+ ),
572
+ ...(unparseable.length > 0
573
+ ? [`(skipped: ${unparseable.join(", ")} — could not find duration in STORYBOARD.md)`]
574
+ : []),
575
+ ].join("\n "),
576
+ };
577
+ }
578
+
579
+ async function checkMp4Exists() {
580
+ const candidates = [PROJECT_DIR, join(PROJECT_DIR, "output"), join(PROJECT_DIR, "renders")];
581
+ for (const dir of candidates) {
582
+ if (!existsSync(dir)) continue;
583
+ try {
584
+ const files = await readdir(dir);
585
+ if (files.some((f) => f.endsWith(".mp4"))) {
586
+ return {
587
+ name: "Rendered MP4",
588
+ status: "PASS",
589
+ detail: `found .mp4 in ${dir.replace(PROJECT_DIR, ".")}`,
590
+ };
591
+ }
592
+ } catch {
593
+ /* ignore */
594
+ }
595
+ }
596
+ return {
597
+ name: "Rendered MP4",
598
+ status: "INFO",
599
+ detail:
600
+ "no .mp4 found — preview-only delivery; if claiming verified motion, render is required (Path 2 of audio+motion verification)",
601
+ };
602
+ }
603
+
604
+ // ─── Helpers ─────────────────────────────────────────────────────────────────
605
+
606
+ // Cached so multiple checks don't re-read the same files. The script is a
607
+ // one-shot CLI so a process-scoped cache is fine; no invalidation needed.
608
+ let _compositionsCache = null;
609
+ async function readBeatCompositions() {
610
+ if (_compositionsCache) return _compositionsCache;
611
+ const dir = join(PROJECT_DIR, "compositions");
612
+ if (!existsSync(dir)) {
613
+ _compositionsCache = [];
614
+ return _compositionsCache;
615
+ }
616
+ const files = await readdir(dir);
617
+ const beats = files.filter((f) => /^beat-/i.test(f) && f.endsWith(".html"));
618
+ const out = [];
619
+ for (const f of beats) {
620
+ const content = await readFile(join(dir, f), "utf-8");
621
+ out.push({ name: f, content });
622
+ }
623
+ _compositionsCache = out;
624
+ return out;
625
+ }
626
+
627
+ // Extract the trailing numeric position argument from each `tl.<method>(...)`
628
+ // call in a script. Uses balanced-paren scanning so multi-line calls and
629
+ // nested patterns like rgba(86,131,218,0.35) don't false-match.
630
+ function extractTopLevelPositionArgs(content) {
631
+ const positions = [];
632
+ const methodRe = /\btl\.(?:to|set|fromTo|from|call|add)\(/g;
633
+ let startMatch;
634
+ while ((startMatch = methodRe.exec(content)) !== null) {
635
+ let i = startMatch.index + startMatch[0].length;
636
+ let depth = 1;
637
+ let lastTopLevelCommaIdx = -1;
638
+ let inString = false;
639
+ let stringChar = null;
640
+ while (i < content.length && depth > 0) {
641
+ const c = content[i];
642
+ if (inString) {
643
+ if (c === "\\") {
644
+ i += 2;
645
+ continue;
646
+ }
647
+ if (c === stringChar) inString = false;
648
+ i++;
649
+ continue;
650
+ }
651
+ if (c === '"' || c === "'" || c === "`") {
652
+ inString = true;
653
+ stringChar = c;
654
+ i++;
655
+ continue;
656
+ }
657
+ if (c === "(" || c === "{" || c === "[") depth++;
658
+ else if (c === ")" || c === "}" || c === "]") {
659
+ depth--;
660
+ if (depth === 0) break;
661
+ } else if (c === "," && depth === 1) lastTopLevelCommaIdx = i;
662
+ i++;
663
+ }
664
+ if (depth === 0 && lastTopLevelCommaIdx > 0) {
665
+ const lastArg = content.substring(lastTopLevelCommaIdx + 1, i).trim();
666
+ const numMatch = lastArg.match(/^([0-9.]+)$/);
667
+ if (numMatch) positions.push(parseFloat(numMatch[1]));
668
+ }
669
+ }
670
+ return positions;
671
+ }
672
+
673
+ // Returns a map of { "beat-1-name": durationInSeconds, ... } from index.html.
674
+ // Cached per-process (one-shot CLI, no invalidation needed).
675
+ let _beatDurationsCache = null;
676
+ async function readBeatDurationsFromIndex() {
677
+ if (_beatDurationsCache) return _beatDurationsCache;
678
+ const indexPath = join(PROJECT_DIR, "index.html");
679
+ if (!existsSync(indexPath)) {
680
+ _beatDurationsCache = {};
681
+ return _beatDurationsCache;
682
+ }
683
+ const content = await readFile(indexPath, "utf-8");
684
+ const map = {};
685
+
686
+ // Pattern: <div data-composition-id="beat-N-name" ... data-duration="5.5" ...>
687
+ // OR: data-composition-src="compositions/beat-N-name.html" ... data-duration="5.5"
688
+ const divRegex = /<div[^>]*?>/g;
689
+ let m;
690
+ while ((m = divRegex.exec(content)) !== null) {
691
+ const tag = m[0];
692
+ const idMatch = tag.match(/data-composition-id=["']([^"']+)["']/);
693
+ const srcMatch = tag.match(/data-composition-src=["'][^"']*?\/?(beat-[\w-]+)\.html["']/);
694
+ const durMatch = tag.match(/data-duration=["']([0-9.]+)["']/);
695
+ if (!durMatch) continue;
696
+ const dur = parseFloat(durMatch[1]);
697
+ if (idMatch) map[idMatch[1]] = dur;
698
+ if (srcMatch) map[srcMatch[1]] = dur;
699
+ }
700
+ _beatDurationsCache = map;
701
+ return map;
702
+ }
703
+
704
+ // ─── Report ──────────────────────────────────────────────────────────────────
705
+
706
+ function printReport(results) {
707
+ const cols = { name: 26, status: 8, detail: 60 };
708
+ const line = "─".repeat(cols.name + cols.status + cols.detail + 6);
709
+
710
+ console.log("");
711
+ console.log(`w2h-verify · ${PROJECT_DIR}`);
712
+ console.log(line);
713
+ console.log("Check".padEnd(cols.name) + " │ " + "Status".padEnd(cols.status) + " │ " + "Detail");
714
+ console.log(line);
715
+
716
+ for (const r of results) {
717
+ const symbol = r.status === "PASS" ? "✓" : r.status === "FAIL" ? "✗" : "·";
718
+ console.log(
719
+ r.name.padEnd(cols.name) +
720
+ " │ " +
721
+ `${symbol} ${r.status}`.padEnd(cols.status) +
722
+ " │ " +
723
+ (r.detail || ""),
724
+ );
725
+ if (r.extra) {
726
+ const indent = " ".repeat(cols.name + cols.status + 6 + 4);
727
+ console.log(
728
+ "".padEnd(cols.name) +
729
+ " │ " +
730
+ "".padEnd(cols.status) +
731
+ " │ " +
732
+ r.extra.split("\n").join("\n" + indent),
733
+ );
734
+ }
735
+ }
736
+
737
+ console.log(line);
738
+ const pass = results.filter((r) => r.status === "PASS").length;
739
+ const fail = results.filter((r) => r.status === "FAIL").length;
740
+ const info = results.filter((r) => r.status === "INFO").length;
741
+ console.log(`SUMMARY: ${pass} PASS · ${fail} FAIL · ${info} INFO`);
742
+
743
+ if (fail > 0) {
744
+ console.log("");
745
+ console.log("Step 6 NOT done. Fix FAIL items, OR include this report verbatim in your final");
746
+ console.log("summary's \"What I did NOT verify\" section so the user knows what's broken.");
747
+ } else {
748
+ console.log("");
749
+ console.log(
750
+ "All gates pass. Paste this report into your final user-facing summary as evidence.",
751
+ );
752
+ }
753
+ console.log("");
754
+ }
755
+
756
+ main().catch((e) => {
757
+ console.error("w2h-verify script error:", e);
758
+ process.exit(2);
759
+ });