dsh-hyperframes 0.3.1 → 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 +6 -5
  2. package/README.md +7 -6
  3. package/lib/index.d.ts +1 -1
  4. package/lib/index.js +1 -0
  5. package/package.json +63 -63
  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
@@ -1,91 +0,0 @@
1
- // Reuse candidates: a side-effect-free view of assets already available to this
2
- // project (its own manifest) and across every project (the global ~/.media
3
- // cache), so the calling agent can judge semantic fit itself. No download, no
4
- // provider, no mutation. The ranker only *surfaces* — it orders by lexical
5
- // overlap but never filters a candidate out on zero overlap (that would
6
- // pre-empt the agent's judgment); the agent does the semantic call.
7
-
8
- import { readManifest } from "./manifest.mjs";
9
- import { readGlobalManifest } from "./cache.mjs";
10
- import { tokenOverlap, typesMatch } from "./match.mjs";
11
-
12
- export const CANDIDATE_CAP = 8;
13
-
14
- function shape(record, scope, intent) {
15
- const description = record.description || record.provenance?.prompt || "";
16
- const prompt = record.provenance?.prompt || null;
17
- return {
18
- id: record.id,
19
- type: record.type,
20
- scope,
21
- description,
22
- prompt,
23
- provider: record.provenance?.provider || null,
24
- duration: record.duration ?? null,
25
- width: record.width ?? null,
26
- height: record.height ?? null,
27
- // Only global records carry a content sha — it is the stable reuse handle
28
- // for `resolve --reuse <sha>`. Project assets are reused by referencing
29
- // their path directly, so they need no handle.
30
- sha: scope === "global" ? record.sha || null : null,
31
- path: scope === "project" ? record.path : null,
32
- score: intent ? tokenOverlap(intent, `${description} ${prompt || ""}`) : 0,
33
- };
34
- }
35
-
36
- // Rank one scope: type-matched (icon<->image aware), newest-first within equal
37
- // overlap, ordered by overlap desc. Returns the full ranked list (uncapped).
38
- function rankScope(records, scope, type, intent) {
39
- return records
40
- .filter((r) => typesMatch(r.type, type))
41
- .reverse() // manifest is append-order (oldest first); newest-first at equal score
42
- .map((r) => shape(r, scope, intent))
43
- .sort((a, b) => b.score - a.score); // Array.sort is stable → recency preserved
44
- }
45
-
46
- // List reuse candidates for `type`, capped per scope. Returns:
47
- // candidates: capped project candidates followed by capped global candidates
48
- // truncated: true if either scope had more than `cap`
49
- // total: { project, global } counts before the cap (machine-readable)
50
- // similar: count of candidates with lexical overlap > 0 (drives the nudge)
51
- export function listCandidates({ projectDir, type, intent = "", cap = CANDIDATE_CAP }) {
52
- const project = rankScope(readManifest(projectDir), "project", type, intent);
53
- const global = rankScope(readGlobalManifest(), "global", type, intent);
54
- const candidates = [...project.slice(0, cap), ...global.slice(0, cap)];
55
- return {
56
- candidates,
57
- truncated: project.length > cap || global.length > cap,
58
- total: { project: project.length, global: global.length },
59
- similar: [...project, ...global].filter((c) => c.score > 0).length,
60
- };
61
- }
62
-
63
- function meta(c) {
64
- const parts = [];
65
- if (c.duration != null) parts.push(`${c.duration}s`);
66
- if (c.width && c.height) parts.push(`${c.width}x${c.height}`);
67
- if (c.provider) parts.push(c.provider);
68
- return parts.join(", ");
69
- }
70
-
71
- // Human-readable listing. The agent can read this directly; --json is for
72
- // programmatic use. Reuse handle differs by scope: path for project, sha for
73
- // global.
74
- export function formatCandidates(candidates, { truncated, total } = {}) {
75
- if (candidates.length === 0) return "no reuse candidates found (project or global cache)";
76
- const lines = [`${candidates.length} reuse candidate${candidates.length === 1 ? "" : "s"}:`, ""];
77
- for (const c of candidates) {
78
- const handle =
79
- c.scope === "global" ? `--reuse ${String(c.sha).slice(0, 16)}` : c.path || `manifest:${c.id}`;
80
- const m = meta(c);
81
- lines.push(` [${c.scope}] ${c.description}${m ? ` (${m})` : ""}`);
82
- lines.push(` ${handle}`);
83
- }
84
- if (truncated && total) {
85
- lines.push("");
86
- lines.push(
87
- ` (showing top ${CANDIDATE_CAP} per scope; ${total.project} project / ${total.global} global total — refine --intent to narrow)`,
88
- );
89
- }
90
- return lines.join("\n");
91
- }
@@ -1,155 +0,0 @@
1
- import { test } from "node:test";
2
- import { strict as assert } from "node:assert";
3
- import { mkdtempSync, rmSync, mkdirSync, writeFileSync } from "node:fs";
4
- import { join } from "node:path";
5
- import { tmpdir } from "node:os";
6
- import { listCandidates, formatCandidates, CANDIDATE_CAP } from "./candidates.mjs";
7
- import { findGlobalBySha } from "./cache.mjs";
8
-
9
- // candidates + findGlobalBySha are offline (no heygen), so we can override HOME
10
- // to a temp dir and seed a fake global ~/.media manifest deterministically.
11
- function sandbox() {
12
- const root = mkdtempSync(join(tmpdir(), "mu-cand-"));
13
- const project = join(root, "proj");
14
- const home = join(root, "home");
15
- process.env.HOME = home;
16
- return { root, project, home };
17
- }
18
- function seedManifest(dir, records) {
19
- const md = join(dir, ".media");
20
- mkdirSync(md, { recursive: true });
21
- writeFileSync(md + "/manifest.jsonl", records.map((r) => JSON.stringify(r)).join("\n") + "\n");
22
- }
23
- function proj(id, type, description, prompt) {
24
- return { id, type, path: `.media/audio/bgm/${id}.wav`, description, provenance: { prompt } };
25
- }
26
- function glob(id, type, description, prompt, sha) {
27
- return {
28
- id,
29
- type,
30
- sha,
31
- reusable: true,
32
- cached_path: `/x/${sha}/${id}.wav`,
33
- description,
34
- provenance: { prompt, provider: "heygen.audio.sounds" },
35
- };
36
- }
37
-
38
- test("ranks project + global by overlap, tags scope", () => {
39
- const { root, project, home } = sandbox();
40
- try {
41
- seedManifest(project, [proj("bgm_001", "bgm", "calm ambient piano", "calm ambient piano")]);
42
- seedManifest(home, [
43
- glob("bgm_009", "bgm", "energetic tech launch", "energetic tech launch", "a".repeat(64)),
44
- glob("bgm_010", "bgm", "sad corporate piano", "sad corporate piano", "b".repeat(64)),
45
- ]);
46
- const { candidates } = listCandidates({
47
- projectDir: project,
48
- type: "bgm",
49
- intent: "tech launch",
50
- });
51
- assert.equal(candidates[0].scope, "project"); // project listed first
52
- const g = candidates.filter((c) => c.scope === "global");
53
- assert.equal(g[0].description, "energetic tech launch"); // higher overlap ranks first
54
- assert.ok(g[0].score >= g[1].score);
55
- } finally {
56
- rmSync(root, { recursive: true, force: true });
57
- }
58
- });
59
-
60
- test("zero-overlap intent still lists candidates (no hard filter)", () => {
61
- const { root, project, home } = sandbox();
62
- try {
63
- seedManifest(project, []);
64
- seedManifest(home, [glob("bgm_009", "bgm", "driving synth", "driving synth", "c".repeat(64))]);
65
- const { candidates, similar } = listCandidates({
66
- projectDir: project,
67
- type: "bgm",
68
- intent: "totally unrelated words xyz",
69
- });
70
- assert.equal(candidates.length, 1, "listed despite zero overlap");
71
- assert.equal(candidates[0].score, 0);
72
- assert.equal(similar, 0, "similar counts only overlap>0");
73
- } finally {
74
- rmSync(root, { recursive: true, force: true });
75
- }
76
- });
77
-
78
- test("caps per scope and reports truncation + totals", () => {
79
- const { root, project, home } = sandbox();
80
- try {
81
- const many = Array.from({ length: CANDIDATE_CAP + 3 }, (_, i) =>
82
- glob(`bgm_${i}`, "bgm", `track ${i}`, `track ${i}`, String(i).padStart(64, "0")),
83
- );
84
- seedManifest(project, []);
85
- seedManifest(home, many);
86
- const { candidates, truncated, total } = listCandidates({ projectDir: project, type: "bgm" });
87
- assert.equal(candidates.length, CANDIDATE_CAP);
88
- assert.equal(truncated, true);
89
- assert.equal(total.global, CANDIDATE_CAP + 3);
90
- } finally {
91
- rmSync(root, { recursive: true, force: true });
92
- }
93
- });
94
-
95
- test("honors icon<->image adjacency", () => {
96
- const { root, project, home } = sandbox();
97
- try {
98
- seedManifest(project, []);
99
- seedManifest(home, [glob("image_1", "image", "rocket logo", "rocket logo", "d".repeat(64))]);
100
- const { candidates } = listCandidates({ projectDir: project, type: "icon", intent: "rocket" });
101
- assert.equal(candidates.length, 1, "image asset surfaces for icon request");
102
- } finally {
103
- rmSync(root, { recursive: true, force: true });
104
- }
105
- });
106
-
107
- test("sha only on global, path only on project", () => {
108
- const { root, project, home } = sandbox();
109
- try {
110
- seedManifest(project, [proj("bgm_001", "bgm", "x", "x")]);
111
- seedManifest(home, [glob("bgm_009", "bgm", "y", "y", "e".repeat(64))]);
112
- const { candidates } = listCandidates({ projectDir: project, type: "bgm" });
113
- const p = candidates.find((c) => c.scope === "project");
114
- const g = candidates.find((c) => c.scope === "global");
115
- assert.ok(p.path && !p.sha);
116
- assert.ok(g.sha && !g.path);
117
- } finally {
118
- rmSync(root, { recursive: true, force: true });
119
- }
120
- });
121
-
122
- test("findGlobalBySha resolves unique prefix, flags ambiguity, misses cleanly", () => {
123
- const { root, project, home } = sandbox();
124
- try {
125
- seedManifest(project, []);
126
- seedManifest(home, [
127
- glob("bgm_1", "bgm", "a", "a", "abc" + "0".repeat(61)),
128
- glob("bgm_2", "bgm", "b", "b", "abd" + "0".repeat(61)),
129
- glob("bgm_3", "bgm", "c", "c", "fff" + "0".repeat(61)),
130
- ]);
131
- assert.equal(findGlobalBySha("fff").id, "bgm_3", "unique prefix resolves");
132
- assert.deepEqual(
133
- { ambiguous: findGlobalBySha("ab").ambiguous, count: findGlobalBySha("ab").count },
134
- { ambiguous: true, count: 2 },
135
- "ambiguous prefix flagged",
136
- );
137
- assert.equal(findGlobalBySha("zzz"), null, "miss returns null");
138
- assert.equal(findGlobalBySha(""), null, "empty returns null");
139
- } finally {
140
- rmSync(root, { recursive: true, force: true });
141
- }
142
- });
143
-
144
- test("formatCandidates shows reuse handles by scope; empty message", () => {
145
- const { candidates } = {
146
- candidates: [
147
- { scope: "project", description: "p", path: ".media/audio/bgm/bgm_001.wav" },
148
- { scope: "global", description: "g", sha: "f".repeat(64) },
149
- ],
150
- };
151
- const out = formatCandidates(candidates, {});
152
- assert.match(out, /\.media\/audio\/bgm\/bgm_001\.wav/);
153
- assert.match(out, /--reuse ffffffffffffffff/);
154
- assert.match(formatCandidates([], {}), /no reuse candidates/);
155
- });
@@ -1,161 +0,0 @@
1
- import { execFileSync } from "node:child_process";
2
- import { copyFileSync, existsSync, readdirSync, statSync, unlinkSync } from "node:fs";
3
- import { homedir, tmpdir } from "node:os";
4
- import { join } from "node:path";
5
-
6
- // Image generation via the OpenAI Codex CLI's built-in image tool (gpt-image-2)
7
- // on the user's ChatGPT subscription: the codex CLI owns auth, media-use holds
8
- // no key (CLI-only). The image UPSELL behind local mflux; skipped by --local-only.
9
- //
10
- // Retrieval mirrors illo-skill rather than trusting the model to save a file:
11
- // `--enable image_generation` makes the built-in tool drop the rendered artifact
12
- // into $CODEX_HOME/generated_images/, and we fetch the freshest file that
13
- // postdates this run. The save-to-path instruction is only a best-effort
14
- // verify-first.
15
- //
16
- // The flag was called `imagegenext` until Codex CLI ~0.145, which renamed it to
17
- // `image_generation` and dropped the old row from `codex features list`. Both
18
- // the gate below and the --enable arg track the new name, with a fallback to
19
- // the old one so older CLIs keep working.
20
-
21
- const TIMEOUT_MS = 600000; // codex exec round-trips the sub; first-run tool spin-up is slow
22
- const MTIME_SKEW_MS = 2000; // tolerate mtime granularity / clock skew (illo uses 2s)
23
-
24
- function codexGeneratedDir() {
25
- // Codex relocates CODEX_HOME on some hosts, so resolve it at run time.
26
- return join(process.env.CODEX_HOME || join(homedir(), ".codex"), "generated_images");
27
- }
28
-
29
- // Newest artifact that postdates `sinceMs` (minus skew), so a stale prior render
30
- // or a concurrent session's file can't be mistaken for this run's output.
31
- function freshestGeneratedImage(sinceMs) {
32
- const dir = codexGeneratedDir();
33
- if (!existsSync(dir)) return null;
34
- const floor = sinceMs - MTIME_SKEW_MS;
35
- let best = null;
36
- for (const name of readdirSync(dir)) {
37
- let st;
38
- try {
39
- st = statSync(join(dir, name));
40
- } catch {
41
- continue;
42
- }
43
- if (!st.isFile() || st.mtimeMs < floor) continue;
44
- if (!best || st.mtimeMs > best.mtimeMs) best = { path: join(dir, name), mtimeMs: st.mtimeMs };
45
- }
46
- return best?.path ?? null;
47
- }
48
-
49
- // Short `codex` subcommand → combined stdout+stderr, or null if it can't run.
50
- function codexRun(args) {
51
- try {
52
- return execFileSync("codex", args, {
53
- encoding: "utf8",
54
- stdio: ["ignore", "pipe", "pipe"],
55
- timeout: 10000,
56
- });
57
- } catch (err) {
58
- return `${err.stdout?.toString() ?? ""}${err.stderr?.toString() ?? ""}` || null;
59
- }
60
- }
61
-
62
- // Name of the feature flag this CLI uses for the extended image tool, or null if
63
- // it exposes neither. Newer CLIs list only `image_generation`; older ones list
64
- // `imagegenext` alongside it and reject the new name on --enable.
65
- export function imageGenFlag(feats) {
66
- if (/\bimagegenext\b/.test(feats)) return "imagegenext";
67
- if (/\bimage_generation\b/.test(feats)) return "image_generation";
68
- return null;
69
- }
70
-
71
- // Fail-fast host check (mirrors illo): don't burn a minutes-long exec when Codex
72
- // isn't usable. Returns { flag } when ready, else { reason }. The flag ships
73
- // default-disabled, so we check the ROW is present (the capability signal) — the
74
- // exec enables it per-render with --enable.
75
- function codexUnavailableReason() {
76
- try {
77
- const which = process.platform === "win32" ? "where" : "which";
78
- execFileSync(which, ["codex"], { stdio: ["ignore", "ignore", "ignore"], timeout: 5000 });
79
- } catch {
80
- // A shell alias (e.g. `codex → /Applications/Codex.app/...`) is NOT enough:
81
- // aliases live only in the interactive shell, so a spawned subprocess's PATH
82
- // lookup can't see them. Symlink the real binary onto PATH.
83
- return {
84
- reason:
85
- 'codex CLI not reachable on PATH (a shell alias won\'t work — spawned processes can\'t see aliases; symlink the real binary onto PATH, e.g. ln -s "$(readlink -f "$(command -v codex)")" ~/.local/bin/codex)',
86
- };
87
- }
88
- // Auth marker: presence of the credentials file, NOT `codex login status`.
89
- // That command prints "Logged in using ChatGPT" only to a human stream
90
- // (stderr / TTY) and exits 0, so its piped stdout — how media-use spawns it —
91
- // is empty, and the gate falsely reported "not logged in", blocking codex
92
- // image gen in every headless / CI / agent run even when fully authed.
93
- // auth.json is the durable, TTY-independent signal; token validity is proven
94
- // by the exec itself, which fails cleanly if the login is stale.
95
- const authPath = join(process.env.CODEX_HOME || join(homedir(), ".codex"), "auth.json");
96
- if (!existsSync(authPath)) return { reason: "codex not logged in (run: codex login)" };
97
- const feats = codexRun(["features", "list"]);
98
- if (feats == null) return { reason: "could not read `codex features list`" };
99
- const flag = imageGenFlag(feats);
100
- if (!flag) return { reason: "codex image generation feature unavailable (upgrade Codex CLI)" };
101
- return { flag };
102
- }
103
-
104
- export async function codexImageGenerate(intent) {
105
- const { reason, flag } = codexUnavailableReason();
106
- if (reason) {
107
- console.error(`media-use: codex image upsell unavailable: ${reason}`);
108
- return null;
109
- }
110
- const outPath = join(tmpdir(), `media-use-codex-${process.pid}-${Date.now()}.png`);
111
- const prompt =
112
- `${intent}\n\n` +
113
- `Use your built-in image generation tool to render this, then save the image ` +
114
- `to ${outPath} (overwrite if it exists). Do not ask for confirmation. ` +
115
- `If you have no built-in image tool, do nothing (no PIL/matplotlib/SVG substitute).`;
116
- try {
117
- unlinkSync(outPath); // clear any prior file so verify-first can't accept a stale render
118
- } catch {
119
- /* no prior file */
120
- }
121
- const started = Date.now();
122
- try {
123
- execFileSync(
124
- "codex",
125
- [
126
- "exec",
127
- "--cd",
128
- tmpdir(),
129
- "-s",
130
- "workspace-write",
131
- "--skip-git-repo-check",
132
- "--enable",
133
- flag,
134
- "-",
135
- ],
136
- { input: prompt, encoding: "utf8", timeout: TIMEOUT_MS, stdio: ["pipe", "pipe", "pipe"] },
137
- );
138
- } catch (err) {
139
- console.error(
140
- `media-use: \`codex exec\` image generation failed: ${err.stderr?.toString().trim().slice(-200) || err.message}`,
141
- );
142
- return null;
143
- }
144
- // Verify-first (save-to-path may have worked), else fetch the image-tool artifact.
145
- const produced =
146
- existsSync(outPath) && statSync(outPath).size > 0 ? outPath : freshestGeneratedImage(started);
147
- if (!produced) return null;
148
- if (produced !== outPath) {
149
- try {
150
- copyFileSync(produced, outPath);
151
- } catch {
152
- return null;
153
- }
154
- }
155
- return {
156
- localPath: outPath,
157
- ext: ".png",
158
- source: "generated",
159
- metadata: { description: intent, provider: "codex.image_gen", provenance: { prompt: intent } },
160
- };
161
- }
@@ -1,34 +0,0 @@
1
- import test from "node:test";
2
- import assert from "node:assert";
3
- import { imageGenFlag } from "./codex-provider.mjs";
4
-
5
- // Real `codex features list` output is three space-padded columns:
6
- // <name> <stage> <enabled>
7
- const OLD_CLI = [
8
- "image_detail_original removed false",
9
- "image_generation stable true",
10
- "imagegenext under development false",
11
- ].join("\n");
12
-
13
- const NEW_CLI = [
14
- "image_detail_original removed false",
15
- "image_generation stable true",
16
- ].join("\n");
17
-
18
- test("older CLIs keep the old flag — they reject --enable image_generation", () => {
19
- assert.equal(imageGenFlag(OLD_CLI), "imagegenext");
20
- });
21
-
22
- test("Codex CLI >=0.145 dropped the imagegenext row; fall back to its new name", () => {
23
- // The regression this guards: gating on `imagegenext` alone made the provider
24
- // report "unavailable" on every up-to-date CLI, without attempting a render.
25
- assert.equal(imageGenFlag(NEW_CLI), "image_generation");
26
- });
27
-
28
- test("no image feature at all is unavailable, not a silent default", () => {
29
- assert.equal(imageGenFlag("apps stable true\nhooks stable true"), null);
30
- });
31
-
32
- test("substring lookalikes do not count as the feature row", () => {
33
- assert.equal(imageGenFlag("image_generation_v2 stable true"), null);
34
- });
@@ -1,117 +0,0 @@
1
- import { strict as assert } from "node:assert";
2
- import { test } from "node:test";
3
- import { existsSync } from "node:fs";
4
- import { join, dirname } from "node:path";
5
- import { fileURLToPath } from "node:url";
6
- import { listTypes, getProviders } from "./registry.mjs";
7
- import { CAPABILITIES, listModels } from "./local-models.mjs";
8
-
9
- // Capstone: media-use must actually OWN each hyperframes media weakness. This
10
- // test enforces the weakness→owner matrix in references/meta.md so a claim can't rot — if
11
- // a capability's entrypoint disappears, this fails.
12
-
13
- const SKILL = join(dirname(fileURLToPath(import.meta.url)), "..", "..");
14
-
15
- test("weakness: audio-only → media-use resolves image + icon", () => {
16
- for (const t of ["image", "icon"]) {
17
- assert.ok(getProviders(t).length > 0, `no provider for ${t}`);
18
- }
19
- });
20
-
21
- test("weakness: no third-party brand logos → media-use resolves logo", () => {
22
- assert.ok(listTypes().includes("logo"), "logo type missing");
23
- assert.ok(getProviders("logo").length >= 4, "logo cascade incomplete");
24
- });
25
-
26
- test("weakness: no voice/audio gen → media-use exposes voice + the audio engine", () => {
27
- assert.ok(listTypes().includes("voice"), "voice type missing");
28
- assert.ok(getProviders("voice").length > 0, "no enabled voice provider (Bin approved)");
29
- assert.ok(existsSync(join(SKILL, "audio", "scripts", "audio.mjs")), "audio engine missing");
30
- });
31
-
32
- test("weakness: scattered audio engine → consolidated under media-use (hyperframes-media gone)", () => {
33
- assert.ok(existsSync(join(SKILL, "audio", "scripts", "lib", "tts.mjs")), "tts engine missing");
34
- assert.ok(
35
- existsSync(join(SKILL, "audio", "assets", "sfx", "manifest.json")),
36
- "bundled SFX missing",
37
- );
38
- });
39
-
40
- test("weakness: no media-ops → ops guidance reference exists", () => {
41
- assert.ok(existsSync(join(SKILL, "references", "operations.md")), "operations.md missing");
42
- });
43
-
44
- test("weakness: no transcript-driven cutting → cut compiler entrypoints exist", async () => {
45
- assert.ok(existsSync(join(SKILL, "scripts", "transcript-cut.mjs")), "transcript-cut missing");
46
- assert.ok(existsSync(join(SKILL, "scripts", "lib", "cutlist.mjs")), "cutlist lib missing");
47
- const cutlist = await import("./cutlist.mjs");
48
- assert.equal(typeof cutlist.compileCutList, "function");
49
- });
50
-
51
- test("weakness: whisper.cpp is weak → better local ASR (Parakeet) entrypoint exists", async () => {
52
- assert.ok(existsSync(join(SKILL, "scripts", "transcribe.mjs")), "transcribe.mjs missing");
53
- const pw = await import("./parakeet-words.mjs");
54
- assert.equal(typeof pw.mergeTokensToWords, "function", "token->word merge missing");
55
- const lm = await import("./local-models.mjs");
56
- const asr = lm.listModels("asr");
57
- const parakeet = asr.find((m) => m.id === "parakeet-mlx");
58
- assert.ok(parakeet && parakeet.rank === 0, "Parakeet must be the rank-0 preferred ASR");
59
- });
60
-
61
- test("weakness: no auto-duck/loudness → duck compiler and recipes exist", async () => {
62
- assert.ok(existsSync(join(SKILL, "scripts", "audio-duck.mjs")), "audio-duck missing");
63
- assert.ok(existsSync(join(SKILL, "scripts", "lib", "duck.mjs")), "duck lib missing");
64
- assert.ok(existsSync(join(SKILL, "references", "operations.md")), "operations.md missing");
65
- const duck = await import("./duck.mjs");
66
- assert.equal(typeof duck.speechSpans, "function");
67
- assert.equal(typeof duck.duckKeyframes, "function");
68
- });
69
-
70
- test("weakness: no cross-project memory → global cache + ingest entrypoints exist", async () => {
71
- const cache = await import("./cache.mjs");
72
- assert.equal(typeof cache.cachePut, "function");
73
- assert.equal(typeof cache.promote, "function");
74
- assert.equal(typeof cache.globalMediaDir, "function");
75
- const freeze = await import("./freeze.mjs");
76
- assert.equal(typeof freeze.isDirectMediaUrl, "function", "ingest URL guard missing");
77
- });
78
-
79
- // Wenbo (06-29): heygen free-usage is the default; local models are the opt-out
80
- // fallback ("if user no, then local"). We still assert the fallback table is
81
- // populated so the opt-out path stays real.
82
- test("weakness: weak local defaults → local models exist as the opt-out fallback (tts/asr/upscale)", () => {
83
- for (const cap of ["tts", "asr", "upscale"]) {
84
- assert.ok(CAPABILITIES.includes(cap), `capability ${cap} missing`);
85
- assert.ok(listModels(cap).length > 0, `no local models for ${cap}`);
86
- }
87
- });
88
-
89
- test("weakness: no image generation → local mflux (RAM-graded) + codex upsell", async () => {
90
- const ps = getProviders("image");
91
- assert.ok(
92
- ps.some((p) => p.name === "mflux.local" && typeof p.generate === "function"),
93
- "local image gen missing",
94
- );
95
- assert.ok(
96
- ps.some((p) => p.name === "codex.image_gen" && typeof p.generate === "function"),
97
- "codex image upsell missing",
98
- );
99
- const lm = await import("./local-models.mjs");
100
- assert.ok(lm.CAPABILITIES.includes("imagegen"), "imagegen capability missing");
101
- assert.ok(lm.listModels("imagegen").length >= 3, "imagegen RAM ladder too small");
102
- assert.equal(typeof lm.describeModelLadder, "function", "agent-facing ladder missing");
103
- });
104
-
105
- test("weakness: no video generation → local videogen ladder + heygen avatar upsell", async () => {
106
- const lm = await import("./local-models.mjs");
107
- assert.ok(lm.CAPABILITIES.includes("videogen"), "videogen capability missing");
108
- assert.ok(lm.listModels("videogen").length >= 2, "videogen ladder too small");
109
- const ops = existsSync(join(SKILL, "references", "operations.md"));
110
- assert.ok(ops, "operations.md (avatar-upsell recipe) missing");
111
- });
112
-
113
- test("every resolve type has at least one enabled provider", () => {
114
- for (const t of listTypes()) {
115
- assert.ok(getProviders(t).length > 0, `type ${t} has no enabled provider`);
116
- }
117
- });