dsh-hyperframes 0.3.2 → 0.4.1

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 (375) hide show
  1. package/README.en.md +5 -4
  2. package/README.md +6 -5
  3. package/lib/index.d.ts +1 -1
  4. package/lib/index.js +1 -0
  5. package/package.json +2 -2
  6. package/skills/embedded-captions/SKILL.md +28 -3
  7. package/skills/embedded-captions/references/aesthetic-principles.md +2 -3
  8. package/skills/embedded-captions/references/rail.md +1 -1
  9. package/skills/embedded-captions/scripts/check-occlusion.cjs +4 -1
  10. package/skills/embedded-captions/scripts/check-overflow.cjs +1 -0
  11. package/skills/embedded-captions/scripts/check-rail-climax.cjs +5 -1
  12. package/skills/embedded-captions/scripts/fixtures/heroless/theme.json +11 -0
  13. package/skills/embedded-captions/scripts/hf-cli.cjs +33 -0
  14. package/skills/embedded-captions/scripts/make-theme.cjs +95 -57
  15. package/skills/embedded-captions/scripts/make-theme.test.mjs +131 -0
  16. package/skills/embedded-captions/scripts/matte.cjs +1 -13
  17. package/skills/embedded-captions/scripts/measure-layout.cjs +2 -1
  18. package/skills/embedded-captions/scripts/preview-frames.cjs +39 -11
  19. package/skills/embedded-captions/scripts/preview-frames.test.mjs +24 -0
  20. package/skills/embedded-captions/scripts/render-and-composite.sh +8 -52
  21. package/skills/embedded-captions/scripts/safe-zones.cjs +4 -1
  22. package/skills/embedded-captions/scripts/transcribe.cjs +5 -14
  23. package/skills/embedded-captions/scripts/transcribe.test.mjs +41 -0
  24. package/skills/faceless-explainer/SKILL.md +20 -16
  25. package/skills/faceless-explainer/references/story-design.md +1 -1
  26. package/skills/faceless-explainer/scripts/assemble-index.mjs +6 -4
  27. package/skills/faceless-explainer/scripts/assemble-index.test.mjs +57 -2
  28. package/skills/faceless-explainer/scripts/audio.mjs +2 -0
  29. package/skills/faceless-explainer/scripts/build-frame.mjs +6 -3
  30. package/skills/faceless-explainer/scripts/captions.mjs +7 -4
  31. package/skills/faceless-explainer/scripts/frame-packets.mjs +4 -4
  32. package/skills/faceless-explainer/scripts/lib/bgm-volume.mjs +4 -0
  33. package/skills/faceless-explainer/scripts/lib/captured-fonts.mjs +58 -0
  34. package/skills/{hyperframes-core → faceless-explainer}/scripts/lib/frame-packets-core.mjs +5 -23
  35. package/skills/faceless-explainer/scripts/lib/storyboard.mjs +1 -1
  36. package/skills/faceless-explainer/scripts/lib/transitions.json +3 -3
  37. package/skills/faceless-explainer/scripts/transitions.mjs +1 -0
  38. package/skills/faceless-explainer/scripts/transitions.test.mjs +2 -0
  39. package/skills/faceless-explainer/sub-agents/frame-worker.md +1 -1
  40. package/skills/figma/SKILL.md +2 -0
  41. package/skills/general-video/SKILL.md +13 -11
  42. package/skills/general-video/scripts/frame-packets.mjs +4 -4
  43. package/skills/general-video/scripts/lib/frame-packets-core.mjs +194 -0
  44. package/skills/general-video/sub-agents/frame-worker.md +1 -1
  45. package/skills/hyperframes/SKILL.md +40 -30
  46. package/skills/{hyperframes-core → hyperframes}/references/brief-contract.md +15 -15
  47. package/skills/{hyperframes-core → hyperframes}/references/brief-format.md +8 -8
  48. package/skills/hyperframes/references/capability-menu.md +2 -2
  49. package/skills/{hyperframes-core → hyperframes}/references/frame-worker-core.md +1 -1
  50. package/skills/hyperframes/references/intent-interview.md +16 -16
  51. package/skills/hyperframes/references/plugin-installation.md +43 -0
  52. package/skills/{hyperframes-core → hyperframes}/references/production-loop.md +11 -11
  53. package/skills/hyperframes/references/review-loop.md +37 -0
  54. package/skills/hyperframes/references/route-briefs.md +1 -1
  55. package/skills/hyperframes/references/routes/motion-graphics.md +1 -1
  56. package/skills/{hyperframes-core → hyperframes}/references/script-format.md +3 -3
  57. package/skills/hyperframes/references/skill-lifecycle.md +2 -0
  58. package/skills/{hyperframes-core → hyperframes}/references/storyboard-format.md +3 -34
  59. package/skills/hyperframes/scripts/lib/frame-packets-core.mjs +194 -0
  60. package/skills/hyperframes/scripts/plugin-cli.mjs +88 -0
  61. package/skills/hyperframes/scripts/plugin-cli.test.mjs +117 -0
  62. package/skills/hyperframes-animation/SKILL.md +5 -1
  63. package/skills/hyperframes-animation/adapters/gsap.md +1 -1
  64. package/skills/hyperframes-animation/adapters/lottie.md +15 -2
  65. package/skills/hyperframes-animation/adapters/three.md +14 -0
  66. package/skills/hyperframes-animation/blueprints/titlecard-reveal.md +1 -1
  67. package/skills/hyperframes-animation/references/motion-blur.md +133 -0
  68. package/skills/hyperframes-animation/rules/cursor-click-ripple.md +1 -1
  69. package/skills/hyperframes-animation/rules/dynamic-content-sequencing.md +1 -1
  70. package/skills/hyperframes-animation/rules/hacker-flip-3d.md +1 -1
  71. package/skills/hyperframes-animation/rules/kinetic-beat-slam.md +2 -2
  72. package/skills/hyperframes-animation/rules/motion-blur-streak.md +1 -1
  73. package/skills/hyperframes-animation/rules/vertical-spring-ticker.md +1 -1
  74. package/skills/hyperframes-animation/scripts/package-loader.mjs +47 -16
  75. package/skills/hyperframes-animation/scripts/package-loader.test.mjs +52 -0
  76. package/skills/hyperframes-animation/techniques.md +1 -1
  77. package/skills/hyperframes-animation/transitions/TRANSITION-REGISTRY.md +3 -3
  78. package/skills/hyperframes-animation/transitions/css-push.md +4 -4
  79. package/skills/hyperframes-audio/SKILL.md +30 -22
  80. package/skills/hyperframes-audio/scripts/carve.mjs +6 -3
  81. package/skills/hyperframes-audio/scripts/carve.test.mjs +16 -1
  82. package/skills/hyperframes-cli/SKILL.md +44 -35
  83. package/skills/hyperframes-cli/references/init-and-scaffold.md +8 -6
  84. package/skills/hyperframes-cli/references/lint-validate-inspect.md +3 -3
  85. package/skills/hyperframes-cli/references/preview-render.md +35 -32
  86. package/skills/hyperframes-cli/references/upgrade-info-misc.md +50 -1
  87. package/skills/hyperframes-core/SKILL.md +30 -24
  88. package/skills/hyperframes-core/references/composition-patterns.md +3 -42
  89. package/skills/hyperframes-core/references/creator-editing-recipes.md +131 -7
  90. package/skills/hyperframes-core/references/data-attributes.md +11 -11
  91. package/skills/hyperframes-core/references/determinism-rules.md +2 -19
  92. package/skills/hyperframes-core/references/full-screen-motion.md +0 -9
  93. package/skills/hyperframes-core/references/minimal-composition.md +2 -2
  94. package/skills/hyperframes-core/references/sub-compositions.md +3 -66
  95. package/skills/hyperframes-core/references/tailwind.md +1 -20
  96. package/skills/hyperframes-core/references/tracks-and-clips.md +2 -6
  97. package/skills/hyperframes-core/references/variables-and-media.md +3 -3
  98. package/skills/hyperframes-creative/SKILL.md +2 -0
  99. package/skills/hyperframes-creative/references/house-style.md +15 -15
  100. package/skills/hyperframes-creative/references/story-spine.md +3 -1
  101. package/skills/hyperframes-creative/references/storyboard-recipe.md +57 -0
  102. package/skills/hyperframes-creative/references/typography.md +1 -1
  103. package/skills/hyperframes-creative/scripts/package-loader.mjs +47 -16
  104. package/skills/hyperframes-creative/scripts/package-loader.test.mjs +52 -0
  105. package/skills/hyperframes-keyframes/SKILL.md +4 -2
  106. package/skills/hyperframes-registry/SKILL.md +3 -1
  107. package/skills/hyperframes-registry/references/contributing.md +8 -2
  108. package/skills/hyperframes-registry/references/discovery.md +20 -34
  109. package/skills/hyperframes-studio/SKILL.md +77 -0
  110. package/skills/media-use/SKILL.md +14 -12
  111. package/skills/media-use/audio/references/captions/authoring.md +4 -0
  112. package/skills/media-use/audio/references/remove-background.md +1 -1
  113. package/skills/media-use/audio/references/tts-to-captions.md +11 -2
  114. package/skills/media-use/audio/references/tts.md +84 -6
  115. package/skills/media-use/audio/scripts/audio.mjs +15 -6
  116. package/skills/media-use/audio/scripts/gemini-pipeline.test.mjs +113 -0
  117. package/skills/media-use/audio/scripts/lib/audio-meta.mjs +39 -0
  118. package/skills/media-use/audio/scripts/lib/audio-meta.test.mjs +136 -0
  119. package/skills/media-use/audio/scripts/lib/bgm-volume.mjs +4 -0
  120. package/skills/media-use/audio/scripts/lib/bgm.mjs +2 -6
  121. package/skills/media-use/audio/scripts/lib/gemini-auth.mjs +43 -0
  122. package/skills/media-use/audio/scripts/lib/gemini-auth.py +52 -0
  123. package/skills/media-use/audio/scripts/lib/gemini-auth.test.mjs +86 -0
  124. package/skills/media-use/audio/scripts/lib/gemini-auth_test.py +90 -0
  125. package/skills/media-use/audio/scripts/lib/gemini-tts.mjs +122 -0
  126. package/skills/media-use/audio/scripts/lib/gemini-tts.test.mjs +243 -0
  127. package/skills/media-use/audio/scripts/lib/heygen.mjs +2 -1
  128. package/skills/media-use/audio/scripts/lib/tts.mjs +15 -3
  129. package/skills/media-use/audio/scripts/wait-bgm.mjs +8 -4
  130. package/skills/media-use/audio/scripts/wait-bgm.test.mjs +65 -0
  131. package/skills/media-use/references/audio.md +3 -2
  132. package/skills/media-use/references/grading.md +7 -7
  133. package/skills/media-use/references/media-treatment-recipes.md +1 -1
  134. package/skills/media-use/references/memory.md +2 -2
  135. package/skills/media-use/references/meta.md +2 -2
  136. package/skills/media-use/references/operations.md +15 -13
  137. package/skills/media-use/references/resolve.md +22 -11
  138. package/skills/media-use/references/setup-providers.md +11 -11
  139. package/skills/media-use/scripts/audio-duck.mjs +19 -27
  140. package/skills/media-use/scripts/compatibility.test.mjs +96 -0
  141. package/skills/media-use/scripts/lib/config-lock.mjs +45 -0
  142. package/skills/media-use/scripts/lib/duck.mjs +16 -10
  143. package/skills/media-use/scripts/lib/media-fetch.mjs +85 -0
  144. package/skills/media-use/scripts/lib/media-home.mjs +20 -0
  145. package/skills/media-use/scripts/lib/npx-sync.mjs +28 -2
  146. package/skills/media-use/scripts/lib/prefs-store.mjs +2 -2
  147. package/skills/media-use/scripts/lib/recipe-store.mjs +2 -2
  148. package/skills/media-use/scripts/lib/telemetry.mjs +29 -41
  149. package/skills/media-use/scripts/lib/transcriptCutFade.mjs +21 -0
  150. package/skills/media-use/scripts/prefs.mjs +1 -1
  151. package/skills/media-use/scripts/recipe.mjs +1 -1
  152. package/skills/media-use/scripts/resolve-plugin.test.mjs +62 -0
  153. package/skills/media-use/scripts/resolve.mjs +27 -1267
  154. package/skills/media-use/scripts/transcribe.mjs +39 -25
  155. package/skills/media-use/scripts/transcribe.test.mjs +112 -0
  156. package/skills/media-use/scripts/transcript-cut.mjs +39 -8
  157. package/skills/media-use/scripts/transcript-cut.test.mjs +117 -0
  158. package/skills/motion-graphics/SKILL.md +3 -1
  159. package/skills/motion-graphics/agents/builder.md +1 -0
  160. package/skills/motion-graphics/agents/director.md +2 -1
  161. package/skills/motion-graphics/catalog-map.md +25 -13
  162. package/skills/motion-graphics/categories/charts/module.md +2 -1
  163. package/skills/motion-graphics/categories/lower-thirds/module.md +4 -0
  164. package/skills/motion-graphics/categories/news/module.md +1 -1
  165. package/skills/motion-graphics/references/motion-vocabulary.md +4 -0
  166. package/skills/music-to-video/SKILL.md +8 -6
  167. package/skills/music-to-video/references/montage.md +3 -6
  168. package/skills/music-to-video/references/motion-primitives/3d-card-flip/index.html +10 -111
  169. package/skills/music-to-video/references/motion-primitives/3d-card-flip/scene.html +119 -0
  170. package/skills/music-to-video/references/motion-primitives/bg-flow-field/index.html +11 -284
  171. package/skills/music-to-video/references/motion-primitives/bg-flow-field/scene.html +294 -0
  172. package/skills/music-to-video/references/motion-primitives/binary-decrypt/index.html +10 -76
  173. package/skills/music-to-video/references/motion-primitives/binary-decrypt/scene.html +85 -0
  174. package/skills/music-to-video/references/motion-primitives/blur-resolve/index.html +10 -52
  175. package/skills/music-to-video/references/motion-primitives/blur-resolve/scene.html +60 -0
  176. package/skills/music-to-video/references/motion-primitives/braam-punch/index.html +10 -92
  177. package/skills/music-to-video/references/motion-primitives/braam-punch/scene.html +100 -0
  178. package/skills/music-to-video/references/motion-primitives/chromatic-split/index.html +10 -103
  179. package/skills/music-to-video/references/motion-primitives/chromatic-split/scene.html +111 -0
  180. package/skills/music-to-video/references/motion-primitives/chrome-sweep/index.html +10 -60
  181. package/skills/music-to-video/references/motion-primitives/chrome-sweep/scene.html +68 -0
  182. package/skills/music-to-video/references/motion-primitives/counting-punch/index.html +10 -110
  183. package/skills/music-to-video/references/motion-primitives/counting-punch/scene.html +119 -0
  184. package/skills/music-to-video/references/motion-primitives/crash-zoom-in/index.html +10 -112
  185. package/skills/music-to-video/references/motion-primitives/crash-zoom-in/scene.html +120 -0
  186. package/skills/music-to-video/references/motion-primitives/datamosh-smear/index.html +10 -121
  187. package/skills/music-to-video/references/motion-primitives/datamosh-smear/scene.html +131 -0
  188. package/skills/music-to-video/references/motion-primitives/directional-fill/index.html +10 -90
  189. package/skills/music-to-video/references/motion-primitives/directional-fill/scene.html +103 -0
  190. package/skills/music-to-video/references/motion-primitives/dolly-zoom/index.html +10 -94
  191. package/skills/music-to-video/references/motion-primitives/dolly-zoom/scene.html +102 -0
  192. package/skills/music-to-video/references/motion-primitives/electric-arc/index.html +10 -100
  193. package/skills/music-to-video/references/motion-primitives/electric-arc/scene.html +105 -0
  194. package/skills/music-to-video/references/motion-primitives/flash-cut/index.html +10 -89
  195. package/skills/music-to-video/references/motion-primitives/flash-cut/scene.html +97 -0
  196. package/skills/music-to-video/references/motion-primitives/gooey-metaball/index.html +10 -197
  197. package/skills/music-to-video/references/motion-primitives/gooey-metaball/scene.html +206 -0
  198. package/skills/music-to-video/references/motion-primitives/hard-cut/index.html +10 -74
  199. package/skills/music-to-video/references/motion-primitives/hard-cut/scene.html +82 -0
  200. package/skills/music-to-video/references/motion-primitives/hypercut-whip/index.html +10 -36
  201. package/skills/music-to-video/references/motion-primitives/hypercut-whip/scene.html +44 -0
  202. package/skills/music-to-video/references/motion-primitives/iris-open/index.html +10 -61
  203. package/skills/music-to-video/references/motion-primitives/iris-open/scene.html +69 -0
  204. package/skills/music-to-video/references/motion-primitives/kinetic-letter-in/index.html +10 -55
  205. package/skills/music-to-video/references/motion-primitives/kinetic-letter-in/scene.html +64 -0
  206. package/skills/music-to-video/references/motion-primitives/liquid-morph/index.html +10 -88
  207. package/skills/music-to-video/references/motion-primitives/liquid-morph/scene.html +96 -0
  208. package/skills/music-to-video/references/motion-primitives/mask-reveal/index.html +10 -66
  209. package/skills/music-to-video/references/motion-primitives/mask-reveal/scene.html +74 -0
  210. package/skills/music-to-video/references/motion-primitives/mosaic-pack/index.html +10 -81
  211. package/skills/music-to-video/references/motion-primitives/mosaic-pack/scene.html +89 -0
  212. package/skills/music-to-video/references/motion-primitives/neon-flicker/index.html +10 -65
  213. package/skills/music-to-video/references/motion-primitives/neon-flicker/scene.html +73 -0
  214. package/skills/music-to-video/references/motion-primitives/outline-to-fill/index.html +10 -74
  215. package/skills/music-to-video/references/motion-primitives/outline-to-fill/scene.html +82 -0
  216. package/skills/music-to-video/references/motion-primitives/palette-flip/index.html +10 -89
  217. package/skills/music-to-video/references/motion-primitives/palette-flip/scene.html +97 -0
  218. package/skills/music-to-video/references/motion-primitives/particle-burst/index.html +10 -98
  219. package/skills/music-to-video/references/motion-primitives/particle-burst/scene.html +106 -0
  220. package/skills/music-to-video/references/motion-primitives/pixel-dissolve/index.html +10 -78
  221. package/skills/music-to-video/references/motion-primitives/pixel-dissolve/scene.html +86 -0
  222. package/skills/music-to-video/references/motion-primitives/radial-burst-lines/index.html +10 -117
  223. package/skills/music-to-video/references/motion-primitives/radial-burst-lines/scene.html +130 -0
  224. package/skills/music-to-video/references/motion-primitives/screen-shake/index.html +10 -70
  225. package/skills/music-to-video/references/motion-primitives/screen-shake/scene.html +78 -0
  226. package/skills/music-to-video/references/motion-primitives/slot-machine-reveal/index.html +10 -87
  227. package/skills/music-to-video/references/motion-primitives/slot-machine-reveal/scene.html +100 -0
  228. package/skills/music-to-video/references/motion-primitives/spotlight-sweep/index.html +10 -94
  229. package/skills/music-to-video/references/motion-primitives/spotlight-sweep/scene.html +102 -0
  230. package/skills/music-to-video/references/motion-primitives/staggered-exit/index.html +10 -74
  231. package/skills/music-to-video/references/motion-primitives/staggered-exit/scene.html +82 -0
  232. package/skills/music-to-video/references/motion-primitives/text-spectral-rays/index.html +11 -271
  233. package/skills/music-to-video/references/motion-primitives/text-spectral-rays/scene.html +280 -0
  234. package/skills/music-to-video/references/motion-primitives/text-wave-distort/index.html +10 -92
  235. package/skills/music-to-video/references/motion-primitives/text-wave-distort/scene.html +106 -0
  236. package/skills/music-to-video/references/motion-primitives/tile-mosaic/index.html +10 -101
  237. package/skills/music-to-video/references/motion-primitives/tile-mosaic/scene.html +109 -0
  238. package/skills/music-to-video/references/motion-primitives/typewriter-reveal/index.html +10 -79
  239. package/skills/music-to-video/references/motion-primitives/typewriter-reveal/scene.html +91 -0
  240. package/skills/music-to-video/references/motion-primitives/word-grid-burst/index.html +10 -83
  241. package/skills/music-to-video/references/motion-primitives/word-grid-burst/scene.html +96 -0
  242. package/skills/music-to-video/references/planning.md +2 -2
  243. package/skills/music-to-video/scripts/lib/storyboard.mjs +1 -1
  244. package/skills/music-to-video/sub-agents/frame-worker.md +2 -2
  245. package/skills/pr-to-video/SKILL.md +20 -16
  246. package/skills/pr-to-video/references/code-vocabulary.md +14 -12
  247. package/skills/pr-to-video/references/story-design.md +1 -1
  248. package/skills/pr-to-video/scripts/assemble-index.mjs +6 -4
  249. package/skills/pr-to-video/scripts/assemble-index.test.mjs +57 -2
  250. package/skills/pr-to-video/scripts/audio.mjs +2 -0
  251. package/skills/pr-to-video/scripts/build-frame.mjs +6 -3
  252. package/skills/pr-to-video/scripts/captions.mjs +7 -4
  253. package/skills/pr-to-video/scripts/captions.test.mjs +41 -0
  254. package/skills/pr-to-video/scripts/frame-packets.mjs +4 -4
  255. package/skills/pr-to-video/scripts/lib/bgm-volume.mjs +4 -0
  256. package/skills/pr-to-video/scripts/lib/captured-fonts.mjs +58 -0
  257. package/skills/pr-to-video/scripts/lib/frame-packets-core.mjs +194 -0
  258. package/skills/pr-to-video/scripts/lib/storyboard.mjs +1 -1
  259. package/skills/pr-to-video/scripts/lib/transitions.json +3 -3
  260. package/skills/pr-to-video/scripts/transitions.mjs +7 -5
  261. package/skills/pr-to-video/sub-agents/frame-worker.md +1 -1
  262. package/skills/product-launch-video/SKILL.md +20 -16
  263. package/skills/product-launch-video/references/story-design.md +1 -1
  264. package/skills/product-launch-video/scripts/assemble-index.mjs +6 -4
  265. package/skills/product-launch-video/scripts/assemble-index.test.mjs +57 -2
  266. package/skills/product-launch-video/scripts/audio.mjs +2 -0
  267. package/skills/product-launch-video/scripts/audio.test.mjs +16 -0
  268. package/skills/product-launch-video/scripts/build-frame-subsets.test.mjs +152 -0
  269. package/skills/product-launch-video/scripts/build-frame.mjs +6 -3
  270. package/skills/product-launch-video/scripts/captions.mjs +7 -4
  271. package/skills/product-launch-video/scripts/frame-packets.mjs +4 -4
  272. package/skills/product-launch-video/scripts/lib/bgm-volume.mjs +4 -0
  273. package/skills/product-launch-video/scripts/lib/captured-fonts.mjs +58 -0
  274. package/skills/product-launch-video/scripts/lib/frame-packets-core.mjs +194 -0
  275. package/skills/product-launch-video/scripts/lib/storyboard.mjs +1 -1
  276. package/skills/product-launch-video/scripts/lib/transitions.json +3 -3
  277. package/skills/product-launch-video/scripts/transitions.mjs +7 -5
  278. package/skills/product-launch-video/scripts/transitions.test.mjs +68 -0
  279. package/skills/product-launch-video/sub-agents/frame-worker.md +1 -1
  280. package/skills/remotion-to-hyperframes/SKILL.md +7 -4
  281. package/skills/remotion-to-hyperframes/assets/test-corpus/tier-1-title-card/expected.json +5 -5
  282. package/skills/remotion-to-hyperframes/assets/test-corpus/tier-1-title-card/hf-src/compositions/title.html +31 -0
  283. package/skills/remotion-to-hyperframes/assets/test-corpus/tier-1-title-card/hf-src/index.html +10 -25
  284. package/skills/remotion-to-hyperframes/assets/test-corpus/tier-2-multi-scene/README.md +8 -8
  285. package/skills/remotion-to-hyperframes/assets/test-corpus/tier-2-multi-scene/expected.json +9 -9
  286. package/skills/remotion-to-hyperframes/assets/test-corpus/tier-2-multi-scene/hf-src/compositions/scene-1.html +35 -0
  287. package/skills/remotion-to-hyperframes/assets/test-corpus/tier-2-multi-scene/hf-src/compositions/scene-2.html +35 -0
  288. package/skills/remotion-to-hyperframes/assets/test-corpus/tier-2-multi-scene/hf-src/compositions/scene-3.html +36 -0
  289. package/skills/remotion-to-hyperframes/assets/test-corpus/tier-2-multi-scene/hf-src/index.html +28 -71
  290. package/skills/remotion-to-hyperframes/assets/test-corpus/tier-3-data-driven/expected.json +3 -3
  291. package/skills/remotion-to-hyperframes/assets/test-corpus/tier-3-data-driven/hf-src/compositions/scene-1.html +52 -0
  292. package/skills/remotion-to-hyperframes/assets/test-corpus/tier-3-data-driven/hf-src/compositions/scene-2.html +99 -0
  293. package/skills/remotion-to-hyperframes/assets/test-corpus/tier-3-data-driven/hf-src/compositions/scene-3.html +55 -0
  294. package/skills/remotion-to-hyperframes/assets/test-corpus/tier-3-data-driven/hf-src/index.html +13 -212
  295. package/skills/remotion-to-hyperframes/references/api-map.md +16 -16
  296. package/skills/remotion-to-hyperframes/references/limitations.md +7 -7
  297. package/skills/remotion-to-hyperframes/references/lottie.md +5 -7
  298. package/skills/remotion-to-hyperframes/references/media.md +3 -3
  299. package/skills/remotion-to-hyperframes/references/parameters.md +5 -0
  300. package/skills/remotion-to-hyperframes/references/sequencing.md +71 -18
  301. package/skills/slideshow/SKILL.md +4 -1
  302. package/skills/slideshow/references/standalone-harness.md +0 -3
  303. package/skills/talking-head-recut/SKILL.md +10 -1
  304. package/skills/hyperframes-core/references/review-loop.md +0 -41
  305. package/skills/media-use/scripts/lib/adopt.mjs +0 -128
  306. package/skills/media-use/scripts/lib/adopt.test.mjs +0 -95
  307. package/skills/media-use/scripts/lib/bgm-provider.mjs +0 -20
  308. package/skills/media-use/scripts/lib/brand-provider.mjs +0 -59
  309. package/skills/media-use/scripts/lib/bundled-sfx-provider.mjs +0 -108
  310. package/skills/media-use/scripts/lib/bundled-sfx-provider.test.mjs +0 -85
  311. package/skills/media-use/scripts/lib/cache.mjs +0 -150
  312. package/skills/media-use/scripts/lib/candidates.mjs +0 -91
  313. package/skills/media-use/scripts/lib/candidates.test.mjs +0 -155
  314. package/skills/media-use/scripts/lib/codex-provider.mjs +0 -161
  315. package/skills/media-use/scripts/lib/codex-provider.test.mjs +0 -34
  316. package/skills/media-use/scripts/lib/coverage.test.mjs +0 -117
  317. package/skills/media-use/scripts/lib/cube-build.mjs +0 -181
  318. package/skills/media-use/scripts/lib/cube-build.test.mjs +0 -80
  319. package/skills/media-use/scripts/lib/cube-validate.mjs +0 -198
  320. package/skills/media-use/scripts/lib/cube-validate.test.mjs +0 -125
  321. package/skills/media-use/scripts/lib/cutlist.test.mjs +0 -148
  322. package/skills/media-use/scripts/lib/duck.test.mjs +0 -118
  323. package/skills/media-use/scripts/lib/error-diffusion.test.mjs +0 -102
  324. package/skills/media-use/scripts/lib/freeze.mjs +0 -70
  325. package/skills/media-use/scripts/lib/freeze.test.mjs +0 -46
  326. package/skills/media-use/scripts/lib/grade-analyzer.mjs +0 -264
  327. package/skills/media-use/scripts/lib/grade-analyzer.test.mjs +0 -285
  328. package/skills/media-use/scripts/lib/heygen-cli.mjs +0 -191
  329. package/skills/media-use/scripts/lib/heygen-cli.test.mjs +0 -301
  330. package/skills/media-use/scripts/lib/heygen-search.mjs +0 -45
  331. package/skills/media-use/scripts/lib/heygen-search.test.mjs +0 -49
  332. package/skills/media-use/scripts/lib/heygen-video-provider.mjs +0 -127
  333. package/skills/media-use/scripts/lib/heygen-video-provider.test.mjs +0 -344
  334. package/skills/media-use/scripts/lib/image-provider.mjs +0 -44
  335. package/skills/media-use/scripts/lib/local-models.mjs +0 -318
  336. package/skills/media-use/scripts/lib/local-models.test.mjs +0 -220
  337. package/skills/media-use/scripts/lib/local-run.mjs +0 -78
  338. package/skills/media-use/scripts/lib/local-run.test.mjs +0 -121
  339. package/skills/media-use/scripts/lib/logo-provider.mjs +0 -222
  340. package/skills/media-use/scripts/lib/logo-provider.test.mjs +0 -137
  341. package/skills/media-use/scripts/lib/ltx-video-provider.mjs +0 -94
  342. package/skills/media-use/scripts/lib/ltx-video-provider.test.mjs +0 -316
  343. package/skills/media-use/scripts/lib/lut-preset-provider.mjs +0 -266
  344. package/skills/media-use/scripts/lib/lut-preset-provider.test.mjs +0 -176
  345. package/skills/media-use/scripts/lib/manifest.test.mjs +0 -388
  346. package/skills/media-use/scripts/lib/match.mjs +0 -47
  347. package/skills/media-use/scripts/lib/mflux-provider.mjs +0 -128
  348. package/skills/media-use/scripts/lib/mflux-provider.test.mjs +0 -174
  349. package/skills/media-use/scripts/lib/misses.mjs +0 -49
  350. package/skills/media-use/scripts/lib/misses.test.mjs +0 -78
  351. package/skills/media-use/scripts/lib/npx-sync.test.mjs +0 -50
  352. package/skills/media-use/scripts/lib/parakeet-words.test.mjs +0 -44
  353. package/skills/media-use/scripts/lib/prefs-store.test.mjs +0 -189
  354. package/skills/media-use/scripts/lib/probe.mjs +0 -39
  355. package/skills/media-use/scripts/lib/probe.test.mjs +0 -31
  356. package/skills/media-use/scripts/lib/providers.mjs +0 -5
  357. package/skills/media-use/scripts/lib/recipe-store.test.mjs +0 -367
  358. package/skills/media-use/scripts/lib/registry.mjs +0 -218
  359. package/skills/media-use/scripts/lib/registry.test.mjs +0 -261
  360. package/skills/media-use/scripts/lib/search.mjs +0 -24
  361. package/skills/media-use/scripts/lib/search.test.mjs +0 -32
  362. package/skills/media-use/scripts/lib/sfx-provider.mjs +0 -23
  363. package/skills/media-use/scripts/lib/specs.mjs +0 -132
  364. package/skills/media-use/scripts/lib/specs.test.mjs +0 -157
  365. package/skills/media-use/scripts/lib/stats.mjs +0 -117
  366. package/skills/media-use/scripts/lib/stats.test.mjs +0 -165
  367. package/skills/media-use/scripts/lib/telemetry.test.mjs +0 -373
  368. package/skills/media-use/scripts/lib/tts-local-provider.mjs +0 -92
  369. package/skills/media-use/scripts/lib/tts-local-provider.test.mjs +0 -72
  370. package/skills/media-use/scripts/lib/usage.mjs +0 -57
  371. package/skills/media-use/scripts/lib/usage.test.mjs +0 -54
  372. package/skills/media-use/scripts/lib/voice-provider.mjs +0 -57
  373. package/skills/media-use/scripts/lib/voice-provider.test.mjs +0 -46
  374. package/skills/media-use/scripts/resolve.test.mjs +0 -1120
  375. /package/skills/{hyperframes-core → hyperframes}/references/subagent-dispatch.md +0 -0
