hyperframes 0.8.183 → 0.8.185

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 (314) hide show
  1. package/dist/{add-HW3ZGR36.js → add-ODTNPRGG.js} +14 -14
  2. package/dist/{agentPromptGenerator-VIIPZCJ3.js → agentPromptGenerator-KYO5MKTW.js} +1 -1
  3. package/dist/{animatedGifPrep-EPLN37ZN.js → animatedGifPrep-PEP5GWOJ.js} +10 -9
  4. package/dist/api.js +18 -17
  5. package/dist/{asset-TOASKL3Z.js → asset-EZG42XPA.js} +2 -2
  6. package/dist/{assetCataloger-PZN5HYG2.js → assetCataloger-OHAJFCA7.js} +10 -9
  7. package/dist/{audio-F5OIQVJO.js → audio-65R4T74I.js} +18 -16
  8. package/dist/{auth-YVQLRS3T.js → auth-VP2SIZFN.js} +1 -1
  9. package/dist/{autoUpdate-EG4ZFW4D.js → autoUpdate-RVSUX4SS.js} +2 -2
  10. package/dist/{backgroundChecks-WINNQVR2.js → backgroundChecks-LEHK74NS.js} +3 -3
  11. package/dist/backgroundChecksWorker.js +3 -3
  12. package/dist/{batchRender-PASZTMEE.js → batchRender-3X6CL7PK.js} +5 -5
  13. package/dist/{beats-KGIOEBLW.js → beats-66VPQLSC.js} +6 -6
  14. package/dist/{benchmark-ZNY2L7HN.js → benchmark-PBJVTOJP.js} +10 -10
  15. package/dist/{browser-REAO7RU4.js → browser-TPL5MWGC.js} +3 -3
  16. package/dist/{bundleWithLocalizedFonts-OAYLYC4W.js → bundleWithLocalizedFonts-67MLTHKM.js} +2 -2
  17. package/dist/{capture-WOSF276U.js → capture-F3GNMRZM.js} +14 -13
  18. package/dist/{capture-IK6GWQDD.js → capture-YYRE7EV3.js} +2 -2
  19. package/dist/{captureCompositionFrame-DDZNKYRE.js → captureCompositionFrame-PXV2ISHD.js} +14 -13
  20. package/dist/{catalog-AKTXS7OJ.js → catalog-6SDD3OHF.js} +14 -14
  21. package/dist/{catch-up-O3VZMPVE.js → catch-up-CWIVA5VG.js} +4 -4
  22. package/dist/{check-6E46NIWI.js → check-YQ6REK2S.js} +35 -34
  23. package/dist/{checkBrowser-UNZHQFNH.js → checkBrowser-5XZCBRXM.js} +32 -31
  24. package/dist/{chunk-TOHA5NAU.js → chunk-2TAS5O4P.js} +56 -11
  25. package/dist/{chunk-3Q47QC46.js → chunk-37CNYTQQ.js} +2 -2
  26. package/dist/chunk-3NPOFC43.js +3805 -0
  27. package/dist/{chunk-EEP5Y5IE.js → chunk-46HEFGXJ.js} +1 -1
  28. package/dist/{chunk-GAGMLVCV.js → chunk-4CTNDBE3.js} +2 -2
  29. package/dist/{chunk-CGK4XZ2J.js → chunk-55YELV7B.js} +1 -1
  30. package/dist/{chunk-TJB4GAV6.js → chunk-5GUKZRQN.js} +1 -1
  31. package/dist/{chunk-J4L5TPLS.js → chunk-5UDRPPN2.js} +48 -6
  32. package/dist/{chunk-SAQYJLI6.js → chunk-6ASIXMFP.js} +1 -1
  33. package/dist/{chunk-GPE3WWTO.js → chunk-6GPR3G3C.js} +14 -11
  34. package/dist/{chunk-MIZDJVPZ.js → chunk-6RIZY7OP.js} +1 -1
  35. package/dist/{chunk-5CS4T6C6.js → chunk-7L37AB57.js} +1 -1
  36. package/dist/{chunk-VH5KESLX.js → chunk-7PS6RVWD.js} +1 -1
  37. package/dist/{chunk-U5YVWG5W.js → chunk-7RAY4WZP.js} +3 -3
  38. package/dist/{chunk-COTLNID2.js → chunk-A6QCO474.js} +5 -5
  39. package/dist/{chunk-YMS5FOMC.js → chunk-B2A56S5C.js} +1 -1
  40. package/dist/{chunk-4FQKS7BJ.js → chunk-BH7TTIPN.js} +11 -13
  41. package/dist/{chunk-LBWRQ4XA.js → chunk-BRAPBUPQ.js} +1 -1
  42. package/dist/{chunk-IC2WYONA.js → chunk-CX3USX23.js} +3 -3
  43. package/dist/{chunk-ITSLKUQM.js → chunk-D42NU3DZ.js} +1 -1
  44. package/dist/{chunk-Q6UYKWBG.js → chunk-EMAWIZ54.js} +481 -36
  45. package/dist/{chunk-ZFO3A3QL.js → chunk-EMSDWBG3.js} +2 -2
  46. package/dist/{chunk-KRFAX5JK.js → chunk-ESBMUZXZ.js} +1 -1
  47. package/dist/{chunk-CAHTO62O.js → chunk-F3OPUWQX.js} +7 -7
  48. package/dist/{chunk-R6OV4J4K.js → chunk-FX6RUJUY.js} +3 -3
  49. package/dist/{chunk-F6WHPHLF.js → chunk-G2UANIDX.js} +1 -1
  50. package/dist/{chunk-DEORFAWP.js → chunk-H5SM5PJI.js} +1 -1
  51. package/dist/{chunk-5OGDBU4G.js → chunk-H6UY725W.js} +2 -2
  52. package/dist/{chunk-K2Z5DZBS.js → chunk-HDIRZGK4.js} +1 -1
  53. package/dist/{chunk-TXGZZKDF.js → chunk-HHSJJFVM.js} +2 -2
  54. package/dist/{chunk-VDJO4DJ7.js → chunk-HXUTX5GR.js} +3 -3
  55. package/dist/{chunk-73LTCCZI.js → chunk-I3IH5MV5.js} +19 -23
  56. package/dist/{chunk-3OLIGYWN.js → chunk-I45HL3VP.js} +3 -3
  57. package/dist/{chunk-TYXH3EKP.js → chunk-I5JRXMCV.js} +16 -1
  58. package/dist/{chunk-RZXUQR42.js → chunk-I7QMXZSB.js} +2 -2
  59. package/dist/{chunk-XOVHO3TT.js → chunk-IDFNKFPL.js} +7 -7
  60. package/dist/{chunk-QX4GGPMY.js → chunk-IDGLGXPA.js} +1 -1
  61. package/dist/{chunk-5MBLWFLM.js → chunk-IPDKZ5IN.js} +33 -6
  62. package/dist/{chunk-ANR6WOC3.js → chunk-ISTRDGIX.js} +1 -1
  63. package/dist/{chunk-4UFJWRHG.js → chunk-IVEFOUZI.js} +211 -83
  64. package/dist/chunk-IZCW2NKT.js +29 -0
  65. package/dist/{chunk-X3IA5RYH.js → chunk-J36JVBLR.js} +9 -2
  66. package/dist/{chunk-Z4R35NJS.js → chunk-J5XEZ24I.js} +3 -3
  67. package/dist/{chunk-OH56PXFH.js → chunk-K2ZKXTVL.js} +1 -1
  68. package/dist/{chunk-ATMDOUNN.js → chunk-K73RJB23.js} +2 -2
  69. package/dist/{chunk-NZ3BE2QE.js → chunk-KQ4JEJLF.js} +10 -10
  70. package/dist/{chunk-VFBAKPRC.js → chunk-KROXPHXX.js} +9 -3
  71. package/dist/{chunk-QGOYNPQT.js → chunk-LLFQA7XF.js} +48 -5
  72. package/dist/chunk-LLMSX6V6.js +17 -0
  73. package/dist/{chunk-XR5BSEUF.js → chunk-LYKSTRAY.js} +3 -3
  74. package/dist/{chunk-UNOSCGBG.js → chunk-OAG47RE6.js} +1 -1
  75. package/dist/{chunk-O7N3A7PE.js → chunk-PHMBMOXF.js} +1 -1
  76. package/dist/{chunk-BP4VNTZL.js → chunk-PMMQRJDE.js} +1 -1
  77. package/dist/{chunk-ADDHW2FS.js → chunk-Q447CX26.js} +82 -12
  78. package/dist/{chunk-WT4PYV2J.js → chunk-Q47FAYYK.js} +202 -55
  79. package/dist/{chunk-AKFADCMS.js → chunk-RTBSA3EA.js} +1 -1
  80. package/dist/{chunk-VAK7A2N6.js → chunk-RUEGYANA.js} +11 -11
  81. package/dist/{chunk-OYLO6TYK.js → chunk-RUOG4VB7.js} +1 -1
  82. package/dist/{chunk-EVAQPW6O.js → chunk-SKYPMHQC.js} +4 -4
  83. package/dist/{chunk-B2SZZFWW.js → chunk-SQVRXHOW.js} +3 -3
  84. package/dist/{chunk-CJYAJ3QM.js → chunk-TAX2ZJAP.js} +24 -16
  85. package/dist/{chunk-GTE5WZAM.js → chunk-TOI35GN2.js} +1 -1
  86. package/dist/{chunk-XJHKJXT4.js → chunk-UPR3MU6Z.js} +1 -1
  87. package/dist/{chunk-DLC2FICN.js → chunk-WQLKDL35.js} +2 -1
  88. package/dist/{chunk-3BA2GP4H.js → chunk-X6L6MD5B.js} +5 -5
  89. package/dist/{chunk-XAQDR5Y5.js → chunk-XGHHVYC7.js} +94 -32
  90. package/dist/{chunk-HLBODNGW.js → chunk-XWC7CNPY.js} +1 -1
  91. package/dist/{clean-WNEIVBF3.js → clean-7J6ZCCGV.js} +19 -18
  92. package/dist/cli.js +53 -53
  93. package/dist/{cloud-6GSSDCJL.js → cloud-7IJCJCDD.js} +4 -4
  94. package/dist/{cloudrun-4NEJRE4T.js → cloudrun-UNZRIIDB.js} +7 -7
  95. package/dist/commands/contrast-audit.browser.js +1 -2
  96. package/dist/commands/layout-audit.browser.js +196 -0
  97. package/dist/{compare-2JWQ5ABA.js → compare-Q7VW5JZT.js} +29 -28
  98. package/dist/{compiler-27KQD7KW.js → compiler-KPHYGFXL.js} +6 -6
  99. package/dist/{component-HCRET3MH.js → component-UUBREJKN.js} +3 -3
  100. package/dist/{compositions-HTSQ6SUJ.js → compositions-T4FTKIDP.js} +14 -13
  101. package/dist/{delete-GHQ5UYM7.js → delete-WZQF2IIA.js} +3 -3
  102. package/dist/{deploy-I3Z3NAVA.js → deploy-JU7A3XNC.js} +1 -1
  103. package/dist/{deterministicFonts-JFLSSKRB.js → deterministicFonts-EGAAE7QL.js} +3 -3
  104. package/dist/{dist-SENYPQGW.js → dist-LM7AVHOU.js} +3 -3
  105. package/dist/{dist-WRDLWRMS.js → dist-ULGTPSU4.js} +8 -4
  106. package/dist/docs/data-attributes.md +1 -1
  107. package/dist/{doctor-UGFVQZHI.js → doctor-VSNGRKXJ.js} +14 -13
  108. package/dist/{events-YS4OVX3I.js → events-CRW2DYUT.js} +3 -3
  109. package/dist/{events-BLJGWMNP.js → events-E63YBUL2.js} +3 -3
  110. package/dist/{feedback-AZ3SJ5HF.js → feedback-OSZWVR6N.js} +9 -9
  111. package/dist/{ffmpeg-2AECXG7V.js → ffmpeg-JLH3Z7G7.js} +10 -9
  112. package/dist/{figma-DRYIJQHV.js → figma-2BQNNR53.js} +3 -3
  113. package/dist/fontLocalizeCli.js +13 -12
  114. package/dist/{get-DDEAOFPB.js → get-P2XI53QW.js} +3 -3
  115. package/dist/{gpuPolicy-UDJT2MQK.js → gpuPolicy-NTKQJY75.js} +10 -9
  116. package/dist/{grade-compare-LJKK5NSY.js → grade-compare-OYASIHIB.js} +30 -29
  117. package/dist/{gsapParserAcorn-7NCK2LVT.js → gsapParserAcorn-SKODXC2N.js} +2 -2
  118. package/dist/{help-TQBGYOID.js → help-HK6K2N4G.js} +1 -1
  119. package/dist/{history-5TOOCF2Y.js → history-JMTYKLXW.js} +6 -6
  120. package/dist/hyperframe.manifest.json +1 -1
  121. package/dist/hyperframe.runtime.iife.js +65 -65
  122. package/dist/hyperframes-player.global.js +1 -1
  123. package/dist/{info-ENI5MP4W.js → info-AW7CIVRE.js} +9 -9
  124. package/dist/{init-JXPXWV3G.js → init-6KIDG4LB.js} +31 -30
  125. package/dist/{inspect-WZNYQ5AB.js → inspect-B7BLYMRZ.js} +30 -29
  126. package/dist/{installer-3SGRBLJW.js → installer-ZP2LQZUQ.js} +7 -7
  127. package/dist/{keyframes-HEOC4CT4.js → keyframes-EQ36A5JE.js} +7 -7
  128. package/dist/{lambda-2VHQ4AL2.js → lambda-E6VURLIS.js} +9 -9
  129. package/dist/{layout-7WEUNO6T.js → layout-XYC64QQQ.js} +30 -29
  130. package/dist/{lint-5YMAF3L7.js → lint-V5DJYWBX.js} +9 -9
  131. package/dist/{lintProject-C2ONSH2U.js → lintProject-JATQKR64.js} +3 -3
  132. package/dist/{list-BIE3X7CO.js → list-RUGVRTVD.js} +3 -3
  133. package/dist/{login-YDIGJWCG.js → login-ZTKGKXGS.js} +4 -4
  134. package/dist/{manager-D2UV6RDQ.js → manager-JUP7PM6N.js} +11 -10
  135. package/dist/{media-treatment-FSKHPMWA.js → media-treatment-VIUPK4OR.js} +16 -15
  136. package/dist/{models-COEK6LXG.js → models-LJS2HBOZ.js} +14 -13
  137. package/dist/{motionShot-HYZ2ZGJQ.js → motionShot-3UAXZ7SN.js} +17 -16
  138. package/dist/{normalize-audio-UXR6WQ7Q.js → normalize-audio-SBYI4YIH.js} +4 -4
  139. package/dist/{open-OFT2GIDG.js → open-S27TUD3A.js} +14 -14
  140. package/dist/{parakeetRunner-4NZ3QXS3.js → parakeetRunner-ETLMLJ4L.js} +15 -14
  141. package/dist/{pipeline-ZKE54JMG.js → pipeline-I2M22M24.js} +11 -10
  142. package/dist/{play-2VG77FT6.js → play-COJU6VJK.js} +22 -21
  143. package/dist/{preflight-QTWDIM5C.js → preflight-FZ24NCHH.js} +11 -10
  144. package/dist/{present-OONXQLJG.js → present-YAHKLC5D.js} +18 -17
  145. package/dist/{preview-6RZJFU76.js → preview-KQOEU5YE.js} +27 -26
  146. package/dist/{producer-6YM3UH3B.js → producer-DTNNG4T6.js} +1 -1
  147. package/dist/{projectConfig-YMW4P2X6.js → projectConfig-4A76VYUP.js} +9 -9
  148. package/dist/{publication-SEINUAPZ.js → publication-SQPMC2W3.js} +4 -4
  149. package/dist/{publish-KZBTBWFO.js → publish-QUEJBGGT.js} +13 -12
  150. package/dist/{remove-background-BIQNMIR7.js → remove-background-FP2ETAQH.js} +12 -11
  151. package/dist/{render-FIH37HJA.js → render-BIFIL4U6.js} +32 -31
  152. package/dist/render-GQFXJWLV.js +1504 -0
  153. package/dist/{render-LW76HOMJ.js → render-P664SMC7.js} +5 -5
  154. package/dist/{render-batch-POLEEYD4.js → render-batch-ZCPMYH6Z.js} +5 -5
  155. package/dist/renderSetupWorker.js +3 -3
  156. package/dist/{resolver-O2SED3XB.js → resolver-BUC2GFZQ.js} +6 -6
  157. package/dist/{sherpa-HTFFFTVQ.js → sherpa-HFT6XEP6.js} +14 -13
  158. package/dist/skills/hyperframes/SKILL.md +52 -174
  159. package/dist/skills/hyperframes/assets/frame-presets/biennale-yellow/FRAME.md +289 -0
  160. package/dist/skills/hyperframes/assets/frame-presets/biennale-yellow/caption-skin.html +220 -0
  161. package/dist/skills/hyperframes/assets/frame-presets/biennale-yellow/frame-showcase.html +1214 -0
  162. package/dist/skills/hyperframes/assets/frame-presets/blockframe/FRAME.md +275 -0
  163. package/dist/skills/hyperframes/assets/frame-presets/blockframe/caption-skin.html +223 -0
  164. package/dist/skills/hyperframes/assets/frame-presets/blockframe/frame-showcase.html +1347 -0
  165. package/dist/skills/hyperframes/assets/frame-presets/blue-professional/FRAME.md +307 -0
  166. package/dist/skills/hyperframes/assets/frame-presets/blue-professional/caption-skin.html +222 -0
  167. package/dist/skills/hyperframes/assets/frame-presets/blue-professional/frame-showcase.html +1372 -0
  168. package/dist/skills/hyperframes/assets/frame-presets/bold-poster/FRAME.md +275 -0
  169. package/dist/skills/hyperframes/assets/frame-presets/bold-poster/caption-skin.html +229 -0
  170. package/dist/skills/hyperframes/assets/frame-presets/bold-poster/frame-showcase.html +1140 -0
  171. package/dist/skills/hyperframes/assets/frame-presets/broadside/FRAME.md +284 -0
  172. package/dist/skills/hyperframes/assets/frame-presets/broadside/caption-skin.html +224 -0
  173. package/dist/skills/hyperframes/assets/frame-presets/broadside/frame-showcase.html +1166 -0
  174. package/dist/skills/hyperframes/assets/frame-presets/capsule/FRAME.md +284 -0
  175. package/dist/skills/hyperframes/assets/frame-presets/capsule/caption-skin.html +223 -0
  176. package/dist/skills/hyperframes/assets/frame-presets/capsule/frame-showcase.html +1465 -0
  177. package/dist/skills/hyperframes/assets/frame-presets/cartesian/FRAME.md +278 -0
  178. package/dist/skills/hyperframes/assets/frame-presets/cartesian/caption-skin.html +221 -0
  179. package/dist/skills/hyperframes/assets/frame-presets/cartesian/frame-showcase.html +1263 -0
  180. package/dist/skills/hyperframes/assets/frame-presets/cobalt-grid/FRAME.md +265 -0
  181. package/dist/skills/hyperframes/assets/frame-presets/cobalt-grid/caption-skin.html +237 -0
  182. package/dist/skills/hyperframes/assets/frame-presets/cobalt-grid/frame-showcase.html +1468 -0
  183. package/dist/skills/hyperframes/assets/frame-presets/code-editorial/FRAME.md +277 -0
  184. package/dist/skills/hyperframes/assets/frame-presets/code-editorial/caption-skin.html +223 -0
  185. package/dist/skills/hyperframes/assets/frame-presets/code-editorial/fonts/EBGaramond-400.woff2 +0 -0
  186. package/dist/skills/hyperframes/assets/frame-presets/code-editorial/fonts/EBGaramond-700.woff2 +0 -0
  187. package/dist/skills/hyperframes/assets/frame-presets/code-editorial/fonts/Inter-400.woff2 +0 -0
  188. package/dist/skills/hyperframes/assets/frame-presets/code-editorial/fonts/Inter-700.woff2 +0 -0
  189. package/dist/skills/hyperframes/assets/frame-presets/code-editorial/fonts/JetBrainsMono-400.woff2 +0 -0
  190. package/dist/skills/hyperframes/assets/frame-presets/code-editorial/fonts/JetBrainsMono-700.woff2 +0 -0
  191. package/dist/skills/hyperframes/assets/frame-presets/code-editorial/fonts/OFL-eb-garamond.txt +93 -0
  192. package/dist/skills/hyperframes/assets/frame-presets/code-editorial/fonts/OFL-inter.txt +93 -0
  193. package/dist/skills/hyperframes/assets/frame-presets/code-editorial/fonts/OFL-jetbrains-mono.txt +93 -0
  194. package/dist/skills/hyperframes/assets/frame-presets/code-editorial/frame-showcase.html +1438 -0
  195. package/dist/skills/hyperframes/assets/frame-presets/coral/FRAME.md +314 -0
  196. package/dist/skills/hyperframes/assets/frame-presets/coral/caption-skin.html +225 -0
  197. package/dist/skills/hyperframes/assets/frame-presets/coral/frame-showcase.html +1268 -0
  198. package/dist/skills/hyperframes/assets/frame-presets/creative-mode/FRAME.md +333 -0
  199. package/dist/skills/hyperframes/assets/frame-presets/creative-mode/caption-skin.html +226 -0
  200. package/dist/skills/hyperframes/assets/frame-presets/creative-mode/frame-showcase.html +1330 -0
  201. package/dist/skills/hyperframes/assets/frame-presets/daisy-days/FRAME.md +274 -0
  202. package/dist/skills/hyperframes/assets/frame-presets/daisy-days/caption-skin.html +229 -0
  203. package/dist/skills/hyperframes/assets/frame-presets/daisy-days/frame-showcase.html +1444 -0
  204. package/dist/skills/hyperframes/assets/frame-presets/editorial-forest/FRAME.md +265 -0
  205. package/dist/skills/hyperframes/assets/frame-presets/editorial-forest/caption-skin.html +222 -0
  206. package/dist/skills/hyperframes/assets/frame-presets/editorial-forest/frame-showcase.html +1273 -0
  207. package/dist/skills/hyperframes/references/captions.md +46 -0
  208. package/dist/skills/hyperframes/references/film.md +47 -0
  209. package/dist/skills/hyperframes/references/format.md +157 -0
  210. package/dist/skills/hyperframes/references/look.md +69 -0
  211. package/dist/skills/hyperframes/references/motion.md +94 -0
  212. package/dist/skills/hyperframes/references/overlays.md +39 -0
  213. package/dist/skills/hyperframes/references/plugin-installation.md +3 -3
  214. package/dist/skills/hyperframes/references/review.md +51 -0
  215. package/dist/skills/hyperframes/references/runtimes.md +43 -0
  216. package/dist/skills/hyperframes/references/skill-lifecycle.md +21 -13
  217. package/dist/skills/hyperframes/references/sound.md +43 -0
  218. package/dist/skills/hyperframes/references/spec.md +76 -0
  219. package/dist/skills/hyperframes/references/story.md +103 -0
  220. package/dist/skills/hyperframes/references/storyboard-format.md +30 -22
  221. package/dist/skills/hyperframes/references/storyboard.md +36 -0
  222. package/dist/skills/hyperframes/references/types/3d.md +25 -0
  223. package/dist/skills/hyperframes/references/types/character.md +20 -0
  224. package/dist/skills/hyperframes/references/types/data.md +19 -0
  225. package/dist/skills/hyperframes/references/types/explainer.md +34 -0
  226. package/dist/skills/hyperframes/references/types/launch.md +31 -0
  227. package/dist/skills/hyperframes/references/types/music.md +24 -0
  228. package/dist/skills/hyperframes/references/types/vertical.md +23 -0
  229. package/dist/skills/hyperframes/scripts/bake-basemap.mjs +324 -0
  230. package/dist/skills/hyperframes/scripts/lib/main-module.test.mjs +1 -6
  231. package/dist/skills/hyperframes/scripts/locate.mjs +228 -0
  232. package/dist/skills/hyperframes-cli/SKILL.md +76 -179
  233. package/dist/skills/hyperframes-cli/references/beats.md +1 -1
  234. package/dist/skills/hyperframes-cli/references/cloud.md +2 -2
  235. package/dist/skills/hyperframes-cli/references/cloudrun.md +1 -1
  236. package/dist/skills/hyperframes-cli/references/conventions.md +17 -0
  237. package/dist/skills/hyperframes-cli/references/feedback.md +14 -0
  238. package/dist/skills/hyperframes-cli/references/init-and-scaffold.md +11 -7
  239. package/dist/skills/hyperframes-cli/references/lambda.md +1 -1
  240. package/dist/skills/hyperframes-cli/references/lint-validate-inspect.md +19 -8
  241. package/dist/skills/hyperframes-cli/references/preview-render.md +8 -2
  242. package/dist/skills/hyperframes-cli/references/upgrade-info-misc.md +8 -0
  243. package/dist/skills/media-use/SKILL.md +47 -91
  244. package/dist/skills/media-use/audio/references/bgm.md +1 -1
  245. package/dist/skills/media-use/audio/references/captions/authoring.md +1 -2
  246. package/dist/skills/media-use/audio/references/captions/motion.md +5 -5
  247. package/dist/skills/media-use/audio/references/tts.md +0 -3
  248. package/dist/skills/media-use/audio/scripts/audio.mjs +5 -6
  249. package/dist/skills/media-use/audio/scripts/carve.mjs +560 -0
  250. package/dist/skills/media-use/audio/scripts/carve.test.mjs +254 -0
  251. package/dist/skills/media-use/audio/scripts/extract-audio-data.py +199 -0
  252. package/dist/skills/media-use/references/local.md +24 -0
  253. package/dist/skills/media-use/references/memory.md +4 -4
  254. package/dist/skills/media-use/references/mixing.md +71 -0
  255. package/dist/skills/media-use/references/operations.md +1 -1
  256. package/dist/skills/media-use/scripts/compatibility.test.mjs +1 -56
  257. package/dist/skills/media-use/scripts/lib/prefs-store.mjs +1 -1
  258. package/dist/skills/media-use/scripts/lib/recipe-store.mjs +1 -1
  259. package/dist/skills/media-use/scripts/prefs.mjs +2 -3
  260. package/dist/skills/media-use/scripts/recipe.mjs +1 -3
  261. package/dist/{skills-J6MBGS5O.js → skills-3WEVO3NU.js} +20 -13
  262. package/dist/{skillsUpdateCheck-ZAXNLBF3.js → skillsUpdateCheck-BFPWFOK5.js} +3 -3
  263. package/dist/{snapshot-TL7TTFS6.js → snapshot-WDQ6S7CJ.js} +458 -98
  264. package/dist/{src-Z5H5N5T4.js → src-NPR2JZOJ.js} +15 -11
  265. package/dist/{src-EL6HGIS4.js → src-RZ574OKP.js} +9 -8
  266. package/dist/{staticProjectServer-EO7X7RAY.js → staticProjectServer-FTGTEZI4.js} +18 -17
  267. package/dist/studio/assets/{hyperframes-player-hz_VqxBZ.js → hyperframes-player-CoOdf435.js} +1 -1
  268. package/dist/studio/assets/{index-CV_ojgp5.js → index-CR85xg2x.js} +1 -1
  269. package/dist/studio/assets/{index-S1ceEagc.js → index-C_6rTpaB.js} +5 -5
  270. package/dist/studio/index.html +1 -1
  271. package/dist/{studio-api-CUZDC5B3.js → studio-api-TAWB7B23.js} +12 -11
  272. package/dist/{studioServer-EZPRV43Y.js → studioServer-HRQGJTBU.js} +49 -48
  273. package/dist/{telemetry-LFUVHARP.js → telemetry-QZ6HJF4W.js} +3 -3
  274. package/dist/templates/_shared/AGENTS.md +14 -19
  275. package/dist/templates/_shared/CLAUDE.md +14 -19
  276. package/dist/templates/blank/index.html +10 -4
  277. package/dist/{timeline-GSH743JE.js → timeline-IKUEW42T.js} +21 -19
  278. package/dist/{tokens-3ZMPSH7B.js → tokens-AUGUEWHS.js} +2 -2
  279. package/dist/{transcribe-4SHNDPWW.js → transcribe-7734CG3N.js} +19 -18
  280. package/dist/{transcribe-TV7JBZQS.js → transcribe-FWU6EMEO.js} +13 -12
  281. package/dist/{updateCheck-W7FTFOQF.js → updateCheck-VIPQ3FPW.js} +2 -2
  282. package/dist/{upgrade-7YYYNAPF.js → upgrade-4VNDQTVO.js} +2 -2
  283. package/dist/{urlDownloader-PQSUS2CP.js → urlDownloader-6CXL4CL7.js} +9 -8
  284. package/dist/{validate-GCHAEVXM.js → validate-QWCMVWID.js} +24 -23
  285. package/dist/{video-KGN7NJS5.js → video-245Q5WN4.js} +10 -9
  286. package/dist/warmCheck.js +37 -36
  287. package/package.json +1 -1
  288. package/dist/chunk-GMNHAOMJ.js +0 -3805
  289. package/dist/render-65K3K6SD.js +0 -719
  290. package/dist/skills/hyperframes/references/brief-contract.md +0 -108
  291. package/dist/skills/hyperframes/references/brief-format.md +0 -72
  292. package/dist/skills/hyperframes/references/capability-menu.md +0 -47
  293. package/dist/skills/hyperframes/references/frame-worker-core.md +0 -82
  294. package/dist/skills/hyperframes/references/intent-interview.md +0 -73
  295. package/dist/skills/hyperframes/references/pitch-round.md +0 -40
  296. package/dist/skills/hyperframes/references/production-loop.md +0 -26
  297. package/dist/skills/hyperframes/references/review-loop.md +0 -37
  298. package/dist/skills/hyperframes/references/route-briefs.md +0 -11
  299. package/dist/skills/hyperframes/references/routes/embedded-captions.md +0 -11
  300. package/dist/skills/hyperframes/references/routes/faceless-explainer.md +0 -12
  301. package/dist/skills/hyperframes/references/routes/general-video.md +0 -12
  302. package/dist/skills/hyperframes/references/routes/motion-graphics.md +0 -11
  303. package/dist/skills/hyperframes/references/routes/music-to-video.md +0 -12
  304. package/dist/skills/hyperframes/references/routes/pr-to-video.md +0 -28
  305. package/dist/skills/hyperframes/references/routes/product-launch-video.md +0 -13
  306. package/dist/skills/hyperframes/references/routes/remotion-to-hyperframes.md +0 -9
  307. package/dist/skills/hyperframes/references/routes/slideshow.md +0 -11
  308. package/dist/skills/hyperframes/references/routes/talking-head-recut.md +0 -11
  309. package/dist/skills/hyperframes/references/script-format.md +0 -52
  310. package/dist/skills/hyperframes/references/subagent-dispatch.md +0 -35
  311. package/dist/skills/hyperframes/references/workflow-catalog.md +0 -10
  312. package/dist/skills/hyperframes/scripts/lib/frame-packets-core.mjs +0 -176
  313. package/dist/skills/media-use/audio/scripts/lib/host-audio.mjs +0 -28
  314. package/dist/skills/media-use/audio/scripts/lib/host-audio.test.mjs +0 -106
