dsh-hyperframes 0.3.2 → 0.4.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 (375) hide show
  1. package/README.en.md +4 -3
  2. package/README.md +5 -4
  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
@@ -2,7 +2,7 @@
2
2
 
3
3
  Defines the storyboard's **base data format** only: the `STORYBOARD.md` file shape and the `StoryboardManifest` it parses into. How a workflow _generates_ a storyboard lives in that workflow; the optional narration/TTS file (`SCRIPT.md`) is a separate concern owned by the TTS step, not here.
4
4
 
5
- A storyboard is the **plan layer** for a video — an ordered set of **frames** (key moments) in one markdown file. HyperFrames Studio renders it as a contact sheet (the Storyboard view, available by default in every Studio session). Parser: `@hyperframes/core/storyboard` → `StoryboardManifest`; read API: `GET /api/projects/<id>/storyboard`.
5
+ A storyboard is the **plan layer** for a video — an ordered set of **frames** (key moments) in one markdown file. Parser: `@hyperframes/core/storyboard` → `StoryboardManifest`.
6
6
 
7
7
  ## Frontmatter (global direction)
8
8
 
@@ -53,41 +53,10 @@ StoryboardManifest {
53
53
  }
54
54
  ```
55
55
 
56
- The read API also adds `srcExists` per frame and attaches the optional `SCRIPT.md` payload when present.
57
-
58
56
  ## `SCRIPT.md` (out of scope here)
59
57
 
60
58
  Optional, free-form, **not parsed into the manifest** — the locked-narration file that drives TTS. Its format is defined in `references/script-format.md`, and it is absent for videos with no narration/TTS. The per-frame `voiceover` above is the storyboard's own narration guide.
61
59
 
62
- ## Frame comments — `.hyperframes/frame-comments.json`
63
-
64
- The storyboard review's **structured feedback channel** — the file Studio's per-frame comment boxes write on submit (chat feedback follows the same rule — `brief-contract.md` § 1, the comments channel). Like `SCRIPT.md`, it is a sibling of the storyboard, not parsed into the manifest.
65
-
66
- ```json
67
- {
68
- "version": 1,
69
- "pass": "sketch",
70
- "submitted_at": "2026-07-09T12:04:00Z",
71
- "comments": [
72
- {
73
- "frame": 3,
74
- "src": "compositions/frames/03-mechanism.html",
75
- "title": "Mechanism",
76
- "text": "Swap the bar chart for a before/after slider."
77
- }
78
- ]
79
- }
80
- ```
81
-
82
- | Field | Meaning |
83
- | ------------------------ | ------------------------------------------------------------------------------------------------------------------- |
84
- | `pass` | which review the batch belongs to: `storyboard` (text layer) / `sketch` (static frames) / `final` (assembled video) |
85
- | `comments[].frame` | the frame's 1-based `index` in the manifest — the key |
86
- | `comments[].src` `title` | copied from the frame at submit time — if frames get reordered after submit, the mismatch shows |
87
- | `comments[].text` | the feedback, verbatim |
88
-
89
- Lifecycle — the whole contract: a workflow finding this file at a checkpoint treats it as the revision feedback — **revise exactly the frames named, delete the file, re-present**. Writers create it only on submit; it never lingers across rounds.
90
-
91
60
  ## Example
92
61
 
93
62
  ```markdown
@@ -125,6 +94,6 @@ The old way: prompt, wait, get something that misses. Establish the pain we remo
125
94
  ## Notes
126
95
 
127
96
  - A frame with `status: outline` and no built `src` renders as an outline placeholder.
128
- - `built` is the middle rung: the frame's HTML exists and its **layout is confirmed** (a wireframe sketch or better) — motion not yet added. Studio chips it blue.
129
- - The process that walks these statuses — plan, sketch, build, each pass reviewed on the board — is `review-loop.md`.
97
+ - `built` is the middle rung: the frame's HTML exists and its **layout is confirmed** (a wireframe sketch or better) — motion not yet added. Nothing is drawn yet beyond the approved layout.
98
+ - The process that walks these statuses — plan, sketch, build, each pass reviewed in chat and in `storyboard.html` — is `review-loop.md`.
130
99
  - Multi-line `voiceover` values collapse to one line on save.