@@ -746,7 +746,7 @@ ${
746
746
  : ""
747
747
  }
748
748
  ${
749
- b.yield
749
+ !HEROLESS && b.yield
750
750
  ? ` // rail yields while the apex lands (furniture never contests the hero).
751
751
  // Overlap guards: dim starts after the line is IN, never runs into the exit;
752
752
  // restore is emitted only with clear runway before the exit (else the line
@@ -777,7 +777,7 @@ function paradigmPanel() {
777
777
  w.display,
778
778
  +w.start.toFixed(3),
779
779
  // redaction: words inside the hero phrase window get blocks until lock
780
- redactLinkage && w.start >= hero.start - 0.01 && w.start <= hero.end + 0.01
780
+ hero && redactLinkage && w.start >= hero.start - 0.01 && w.start <= hero.end + 0.01
781
781
  ? +lockT.toFixed(3)
782
782
  : 0,
783
783
  ]),
@@ -814,7 +814,7 @@ ${lineData.map((L) => ` <div class="ln" id="${L.id}"></div>`).join("\n")}
814
814
  // ---- body paradigm: PANEL (typed console log, accumulate) ----
815
815
  tl.fromTo("#panel", { opacity: 0, x: -16 }, { opacity: 1, x: 0, duration: 0.3, ease: "power2.out" }, 0.05);
816
816
  ${
817
- b.yield
817
+ !HEROLESS && b.yield
818
818
  ? ` tl.to("#panel", { opacity: ${b.yield.dim}, duration: 0.25, ease: "power1.in" }, ${(heroIn - 0.08).toFixed(3)});
819
819
  tl.to("#panel", { opacity: 1, duration: 0.3, ease: "power1.out" }, ${(lockT + 0.15).toFixed(3)});`
820
820
  : ""
@@ -1804,24 +1804,29 @@ function paradigmLastpage() {
1804
1804
  words: L.words.map((w) => [w.display, +w.start.toFixed(3)]),
1805
1805
  }));
1806
1806
  const css = `
1807
- .fld { position:absolute; white-space:nowrap; font-family:'${dna.fonts.body}', serif;
1808
- font-weight:600; color:${dna.palette.body}; filter: blur(${b.fieldBlur || 9}px); }
1807
+ ${
1808
+ HEROLESS
1809
+ ? ""
1810
+ : ` .fld { position:absolute; white-space:nowrap; font-family:'${dna.fonts.body}', serif;
1811
+ font-weight:600; color:${dna.palette.body}; filter: blur(${b.fieldBlur || 9}px); }`
1812
+ }
1809
1813
  .ms { position:absolute; left:${W / 2}px; top:${H - (b.bottomPx || 96)}px; opacity:0; white-space:nowrap;
1810
1814
  font-family:'${dna.fonts.body}', serif; font-size:${b.fontPx}px; line-height:1;
1811
1815
  color:${dna.palette.body}; text-shadow: 0 2px 12px rgba(0,0,0,0.6); }
1812
1816
  .ms .w { display:inline-block; opacity:0; margin:0 0.14em; overflow:hidden; vertical-align:bottom; white-space:nowrap; }`;
1813
1817
  const html =
1814
- inst
1815
- .map(
1816
- (f, i) =>
1817
- ` <div class="fld" id="f${i}" style="left:${f.x}px; top:${f.y}px; font-size:${f.px}px; opacity:${f.op}; transform:translate(-50%,-50%) rotate(${f.rot}deg)">${esc(heroDisplay)}</div>`,
1818
- )
1819
- .join("\n") +
1820
- "\n" +
1818
+ (HEROLESS
1819
+ ? ""
1820
+ : inst
1821
+ .map(
1822
+ (f, i) =>
1823
+ ` <div class="fld" id="f${i}" style="left:${f.x}px; top:${f.y}px; font-size:${f.px}px; opacity:${f.op}; transform:translate(-50%,-50%) rotate(${f.rot}deg)">${esc(heroDisplay)}</div>`,
1824
+ )
1825
+ .join("\n") + "\n") +
1821
1826
  lineData.map((L) => ` <div class="ms" id="${L.id}"></div>`).join("\n");
1822
1827
  const js = `
1823
1828
  // ---- THE LAST PAGE ----
1824
- const I = ${I.toFixed(3)};
1829
+ ${!HEROLESS ? ` const I = ${I.toFixed(3)};` : ""}
1825
1830
  const MS = ${J(lineData)};
1826
1831
  MS.forEach((L) => {
1827
1832
  const line = document.getElementById(L.id);
@@ -1840,7 +1845,9 @@ function paradigmLastpage() {
1840
1845
  tl.to(line, { opacity: 0, duration: 0.16, ease: "power2.in" }, xo);
1841
1846
  tl.set(line, { display: "none" }, xo + 0.18);
1842
1847
  });
1843
- // the field breathes imperceptibly (alive, unreadable)
1848
+ ${
1849
+ !HEROLESS
1850
+ ? ` // the field breathes imperceptibly (alive, unreadable)
1844
1851
  ${inst.map((f, i) => `tl.to("#f${i}", { y: ${prnd() - 0.5 > 0 ? "+" : "-"}${(3 + prnd() * 5).toFixed(1)}, duration: ${(2.4 + prnd() * 2).toFixed(1)}, ease: "sine.inOut" }, 0);`).join("\n ")}
1845
1852
  // APEX: rack focus — the future was only ever one sentence
1846
1853
  tl.to(".fld", { filter: "blur(0px)", duration: 0.38, ease: "power3.inOut" }, I - 0.1);
@@ -1856,7 +1863,9 @@ function paradigmLastpage() {
1856
1863
  tl.to(".fld", { filter: "blur(${b.fieldBlur || 9}px)", duration: 0.6, ease: "power2.inOut" }, I + 1.5);
1857
1864
  tl.to("#f${inst.indexOf(main)}", { filter: "blur(0px)", duration: 0.01 }, I + 1.5);
1858
1865
  ${inst.map((f, i) => (i === inst.indexOf(main) ? "" : `tl.to("#f${i}", { opacity: 0, duration: 0.6 }, I + 1.6);`)).join("\n ")}
1859
- tl.to("#f${inst.indexOf(main)}", { opacity: 0, duration: 0.3, ease: "power2.in" }, ${(heroOut - 0.3).toFixed(3)});`;
1866
+ tl.to("#f${inst.indexOf(main)}", { opacity: 0, duration: 0.3, ease: "power2.in" }, ${(heroOut - 0.3).toFixed(3)});`
1867
+ : ""
1868
+ }`;
1860
1869
  return { css, html, js };
1861
1870
  }
1862
1871
 
@@ -2055,7 +2064,7 @@ ${
2055
2064
  : ""
2056
2065
  }
2057
2066
  ${
2058
- b.yield
2067
+ !HEROLESS && b.yield
2059
2068
  ? ` // rail yields while the apex board locks
2060
2069
  tl.to("#flwrap", { opacity: ${b.yield.dim}, duration: 0.18, ease: "power1.in" }, ${(heroIn - (b.yield.pre || 0.07)).toFixed(3)});
2061
2070
  tl.to("#flwrap", { opacity: 1, duration: 0.22, ease: "power1.out" }, ${(heroIn + (b.yield.post || 0.47)).toFixed(3)});`
@@ -2194,14 +2203,18 @@ ${
2194
2203
  }
2195
2204
 
2196
2205
  // ===== furniture =====
2197
- // status blinks while we wait, then the gag: pages to the OK row
2206
+ ${
2207
+ !HEROLESS
2208
+ ? ` // status blinks while we wait, then the gag: pages to the OK row
2198
2209
  ${J(statBlinks)}.forEach((t) => {
2199
2210
  tl.set("#tstrow1", { opacity: 0.35 }, t);
2200
2211
  tl.set("#tstrow1", { opacity: 1 }, t + 0.042);
2201
2212
  });
2202
2213
  tl.to("#tstatstack", { y: -24, duration: 0.16, ease: "steps(4)" }, ${swapT.toFixed(3)});
2203
2214
  tl.set("#tstrow2", { opacity: 0.5 }, ${(swapT + 0.18).toFixed(3)});
2204
- tl.set("#tstrow2", { opacity: 1 }, ${(swapT + 0.222).toFixed(3)});
2215
+ tl.set("#tstrow2", { opacity: 1 }, ${(swapT + 0.222).toFixed(3)});`
2216
+ : ""
2217
+ }
2205
2218
 
2206
2219
  // clock seconds tick (stacked digit column, stepped shifts)
2207
2220
  for (let k = 1; k <= ${nDig - 1}; k++) tl.set("#tdigcol", { y: -22 * k }, k);
@@ -2212,7 +2225,7 @@ ${
2212
2225
  tl.set("#twin", { opacity: 1 }, t + 0.042);
2213
2226
  });
2214
2227
  ${
2215
- b.yield
2228
+ !HEROLESS && b.yield
2216
2229
  ? `
2217
2230
  // ===== hierarchy: board yields while the apex lands =====
2218
2231
  tl.to("#tboard", { opacity: ${b.yield.dim}, duration: 0.18, ease: "power1.in" }, ${(heroIn - (b.yield.pre || 0.2)).toFixed(3)});
@@ -2343,7 +2356,7 @@ function paradigmVhsrail() {
2343
2356
  gags.push([+(lastOut - 0.01).toFixed(3), null]);
2344
2357
  const js = `
2345
2358
  // ---- body paradigm: VHSRAIL (tracking-glitch words, REWIND exits, OSD furniture) ----
2346
- const I = ${heroIn.toFixed(3)}, X = ${X.toFixed(3)};
2359
+ ${!HEROLESS ? ` const I = ${heroIn.toFixed(3)}, X = ${X.toFixed(3)};` : ""}
2347
2360
 
2348
2361
  // ===== OSD furniture: present the whole clip, 1-frame power-on glitch =====
2349
2362
  tl.set(["#osdplay","#osdts"], { opacity: 1, x: 5 }, 0.02);
@@ -2404,7 +2417,7 @@ function paradigmVhsrail() {
2404
2417
  });
2405
2418
  });