@@ -0,0 +1,324 @@
1
+ // bake-basemap.mjs — bake a real-imagery map camera move for a composition (references/film.md, "Maps").
2
+ //
3
+ // WHAT IT DOES (and why baking at all): drives MapLibre in headless Chrome to record ONLY the
4
+ // real-imagery basemap as an MP4 (camera zoom→hold), and projects each requested country's border
5
+ // to SCREEN coordinates at the held view. The HF composition then plays the MP4 on track 0 and
6
+ // animates a *live* SVG overlay (border draw-on, colour-block / flag fills, labels, pins) from the
7
+ // exported `<NAME>-coords.json`. Borders/fills are NOT baked into the video — they stay editable in HF.
8
+ //
9
+ // Why bake the imagery at all (this is the real reason, not "smoothness"): HF forbids render-time
10
+ // network and requires deterministic output. Live raster tiles re-fetch every render and can change
11
+ // → non-deterministic. Baking FREEZES the imagery into pixels = deterministic + offline-reproducible.
12
+ // (Exposing the engine's per-frame `onBeforeCapture` hook would let MapLibre run live and smooth, but
13
+ // it would NOT remove the need to freeze tiles for determinism — so this bake step stays relevant.)
14
+ //
15
+ // PARAMETRIC — drive everything by env. Example (Brazil + Argentina on satellite):
16
+ // NAME=br-ar STYLE=satellite COUNTRIES="Brazil:#22d3ee,Argentina:#f59e0b" \
17
+ // CENTER="-60,-25" ZSTART=2.4 ZEND=3.4 FPS=30 DUR=5 node bake-basemap.mjs
18
+ // From space down to a street (globe, starfield, a turn from FROM to CENTER, then the dive):
19
+ // NAME=mbs PROJECTION=globe FROM="18,16" CENTER="103.8607,1.2834" ZSTART=1.85 ZEND=16.2 \
20
+ // PITCH=40 DUR=10 HOLD=0.8 node bake-basemap.mjs
21
+ // It encodes frames-<NAME>/f%04d.png → <NAME>.mp4 (all-intra: -g 1) and writes <NAME>-coords.json
22
+ // for the HF composition. One bake at a time: several headless Chromes on a small machine stall.
23
+ import { join } from "node:path";
24
+ import { mkdirSync, writeFileSync, readdirSync, existsSync } from "node:fs";
25
+ import { homedir } from "node:os";
26
+ import { spawnSync } from "node:child_process";
27
+
28
+ if (process.argv.includes("--help") || process.argv.includes("-h")) {
29
+ console.log(`usage: [NAME=..] [STYLE=satellite|dark|light|<{z}/{x}/{y} url>] [CENTER="lng,lat"]
30
+ [PROJECTION=mercator|globe] [FROM="lng,lat"] [PAN=0.35] [ZSTART=..] [ZEND=..] [PITCH=..]
31
+ [BEARING=..] [FPS=30] [DUR=5] [HOLD=0.5] [COUNTRIES="Name:#hex,Name:#hex"] [OUT=dir]
32
+ [CHROME=path] node bake-basemap.mjs
33
+ PROJECTION=globe starts from Earth in space (starfield, atmosphere) and flattens as it zooms in.
34
+ FROM pans the camera from that point to CENTER over the first PAN of the move, while the zoom
35
+ runs from PAN/2 to HOLD; ZSTART about 1.8 frames the whole globe, ZEND 16 is a building.
36
+ Writes <OUT>/<NAME>.mp4 (all-intra basemap) and <OUT>/<NAME>-coords.json (projected borders).
37
+ Needs puppeteer-core, ffmpeg, a Chrome or chrome-headless-shell, and network for the tiles.
38
+ Run one bake at a time; it prints its pace and an estimate as it goes.`);
39
+ process.exit(0);
40
+ }
41
+
42
+ // Loaded after the --help check so usage prints without puppeteer-core installed.
43
+ const { default: puppeteer } = await import("puppeteer-core");
44
+
45
+ // --- resolve Chrome dynamically (no hardcoded machine path) ---
46
+ function resolveChrome() {
47
+ if (process.env.CHROME && existsSync(process.env.CHROME)) return process.env.CHROME;
48
+ const exe = process.platform === "win32" ? "chrome-headless-shell.exe" : "chrome-headless-shell";
49
+ const base = join(homedir(), ".cache", "puppeteer", "chrome-headless-shell");
50
+ if (existsSync(base)) {
51
+ for (const v of readdirSync(base).sort().reverse()) {
52
+ // lexical sort; any working binary is fine
53
+ try {
54
+ for (const inner of readdirSync(join(base, v))) {
55
+ const bin = join(base, v, inner, exe);
56
+ if (existsSync(bin)) return bin;
57
+ }
58
+ } catch {
59
+ /* skip */
60
+ }
61
+ }
62
+ }
63
+ for (const c of [
64
+ "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
65
+ "/usr/bin/google-chrome",
66
+ "/usr/bin/chromium",
67
+ "/usr/bin/chromium-browser",
68
+ ])
69
+ if (existsSync(c)) return c;
70
+ throw new Error(
71
+ "Chrome not found. Set CHROME=/path/to/chrome-headless-shell, or install one:\n" +
72
+ " npx puppeteer browsers install chrome-headless-shell",
73
+ );
74
+ }
75
+
76
+ // --- params (all overridable by env) ---
77
+ const NAME = process.env.NAME || "basemap";
78
+ const STYLE = process.env.STYLE || "satellite"; // satellite | dark | light | raw {z}/{x}/{y} template
79
+ const CENTER = (process.env.CENTER || "2.6,46.6").split(",").map(Number);
80
+ const ZSTART = +(process.env.ZSTART || 4.2);
81
+ const ZEND = +(process.env.ZEND || 5.4);
82
+ const PITCH = +(process.env.PITCH || 0);
83
+ const BEARING = +(process.env.BEARING || 0);
84
+ const FPS = +(process.env.FPS || 30),
85
+ DUR = +(process.env.DUR || 5),
86
+ N = Math.max(1, Math.round(FPS * DUR));
87
+ const HOLD = +(process.env.HOLD || 0.5); // p∈[0,1] at which the zoom finishes; camera holds after
88
+ const PROJECTION = process.env.PROJECTION === "globe" ? "globe" : "mercator";
89
+ const FROM = process.env.FROM ? process.env.FROM.split(",").map(Number) : null; // pan start; null = no pan
90
+ const PAN = +(process.env.PAN || 0.35); // p at which the pan from FROM reaches CENTER
91
+ const MARGIN = (process.env.KEEPMARGIN || "16,13").split(",").map(Number); // [lon°,lat°] keep-box around each country's mainland
92
+ // COUNTRIES="Name:#hex,Name:#hex" — borders to project (optional; omit for a pure zoom-to / pin shot)
93
+ const COUNTRIES = (process.env.COUNTRIES || "")
94
+ .split(",")
95
+ .map((s) => s.trim())
96
+ .filter(Boolean)
97
+ .map((s) => {
98
+ const [name, color] = s.split(":");
99
+ return { name, color: color || "#38bdf8" };
100
+ });
101
+
102
+ // fail fast on bad numeric env — otherwise NaN silently bakes zero/garbage frames and still prints "done"
103
+ for (const [k, v] of Object.entries({
104
+ "CENTER.lng": CENTER[0],
105
+ "CENTER.lat": CENTER[1],
106
+ ZSTART,
107
+ ZEND,
108
+ PITCH,
109
+ BEARING,
110
+ FPS,
111
+ DUR,
112
+ HOLD,
113
+ PAN,
114
+ ...(FROM ? { "FROM.lng": FROM[0], "FROM.lat": FROM[1] } : {}),
115
+ }))
116
+ if (!Number.isFinite(v))
117
+ throw new Error(
118
+ `bad numeric env: ${k}=${v} — check CENTER="lng,lat" / ZSTART / ZEND / FPS / DUR`,
119
+ );
120
+
121
+ // IMPORTANT: tileSize:256 matches Esri/CARTO raster endpoints. MapLibre's INTERNAL world width is
122
+ // 512·2^zoom regardless — a 512px (@2x/retina/vector) tile source needs tileSize:512 or every zoom
123
+ // level is off by one. Keep 256 for these raster sources.
124
+ const TILES =
125
+ {
126
+ satellite:
127
+ "https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}",
128
+ dark: "https://a.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}.png",
129
+ light: "https://a.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png",
130
+ }[STYLE] || STYLE; // STYLE may also be a raw {z}/{x}/{y} template
131
+
132
+ const OUT = process.env.OUT || process.cwd(); // artifacts → workspace (cwd), NOT the installed skill dir
133
+ const framesDir = join(OUT, "frames-" + NAME);
134
+ mkdirSync(framesDir, { recursive: true });
135
+
136
+ // A seeded star field behind the globe, so every bake of the same move is identical.
137
+ let seed = 7;
138
+ const rnd = () => (seed = (seed * 16807) % 2147483647) / 2147483647;
139
+ const STARS = `<svg id="stars" width="1920" height="1080">${Array.from({ length: 260 }, () => {
140
+ const x = (rnd() * 1920).toFixed(0),
141
+ y = (rnd() * 1080).toFixed(0);
142
+ const r = (rnd() * 1.3 + 0.3).toFixed(2),
143
+ a = (rnd() * 0.6 + 0.2).toFixed(2);
144
+ return `<circle cx="${x}" cy="${y}" r="${r}" fill="#fff" opacity="${a}"/>`;
145
+ }).join("")}</svg>`;
146
+
147
+ // Deps PINNED exact (mutable @5/@2 majors would drift the bake over time).
148
+ const PAGE = `<!doctype html><html><head>
149
+ <link href="https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.css" rel="stylesheet">
150
+ <script src="https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.js"></script>
151
+ <script src="https://cdn.jsdelivr.net/npm/topojson-client@3.1.0/dist/topojson-client.min.js"></script>
152
+ <style>*{margin:0}html,body{width:1920px;height:1080px;overflow:hidden;background:radial-gradient(ellipse at 50% 55%,#0b1630 0%,#050812 55%,#020308 100%)}#stars{position:absolute;inset:0}#map{position:absolute;inset:0;width:1920px;height:1080px}.maplibregl-control-container{display:none!important}</style>
153
+ </head><body>${PROJECTION === "globe" ? STARS : ""}<div id="map"></div><script>
154
+ var CENTER=${JSON.stringify(CENTER)}, ZSTART=${ZSTART}, ZEND=${ZEND}, PITCH=${PITCH}, BEARING=${BEARING}, HOLD=${HOLD};
155
+ var FROM=${JSON.stringify(FROM)}, PAN=${PAN};
156
+ var MARGIN=${JSON.stringify(MARGIN)}, WANT=${JSON.stringify(COUNTRIES)};
157
+ var GLOBE=${PROJECTION === "globe"};
158
+ // On the globe the page behind the map shows through (stars), and the atmosphere fades out as the camera nears the ground.
159
+ var map=new maplibregl.Map({container:"map",style:{version:8,projection:{type:GLOBE?"globe":"mercator"},
160
+ sky:GLOBE?{"atmosphere-blend":["interpolate",["linear"],["zoom"],0,1,5,1,7,0]}:undefined,
161
+ sources:{s:{type:"raster",tiles:[${JSON.stringify(TILES)}],tileSize:256,maxzoom:19}},
162
+ layers:(GLOBE?[]:[{id:"bg",type:"background",paint:{"background-color":"#05070d"}}]).concat([{id:"s",type:"raster",source:"s"}])},
163
+ center:FROM||CENTER,zoom:ZSTART,pitch:0,bearing:0,interactive:false,attributionControl:false,fadeDuration:0,preserveDrawingBuffer:true,maxTileCacheSize:6000,
164
+ canvasContextAttributes:{alpha:GLOBE,preserveDrawingBuffer:true}});
165
+ function ease(x){return x<0.5?4*x*x*x:1-Math.pow(-2*x+2,3)/2;} // easeInOutCubic (= Remotion interpolate+Easing)
166
+ function sine(x){return -(Math.cos(Math.PI*x)-1)/2;}
167
+ function seg(p,a,b){return b<=a?1:Math.min(1,Math.max(0,(p-a)/(b-a)));}
168
+ // With FROM, the camera turns to CENTER over [0,PAN] while the zoom runs over [PAN/2,HOLD]; without it, the zoom runs over [0,HOLD].
169
+ function camAt(p){
170
+ var s=FROM?sine(seg(p,0,PAN)):1, t=ease(seg(p,FROM?PAN/2:0,HOLD));
171
+ var c=FROM?[FROM[0]+(CENTER[0]-FROM[0])*s, FROM[1]+(CENTER[1]-FROM[1])*s]:CENTER;
172
+ return {center:c, zoom:ZSTART+(ZEND-ZSTART)*t, pitch:PITCH*t, bearing:BEARING*t}; }
173
+ function ringCentroid(r){ var sx=0,sy=0; for(var k=0;k<r.length;k++){sx+=r[k][0];sy+=r[k][1];} return [sx/r.length, sy/r.length]; }
174
+ // Keep the polygons in a lon/lat box around the country's MAINLAND (the vertex-richest polygon),
175
+ // dropping far-flung overseas territories that would blow up the bbox. Generalizes per subject —
176
+ // no continent-specific constant. Keeps near islands (Corsica, Sicily); drops Guiana, Alaska, Hawaii.
177
+ function mainland(f){
178
+ if(!f) return f;
179
+ if(f.geometry.type!=="MultiPolygon"){ f.__anchorRing=f.geometry.coordinates[0]; return f; } // Polygon: outer ring
180
+ var polys=f.geometry.coordinates, anchor=polys[0], amax=-1;
181
+ polys.forEach(function(poly){ if(poly[0].length>amax){amax=poly[0].length;anchor=poly;} });
182
+ var ac=ringCentroid(anchor[0]);
183
+ var kept=polys.filter(function(poly){ var c=ringCentroid(poly[0]); return Math.abs(c[0]-ac[0])<=MARGIN[0] && Math.abs(c[1]-ac[1])<=MARGIN[1]; });
184
+ var nf={type:"Feature",properties:f.properties,geometry:{type:"MultiPolygon",coordinates:kept}}; nf.__anchorRing=anchor[0]; return nf;
185
+ }
186
+ function lonSpan(f){ var mn=1e9,mx=-1e9; (f.geometry.type==="Polygon"?[f.geometry.coordinates]:f.geometry.coordinates).forEach(function(poly){poly[0].forEach(function(c){if(c[0]<mn)mn=c[0];if(c[0]>mx)mx=c[0];});}); return mx-mn; }
187
+ // ANTIMERIDIAN unwrap (Russia/Fiji/NZ): make all lon contiguous around the camera-center ref so a
188
+ // feature touching ±180° doesn't smear when map.project() runs per-vertex (mercatorX is linear and
189
+ // accepts out-of-range lon, so 181 sits just east of center, not far-west at -179). Mutates in place;
190
+ // __anchorRing shares the same arrays so it's covered.
191
+ function unwrapLon(f, ref){ if(!f) return; function fix(r){ for(var i=0;i<r.length;i++){ var lon=r[i][0]; while(lon-ref>180)lon-=360; while(lon-ref<-180)lon+=360; r[i][0]=lon; } }
192
+ var g=f.geometry; if(g.type==="Polygon") g.coordinates.forEach(fix); else g.coordinates.forEach(function(poly){ poly.forEach(fix); }); }
193
+ var FEATS=[]; window.__warn=[];
194
+ window.__ready=new Promise(function(res){ map.on("load", function(){
195
+ if(!WANT.length){ res(); return; }
196
+ fetch("https://cdn.jsdelivr.net/npm/world-atlas@2.0.2/countries-110m.json").then(function(r){return r.json();}).then(function(w){
197
+ var fc=topojson.feature(w,w.objects.countries);
198
+ WANT.forEach(function(want){
199
+ var f=fc.features.filter(function(x){return x.properties.name===want.name;})[0];
200
+ if(!f){ window.__warn.push("country not found in world-atlas: "+want.name); return; }
201
+ f=mainland(f);
202
+ unwrapLon(f, CENTER[0]); // antimeridian: unwrap lons around the camera ref (CENTER must be near the subject) before projecting
203
+ if(lonSpan(f)>180) window.__warn.push(want.name+" spans >180° lon even after unwrap — projection may still smear.");
204
+ FEATS.push({name:want.name, color:want.color, f:f});
205
+ });
206
+ res();
207
+ });
208
+ });});
209
+ window.__setCam=function(p){ map.jumpTo(camAt(p)); };
210
+ // Resolves false once every tile for this camera is loaded and painted, true if ms passed first.
211
+ // Polls rather than waiting for "idle": that event can fire before a listener is attached, which
212
+ // left every cached frame sitting out the whole timeout.
213
+ window.__waitIdle=function(ms){ return new Promise(function(res){ var t0=performance.now();
214
+ (function poll(){ if(map.loaded()&&map.areTilesLoaded()){ map.triggerRepaint(); requestAnimationFrame(function(){requestAnimationFrame(function(){res(false);});}); return; }
215
+ if(performance.now()-t0>(ms||9000)){ res(!map.areTilesLoaded()); return; } setTimeout(poll,40); })(); }); };
216
+ function featurePath(f){ function ring(r){ return r.map(function(c,i){ var p=map.project(c); return (i?"L":"M")+p.x.toFixed(1)+" "+p.y.toFixed(1); }).join(" ")+"Z"; }
217
+ var g=f.geometry,d=""; if(g.type==="Polygon") g.coordinates.forEach(function(r){d+=ring(r);}); else g.coordinates.forEach(function(poly){poly.forEach(function(r){d+=ring(r);});}); return d; }
218
+ function bboxOf(f){ var mnx=1e9,mny=1e9,mxx=-1e9,mxy=-1e9;
219
+ function eat(r){ r.forEach(function(c){ var p=map.project(c); if(p.x<mnx)mnx=p.x; if(p.y<mny)mny=p.y; if(p.x>mxx)mxx=p.x; if(p.y>mxy)mxy=p.y; }); }
220
+ var g=f.geometry; if(g.type==="Polygon")g.coordinates.forEach(eat); else g.coordinates.forEach(function(poly){poly.forEach(eat);});
221
+ return {x:+mnx.toFixed(1),y:+mny.toFixed(1),w:+(mxx-mnx).toFixed(1),h:+(mxy-mny).toFixed(1)}; }
222
+ window.__project=function(){ return {
223
+ view:{center:CENTER, zoom:ZEND, pitch:PITCH, bearing:BEARING},
224
+ countries: FEATS.map(function(e){ var lc=ringCentroid(e.f.__anchorRing); var lp=map.project(lc);
225
+ return { name:e.name, color:e.color, d:featurePath(e.f), bbox:bboxOf(e.f), label:{x:+lp.x.toFixed(1),y:+lp.y.toFixed(1)} }; }),
226
+ }; };
227
+ </script></body></html>`;
228
+
229
+ // --no-sandbox is intentional: trusted Source-time bake, headless, often root/CI; deps are version-pinned above.
230
+ const browser = await puppeteer.launch({
231
+ executablePath: resolveChrome(),
232
+ headless: true,
233
+ args: [
234
+ "--no-sandbox",
235
+ "--hide-scrollbars",
236
+ "--use-gl=angle",
237
+ "--use-angle=swiftshader",
238
+ "--enable-unsafe-swiftshader",
239
+ "--enable-webgl",
240
+ "--window-size=1920,1080",
241
+ ],
242
+ });
243
+ try {
244
+ const page = await browser.newPage();
245
+ await page.setViewport({ width: 1920, height: 1080, deviceScaleFactor: 1 });
246
+ await page.setContent(PAGE, { waitUntil: "load" });
247
+ await page.evaluate(() => window.__ready);
248
+ for (const w of await page.evaluate(() => window.__warn)) console.warn(`[${NAME}] WARN: ${w}`);
249
+ console.log(
250
+ `[${NAME}] ready (${STYLE}, ${PROJECTION}); baking ${N} frames, zoom ${ZSTART}→${ZEND} hold@p=${HOLD}, ${COUNTRIES.length} border(s)`,
251
+ );
252
+ const t0 = Date.now();
253
+ let coords = null;
254
+ const timeouts = [];
255
+ for (let i = 0; i < N; i++) {
256
+ const p = N === 1 ? 1 : i / (N - 1);
257
+ await page.evaluate((pp) => window.__setCam(pp), p);
258
+ const timedOut = await page.evaluate((ms) => window.__waitIdle(ms), 9000);
259
+ if (timedOut) {
260
+ timeouts.push(i);
261
+ console.warn(`[${NAME}] idle TIMEOUT at frame ${i} — tiles may be incomplete`);
262
+ }
263
+ await page.screenshot({
264
+ path: join(framesDir, `f${String(i).padStart(4, "0")}.png`),
265
+ clip: { x: 0, y: 0, width: 1920, height: 1080 },
266
+ optimizeForSpeed: true,
267
+ });
268
+ if (p >= HOLD && !coords && COUNTRIES.length)
269
+ coords = await page.evaluate(() => window.__project()); // capture at first hold frame
270
+ if (i % 20 === 0 || i === N - 1) {
271
+ const per = (Date.now() - t0) / 1000 / (i + 1);
272
+ console.log(
273
+ ` [${NAME}] ${i + 1}/${N} · ${per.toFixed(2)} s/frame · about ${Math.ceil((per * (N - i - 1)) / 60)} min left`,
274
+ );
275
+ }
276
+ }
277
+ // encode frames → all-intra MP4 (every frame seekable for HF); fall back to printing the command if ffmpeg is absent
278
+ const mp4 = join(OUT, NAME + ".mp4"),
279
+ pat = join(framesDir, "f%04d.png");
280
+ const ff = spawnSync(
281
+ "ffmpeg",
282
+ [
283
+ "-y",
284
+ "-framerate",
285
+ String(FPS),
286
+ "-i",
287
+ pat,
288
+ "-c:v",
289
+ "libx264",
290
+ "-pix_fmt",
291
+ "yuv420p",
292
+ "-g",
293
+ "1",
294
+ "-crf",
295
+ "16",
296
+ "-movflags",
297
+ "+faststart",
298
+ mp4,
299
+ ],
300
+ { stdio: "ignore" },
301
+ );
302
+ if (ff.status === 0) console.log(`[${NAME}] encoded → ${mp4}`);
303
+ else
304
+ console.warn(
305
+ `[${NAME}] ffmpeg unavailable (status ${ff.status}) — encode manually:\n ffmpeg -y -framerate ${FPS} -i ${pat} -c:v libx264 -pix_fmt yuv420p -g 1 -crf 16 -movflags +faststart ${mp4}`,
306
+ );
307
+ if (coords) {
308
+ writeFileSync(join(OUT, NAME + "-coords.json"), JSON.stringify(coords));
309
+ console.log(
310
+ `[${NAME}] coords written: ${coords.countries.map((c) => c.name + "(" + c.d.length + "ch)").join(", ")}`,
311
+ );
312
+ }
313
+ if (timeouts.length) {
314
+ // FAIL LOUD: the asset exists but is suspect — don't let a half-loaded bake pass silently
315
+ console.error(
316
+ `[${NAME}] ${timeouts.length}/${N} frame(s) hit the idle timeout (frames ${timeouts.slice(0, 8).join(",")}${timeouts.length > 8 ? "…" : ""}). The basemap MP4 may have INCOMPLETE tiles. Re-run with a slower zoom / larger timeout / check the tile server.`,
317
+ );
318
+ process.exitCode = 1;
319
+ } else {
320
+ console.log(`[${NAME}] done — all ${N} frames reached map idle (complete tiles).`);
321
+ }
322
+ } finally {
323
+ await browser.close();
324
+ }
@@ -14,12 +14,7 @@ test("skill CLIs run when invoked through a symlinked skills dir", () => {
14
14
  const dir = mkdtempSync(join(tmpdir(), "skills-link-"));
15
15
  try {
16
16
  symlinkSync(SKILLS, join(dir, "skills"), "dir");
17
- for (const script of [
18
- "faceless-explainer/scripts/captions.mjs",
19
- "pr-to-video/scripts/captions.mjs",
20
- "product-launch-video/scripts/captions.mjs",
21
- "media-use/audio/scripts/heygen-voice.mjs",
22
- ]) {
17
+ for (const script of ["media-use/audio/scripts/heygen-voice.mjs"]) {
23
18
  const run = spawnSync(process.execPath, [join(dir, "skills", script), "not-a-command"], {
24
19
  encoding: "utf8",
25
20
  });
@@ -0,0 +1,228 @@
1
+ #!/usr/bin/env node
2
+ /* locate.mjs — find "X" in an image WITHOUT any detector API or key.
3
+ *
4
+ * You (the author model) are weak at regressing pixel coordinates but strong at
5
+ * "which numbered strip is the target in?" — so localization = RSVP grid-index
6
+ * (ACL 2025 long.715): pick strips on a numbered grid, reconstruct the box
7
+ * geometrically. Zero npm deps — node + ffmpeg (both already required by
8
+ * hyperframes). Accuracy notes: references/film.md.
9
+ *
10
+ * THE LOOP (you read images between steps):
11
+ * 1) node locate.mjs overlay <img> --out DIR
12
+ * → DIR/gv.png (vertical strips 1..9) + DIR/gh.png (horizontal 1..9).
13
+ * READ both, pick the strip numbers the target spans.
14
+ * 2) node locate.mjs region <img> --vids 4,5 --hids 6,7 --out DIR
15
+ * → prints coarse region + writes DIR/gc.png (region cropped+upscaled,
16
+ * finer 6×6 grid). READ it, pick the finer strips.
17
+ * 3) node locate.mjs final <img> --region x0,y0,x1,y1 --vids 3,4 --hids 3,4
18
+ * → {box, center} normalized to the FULL image.
19
+ * 4) node locate.mjs mark <img> --box x0,y0,x1,y1 --out DIR/check.png
20
+ * → VERIFY: read check.png — is the red box on the target? If off,
21
+ * redo step 2/3 with corrected strips. Never skip this.
22
+ */
23
+ import { execFileSync } from "node:child_process";
24
+ import { existsSync, mkdirSync, copyFileSync } from "node:fs";
25
+
26
+ const N1 = 9,
27
+ PAD1 = 0.4; // stage 1: strips per axis, padding in STRIP units
28
+ const N2 = 6,
29
+ PAD2 = 0.25; // stage 2 (crop)
30
+ const GREEN = "0x3CDC5A",
31
+ BLUE = "0x3C82FF",
32
+ RED = "0xFF3232";
33
+
34
+ const ff = (args) =>
35
+ execFileSync("ffmpeg", ["-v", "error", "-y", ...args], {
36
+ stdio: ["ignore", "ignore", "inherit"],
37
+ });
38
+ function probe(img) {
39
+ const out = execFileSync("ffprobe", [
40
+ "-v",
41
+ "error",
42
+ "-select_streams",
43
+ "v:0",
44
+ "-show_entries",
45
+ "stream=width,height",
46
+ "-of",
47
+ "csv=p=0",
48
+ "--",
49
+ img,
50
+ ])
51
+ .toString()
52
+ .trim();
53
+ const [w, h] = out.split(",").map(Number);
54
+ return { w, h };
55
+ }
56
+ function font() {
57
+ const dst = "/tmp/locate-font.ttf";
58
+ if (!existsSync(dst)) {
59
+ for (const c of [
60
+ "/System/Library/Fonts/Supplemental/Arial Bold.ttf",
61
+ "/System/Library/Fonts/Supplemental/Arial.ttf",
62
+ "/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf",
63
+ ]) {
64
+ if (existsSync(c)) {
65
+ copyFileSync(c, dst);
66
+ break;
67
+ }
68
+ }
69
+ }
70
+ return dst;
71
+ }
72
+ function gridFilters(w, h, n, axis, fz) {
73
+ const F = font(),
74
+ fs = [];
75
+ if (axis === "v" || axis === "both") {
76
+ for (let i = 1; i < n; i++)
77
+ fs.push(`drawbox=x=${Math.round((i * w) / n)}:y=0:w=2:h=${h}:color=${GREEN}@0.8:t=fill`);
78
+ for (let i = 0; i < n; i++)
79
+ fs.push(
80
+ `drawtext=fontfile=${F}:text='${i + 1}':x=${Math.round(((i + 0.5) * w) / n - fz * 0.3)}:y=6:fontsize=${fz}:fontcolor=black:box=1:boxcolor=white@0.95:boxborderw=5`,
81
+ );
82
+ }
83
+ if (axis === "h" || axis === "both") {
84
+ for (let j = 1; j < n; j++)
85
+ fs.push(`drawbox=x=0:y=${Math.round((j * h) / n)}:w=${w}:h=2:color=${BLUE}@0.8:t=fill`);
86
+ for (let j = 0; j < n; j++)
87
+ fs.push(
88
+ `drawtext=fontfile=${F}:text='${j + 1}':x=6:y=${Math.round(((j + 0.5) * h) / n - fz * 0.5)}:fontsize=${fz}:fontcolor=black:box=1:boxcolor=white@0.95:boxborderw=5`,
89
+ );
90
+ }
91
+ return fs;
92
+ }
93
+ const ids = (s) => String(s).split(",").filter(Boolean).map(Number);
94
+ const regionOf = (v, h, n, pad) => [
95
+ Math.max(Math.min(...v) - 1 - pad, 0) / n,
96
+ Math.max(Math.min(...h) - 1 - pad, 0) / n,
97
+ Math.min(Math.max(...v) + pad, n) / n,
98
+ Math.min(Math.max(...h) + pad, n) / n,
99
+ ];
100
+ const r4 = (x) => Math.round(x * 1e4) / 1e4;
101
+ const out = (o) => console.log(JSON.stringify(o));
102
+
103
+ // --- tiny arg parsing: locate.mjs <cmd> <img?> --k v ---
104
+ const [cmd, ...rest] = process.argv.slice(2);
105
+ const pos = rest.filter((a) => !a.startsWith("--"));
106
+ const opt = {};
107
+ for (let i = 0; i < rest.length; i++)
108
+ if (rest[i].startsWith("--")) opt[rest[i].slice(2)] = rest[i + 1];
109
+ const img = pos[0];
110
+
111
+ if (cmd === "overlay") {
112
+ const dir = opt.out || ".";
113
+ mkdirSync(dir, { recursive: true });
114
+ const n = Number(opt.n || N1);
115
+ const { w, h } = probe(img);
116
+ const fz = Math.max(16, Math.round(Math.min(w, h) / 22));
117
+ ff(["-i", img, "-vf", gridFilters(w, h, n, "v", fz).join(","), `${dir}/gv.png`]);
118
+ ff(["-i", img, "-vf", gridFilters(w, h, n, "h", fz).join(","), `${dir}/gh.png`]);
119
+ out({
120
+ w,
121
+ h,
122
+ n,
123
+ vertical: `${dir}/gv.png`,
124
+ horizontal: `${dir}/gh.png`,
125
+ next: "READ gv.png + gh.png, then: locate.mjs region <img> --vids .. --hids .. --out " + dir,
126
+ });
127
+ } else if (cmd === "region") {
128
+ const dir = opt.out || ".";
129
+ mkdirSync(dir, { recursive: true });
130
+ const n = Number(opt.n || N1),
131
+ nf = Number(opt.nf || N2);
132
+ const reg = regionOf(ids(opt.vids), ids(opt.hids), n, PAD1);
133
+ const { w, h } = probe(img);
134
+ const cx = Math.floor(reg[0] * w),
135
+ cy = Math.floor(reg[1] * h);
136
+ const cw = Math.max(2, Math.floor((reg[2] - reg[0]) * w)),
137
+ ch = Math.max(2, Math.floor((reg[3] - reg[1]) * h));
138
+ const uw = Math.max(cw, 640),
139
+ uh = Math.round((ch * uw) / cw);
140
+ const fz = Math.max(15, Math.round(Math.min(uw, uh) / 16));
141
+ ff([
142
+ "-i",
143
+ img,
144
+ "-vf",
145
+ [
146
+ `crop=${cw}:${ch}:${cx}:${cy}`,
147
+ `scale=${uw}:${uh}`,
148
+ ...gridFilters(uw, uh, nf, "both", fz),
149
+ ].join(","),
150
+ `${dir}/gc.png`,
151
+ ]);
152
+ out({
153
+ region: reg.map(r4),
154
+ crop_grid: `${dir}/gc.png`,
155
+ nf,
156
+ next: `READ gc.png, then: locate.mjs final <img> --region ${reg.map(r4).join(",")} --vids .. --hids ..`,
157
+ });
158
+ } else if (cmd === "final") {
159
+ const nf = Number(opt.nf || N2);
160
+ const reg = opt.region.split(",").map(Number);
161
+ const rl = regionOf(ids(opt.vids), ids(opt.hids), nf, PAD2);
162
+ const [x0, y0, x1, y1] = reg;
163
+ const box = [
164
+ x0 + rl[0] * (x1 - x0),
165
+ y0 + rl[1] * (y1 - y0),
166
+ x0 + rl[2] * (x1 - x0),
167
+ y0 + rl[3] * (y1 - y0),
168
+ ].map(r4);
169
+ out({
170
+ box,
171
+ center: [r4((box[0] + box[2]) / 2), r4((box[1] + box[3]) / 2)],
172
+ next:
173
+ "VERIFY: locate.mjs mark <img> --box " +
174
+ box.join(",") +
175
+ " --out <dir>/check.png — then READ it",
176
+ });
177
+ } else if (cmd === "mark") {
178
+ const box = opt.box.split(",").map(Number);
179
+ const { w, h } = probe(img);
180
+ const bx = Math.round(box[0] * w),
181
+ by = Math.round(box[1] * h);
182
+ const bw = Math.max(2, Math.round((box[2] - box[0]) * w)),
183
+ bh = Math.max(2, Math.round((box[3] - box[1]) * h));
184
+ const dst = opt.out || "./check.png";
185
+ ff(["-i", img, "-vf", `drawbox=x=${bx}:y=${by}:w=${bw}:h=${bh}:color=${RED}@1:t=6`, dst]);
186
+ out({
187
+ marked: dst,
188
+ next: "READ it — red box on the target? If off, redo region/final with corrected strips.",
189
+ });
190
+ } else if (cmd === "auto") {
191
+ // OPTIONAL fast path — only if a strong detector key happens to exist. Never assume it.
192
+ const key = process.env.GEMINI_API_KEY;
193
+ if (!key) {
194
+ console.error(
195
+ "auto needs GEMINI_API_KEY; use the grid loop instead (overlay→region→final→mark)",
196
+ );
197
+ process.exit(1);
198
+ }
199
+ const target = pos[1];
200
+ const b64 = execFileSync("base64", ["-i", img]).toString().replace(/\n/g, "");
201
+ const mime = img.match(/\.png$/i) ? "image/png" : "image/jpeg";
202
+ const body = {
203
+ contents: [
204
+ {
205
+ parts: [
206
+ { inline_data: { mime_type: mime, data: b64 } },
207
+ {
208
+ text: `Detect "${target}". Return ONLY {"box_2d":[ymin,xmin,ymax,xmax]} integers 0-1000.`,
209
+ },
210
+ ],
211
+ },
212
+ ],
213
+ generationConfig: { temperature: 0, response_mime_type: "application/json" },
214
+ };
215
+ const res = await fetch(
216
+ `https://generativelanguage.googleapis.com/v1beta/models/gemini-3.5-flash:generateContent?key=${key}`,
217
+ { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(body) },
218
+ );
219
+ const t = (await res.json()).candidates[0].content.parts[0].text;
220
+ let bb = JSON.parse(t.match(/\{[\s\S]*\}/)[0]).box_2d;
221
+ if (Array.isArray(bb[0])) bb = bb[0];
222
+ const s = Math.max(...bb) > 1.5 ? 1000 : 1;
223
+ const box = [bb[1] / s, bb[0] / s, bb[3] / s, bb[2] / s].map(r4);
224
+ out({ box, center: [r4((box[0] + box[2]) / 2), r4((box[1] + box[3]) / 2)] });
225
+ } else {
226
+ console.error("usage: locate.mjs overlay|region|final|mark|auto … (see header comment)");
227
+ process.exit(1);
228
+ }