@@ -0,0 +1,194 @@
1
+ // Frame packets inline the storyboard frame, blueprint and cited recipes.
2
+ // Workflow wrappers supply resource paths and workflow-specific sections.
3
+ // The role combines the shared worker contract with the workflow delta.
4
+
5
+ import {
6
+ existsSync,
7
+ mkdirSync,
8
+ readFileSync,
9
+ readdirSync,
10
+ realpathSync,
11
+ writeFileSync,
12
+ } from "node:fs";
13
+ import { basename, join, resolve } from "node:path";
14
+ import { pathToFileURL } from "node:url";
15
+
16
+ export function field(block, name) {
17
+ const match = block.match(new RegExp(`^-\\s+${name}:\\s*(.+)$`, "im"));
18
+ return match?.[1]?.trim() ?? null;
19
+ }
20
+
21
+ export function splitFrames(storyboard) {
22
+ const matches = [...storyboard.matchAll(/^## Frame\s+([^\n]+)$/gm)];
23
+ return matches.map((match, index) => {
24
+ const start = match.index;
25
+ const end = matches[index + 1]?.index ?? storyboard.length;
26
+ return {
27
+ heading: match[1].trim(),
28
+ block: storyboard.slice(start, end).trim(),
29
+ };
30
+ });
31
+ }
32
+
33
+ export function frameId(frame) {
34
+ const src = field(frame.block, "src");
35
+ if (!src) throw new Error(`${frame.heading}: missing src`);
36
+ return basename(src).replace(/\.html?$/i, "");
37
+ }
38
+
39
+ export function selectedFile(path, heading) {
40
+ if (!path || !existsSync(path)) return "";
41
+ return `\n## ${heading}\n\n${readFileSync(path, "utf8").trim()}\n`;
42
+ }
43
+
44
+ function escapeRegExp(id) {
45
+ return id.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
46
+ }
47
+
48
+ export function knownRuleIds(animationDir) {
49
+ const rulesDir = join(animationDir, "rules");
50
+ if (!existsSync(rulesDir)) {
51
+ console.warn(
52
+ `frame-packets: no rules dir at ${rulesDir} — packets will inline no motion recipes`,
53
+ );
54
+ return [];
55
+ }
56
+ return readdirSync(rulesDir)
57
+ .filter((name) => name.endsWith(".md"))
58
+ .map((name) => name.replace(/\.md$/, ""));
59
+ }
60
+
61
+ export function citedRules(block, ruleIds) {
62
+ const explicit = (field(block, "rules") ?? "")
63
+ .split(/[,\s]+/)
64
+ .map((rule) => rule.trim())
65
+ .filter(Boolean);
66
+ const mentioned = ruleIds.filter((id) =>
67
+ new RegExp(`(?<![\\w-])${escapeRegExp(id)}(?![\\w-])`, "i").test(block),
68
+ );
69
+ return [...new Set([...explicit, ...mentioned])].filter((id) => ruleIds.includes(id));
70
+ }
71
+
72
+ // visual-design.md tells the author to write the blueprint as `<id> (Reproduce)`
73
+ // or `<id> (Adapt)` — the qualifier is direction for the frame worker, not part of
74
+ // the filename. Parse the field into the id it names (or null for `compose`), so
75
+ // no caller ever resolves a raw field value against the blueprints directory.
76
+ export function blueprintId(block) {
77
+ const raw = field(block, "blueprint");
78
+ if (!raw) return null;
79
+ const id = raw.replace(/\s*\([^)]*\)\s*$/, "").trim();
80
+ return id && id.toLowerCase() !== "compose" ? id : null;
81
+ }
82
+
83
+ export function resourceSections(block, { animationDir, ruleIds, frameId }) {
84
+ let sections = "";
85
+ const blueprint = blueprintId(block);
86
+ if (blueprint) {
87
+ const blueprintsDir = join(animationDir, "blueprints");
88
+ const path = join(blueprintsDir, `${blueprint}.md`);
89
+ // An installed library must contain the named blueprint.
90
+ // An absent on-demand library warns, like missing motion rules.
91
+ if (!existsSync(blueprintsDir)) {
92
+ console.warn(
93
+ `frame-packets: no blueprints dir at ${blueprintsDir} — packets will inline no blueprint`,
94
+ );
95
+ } else if (!existsSync(path)) {
96
+ throw new Error(`${frameId ?? "frame"}: blueprint "${blueprint}" has no file at ${path}`);
97
+ } else {
98
+ sections += selectedFile(path, `Selected blueprint: ${blueprint}`);
99
+ }
100
+ }
101
+ for (const rule of citedRules(block, ruleIds)) {
102
+ sections += selectedFile(
103
+ join(animationDir, "rules", `${rule}.md`),
104
+ `Selected motion rule: ${rule}`,
105
+ );
106
+ }
107
+ return sections;
108
+ }
109
+
110
+ export function buildRolePayload({ corePath, deltaPath, outDir }) {
111
+ const core = readFileSync(corePath, "utf8").trim();
112
+ const delta = readFileSync(deltaPath, "utf8").trim();
113
+ const role = `${core}\n\n---\n\n${delta}\n`;
114
+ mkdirSync(outDir, { recursive: true });
115
+ const path = join(outDir, "_role.md");
116
+ writeFileSync(path, role);
117
+ return { path, bytes: Buffer.byteLength(role) };
118
+ }
119
+
120
+ export function buildFramePackets({
121
+ projectDir,
122
+ storyboardPath = join(projectDir, "STORYBOARD.md"),
123
+ outDir = join(projectDir, ".hyperframes", "frame-packets"),
124
+ maxPacketBytes = 48_000,
125
+ animationDir,
126
+ corePath,
127
+ deltaPath,
128
+ // Per-workflow hooks (all optional):
129
+ // designTruthLine(projectDir) -> the packet's design-truth input line
130
+ // validateFrame(frame, id) -> throw to reject a frame before packing
131
+ // extraSections(block) -> extra packet sections appended after the rule recipes
132
+ designTruthLine = (dir) => `- Design tokens: ${join(resolve(dir), "frame.md")}`,
133
+ validateFrame,
134
+ extraSections,
135
+ }) {
136
+ const storyboard = readFileSync(storyboardPath, "utf8");
137
+ const frames = splitFrames(storyboard);
138
+ if (frames.length === 0) throw new Error("STORYBOARD.md has no frame blocks");
139
+ const ruleIds = knownRuleIds(animationDir);
140
+
141
+ const packets = frames.map((frame) => {
142
+ const id = frameId(frame);
143
+ if (validateFrame) validateFrame(frame, id);
144
+ const packet = `# Frame packet: ${id}\n\n## Project inputs\n\n- Project: ${resolve(projectDir)}\n${designTruthLine(projectDir)}\n- RULES_DIR: ${join(animationDir, "rules")}\n\n## Assigned storyboard block\n\n${frame.block}\n${resourceSections(frame.block, { animationDir, ruleIds, frameId: id })}${extraSections ? extraSections(frame.block) : ""}`;
145
+ const bytes = Buffer.byteLength(packet);
146
+ if (bytes > maxPacketBytes) {
147
+ throw new Error(`${id}: frame packet is ${bytes} bytes (limit ${maxPacketBytes})`);
148
+ }
149
+ return { frameId: id, path: join(outDir, `${id}.md`), bytes, packet };
150
+ });
151
+
152
+ mkdirSync(outDir, { recursive: true });
153
+ for (const { path, packet } of packets) writeFileSync(path, packet);
154
+ buildRolePayload({ corePath, deltaPath, outDir });
155
+ return packets.map(({ packet: _packet, ...result }) => result);
156
+ }
157
+
158
+ export function flag(argv, name, fallback) {
159
+ const index = argv.indexOf(`--${name}`);
160
+ return index >= 0 && argv[index + 1] ? argv[index + 1] : fallback;
161
+ }
162
+
163
+ // realpath both sides: on macOS /tmp → /private/tmp, and node resolves the main
164
+ // module's symlinks in import.meta.url while argv[1] keeps the invoked spelling —
165
+ // a raw compare silently skips main() when invoked through any symlinked path.
166
+ export function isMainModule(importMetaUrl) {
167
+ if (!process.argv[1]) return false;
168
+ try {
169
+ return pathToFileURL(realpathSync(process.argv[1])).href === importMetaUrl;
170
+ } catch {
171
+ return false;
172
+ }
173
+ }
174
+
175
+ export function runCli({ buildFramePackets: build, buildRolePayload: buildRole }) {
176
+ const argv = process.argv.slice(2);
177
+ const projectDir = resolve(flag(argv, "project", "."));
178
+ const outDir = resolve(flag(argv, "out-dir", join(projectDir, ".hyperframes", "frame-packets")));
179
+ try {
180
+ const packets = build({
181
+ projectDir,
182
+ storyboardPath: resolve(flag(argv, "storyboard", join(projectDir, "STORYBOARD.md"))),
183
+ outDir,
184
+ });
185
+ const role = buildRole({ outDir });
186
+ console.log(`✓ frame packets: ${packets.length} bounded packet(s)`);
187
+ for (const packet of packets)
188
+ console.log(` ${packet.frameId}: ${packet.bytes} bytes → ${packet.path}`);
189
+ console.log(` worker role: ${role.bytes} bytes → ${role.path}`);
190
+ } catch (error) {
191
+ console.error(`✗ frame packets: ${error.message}`);
192
+ process.exit(1);
193
+ }
194
+ }
@@ -0,0 +1,88 @@
1
+ #!/usr/bin/env node
2
+ // Run from the user's project; locate the release from this installed file.
3
+ import { spawnSync } from "node:child_process";
4
+ import { existsSync, readFileSync, realpathSync } from "node:fs";
5
+ import { join, win32 } from "node:path";
6
+ import { fileURLToPath, pathToFileURL } from "node:url";
7
+
8
+ const root = fileURLToPath(new URL("../../../", import.meta.url));
9
+ const manifests = [
10
+ "plugin.json",
11
+ ".claude-plugin/plugin.json",
12
+ ".codex-plugin/plugin.json",
13
+ ".cursor-plugin/plugin.json",
14
+ "gemini-extension.json",
15
+ ];
16
+
17
+ export function pluginVersion(pluginRoot = root) {
18
+ for (const path of manifests) {
19
+ const file = join(pluginRoot, path);
20
+ if (!existsSync(file)) continue;
21
+ const manifest = JSON.parse(readFileSync(file, "utf8"));
22
+ if (
23
+ manifest.name !== "hyperframes" ||
24
+ !/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/.test(manifest.version ?? "")
25
+ ) {
26
+ throw new Error(`Invalid HyperFrames plugin release: ${file}`);
27
+ }
28
+ return manifest.version;
29
+ }
30
+ throw new Error(
31
+ "No HyperFrames plugin manifest found. Use the standalone skills installation instructions.",
32
+ );
33
+ }
34
+
35
+ export function invocation(
36
+ args,
37
+ {
38
+ version = pluginVersion(),
39
+ env = process.env,
40
+ platform = process.platform,
41
+ node = process.execPath,
42
+ pathExists = existsSync,
43
+ } = {},
44
+ ) {
45
+ if (args[0] === "skills")
46
+ throw new Error(
47
+ "Update HyperFrames through your agent's plugin manager; bundled skills are release-managed.",
48
+ );
49
+ const childEnv = {
50
+ ...env,
51
+ HYPERFRAMES_SKIP_SKILLS: "1",
52
+ HYPERFRAMES_SKILL_PKG_VERSION: version,
53
+ HYPERFRAMES_PLUGIN_VERSION: version,
54
+ HYPERFRAMES_NO_UPDATE_CHECK: "1",
55
+ };
56
+ if (args[0] === "--script") {
57
+ if (!args[1]) throw new Error("--script requires a Node script path.");
58
+ return { command: node, args: args.slice(1), env: childEnv };
59
+ }
60
+ const cliArgs = ["--yes", `hyperframes@${version}`, ...args];
61
+ if (platform !== "win32") return { command: "npx", args: cliArgs, env: childEnv };
62
+ const candidates = [
63
+ env.npm_execpath && win32.join(win32.dirname(env.npm_execpath), "npx-cli.js"),
64
+ win32.join(win32.dirname(node), "node_modules", "npm", "bin", "npx-cli.js"),
65
+ ].filter(Boolean);
66
+ const npx = candidates.find(pathExists);
67
+ if (!npx)
68
+ throw new Error(
69
+ "Cannot find npx-cli.js. Install Node.js with npm or run from an npm environment.",
70
+ );
71
+ return { command: node, args: [npx, ...cliArgs], env: childEnv };
72
+ }
73
+
74
+ if (process.argv[1] && pathToFileURL(realpathSync(process.argv[1])).href === import.meta.url) {
75
+ try {
76
+ const command = invocation(process.argv.slice(2));
77
+ const result = spawnSync(command.command, command.args, {
78
+ env: command.env,
79
+ stdio: "inherit",
80
+ windowsHide: true,
81
+ });
82
+ if (result.error) throw result.error;
83
+ process.exitCode = result.status ?? 1;
84
+ } catch (error) {
85
+ console.error(error.message);
86
+ process.exitCode = 1;
87
+ }
88
+ }
@@ -0,0 +1,117 @@
1
+ import assert from "node:assert/strict";
2
+ import { spawnSync } from "node:child_process";
3
+ import {
4
+ copyFileSync,
5
+ mkdirSync,
6
+ mkdtempSync,
7
+ readFileSync,
8
+ realpathSync,
9
+ rmSync,
10
+ writeFileSync,
11
+ } from "node:fs";
12
+ import { join } from "node:path";
13
+ import { tmpdir } from "node:os";
14
+ import { test } from "node:test";
15
+ import { invocation, pluginVersion } from "./plugin-cli.mjs";
16
+
17
+ function fixture(t, manifest = "plugin.json", version = "1.2.3") {
18
+ const root = mkdtempSync(join(tmpdir(), "hf-plugin-"));
19
+ t.after(() => rmSync(root, { recursive: true, force: true }));
20
+ mkdirSync(join(root, "skills/hyperframes/scripts"), { recursive: true });
21
+ mkdirSync(join(root, manifest, ".."), { recursive: true });
22
+ writeFileSync(join(root, manifest), JSON.stringify({ name: "hyperframes", version }));
23
+ const launcher = join(root, "skills/hyperframes/scripts/plugin-cli.mjs");
24
+ copyFileSync(new URL("./plugin-cli.mjs", import.meta.url), launcher);
25
+ return { root, launcher };
26
+ }
27
+
28
+ for (const manifest of [
29
+ "plugin.json",
30
+ ".claude-plugin/plugin.json",
31
+ ".codex-plugin/plugin.json",
32
+ ".cursor-plugin/plugin.json",
33
+ "gemini-extension.json",
34
+ ]) {
35
+ test(`locates ${manifest} without repository packages`, (t) => {
36
+ const { root } = fixture(t, manifest);
37
+ assert.equal(pluginVersion(root), "1.2.3");
38
+ });
39
+ }
40
+
41
+ test("rejects missing and floating plugin versions", (t) => {
42
+ const { root } = fixture(t, "plugin.json", "latest");
43
+ assert.throws(() => pluginVersion(root), /Invalid HyperFrames plugin release/);
44
+ rmSync(join(root, "plugin.json"));
45
+ assert.throws(() => pluginVersion(root), /No HyperFrames plugin manifest/);
46
+ });
47
+
48
+ test("pins CLI, suppresses standalone refresh, preserves unrelated environment", () => {
49
+ const result = invocation(["init", "project with spaces", "--non-interactive"], {
50
+ version: "1.2.3",
51
+ platform: "darwin",
52
+ env: { PATH: "/bin", HYPERFRAMES_SKIP_SKILLS: "0" },
53
+ });
54
+ assert.equal(result.command, "npx");
55
+ assert.deepEqual(result.args, [
56
+ "--yes",
57
+ "hyperframes@1.2.3",
58
+ "init",
59
+ "project with spaces",
60
+ "--non-interactive",
61
+ ]);
62
+ assert.deepEqual(result.env, {
63
+ PATH: "/bin",
64
+ HYPERFRAMES_SKIP_SKILLS: "1",
65
+ HYPERFRAMES_SKILL_PKG_VERSION: "1.2.3",
66
+ HYPERFRAMES_PLUGIN_VERSION: "1.2.3",
67
+ HYPERFRAMES_NO_UPDATE_CHECK: "1",
68
+ });
69
+ assert.throws(() => invocation(["skills", "update"], { version: "1.2.3" }), /plugin manager/);
70
+ });
71
+
72
+ test("Windows launches npx through Node without shell argument interpretation", () => {
73
+ const result = invocation(["render", "a & b"], {
74
+ version: "1.2.3",
75
+ platform: "win32",
76
+ node: String.raw`C:\Program Files\nodejs\node.exe`,
77
+ env: { npm_execpath: String.raw`C:\Program Files\nodejs\node_modules\npm\bin\npm-cli.js` },
78
+ pathExists: (p) => p === String.raw`C:\Program Files\nodejs\node_modules\npm\bin\npx-cli.js`,
79
+ });
80
+ assert.equal(result.command, String.raw`C:\Program Files\nodejs\node.exe`);
81
+ assert.deepEqual(result.args, [
82
+ String.raw`C:\Program Files\nodejs\node_modules\npm\bin\npx-cli.js`,
83
+ "--yes",
84
+ "hyperframes@1.2.3",
85
+ "render",
86
+ "a & b",
87
+ ]);
88
+ assert.throws(
89
+ () => invocation([], { version: "1.2.3", platform: "win32", env: {}, pathExists: () => false }),
90
+ /Cannot find npx/,
91
+ );
92
+ });
93
+
94
+ test("installed helper keeps cwd, arguments, release environment and exit code", (t) => {
95
+ const { root, launcher } = fixture(t);
96
+ const project = join(root, "user project");
97
+ mkdirSync(project);
98
+ const helper = join(root, "helper.mjs");
99
+ writeFileSync(
100
+ helper,
101
+ "console.log(JSON.stringify({ cwd: process.cwd(), args: process.argv.slice(2), skip: process.env.HYPERFRAMES_SKIP_SKILLS, version: process.env.HYPERFRAMES_SKILL_PKG_VERSION })); process.exit(7);",
102
+ );
103
+ const before = readFileSync(join(root, "plugin.json"), "utf8");
104
+ const result = spawnSync(
105
+ process.execPath,
106
+ [launcher, "--script", helper, "literal $value & spaces"],
107
+ { cwd: project, encoding: "utf8" },
108
+ );
109
+ assert.equal(result.status, 7, result.stderr);
110
+ assert.deepEqual(JSON.parse(result.stdout), {
111
+ cwd: realpathSync(project),
112
+ args: ["literal $value & spaces"],
113
+ skip: "1",
114
+ version: "1.2.3",
115
+ });
116
+ assert.equal(readFileSync(join(root, "plugin.json"), "utf8"), before);
117
+ });
@@ -3,6 +3,8 @@ name: hyperframes-animation
3
3
  description: "All animation knowledge for HyperFrames — atomic motion rules, multi-phase scene blueprints, scene transitions, broader motion-design techniques, AND the seven runtime adapters (GSAP default, plus Lottie, Three.js, Anime.js, CSS keyframes, Web Animations API, TypeGPU). Use for any motion or animation task: pick 2-4 rules and compose, or load a blueprint, or look up runtime-specific API (e.g. GSAP eases / Lottie player / Three.js mixer). Also covers auditing an existing composition's choreography (animation map) and 24 named text-animation effects. HyperFrames-native: single paused timeline, seek-safe, deterministic."
4
4
  ---
5
5
 
6
+ **Plugin installs:** Before setup or freshness commands, follow [plugin execution rules](../hyperframes/references/plugin-installation.md) when this skill is inside a HyperFrames plugin. Standalone installs keep the update instructions below.
7
+
6
8
  # HyperFrames Animation
7
9
 
8
10
  All motion knowledge in one skill: **rules** (atomic recipes), **blueprints** (multi-phase scene templates), **transitions** (scene-to-scene), **techniques** (broader motion-design patterns), and **adapters** (per-runtime APIs).
@@ -30,6 +32,7 @@ Blueprints live in `blueprints-index.md`. Each entry points to `blueprints/<id>.
30
32
  | Read one blueprint's full recipe | `blueprints/<id>.md` |
31
33
  | Author a scene transition (CSS-driven, between two clips) | `transitions/overview.md`, `transitions/catalog.md` |
32
34
  | Look up a broader motion-design technique | `techniques.md` |
35
+ | Motion blur — shutter smear on an element, and when not to use it | `references/motion-blur.md` |
33
36
  | Analyze an existing composition's animation map | `scripts/animation-map.mjs` |
34
37
  | GSAP API — timeline / tweens / position parameters | `adapters/gsap.md` |
35
38
  | GSAP — drop-in effect recipes | `rules/gsap-effects.md` |
@@ -37,6 +40,7 @@ Blueprints live in `blueprints-index.md`. Each entry points to `blueprints/<id>.
37
40
  | GSAP — eases / stagger | `adapters/gsap-easing-and-stagger.md` |
38
41
  | GSAP — timeline / labels | `adapters/gsap-timeline-and-labels.md` |
39
42
  | Lottie / dotLottie (After Effects exports, `window.__hfLottie`) | `adapters/lottie.md` |
43
+ | Character animation (walk cycle, mascot, jointed puppet, gestures) | `adapters/lottie.md` → Characters |
40
44
  | Three.js / WebGL (3D scenes, `AnimationMixer`, `hf-seek`) | `adapters/three.md` |
41
45
  | Anime.js (`window.__hfAnime`) | `adapters/animejs.md` |
42
46
  | CSS keyframes (`animation-delay` / `play-state` / `fill-mode`) | `adapters/css-animations.md` |
@@ -48,7 +52,7 @@ Blueprints live in `blueprints-index.md`. Each entry points to `blueprints/<id>.
48
52
  ## Picking a runtime
49
53
 
50
54
  - **GSAP** is the default for 95% of motion work — covers timeline orchestration, transforms, easing, stagger. All atomic rules in this skill are GSAP-based.
51
- - **Lottie** when an asset has its own pre-baked timeline (typically After Effects exports).
55
+ - **Lottie** when an asset has its own pre-baked timeline (typically After Effects exports), including characters that walk, gesture or react.
52
56
  - **Three.js** for 3D scenes, camera motion, shader-driven visuals.
53
57
  - **Anime.js** for lightweight tweening when GSAP is overkill.
54
58
  - **CSS** for simple repeated motifs, decoration, shimmer — no JavaScript animation cost.
@@ -61,7 +61,7 @@ HyperFrames is stricter than vanilla GSAP. Animate only:
61
61
  - **Compositor-cheap**: `opacity`, `x`, `y`, `scale`, `scaleX`, `scaleY`, `rotation`, `rotationX`, `rotationY`, `skewX`, `skewY`, `transformOrigin`
62
62
  - **Visual fills**: `color`, `backgroundColor`, `borderColor`, `borderRadius`
63
63
  - **CSS variables**: `"--hue": 180` etc.
64
- - **Media `volume`** (on `<audio>` / `<video>`): animate for fades/ducking, e.g. `tl.to("#bgm", { volume: 0, duration: 1 }, "outro")`. The runtime probes these keyframes from the timeline and drives them in both preview and render (they match). This sets the _author_ volume; `data-volume` is the static baseline when no tween touches the element.
64
+ - **Media `volume`** (on `<audio>` / `<video>`): do not tween it for fades or ducking; use the `data-automation` volume lane (`creator-editing-recipes.md` in `hyperframes-core`). A lane wins over a tween on the same element.
65
65
  - **DOM text `innerText`** (for numeric counters): tween it directly, e.g. `tl.to(el, { innerText: 100, snap: { innerText: 1 } })` — `snap` keeps it integer; the GSAP inspector recognizes it as a counter. Equivalent to the `onUpdate`-proxy form in `../rules/counting-dynamic-scale.md`; prefer that proxy form for locale formatting (`toLocaleString`) or suffix logic, and pair it with a separate transform-scale tween when the number should grow.
66
66
 
67
67
  **Avoid** (use the transform alias instead):
@@ -11,7 +11,7 @@ HyperFrames can seek both `lottie-web` and dotLottie players through its `lottie
11
11
 
12
12
  - Load assets from local project files, usually under `assets/`.
13
13
  - Set `autoplay: false`.
14
- - Prefer `loop: false` unless the user explicitly wants a loop.
14
+ - Use `loop: false` for a one-shot and `loop: true` for a cycle (walk, idle, spinner). A looping animation is seeked to composition time modulo its own length, so it keeps cycling for the whole scene; a one-shot holds its last frame. Always set `loop`: lottie-web treats a missing `loop` as `true`. A numeric `loop` count does not repeat under seeking; bake the repeats into the file.
15
15
  - Register every returned animation or player on `window.__hfLottie`.
16
16
  - Keep the Lottie container dimensions stable with CSS.
17
17
 
@@ -84,12 +84,25 @@ HyperFrames seeks them all to the same composition time.
84
84
 
85
85
  ## Composition Duration
86
86
 
87
- The render engine needs the composition's total length. GSAP timelines report duration automatically; a Lottie-only composition has no timeline object, so the runtime reads the registered animation's native length directly — `totalFrames / frameRate` for `lottie-web`, or the player's own `duration` for dotLottie. `data-duration` on the root element is optional for Lottie compositions: as long as every animation is registered on `window.__hfLottie` (per the contract above), the runtime has a finite duration to work with even when you set `loop: true`.
87
+ The render engine needs the composition's total length. GSAP timelines report duration automatically; a Lottie-only composition has no timeline object, so the runtime reads the registered animation's native length directly — `totalFrames / frameRate` for `lottie-web`, or the player's own `duration` for dotLottie. `data-duration` on the root element is optional for Lottie compositions: as long as every animation is registered on `window.__hfLottie` (per the contract above), the runtime has a finite duration to work with. With `loop: true` that length is one cycle, so a looping Lottie in a longer scene needs `data-duration` or a GSAP timeline to set the scene length.
88
+
89
+ ## Characters
90
+
91
+ For a character that walks, gestures or reacts (a mascot, a walk cycle, a jointed puppet), put the acting in one Lottie and the stage in GSAP:
92
+
93
+ - **The Lottie owns the body.** Walk, stop, point and idle live in the file's own timeline, so limbs stay jointed and feet stay planted exactly as the animator made them.
94
+ - **GSAP owns everything around it.** Cards, captions and camera moves go on the paused timeline, timed to the Lottie's beats. Read the beat times from the file's `markers` array (`tm` is in frames, divide by `fr`) or from the animator's notes.
95
+ - **Every registered animation plays against composition time.** There is no per-animation start offset, so a gesture that should begin at 4 s must begin at 4 s inside its file. Author the whole performance as one Lottie, or offset the action inside the file, rather than stacking separate action files.
96
+ - **A short cycle is fine.** A 1 s walk cycle with `loop: true` cycles for the whole scene. Move the character across the stage with GSAP `x` only if the cycle walks in place, and match the travel speed to the stride or the feet slide.
97
+ - **License the character.** Use a file the user or their designer made, or one whose license allows redistribution, and say where it came from. Never ship a character ripped from a site.
98
+
99
+ The `lottie-character-walk` registry block is a working example: a jointed flat character walks in on planted feet, stops, and points at a card that GSAP brings in on the point (`npx hyperframes add lottie-character-walk`).
88
100
 
89
101
  ## Good Uses
90
102
 
91
103
  - After Effects exports that are already known to render correctly in lottie-web.
92
104
  - Logo reveals, icon loops, decorative accents, and product UI motion.
105
+ - Characters: walk cycles, mascots, gestures (see Characters above).
93
106
  - Translating Remotion Lottie usage into plain HyperFrames HTML.
94
107
 
95
108
  ## Avoid
@@ -87,6 +87,20 @@ For anything under `three/addons/`, use an importmap so bare specifiers resolve.
87
87
 
88
88
  Pin the `three` version in both entries to the same value. Mixing versions across the map and bare imports causes silent breakage.
89
89
 
90
+ ## Heavy Setup (Large Meshes, Shader Compiles)
91
+
92
+ The runtime already waits for textures/models queued through Three's `DefaultLoadingManager` before publishing render-ready. It has no visibility into CPU-bound work you do yourself after assets load — building a large procedural mesh, compiling shaders, warming a pipeline. That work can leave the canvas blank for seconds after the runtime and player already say "ready".
93
+
94
+ If your setup does this kind of work, register a promise on `window.__hf.buildReady` (declared-compute hold: runtime waits, player shows its loading state instead of a blank frame):
95
+
96
+ ```js
97
+ window.__hf = window.__hf || {};
98
+ window.__hf.buildReady = window.__hf.buildReady || {};
99
+ window.__hf.buildReady["<your-piece-name>"] = buildScene(); // resolves once the scene is actually drawable
100
+ ```
101
+
102
+ Register it synchronously, in the same script block that starts the build — same timing as `DefaultLoadingManager`, so the runtime's first readiness check already sees it. Only do this for setup an adapter cannot see; render-critical seeking still comes from `hf-seek`, not this hold. The key must be unique within the composition — a second registration under the same key silently replaces the first, dropping its hold.
103
+
90
104
  ## AnimationMixer Pattern
91
105
 
92
106
  For GLTF or authored clip animation, seek the mixer directly:
@@ -54,7 +54,7 @@ monochrome text-on-solid throughout.
54
54
 
55
55
  - gentle fade-in + subtle scale-up settle (Benefits Scene 2) → `rules/scale-swap-transition.md` (restrained in/settle; cross-reference the fade ease in `techniques.md`)
56
56
  - single slide-up crossfade between two centered lines (Benefits Scene 3) → `rules/discrete-text-sequence.md` (one line hands off to the next; translate-up + crossfade)
57
- - diagonal pill-wipe reveal (Social_Proof Scene 2) → `rules/techniques.md` (clip-path reveal masks — the wipe)
57
+ - diagonal pill-wipe reveal (Social_Proof Scene 2) → `../techniques.md` (clip-path reveal masks — the wipe)
58
58
  - icon stroke draw-on (Social_Proof Scene 2) → `rules/svg-path-draw.md`
59
59
  - "[N]+ teams" count-up (Social_Proof Scene 3, optional) → `rules/counting-dynamic-scale.md`
60
60
  - logo + tagline spring-settle-and-hold (Social_Proof Scene 3) → `rules/spring-pop-entrance.md` (single soft settle; intentionally one beat, not a chain)