2406
2419
  ${
2407
- b.yield
2420
+ !HEROLESS && b.yield
2408
2421
  ? `
2409
2422
  // rail yields while the apex lands (dim clamped ≥ line-in; restore only with runway)
2410
2423
  VRAIL.forEach((L) => {
@@ -2427,7 +2440,9 @@ ${
2427
2440
  tl.set("#drift", { opacity: 0 }, L.out + 0.7);
2428
2441
  });
2429
2442
 
2430
- // ===== REC FREEZE artifacts (apex-coupled, in FRONT of the subject) =====
2443
+ ${
2444
+ !HEROLESS
2445
+ ? ` // ===== REC FREEZE artifacts (apex-coupled, in FRONT of the subject) =====
2431
2446
  // 1-frame full white tear band
2432
2447
  tl.set("#tear", { opacity: 0.95 }, I);
2433
2448
  tl.set("#tear", { opacity: 0 }, I + F);
@@ -2446,7 +2461,9 @@ ${
2446
2461
  tl.set("#hsbar", { opacity: 0 }, I + 10 * F);
2447
2462
 
2448
2463
  // apex REWIND exit: 2 scrub lines at the apex band
2449
- [0.6, 0.25, 0.5, 0].forEach((o, k) => tl.set(["#scrub3","#scrub4"], { opacity: o }, X + k * F));
2464
+ [0.6, 0.25, 0.5, 0].forEach((o, k) => tl.set(["#scrub3","#scrub4"], { opacity: o }, X + k * F));`
2465
+ : ""
2466
+ }
2450
2467
  // head-switch reprise on the final rewind
2451
2468
  [[0, 0.85, 40], [0.04, 0.6, 190], [0.08, 0.8, 90]].forEach(([dt, o, px]) => {
2452
2469
  tl.set("#hsbar", { opacity: o, backgroundPositionX: px + "px" }, ${lastOut.toFixed(3)} + dt);
@@ -2551,7 +2568,7 @@ ${lineData.map((L) => ` <div class="hln" id="${L.id}"></div>`).join("\n")
2551
2568
  tl.set(line, { opacity: 0, display: "none" }, Math.min(L.xo + 0.15, ${(DUR - 0.02).toFixed(2)}));
2552
2569
  });
2553
2570
  ${
2554
- b.yield
2571
+ !HEROLESS && b.yield
2555
2572
  ? ` // HUD yields while the boss lands (restore only with runway)
2556
2573
  tl.to("#hud", { opacity: ${b.yield.dim}, duration: 0.15, ease: "power1.in" }, ${(heroIn - (b.yield.pre || 0.2)).toFixed(3)});
2557
2574
  ${
@@ -2791,7 +2808,7 @@ ${pageData
2791
2808
  }
2792
2809
  });
2793
2810
  ${
2794
- b.yield
2811
+ !HEROLESS && b.yield
2795
2812
  ? `
2796
2813
  // ===== apex etiquette: the strip yields while the stamp lands =====
2797
2814
  tl.to(strip, { opacity: ${b.yield.dim}, duration: 0.18, ease: "power1.in" }, ${dimT});
@@ -2799,7 +2816,7 @@ ${resT + 0.3 < FY ? ` tl.to(strip, { opacity: 1, duration: 0.25, ease: "power1.
2799
2816
  : ""
2800
2817
  }
2801
2818
  ${
2802
- shadeDur > 0.4
2819
+ !HEROLESS && shadeDur > 0.4
2803
2820
  ? `
2804
2821
  // strip top-shadow breathes during the stamp's dead-still hold
2805
2822
  tl.to("#shade", { keyframes: { opacity: [0.5, 0.72, 0.54, 0.7, 0.55, 0.66, 0.5] },
@@ -2915,9 +2932,13 @@ function paradigmLaserrail() {
2915
2932
  L.words.forEach(([txt, st, em], wi) => {
2916
2933
  const el = line.children[wi];
2917
2934
  const [wx, wy] = L.pos[wi];
2918
- // beams yield inside the apex window (the hero owns the light)
2935
+ ${
2936
+ HEROLESS
2937
+ ? " const yld = 1;"
2938
+ : ` // beams yield inside the apex window (the hero owns the light)
2919
2939
  const yld = (st > ${(heroIn - 0.41).toFixed(3)} && st < ${(heroIn + 0.99).toFixed(3)})
2920
- ? ${b.yield ? (b.yield.beamDim ?? 0.55) : 1} : 1;
2940
+ ? ${b.yield ? (b.yield.beamDim ?? 0.55) : 1} : 1;`
2941
+ }
2921
2942
  const t0 = st - 0.21, cv = st - 0.083;
2922
2943
  // two beams converge on the word 2 frames before its time
2923
2944
  [[-25, -15, LACC, wx - 170], [${W + 25}, -15, LMAG, wx + 170]].forEach(([ex, ey, col, sx]) => {
@@ -2975,7 +2996,7 @@ function paradigmLaserrail() {
2975
2996
  tl.set(line, { display: "none" }, Math.min(L.sweepT + 0.32, ${(DUR - 0.02).toFixed(3)}));
2976
2997
  });
2977
2998
  ${
2978
- b.yield
2999
+ !HEROLESS && b.yield
2979
3000
  ? ` // rail yields while the apex lands (restore only with clear runway)
2980
3001
  LRAIL.forEach((L) => {
2981
3002
  if (L.in < ${heroIn.toFixed(3)} + 0.9 && L.sweepT > ${heroIn.toFixed(3)} - 0.3) {
@@ -3035,7 +3056,7 @@ function paradigmStormrail() {
3035
3056
  <div id="rain2"></div>`;
3036
3057
  const js = `
3037
3058
  // ---- body paradigm: STORMRAIL (lightning-kiss words, rain-wash exits, ambient rain) ----
3038
- const I = ${heroIn.toFixed(3)};
3059
+ ${!HEROLESS ? ` const I = ${heroIn.toFixed(3)};` : ""}
3039
3060
  // ambient rain: seeded streaks on repeating linear cycles (f(t), no random at render)
3040
3061
  function makeRain(container, n, seed, t0, t1) {
3041
3062
  const rnd = mulberry32(seed);
@@ -3059,10 +3080,14 @@ function paradigmStormrail() {
3059
3080
  }
3060
3081
  }
3061
3082
  makeRain(document.getElementById("rain"), ${r.count ?? 18}, ${r.seed ?? 9021}, 0, ${(DUR - 0.02).toFixed(2)});
3062
- makeRain(document.getElementById("rain2"), ${r.count ?? 18}, ${r.seed2 ?? 4477}, ${(heroIn - 0.11).toFixed(3)}, ${Math.min(heroIn + 1.24, DUR - 0.02).toFixed(3)});
3083
+ ${
3084
+ !HEROLESS
3085
+ ? ` makeRain(document.getElementById("rain2"), ${r.count ?? 18}, ${r.seed2 ?? 4477}, ${(heroIn - 0.11).toFixed(3)}, ${Math.min(heroIn + 1.24, DUR - 0.02).toFixed(3)});
3063
3086
  // rain doubles for ~1s after the strike
3064
3087
  tl.set("#rain2", { opacity: 0.11 }, I + 0.02);
3065
- tl.to("#rain2", { opacity: 0, duration: 0.30 }, ${Math.min(heroIn + 1.02, DUR - 0.34).toFixed(3)});
3088
+ tl.to("#rain2", { opacity: 0, duration: 0.30 }, ${Math.min(heroIn + 1.02, DUR - 0.34).toFixed(3)});`
3089
+ : ""
3090
+ }
3066
3091
 
3067
3092
  // rail scrim (stable reading surface against the busy lower frame)
3068
3093
  tl.to("#stscrim", { opacity: 1, duration: 0.20 }, 0.05);
@@ -3097,7 +3122,7 @@ function paradigmStormrail() {
3097
3122
  tl.set(line, { display: "none" }, Math.min(L.out + 0.20, ${(DUR - 0.02).toFixed(2)}));
3098
3123
  });
3099
3124
  ${
3100
- b.yield
3125
+ !HEROLESS && b.yield
3101
3126
  ? ` // rail yields while the bolt lands; the visible line's shadow flips toward
3102
3127
  // the strike for the flash frames (light from the bolt side)
3103
3128
  SRAIL.forEach((L) => {
@@ -3244,7 +3269,7 @@ function paradigmHolorail() {
3244
3269
  tl.set(line, { opacity: 0, display: "none" }, ex + 0.15);
3245
3270
  });
3246
3271
  ${
3247
- b.yield
3272
+ !HEROLESS && b.yield
3248
3273
  ? ` // the whole rail (plate included) yields while the apex lands
3249
3274
  tl.to("#railwrap", { opacity: ${b.yield.dim}, duration: 0.18, ease: "power1.in" }, ${(heroIn - (b.yield.pre ?? 0.18)).toFixed(3)});
3250
3275
  tl.to("#railwrap", { opacity: 1, duration: 0.22, ease: "power1.out" }, ${(heroIn + (b.yield.post ?? 0.37)).toFixed(3)});`
@@ -3324,14 +3349,14 @@ function paradigmPlanktonrail() {
3324
3349
  .join("\n");
3325
3350
  const js = `
3326
3351
  // ---- body paradigm: PLANKTONRAIL (jellyfish glow-on, two-row float, sinking exits) ----
3327
- const I = ${heroIn.toFixed(3)};
3352
+ ${!HEROLESS ? ` const I = ${heroIn.toFixed(3)};` : ""}
3328
3353
  const mrnd = mulberry32(${m.seed ?? 2929});
3329
3354
  const mf = document.getElementById("mfield");
3330
3355
  // plankton motes: seeded drift walks f(t); the first ${m.near ?? 5} seed a
3331
3356
  // ring around the bloom heart and get ATTRACTED to it as the apex lands
3332
3357
  const APX = ${HG.x}, APY = ${HG.y};
3333
3358
  for (let i = 0; i < ${m.count ?? 12}; i++) {
3334
- const near = i < ${m.near ?? 5};
3359
+ const near = ${HEROLESS ? "false" : `i < ${m.near ?? 5}`};
3335
3360
  const el = document.createElement("div");
3336
3361
  el.className = "mote"; mf.appendChild(el);
3337
3362
  let L, T;
@@ -3352,11 +3377,13 @@ function paradigmPlanktonrail() {
3352
3377
  // slow seeded drift walk
3353
3378
  const a1 = (mrnd() - 0.5) * 36, a2 = a1 + (mrnd() - 0.5) * 36, a3 = a2 + (mrnd() - 0.5) * 30;
3354
3379
  const b1 = (mrnd() - 0.5) * 28, b2 = b1 + (mrnd() - 0.5) * 28, b3 = b2 + (mrnd() - 0.5) * 24;
3355
- const dEnd = near ? I - 0.25 : ${(DUR - 0.34).toFixed(3)};
3380
+ const dEnd = ${HEROLESS ? (DUR - 0.34).toFixed(3) : `near ? I - 0.25 : ${(DUR - 0.34).toFixed(3)}`};
3356
3381
  tl.to(el, { keyframes: { x: [a1, a2, a3], y: [b1, b2, b3],
3357
3382
  opacity: [0.13, 0.07, 0.11] },
3358
3383
  duration: dEnd - (tin + 0.32), ease: "sine.inOut" }, tin + 0.32);
3359
- if (near) {
3384
+ ${
3385
+ !HEROLESS
3386
+ ? ` if (near) {
3360
3387
  // ATTRACTION: pulled toward the bloom, brightening
3361
3388
  const tx = (APX - L) * 0.72 + (mrnd() - 0.5) * 24;
3362
3389
  const ty = (APY - T) * 0.72 + (mrnd() - 0.5) * 18;
@@ -3367,7 +3394,9 @@ function paradigmPlanktonrail() {
3367
3394
  tl.to(el, { y: ty + 18, opacity: 0, duration: 0.18, ease: "power1.in" }, ${(DUR - 0.22).toFixed(3)});
3368
3395
  } else {
3369
3396
  tl.to(el, { y: "+=14", opacity: 0, duration: 0.16, ease: "power1.in" }, ${(DUR - 0.2).toFixed(3)});
3370
- }
3397
+ }`
3398
+ : ` tl.to(el, { y: "+=14", opacity: 0, duration: 0.16, ease: "power1.in" }, ${(DUR - 0.2).toFixed(3)});`
3399
+ }
3371
3400
  }
3372
3401
 
3373
3402
  // ---- body lines: jellyfish glow-on, floating couplet rows, sinking exits ----
@@ -3415,7 +3444,9 @@ function paradigmPlanktonrail() {
3415
3444
  }
3416
3445
  });
3417
3446
 
3418
- // rail yields to the apex landing: the feeding line dims (and exits dimmed
3447
+ ${
3448
+ !HEROLESS
3449
+ ? ` // rail yields to the apex landing: the feeding line dims (and exits dimmed
3419
3450
  // unless it has ≥0.9s of hold left); a line entering during the hold
3420
3451
  // arrives at ${yld.enter ?? 0.8} and restores once the bloom settles
3421
3452
  PRAIL.forEach((L, i) => {
@@ -3429,7 +3460,9 @@ function paradigmPlanktonrail() {
3429
3460
  tl.to("#" + L.id, { opacity: 1, duration: 0.25, ease: "power1.out" },
3430
3461
  Math.min(Math.max(I + ${(yld.post ?? 0.63).toFixed(2)}, L.in + 0.1), ${(DUR - 0.28).toFixed(2)}));
3431
3462
  }
3432
- });`;
3463
+ });`
3464
+ : ""
3465
+ }`;
3433
3466
  return { css, html, js };
3434
3467
  }
3435
3468
 
@@ -3510,7 +3543,7 @@ function paradigmSheenrail() {
3510
3543
  </div>`;
3511
3544
  const js = `
3512
3545
  // ---- body paradigm: SHEENRAIL (flow-on entrance, sheen-sweep emphasis, dissolve-to-streaks exits) ----
3513
- const I = ${heroIn.toFixed(3)};
3546
+ ${!HEROLESS ? ` const I = ${heroIn.toFixed(3)};` : ""}
3514
3547
  const srnd = mulberry32(${b.seed ?? 20260611});
3515
3548
  const stg = document.getElementById("stage");
3516
3549
  const PAL = ${J(PAL)};
@@ -3564,9 +3597,13 @@ function paradigmSheenrail() {
3564
3597
  // continuous iridescent sheen drift f(t) — the body's hold life
3565
3598
  tl.fromTo(allGrads, { backgroundPosition: "0% 50%" },
3566
3599
  { backgroundPosition: "300% 50%", duration: ${(DUR - 0.04).toFixed(3)}, ease: "none" }, 0);
3567
- // rail yields — band included — while the ribbon writes (apex owns the frame)
3600
+ ${
3601
+ !HEROLESS
3602
+ ? ` // rail yields — band included — while the ribbon writes (apex owns the frame)
3568
3603
  tl.to("#skwrap", { opacity: ${yld.dim ?? 0.5}, duration: 0.2, ease: "sine.in" }, I - ${(yld.pre ?? 0.16).toFixed(2)});
3569
- tl.to("#skwrap", { opacity: 1, duration: 0.3, ease: "sine.out" }, I + ${(yld.post ?? 0.62).toFixed(2)});`;
3604
+ tl.to("#skwrap", { opacity: 1, duration: 0.3, ease: "sine.out" }, I + ${(yld.post ?? 0.62).toFixed(2)});`
3605
+ : ""
3606
+ }`;
3570
3607
  return { css, html, js };
3571
3608
  }
3572
3609
 
@@ -3626,7 +3663,7 @@ function paradigmScoperail() {
3626
3663
  x += ws[i] + GAPem * b.fontPx;
3627
3664
  });
3628
3665
  });
3629
- if (!heroInline)
3666
+ if (hero && !heroInline)
3630
3667
  for (let k = 0; k < hero.len; k++) {
3631
3668
  const hx = HG.x + (hero.len === 1 ? 0 : (k / (hero.len - 1)) * 0.6 * (HG.halfW || 300));
3632
3669
  burst.push([+tWords[hero.idx + k].start.toFixed(3), +hx.toFixed(1), 1]);
@@ -3744,7 +3781,7 @@ function paradigmScoperail() {
3744
3781
  tl.fromTo("#scwavewrap", { scaleX: 0.04, transformOrigin: "50% 50%" },
3745
3782
  { scaleX: 1, duration: 0.22, ease: "power2.out" }, 0.04);
3746
3783
  ${
3747
- b.yield && !heroInline
3784
+ !HEROLESS && b.yield && !heroInline
3748
3785
  ? `
3749
3786
  // rail yields while the apex trace writes (band carries lines + wave + HUD)
3750
3787
  tl.to("#scband", { opacity: ${b.yield.dim}, duration: 0.18, ease: "power1.in" }, ${Math.max(heroIn - (b.yield.pre || 0.13), 0.2).toFixed(3)});
@@ -3940,7 +3977,7 @@ ${lineData.map((L) => ` <div class="pline" id="${L.id}"></div>`).join("\n
3940
3977
  for (let t = 0.45; t < ${(DUR - 0.06).toFixed(3)}; t += 1/6)
3941
3978
  tl.set("#pstrip", { x: (rrnd()-0.5)*1.4, y: (rrnd()-0.5)*1.4, rotation: (rrnd()-0.5)*0.36 }, t);
3942
3979
  ${
3943
- b.yield && !heroInline
3980
+ !HEROLESS && b.yield && !heroInline
3944
3981
  ? `
3945
3982
  // rail yields while the apex chips land (furniture never contests the hero)
3946
3983
  tl.to(["#pstrip", "#plines"], { opacity: ${b.yield.dim}, duration: 0.10 }, ${dimT});
@@ -4137,7 +4174,7 @@ ${lineData.map((L) => ` <div class="puline" id="${L.id}"></div>`).join("\
4137
4174
  });
4138
4175
  });
4139
4176
  ${
4140
- b.yield && !heroInline
4177
+ !HEROLESS && b.yield && !heroInline
4141
4178
  ? `
4142
4179
  // APEX OWNS ITS WINDOW — page yields while the centerfold lands, restores
4143
4180
  tl.to("#pupage", { opacity: ${b.yield.dim}, duration: 0.12, ease: "power1.out" }, ${(heroIn - (b.yield.pre || 0.03)).toFixed(3)});
@@ -4331,7 +4368,7 @@ ${lineData.map((L) => ` <div class="crow" id="${L.id}" style="top:${L.top
4331
4368
  }
4332
4369
  });
4333
4370
  ${
4334
- b.yield && !heroInline
4371
+ !HEROLESS && b.yield && !heroInline
4335
4372
  ? `
4336
4373
  // APEX OWNS ITS WINDOW — band yields while the chalk word writes, restores
4337
4374
  tl.to("#cband", { opacity: ${b.yield.dim}, duration: 0.14, ease: "power1.in" }, ${(heroIn - (b.yield.pre || 0.07)).toFixed(3)});
@@ -4467,7 +4504,7 @@ function paradigmMarkerrail() {
4467
4504
  }
4468
4505
  });
4469
4506
  ${
4470
- b.yield && !heroInline
4507
+ !HEROLESS && b.yield && !heroInline
4471
4508
  ? ` // APEX OWNS ITS WINDOW — the line visible at the tag's onset yields.
4472
4509
  // Restore only with runway before the buff (else the line exits dimmed).
4473
4510
  RAILM.forEach((L) => {
@@ -4647,7 +4684,7 @@ ${lineData.map((L) => ` <div class="bline" id="${L.id}"></div>`).join("\n
4647
4684
  tl.set(line, { opacity: 0 }, L.eraseEnd + 0.02);
4648
4685
  });
4649
4686
  ${
4650
- b.yield && !heroInline
4687
+ !HEROLESS && b.yield && !heroInline
4651
4688
  ? `
4652
4689
  // APEX OWNS ITS WINDOW — band + the line under the gesture yield, band restores
4653
4690
  tl.to(${heroLi >= 0 ? `["#band", "#br${heroLi}"]` : `"#band"`}, { opacity: ${b.yield.dim}, duration: 0.16 }, ${(heroIn - (b.yield.pre || 0.16)).toFixed(3)});
@@ -4782,7 +4819,7 @@ function paradigmInkrail() {
4782
4819
  }
4783
4820
  });
4784
4821
  ${
4785
- b.yield && !heroInline
4822
+ !HEROLESS && b.yield && !heroInline
4786
4823
  ? `
4787
4824
  // rows visible under the bloom yield while the drop blooms, restore after.
4788
4825
  // Overlap guards: dim only after the line is IN with runway before its exit;
@@ -4930,7 +4967,7 @@ ${lineData.map((L) => ` <div class="rline" id="${L.id}"></div>`).join("\n
4930
4967
  duration: L.bd, ease: "none" }, L.bs);
4931
4968
  });
4932
4969
  ${
4933
- b.yield && !heroInline
4970
+ !HEROLESS && b.yield && !heroInline
4934
4971
  ? ` // rail yields while the apex letters slam behind the subject (container
4935
4972
  // opacity — never contests the per-chip channels)
4936
4973
  tl.to("#rrailwrap", { opacity: ${b.yield.dim}, duration: 0.12 }, ${Math.max(0.05, heroIn - (b.yield.pre ?? 0.02)).toFixed(3)});
@@ -8495,7 +8532,7 @@ if (!heroInline && !HEROLESS) {
8495
8532
  throw new Error("[make-theme] unknown setpiece: " + dna.hero.setpiece);
8496
8533
  setp = SETPIECES[dna.hero.setpiece]();
8497
8534
  }
8498
- const fx = frontFx();
8535
+ const fx = HEROLESS ? { css: "", html: "", js: "" } : frontFx();
8499
8536
 
8500
8537
  // bg file: plate reaction + embedded setpiece (+ body if body.layer === "bg")
8501
8538
  const bodyInBg = dna.body.layer === "bg";
@@ -8537,7 +8574,9 @@ if (!bodyInBg || fx.html || fx.js || setp.fgHtml) {
8537
8574
  }
8538
8575
 
8539
8576
  // _postfx.sh: plate reaction after the matte composite (subject+text move as one)
8540
- const P = HEROLESS ? { grain: (dna.plate || {}).grain || 5 } : dna.plate || {};
8577
+ const P = HEROLESS ? { grain: dna.plate?.grain ?? 5 } : dna.plate || {};
8578
+ const grain = P.grain ?? 5;
8579
+ const noise = grain === 0 ? "" : `,noise=alls=${grain}:allf=t+u`;
8541
8580
  // punchOffset: themes whose impact is NOT the hero onset (e.g. flapboard's
8542
8581
  // lock-complete clack) shift the plate punch anchor; default keeps onset+2f
8543
8582
  const anchorT = (heroIn + (P.punchOffset ?? 0.045)).toFixed(3);
@@ -8569,8 +8608,7 @@ fs.writeFileSync(
8569
8608
  set -euo pipefail
8570
8609
  cd "$(dirname "$0")"
8571
8610
  ffmpeg -y -v error -i final.mp4 -filter_complex "
8572
- [0:v]${filter}${rgba},
8573
- noise=alls=${P.grain || 5}:allf=t+u[v]" \\
8611
+ [0:v]${filter}${rgba}${noise}[v]" \\
8574
8612
  -map "[v]" -map 0:a -c:v libx264 -crf 14 -preset slow -profile:v high -c:a copy \\
8575
8613
  final_fx.mp4
8576
8614
  echo "[postfx] ${dna.name} → final_fx.mp4"
@@ -0,0 +1,131 @@
1
+ import assert from "node:assert/strict";
2
+ import { spawnSync } from "node:child_process";
3
+ import {
4
+ cpSync,
5
+ mkdirSync,
6
+ mkdtempSync,
7
+ readFileSync,
8
+ readdirSync,
9
+ rmSync,
10
+ writeFileSync,
11
+ } from "node:fs";
12
+ import { tmpdir } from "node:os";
13
+ import { dirname, join, resolve } from "node:path";
14
+ import test from "node:test";
15
+ import { fileURLToPath } from "node:url";
16
+
17
+ const scriptsDir = dirname(fileURLToPath(import.meta.url));
18
+ const skillDir = resolve(scriptsDir, "..");
19
+ const fixturesDir = join(scriptsDir, "fixtures", "heroless");
20
+ const makeTheme = join(scriptsDir, "make-theme.cjs");
21
+ const themeNames = readdirSync(join(skillDir, "themes"))
22
+ .filter((name) => name.endsWith(".json"))
23
+ .map((name) => name.slice(0, -5))
24
+ .sort();
25
+ const expectedThemes = [
26
+ "anchor",
27
+ "arcade",
28
+ "aurora",
29
+ "biolume",
30
+ "brush",
31
+ "chalkboard",
32
+ "dossier",
33
+ "graffiti",
34
+ "hologram",
35
+ "inkwater",
36
+ "laser",
37
+ "lastpage",
38
+ "neonsign",
39
+ "ordnance",
40
+ "papercut",
41
+ "popup",
42
+ "ransom",
43
+ "scoreboard",
44
+ "spectrum",
45
+ "stardust",
46
+ "stomp",
47
+ "terminal",
48
+ "thunder",
49
+ "transit",
50
+ "vhs",
51
+ ];
52
+ const fixtureTheme = JSON.parse(readFileSync(join(fixturesDir, "theme.json"), "utf8"));
53
+ const fixtureWords = fixtureTheme.lines.flat();
54
+
55
+ test("every embedded-caption theme compiles a sane heroless body timeline", async (t) => {
56
+ assert.deepEqual(themeNames, expectedThemes);
57
+ assert.equal(Object.hasOwn(fixtureTheme, "hero"), false);
58
+
59
+ const workspace = mkdtempSync(join(tmpdir(), "embedded-captions-heroless-"));
60
+ t.after(() => rmSync(workspace, { recursive: true, force: true }));
61
+
62
+ for (const themeName of themeNames) {
63
+ await t.test(themeName, () => {
64
+ const project = join(workspace, themeName);
65
+ cpSync(fixturesDir, project, { recursive: true });
66
+ writeFileSync(
67
+ join(project, "theme.json"),
68
+ JSON.stringify({ ...fixtureTheme, dna: themeName }),
69
+ );
70
+
71
+ const result = spawnSync(process.execPath, [makeTheme, project], {
72
+ encoding: "utf8",
73
+ timeout: 10_000,
74
+ });
75
+ assert.equal(result.status, 0, `${result.stdout}\n${result.stderr}`);
76
+
77
+ const dna = JSON.parse(readFileSync(join(skillDir, "themes", `${themeName}.json`), "utf8"));
78
+ const bodyPage = dna.body.layer === "bg" ? "index.html" : "rail.html";
79
+ const generated = readFileSync(join(project, bodyPage), "utf8");
80
+ const generatedPages = readdirSync(project)
81
+ .filter((name) => name.endsWith(".html"))
82
+ .map((name) => readFileSync(join(project, name), "utf8"));
83
+
84
+ assert.match(generated, /data-composition-id="main"[^>]+data-duration="6"/s);
85
+ assert.match(generated, /window\.__timelines\["main"\] = tl;/);
86
+ for (const word of fixtureWords) assert.match(generated, new RegExp(`\\b${word}\\b`, "i"));
87
+ for (const page of generatedPages) assert.doesNotMatch(page, /-99\d(?:\.\d+)?/);
88
+ });
89
+ }
90
+ });
91
+
92
+ for (const heroless of [false, true]) {
93
+ for (const grain of [0, 3, undefined]) {
94
+ test(`postfx preserves grain ${grain} with heroless=${heroless}`, (t) => {
95
+ const workspace = mkdtempSync(join(tmpdir(), "embedded-captions-grain-"));
96
+ t.after(() => rmSync(workspace, { recursive: true, force: true }));
97
+ const project = join(workspace, "project");
98
+ cpSync(fixturesDir, project, { recursive: true });
99
+ mkdirSync(join(workspace, "scripts"));
100
+ mkdirSync(join(workspace, "themes"));
101
+ const compiler = join(workspace, "scripts", "make-theme.cjs");
102
+ cpSync(makeTheme, compiler);
103
+ const dna = JSON.parse(readFileSync(join(skillDir, "themes", "anchor.json"), "utf8"));
104
+ dna.plate.grain = grain;
105
+ writeFileSync(join(workspace, "themes", "anchor.json"), JSON.stringify(dna));
106
+ writeFileSync(
107
+ join(project, "theme.json"),
108
+ JSON.stringify({
109
+ ...fixtureTheme,
110
+ dna: "anchor",
111
+ ...(heroless
112
+ ? {}
113
+ : {
114
+ hero: { match: "hero" },
115
+ lines: fixtureTheme.lines.map((line) => line.filter((word) => word !== "hero")),
116
+ }),
117
+ }),
118
+ );
119
+ const result = spawnSync(process.execPath, [compiler, project], {
120
+ encoding: "utf8",
121
+ timeout: 10_000,
122
+ });
123
+ assert.equal(result.status, 0, `${result.stdout}\n${result.stderr}`);
124
+ const postfx = readFileSync(join(project, "_postfx.sh"), "utf8");
125
+ if (grain === 0) assert.doesNotMatch(postfx, /noise=/);
126
+ else assert.match(postfx, new RegExp(`noise=alls=${grain ?? 5}:allf=t\\+u`));
127
+ assert.doesNotMatch(postfx, /,\s*\[v\]/);
128
+ assert.match(postfx, heroless ? /\[0:v\]null/ : /zoompan=/);
129
+ });
130
+ }
131
+ }
@@ -30,19 +30,7 @@ const fs = require("fs");
30
30
  const os = require("os");
31
31
  const cp = require("child_process");
32
32
 
33
- function hfCli() {
34
- const roots = [
35
- process.env.HYPERFRAMES_ROOT,
36
- path.resolve(__dirname, "..", "..", ".."), // skills/embedded-captions/scripts → repo root if in-repo
37
- path.join(os.homedir(), "Downloads", "hyperframes"),
38
- ].filter(Boolean);
39
- for (const root of roots) {
40
- const cli = path.join(root, "packages", "cli", "dist", "cli.js");
41
- if (fs.existsSync(cli)) return cli;
42
- }
43
- console.error("[matte] cannot find hyperframes cli — set HYPERFRAMES_ROOT to a built checkout");
44
- process.exit(3);
45
- }
33
+ const { hfCli } = require("./hf-cli.cjs");
46
34
 
47
35
  function ensureSource(project) {
48
36
  const src = path.join(project, "source.mp4");
@@ -22,6 +22,7 @@ const os = require("os");
22
22
  // HYPERFRAMES_ROOT; standalone we also try the in-repo path + ~/Downloads, and
23
23
  // accept ANY puppeteer@* the bun store holds (not a pinned version).
24
24
  const HF_ROOTS = [
25
+ process.argv[2] && path.resolve(process.argv[2]), // project-owned helper dependencies
25
26
  process.env.HYPERFRAMES_ROOT,
26
27
  path.resolve(__dirname, "../../.."), // skills/embedded-captions/scripts → repo root if in-repo
27
28
  path.join(os.homedir(), "Downloads", "hyperframes"),
@@ -54,7 +55,7 @@ for (const root of HF_ROOTS) {
54
55
  }
55
56
  if (!puppeteer) {
56
57
  console.error(
57
- "[measure] could not locate puppeteer — set HYPERFRAMES_ROOT to a built hyperframes checkout",
58
+ "[measure] could not locate puppeteer — install project dependencies per embedded-captions SKILL.md Runtime prerequisites",
58
59
  );
59
60
  process.exit(3);
60
61
  }