hyperframes 0.8.111 → 0.8.113

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 (189) hide show
  1. package/dist/{add-M5WN2AM2.js → add-ILIGSLV4.js} +15 -15
  2. package/dist/{agentPromptGenerator-QL2KAWEP.js → agentPromptGenerator-VIIPZCJ3.js} +1 -1
  3. package/dist/{animatedGifPrep-NMGFOSIL.js → animatedGifPrep-U7FMC7DB.js} +6 -6
  4. package/dist/{asset-GUASPIKN.js → asset-OFDEIAGM.js} +2 -2
  5. package/dist/{assetCataloger-FXEHOUA3.js → assetCataloger-5LCGR5XU.js} +2 -2
  6. package/dist/{auth-3YMEVUKJ.js → auth-5JDDEX2M.js} +2 -2
  7. package/dist/{autoUpdate-FYCGHBPC.js → autoUpdate-JXVZVJCV.js} +2 -2
  8. package/dist/{backgroundChecks-ZLYIRMTS.js → backgroundChecks-BBWGY3V6.js} +3 -3
  9. package/dist/backgroundChecksWorker.js +3 -3
  10. package/dist/{batchRender-ZTHFMHZY.js → batchRender-QVJ7NEUH.js} +3 -3
  11. package/dist/{beats-GXY5ZBPB.js → beats-YEYVQMX6.js} +11 -11
  12. package/dist/{benchmark-MJFVBVNW.js → benchmark-J2V46VWI.js} +12 -12
  13. package/dist/{browser-ZDI7IX6H.js → browser-XBWASLD2.js} +11 -11
  14. package/dist/{bundleWithLocalizedFonts-4Q3ETTHW.js → bundleWithLocalizedFonts-4CVITCYK.js} +2 -2
  15. package/dist/{capture-4OPH4PMK.js → capture-F2Y7TIHU.js} +41 -43
  16. package/dist/{capture-OG6532RA.js → capture-GLHK4ST7.js} +3 -3
  17. package/dist/{captureFile-JOPOCRU7.js → captureFile-LYOJOUIE.js} +3 -1
  18. package/dist/{catalog-23DP7KCW.js → catalog-3QDMTDK2.js} +15 -15
  19. package/dist/{check-5X6BJA2P.js → check-O3RR4NWI.js} +52 -40
  20. package/dist/{checkBrowser-3QHBTMYM.js → checkBrowser-K36DAG4S.js} +32 -31
  21. package/dist/{chunk-NIGUNLOO.js → chunk-2DBYGR4N.js} +10 -9
  22. package/dist/{chunk-TIZQC44K.js → chunk-3IUSKIZW.js} +1 -1
  23. package/dist/{chunk-YLOSZHA2.js → chunk-3XPZJUKM.js} +2 -2
  24. package/dist/{chunk-32P7FTFC.js → chunk-4KGMIOMY.js} +9 -8
  25. package/dist/{chunk-N34BYX3E.js → chunk-4PFZPP2N.js} +54 -30
  26. package/dist/{chunk-JTTAS7N6.js → chunk-7543YIMQ.js} +1 -1
  27. package/dist/{chunk-AMSBTN6L.js → chunk-7CGIICLA.js} +3 -3
  28. package/dist/{chunk-LAQEZHOH.js → chunk-BOUDTDBQ.js} +1 -1
  29. package/dist/chunk-C6AIZOQN.js +3541 -0
  30. package/dist/{chunk-EE6SV6KW.js → chunk-DDK22K3I.js} +3 -3
  31. package/dist/{chunk-QXERSWXX.js → chunk-DQBY7FRR.js} +123 -3
  32. package/dist/{chunk-HQGJLZB6.js → chunk-DR7QW6C5.js} +2 -2
  33. package/dist/{chunk-E4AYSXMS.js → chunk-E52XEEAA.js} +3 -3
  34. package/dist/{chunk-J4RPT4QW.js → chunk-E6RPWJVC.js} +1 -1
  35. package/dist/{chunk-QMAXDSCH.js → chunk-EMZF2TPA.js} +2 -2
  36. package/dist/{chunk-XYVFPDNU.js → chunk-ENHAGQEP.js} +1 -1
  37. package/dist/{chunk-B25H4M4V.js → chunk-FCEFKWPM.js} +1 -1
  38. package/dist/{chunk-BQYGGX3B.js → chunk-FW7K32YT.js} +1 -1
  39. package/dist/{chunk-6CI65KCP.js → chunk-FXHVADV6.js} +1 -1
  40. package/dist/{chunk-OF3RKOPU.js → chunk-G2T2X6FZ.js} +189 -111
  41. package/dist/{chunk-5ON5GH3X.js → chunk-GDJ74GHW.js} +4 -3
  42. package/dist/{chunk-I5WWEBDG.js → chunk-HTQR7SUZ.js} +1 -1
  43. package/dist/{chunk-TQKKC4MB.js → chunk-HYXL3VJA.js} +5 -5
  44. package/dist/{chunk-AWUZ3AUD.js → chunk-IP3XINRB.js} +1 -1
  45. package/dist/{chunk-HPEHQUJX.js → chunk-IRJBTYJF.js} +1 -1
  46. package/dist/chunk-K4WKGXRC.js +18 -0
  47. package/dist/{chunk-CQRF7VU3.js → chunk-L5QASNBN.js} +1 -1
  48. package/dist/{chunk-ITBEN3QD.js → chunk-L5SYYW2P.js} +2 -2
  49. package/dist/{chunk-MGFVNTIB.js → chunk-LMC46FK5.js} +2 -2
  50. package/dist/chunk-MRF4AMKD.js +104 -0
  51. package/dist/{chunk-U4TDAJZE.js → chunk-OCNCK5FQ.js} +2 -2
  52. package/dist/{chunk-JWPSBANO.js → chunk-OEA2J2TF.js} +3 -3
  53. package/dist/{chunk-N32ITJ7L.js → chunk-P3FGUSFK.js} +15 -12
  54. package/dist/{chunk-2JXJ5SGK.js → chunk-QPR4N2D4.js} +6 -6
  55. package/dist/{chunk-LFUXJBYA.js → chunk-R4NWAW35.js} +7 -7
  56. package/dist/{chunk-C4TZBEHY.js → chunk-SIN32SJB.js} +2 -2
  57. package/dist/{chunk-M224DAMG.js → chunk-T3NMEYGM.js} +1 -1
  58. package/dist/{chunk-Q2QNAFQV.js → chunk-U4VSY56O.js} +1 -1
  59. package/dist/{chunk-NH75EKOP.js → chunk-VFCKXTBB.js} +6 -3
  60. package/dist/{chunk-V4HKT2LV.js → chunk-VIJ35BJ6.js} +10 -10
  61. package/dist/{chunk-5ER3PYYP.js → chunk-VLC7JS4K.js} +1 -1
  62. package/dist/{chunk-MR2LOG32.js → chunk-VTP4VSRP.js} +8 -8
  63. package/dist/{chunk-ZU54D6MI.js → chunk-XFJXFNJF.js} +3 -3
  64. package/dist/{chunk-YIXEH4TF.js → chunk-XXKBPGPJ.js} +2 -2
  65. package/dist/{chunk-JUP65S7D.js → chunk-XZM2I47O.js} +3 -3
  66. package/dist/{chunk-BAVM2XBR.js → chunk-YJEGT5L6.js} +209 -33
  67. package/dist/{chunk-CFC3EEDQ.js → chunk-ZMMSMDCA.js} +1 -1
  68. package/dist/{chunk-PFEKMIN5.js → chunk-ZYSS3JED.js} +1 -1
  69. package/dist/{chunk-ZXSNGIYS.js → chunk-ZZIXIOK2.js} +4 -4
  70. package/dist/{clean-ATMEGSGP.js → clean-RPB34TT6.js} +16 -16
  71. package/dist/cli.js +122 -54
  72. package/dist/{cloud-ZFGUHACY.js → cloud-QECFFPKC.js} +4 -4
  73. package/dist/{cloudrun-LVZ4OPPC.js → cloudrun-BML6ZG7K.js} +3 -3
  74. package/dist/commands/layout-audit.browser.js +178 -202
  75. package/dist/commands/motion-sample.browser.js +24 -71
  76. package/dist/commands/motion-signature.browser.js +374 -0
  77. package/dist/{compare-55LEUY7M.js → compare-PF6WHQ4T.js} +26 -26
  78. package/dist/{compiler-C32VXLE2.js → compiler-ZHVIEP26.js} +3 -3
  79. package/dist/{component-3EDFANIC.js → component-4ENCNLED.js} +3 -3
  80. package/dist/{compositions-OPU6U6GM.js → compositions-5UA33RSG.js} +11 -11
  81. package/dist/{contactSheet-54AJDSR5.js → contactSheet-27SRU7A4.js} +2 -2
  82. package/dist/{delete-PJE4P3HH.js → delete-SARS5LIK.js} +2 -2
  83. package/dist/{deploy-4T3RMA5G.js → deploy-MX76RZ36.js} +1 -1
  84. package/dist/{destroy-EYDBVHGF.js → destroy-H2TZBYHH.js} +1 -1
  85. package/dist/{dist-FMHQMEMX.js → dist-HRBNHR4M.js} +1 -1
  86. package/dist/{dist-YUIPB7OX.js → dist-OKRUIHYU.js} +2 -2
  87. package/dist/docker/Dockerfile.render +1 -1
  88. package/dist/{doctor-EIVBJJAF.js → doctor-TSAQGYP4.js} +11 -11
  89. package/dist/{events-NP666TF4.js → events-3HUO73ZE.js} +9 -9
  90. package/dist/{events-ISMT4RDW.js → events-SZ5NWYWD.js} +8 -8
  91. package/dist/{feedback-4OSLMKBW.js → feedback-42OTOFC6.js} +10 -10
  92. package/dist/{figma-Y7ZHFCOU.js → figma-RYNFCYXB.js} +3 -3
  93. package/dist/fontLocalizeCli.js +8 -8
  94. package/dist/{get-E4GBRHQK.js → get-IRHLG5OQ.js} +2 -2
  95. package/dist/{gpuPolicy-CA6KRFQQ.js → gpuPolicy-LRMOZXFU.js} +6 -6
  96. package/dist/{grade-compare-B2EHEOLR.js → grade-compare-KGJP5HV7.js} +24 -24
  97. package/dist/{help-ISGUWGOR.js → help-C5HS56RZ.js} +1 -1
  98. package/dist/{history-FNRU3TL4.js → history-DFJNDM2T.js} +16 -17
  99. package/dist/hyperframe-runtime.js +54 -54
  100. package/dist/hyperframe.manifest.json +1 -1
  101. package/dist/hyperframe.runtime.iife.js +54 -54
  102. package/dist/hyperframes-player.global.js +1 -1
  103. package/dist/{info-FO7VR5NC.js → info-26GTDTKN.js} +11 -11
  104. package/dist/{init-IGW4DTVC.js → init-RXA6NI73.js} +25 -24
  105. package/dist/{inspect-D4GUGDW7.js → inspect-2S5GAZYC.js} +25 -25
  106. package/dist/{installer-NBEN3ZIP.js → installer-DGYYDGWJ.js} +4 -4
  107. package/dist/{keyframes-CXZLEC3R.js → keyframes-WBMAX7XZ.js} +12 -12
  108. package/dist/{lambda-BFHJMMCG.js → lambda-OQBFCEFA.js} +6 -6
  109. package/dist/{layout-XEDEOLAH.js → layout-ZRU7PXBG.js} +25 -25
  110. package/dist/{lint-LLGMCVZ5.js → lint-ATVNZ6FG.js} +12 -12
  111. package/dist/{lintProject-X7L7EZWZ.js → lintProject-TOLC6HDS.js} +1 -1
  112. package/dist/{list-LUCWSLK6.js → list-E2GHYPCQ.js} +2 -2
  113. package/dist/{login-SMWYXJWJ.js → login-LOC4KA7H.js} +4 -4
  114. package/dist/{manager-NEVLEZK3.js → manager-CT3D67CG.js} +1 -1
  115. package/dist/{media-treatment-OYTNU6PX.js → media-treatment-L43MVH2V.js} +15 -14
  116. package/dist/{models-RILNQV3Z.js → models-JF5OOZ5A.js} +7 -7
  117. package/dist/{motionShot-5F4DCMWC.js → motionShot-BJ5CLYMN.js} +12 -12
  118. package/dist/{normalize-audio-4LHYKFON.js → normalize-audio-K33FKGAF.js} +11 -11
  119. package/dist/{pipeline-5UY45ELH.js → pipeline-IWPF5ZMK.js} +6 -6
  120. package/dist/{play-D4AHRZQD.js → play-PHHXYCQI.js} +20 -20
  121. package/dist/{preflight-3V5IHGWQ.js → preflight-2GH2Z4GZ.js} +8 -8
  122. package/dist/{present-VUH7PLOO.js → present-KBFK2YVB.js} +16 -16
  123. package/dist/{preview-NCFC65VR.js → preview-T3E5TFDC.js} +159 -87
  124. package/dist/{producer-7JGAPEAF.js → producer-SL66UNEP.js} +1 -1
  125. package/dist/{projectConfig-JHEWPAA5.js → projectConfig-7AKXZNNR.js} +6 -6
  126. package/dist/{publication-7XA2H7UB.js → publication-B2OERUY7.js} +2 -2
  127. package/dist/{publish-257VZMWI.js → publish-ZGKT7KED.js} +8 -8
  128. package/dist/{remove-background-EV6XVADN.js → remove-background-4LRTT6YL.js} +7 -7
  129. package/dist/{render-DHCMWKFV.js → render-H6RSJF2V.js} +12 -12
  130. package/dist/{render-DKXGFQVW.js → render-OKNPNMFS.js} +23 -23
  131. package/dist/{render-4C3YKVZI.js → render-TGCDBKMP.js} +3 -3
  132. package/dist/{render-batch-AFDBPDMM.js → render-batch-WRQFW4UC.js} +3 -3
  133. package/dist/{renderCancellation-VIZELWDD.js → renderCancellation-BFCQYGVV.js} +6 -6
  134. package/dist/renderSetupWorker.js +2 -2
  135. package/dist/{resolver-S72XBTEQ.js → resolver-37UOGAMT.js} +4 -4
  136. package/dist/{screenshotCapture-FA5HPN7Q.js → screenshotCapture-ECBTLCU6.js} +3 -3
  137. package/dist/{sherpa-BAADWCHB.js → sherpa-SDVKYXCX.js} +7 -7
  138. package/dist/skills/hyperframes/references/frame-worker-core.md +2 -2
  139. package/dist/skills/hyperframes-cli/references/lint-validate-inspect.md +2 -2
  140. package/dist/skills/media-use/audio/references/bgm.md +1 -1
  141. package/dist/skills/media-use/audio/references/tts.md +1 -1
  142. package/dist/skills/media-use/audio/scripts/lib/python.mjs +19 -5
  143. package/dist/skills/media-use/audio/scripts/lib/python.test.mjs +69 -1
  144. package/dist/{skills-2BGFBUR6.js → skills-O25ZTFTO.js} +40 -14
  145. package/dist/{skillsUpdateCheck-5LYFYHUF.js → skillsUpdateCheck-Y2V4OMMT.js} +3 -3
  146. package/dist/{snapshot-Z37DZL4T.js → snapshot-KGM2HZIC.js} +52 -31
  147. package/dist/{src-GD7RGV5U.js → src-PJJ6NISA.js} +5 -5
  148. package/dist/{src-GRC63B6L.js → src-PLWCT745.js} +7 -7
  149. package/dist/{staticProjectServer-SFINO3DE.js → staticProjectServer-OCE7GU5S.js} +14 -14
  150. package/dist/{status-LXQL3L3H.js → status-LENRPQS5.js} +6 -6
  151. package/dist/studio/assets/{hyperframes-player-DvJeHBHi.js → hyperframes-player-DzJbtQVO.js} +1 -1
  152. package/dist/studio/assets/{index-SFktf7O1.js → index-DRhF3v4Z.js} +194 -194
  153. package/dist/studio/assets/{index-C7apTvpr.css → index-DbfKVTId.css} +1 -1
  154. package/dist/studio/assets/{index--G6c4Q_x.js → index-DgwDQK5G.js} +1 -1
  155. package/dist/studio/assets/{index-Bt4vDkfw.js → index-n5FUn1xv.js} +1 -1
  156. package/dist/studio/{chunk-PQFEBX32.js → chunk-BIUXP3PG.js} +2 -2
  157. package/dist/studio/{chunk-6LUNLTHR.js → chunk-K47E2ZJA.js} +13 -8
  158. package/dist/studio/chunk-K47E2ZJA.js.map +1 -0
  159. package/dist/studio/{chunk-QUXZVHOJ.js → chunk-VWT7STY3.js} +2 -2
  160. package/dist/studio/{domEditingLayers-JQPQGGT7.js → domEditingLayers-V67MS4WP.js} +3 -3
  161. package/dist/studio/index.d.ts +80 -46
  162. package/dist/studio/index.html +2 -2
  163. package/dist/studio/index.js +7294 -6844
  164. package/dist/studio/index.js.map +1 -1
  165. package/dist/studio/player.js +2 -2
  166. package/dist/studio/styles.css +1 -1
  167. package/dist/{studio-api-WRSCXPWS.js → studio-api-IEQ5BIHT.js} +8 -8
  168. package/dist/{studioSelectionClient-A6JCWRRW.js → studioSelectionClient-IUUPKUHZ.js} +1 -2
  169. package/dist/{studioServer-HTLRGC5G.js → studioServer-LXJ34MGN.js} +43 -43
  170. package/dist/{system-EEWYEHYX.js → system-4KRSV2B7.js} +6 -6
  171. package/dist/{telemetry-NLEEMXO2.js → telemetry-R3BPD6VK.js} +9 -9
  172. package/dist/{timeline-7C4KM3KD.js → timeline-N5UKVS2S.js} +15 -15
  173. package/dist/{tokens-QQLJXW4G.js → tokens-774UBF2R.js} +2 -2
  174. package/dist/{transcribe-GCKJF5A6.js → transcribe-3UXXEDXX.js} +7 -7
  175. package/dist/{transcribe-TGR5CTA7.js → transcribe-IP74EZLM.js} +12 -12
  176. package/dist/{tts-DO2W6NLB.js → tts-P3LIPIL5.js} +13 -6
  177. package/dist/{updateCheck-73JM5QR3.js → updateCheck-EXHNAPKI.js} +2 -2
  178. package/dist/{upgrade-V6E5P53C.js → upgrade-A4M3O2F2.js} +2 -2
  179. package/dist/{urlDownloader-NYXPEBUN.js → urlDownloader-4KNER64L.js} +5 -5
  180. package/dist/{validate-INP7WJAK.js → validate-DV75GM6J.js} +15 -15
  181. package/dist/{video-KWQ5TSVD.js → video-GINAMW5I.js} +17 -9
  182. package/package.json +1 -1
  183. package/dist/chunk-5GQAJ43Q.js +0 -31
  184. package/dist/chunk-VWA4HODG.js +0 -129
  185. package/dist/chunk-YLVI7VL5.js +0 -3541
  186. package/dist/studio/chunk-6LUNLTHR.js.map +0 -1
  187. /package/dist/studio/{chunk-PQFEBX32.js.map → chunk-BIUXP3PG.js.map} +0 -0
  188. /package/dist/studio/{chunk-QUXZVHOJ.js.map → chunk-VWT7STY3.js.map} +0 -0
  189. /package/dist/studio/{domEditingLayers-JQPQGGT7.js.map → domEditingLayers-V67MS4WP.js.map} +0 -0
@@ -28,7 +28,7 @@ import {
28
28
  reportVariableIssues,
29
29
  resolveVariablesArg,
30
30
  validateVariablesAgainstProject
31
- } from "./chunk-CFC3EEDQ.js";
31
+ } from "./chunk-ZMMSMDCA.js";
32
32
  import {
33
33
  buildPublishFileMap,
34
34
  zipPublishFileMap
@@ -38,20 +38,20 @@ import "./chunk-DNXD7TOA.js";
38
38
  import "./chunk-WEATBQTR.js";
39
39
  import {
40
40
  resolveProject
41
- } from "./chunk-HPEHQUJX.js";
41
+ } from "./chunk-IRJBTYJF.js";
42
42
  import {
43
43
  errorBox,
44
44
  formatBytes,
45
45
  formatDuration
46
46
  } from "./chunk-IHFUKJOR.js";
47
47
  import "./chunk-PFCFR3KZ.js";
48
- import "./chunk-AMSBTN6L.js";
49
- import "./chunk-EE6SV6KW.js";
48
+ import "./chunk-7CGIICLA.js";
49
+ import "./chunk-DDK22K3I.js";
50
50
  import "./chunk-VWG7OQKU.js";
51
51
  import {
52
52
  c
53
53
  } from "./chunk-ZTZA4UWZ.js";
54
- import "./chunk-CQRF7VU3.js";
54
+ import "./chunk-L5QASNBN.js";
55
55
  import "./chunk-AMKC3AXA.js";
56
56
  import {
57
57
  defineCommand
@@ -60,16 +60,16 @@ import "./chunk-54HJ63Q2.js";
60
60
  import {
61
61
  failCommand
62
62
  } from "./chunk-PBN6GBJE.js";
63
- import "./chunk-OF3RKOPU.js";
64
- import "./chunk-B25H4M4V.js";
63
+ import "./chunk-G2T2X6FZ.js";
64
+ import "./chunk-FCEFKWPM.js";
65
65
  import "./chunk-UUDQD62L.js";
66
66
  import "./chunk-DPVXBVLL.js";
67
- import "./chunk-U4TDAJZE.js";
68
- import "./chunk-YLVI7VL5.js";
67
+ import "./chunk-OCNCK5FQ.js";
68
+ import "./chunk-C6AIZOQN.js";
69
69
  import "./chunk-VC76R6W2.js";
70
70
  import "./chunk-OFQWTKPW.js";
71
71
  import "./chunk-TWWSYAKJ.js";
72
- import "./chunk-BAVM2XBR.js";
72
+ import "./chunk-YJEGT5L6.js";
73
73
  import "./chunk-HBBJFK6I.js";
74
74
  import "./chunk-PJ3HDUCY.js";
75
75
  import "./chunk-TQFG7HTI.js";
@@ -77,12 +77,12 @@ import "./chunk-GK4AIFIH.js";
77
77
  import "./chunk-2PSPARWP.js";
78
78
  import {
79
79
  withMeta
80
- } from "./chunk-Q2QNAFQV.js";
80
+ } from "./chunk-U4VSY56O.js";
81
81
  import "./chunk-K4WIOZFP.js";
82
82
  import "./chunk-XUXGIA7H.js";
83
83
  import "./chunk-WERLJGIC.js";
84
84
  import "./chunk-ISN5GRYI.js";
85
- import "./chunk-YLOSZHA2.js";
85
+ import "./chunk-3XPZJUKM.js";
86
86
  import {
87
87
  normalizeErrorMessage
88
88
  } from "./chunk-KNU5COPB.js";
@@ -6,15 +6,15 @@ var __filename = __hf_fileURLToPath(import.meta.url);
6
6
  var __dirname = __hf_dirname(__filename);
7
7
  import {
8
8
  maybePromptRenderFeedback
9
- } from "./chunk-ZXSNGIYS.js";
9
+ } from "./chunk-ZZIXIOK2.js";
10
10
  import {
11
11
  reportVariableIssues,
12
12
  resolveVariablesArg,
13
13
  validateVariablesAgainstProject
14
- } from "./chunk-CFC3EEDQ.js";
14
+ } from "./chunk-ZMMSMDCA.js";
15
15
  import {
16
16
  loadProducer
17
- } from "./chunk-5ER3PYYP.js";
17
+ } from "./chunk-VLC7JS4K.js";
18
18
  import {
19
19
  renderJobObservabilityTelemetryPayload
20
20
  } from "./chunk-VXVRPIJA.js";
@@ -28,11 +28,11 @@ import {
28
28
  resolveBrowserTimeoutMsArg,
29
29
  resolveCompositionEntryArg,
30
30
  resolveDefaultFpsArg
31
- } from "./chunk-TIZQC44K.js";
31
+ } from "./chunk-3IUSKIZW.js";
32
32
  import "./chunk-YEIFI443.js";
33
33
  import {
34
34
  resolveProject
35
- } from "./chunk-HPEHQUJX.js";
35
+ } from "./chunk-IRJBTYJF.js";
36
36
  import {
37
37
  formatLintStartupMessage
38
38
  } from "./chunk-6CSYCFQV.js";
@@ -46,21 +46,21 @@ import {
46
46
  } from "./chunk-IHFUKJOR.js";
47
47
  import {
48
48
  runEnvironmentChecks
49
- } from "./chunk-E4AYSXMS.js";
49
+ } from "./chunk-E52XEEAA.js";
50
50
  import "./chunk-PFCFR3KZ.js";
51
51
  import {
52
52
  loadProjectConfig,
53
53
  readProjectConfigWithStatus,
54
54
  seedProjectAuthoringSkill
55
- } from "./chunk-LAQEZHOH.js";
55
+ } from "./chunk-BOUDTDBQ.js";
56
56
  import "./chunk-XT7X6QCP.js";
57
57
  import "./chunk-4YYJOFKS.js";
58
58
  import {
59
59
  normalizeSkillSlug
60
60
  } from "./chunk-HVW7ABXD.js";
61
- import "./chunk-XYVFPDNU.js";
62
- import "./chunk-HQGJLZB6.js";
63
- import "./chunk-AWUZ3AUD.js";
61
+ import "./chunk-ENHAGQEP.js";
62
+ import "./chunk-DR7QW6C5.js";
63
+ import "./chunk-IP3XINRB.js";
64
64
  import "./chunk-AWDFDFI3.js";
65
65
  import "./chunk-GMECXFAN.js";
66
66
  import {
@@ -73,21 +73,21 @@ import {
73
73
  } from "./chunk-TVCRUG2S.js";
74
74
  import {
75
75
  createRenderCancellationScope
76
- } from "./chunk-JTTAS7N6.js";
76
+ } from "./chunk-7543YIMQ.js";
77
77
  import {
78
78
  trackRenderComplete,
79
79
  trackRenderError,
80
80
  trackRenderObservation,
81
81
  trackRenderPreflightRejected
82
- } from "./chunk-AMSBTN6L.js";
83
- import "./chunk-EE6SV6KW.js";
82
+ } from "./chunk-7CGIICLA.js";
83
+ import "./chunk-DDK22K3I.js";
84
84
  import "./chunk-VWG7OQKU.js";
85
85
  import {
86
86
  c
87
87
  } from "./chunk-ZTZA4UWZ.js";
88
88
  import {
89
89
  bytesToMb
90
- } from "./chunk-CQRF7VU3.js";
90
+ } from "./chunk-L5QASNBN.js";
91
91
  import "./chunk-AMKC3AXA.js";
92
92
  import {
93
93
  markRenderSucceeded,
@@ -109,13 +109,13 @@ import {
109
109
  MAX_VP9_CPU_USED,
110
110
  MIN_VP9_CPU_USED,
111
111
  isVideoFrameFormat
112
- } from "./chunk-OF3RKOPU.js";
112
+ } from "./chunk-G2T2X6FZ.js";
113
113
  import {
114
114
  formatRenderOutputTimestamp,
115
115
  fpsToFfmpegArg,
116
116
  fpsToNumber,
117
117
  parseFps
118
- } from "./chunk-B25H4M4V.js";
118
+ } from "./chunk-FCEFKWPM.js";
119
119
  import {
120
120
  checkOutputResolutionCompatibility,
121
121
  isAspectAgnosticResolutionAlias,
@@ -123,14 +123,14 @@ import {
123
123
  suggestMatchingPreset
124
124
  } from "./chunk-UUDQD62L.js";
125
125
  import "./chunk-DPVXBVLL.js";
126
- import "./chunk-U4TDAJZE.js";
127
- import "./chunk-YLVI7VL5.js";
126
+ import "./chunk-OCNCK5FQ.js";
127
+ import "./chunk-C6AIZOQN.js";
128
128
  import "./chunk-VC76R6W2.js";
129
129
  import "./chunk-OFQWTKPW.js";
130
130
  import {
131
131
  hasDefinitiveEntryMismatch
132
132
  } from "./chunk-Q5X2B5WT.js";
133
- import "./chunk-N34BYX3E.js";
133
+ import "./chunk-4PFZPP2N.js";
134
134
  import {
135
135
  killOrphanedProcessesForRender
136
136
  } from "./chunk-LAOCA3MQ.js";
@@ -142,7 +142,7 @@ import {
142
142
  collectSubCompositionSrcs,
143
143
  lintProject,
144
144
  shouldBlockRender
145
- } from "./chunk-BAVM2XBR.js";
145
+ } from "./chunk-YJEGT5L6.js";
146
146
  import "./chunk-HBBJFK6I.js";
147
147
  import "./chunk-PJ3HDUCY.js";
148
148
  import "./chunk-TQFG7HTI.js";
@@ -161,7 +161,7 @@ import {
161
161
  } from "./chunk-ISN5GRYI.js";
162
162
  import {
163
163
  VERSION
164
- } from "./chunk-YLOSZHA2.js";
164
+ } from "./chunk-3XPZJUKM.js";
165
165
  import {
166
166
  normalizeErrorMessage
167
167
  } from "./chunk-KNU5COPB.js";
@@ -659,7 +659,7 @@ async function executeRenderPlan(plan, dependencies, cancellation) {
659
659
  let batchModule;
660
660
  let preparedBatch;
661
661
  if (plan.batchPath) {
662
- batchModule = await import("./batchRender-ZTHFMHZY.js");
662
+ batchModule = await import("./batchRender-QVJ7NEUH.js");
663
663
  try {
664
664
  preparedBatch = batchModule.prepareBatchRender({
665
665
  batchPath: plan.batchPath,
@@ -748,7 +748,7 @@ function assertRenderActive(cancellation) {
748
748
  cancellation?.signal.throwIfAborted();
749
749
  }
750
750
  async function ensureRenderBrowser(plan, signal) {
751
- const { ensureBrowser } = await import("./manager-NEVLEZK3.js");
751
+ const { ensureBrowser } = await import("./manager-CT3D67CG.js");
752
752
  let browserSpinner;
753
753
  try {
754
754
  if (plan.effectiveQuiet) {
@@ -15,7 +15,7 @@ import {
15
15
  reportVariableIssues,
16
16
  resolveVariablesArg,
17
17
  validateVariablesAgainstProject
18
- } from "./chunk-CFC3EEDQ.js";
18
+ } from "./chunk-ZMMSMDCA.js";
19
19
  import "./chunk-5Z63TBTX.js";
20
20
  import "./chunk-IHFUKJOR.js";
21
21
  import "./chunk-PFCFR3KZ.js";
@@ -25,10 +25,10 @@ import {
25
25
  import {
26
26
  setCommandExitCode
27
27
  } from "./chunk-PBN6GBJE.js";
28
- import "./chunk-B25H4M4V.js";
28
+ import "./chunk-FCEFKWPM.js";
29
29
  import "./chunk-UUDQD62L.js";
30
30
  import "./chunk-DPVXBVLL.js";
31
- import "./chunk-YLVI7VL5.js";
31
+ import "./chunk-C6AIZOQN.js";
32
32
  import "./chunk-VC76R6W2.js";
33
33
  import "./chunk-OFQWTKPW.js";
34
34
  import "./chunk-TQFG7HTI.js";
@@ -14,7 +14,7 @@ import {
14
14
  loadProjectVariableSchema,
15
15
  reportVariableIssues,
16
16
  validateVariablesAgainstSchema
17
- } from "./chunk-CFC3EEDQ.js";
17
+ } from "./chunk-ZMMSMDCA.js";
18
18
  import "./chunk-5Z63TBTX.js";
19
19
  import {
20
20
  errorBox
@@ -27,10 +27,10 @@ import {
27
27
  failCommand,
28
28
  setCommandExitCode
29
29
  } from "./chunk-PBN6GBJE.js";
30
- import "./chunk-B25H4M4V.js";
30
+ import "./chunk-FCEFKWPM.js";
31
31
  import "./chunk-UUDQD62L.js";
32
32
  import "./chunk-DPVXBVLL.js";
33
- import "./chunk-YLVI7VL5.js";
33
+ import "./chunk-C6AIZOQN.js";
34
34
  import "./chunk-VC76R6W2.js";
35
35
  import "./chunk-OFQWTKPW.js";
36
36
  import "./chunk-TQFG7HTI.js";
@@ -7,19 +7,19 @@ var __dirname = __hf_dirname(__filename);
7
7
  import {
8
8
  createRenderCancellationScope,
9
9
  stoppedByCancelSignal
10
- } from "./chunk-JTTAS7N6.js";
11
- import "./chunk-OF3RKOPU.js";
12
- import "./chunk-B25H4M4V.js";
10
+ } from "./chunk-7543YIMQ.js";
11
+ import "./chunk-G2T2X6FZ.js";
12
+ import "./chunk-FCEFKWPM.js";
13
13
  import "./chunk-UUDQD62L.js";
14
14
  import "./chunk-DPVXBVLL.js";
15
- import "./chunk-U4TDAJZE.js";
16
- import "./chunk-YLVI7VL5.js";
15
+ import "./chunk-OCNCK5FQ.js";
16
+ import "./chunk-C6AIZOQN.js";
17
17
  import "./chunk-VC76R6W2.js";
18
18
  import "./chunk-OFQWTKPW.js";
19
19
  import "./chunk-LAOCA3MQ.js";
20
20
  import "./chunk-LCSMOLGX.js";
21
21
  import "./chunk-TWWSYAKJ.js";
22
- import "./chunk-BAVM2XBR.js";
22
+ import "./chunk-YJEGT5L6.js";
23
23
  import "./chunk-HBBJFK6I.js";
24
24
  import "./chunk-PJ3HDUCY.js";
25
25
  import "./chunk-TQFG7HTI.js";
@@ -8,7 +8,7 @@ import "./chunk-Q5X2B5WT.js";
8
8
  import {
9
9
  ensureBrowser,
10
10
  releaseOwnedBrowserInstallLock
11
- } from "./chunk-N34BYX3E.js";
11
+ } from "./chunk-4PFZPP2N.js";
12
12
  import {
13
13
  killOrphanedProcesses
14
14
  } from "./chunk-LAOCA3MQ.js";
@@ -16,7 +16,7 @@ import "./chunk-LCSMOLGX.js";
16
16
  import "./chunk-TWWSYAKJ.js";
17
17
  import {
18
18
  lintProject
19
- } from "./chunk-BAVM2XBR.js";
19
+ } from "./chunk-YJEGT5L6.js";
20
20
  import "./chunk-HBBJFK6I.js";
21
21
  import "./chunk-PJ3HDUCY.js";
22
22
  import "./chunk-TQFG7HTI.js";
@@ -11,14 +11,14 @@ import {
11
11
  resolveItemWithDependencies,
12
12
  resolveItemsByTag,
13
13
  unreachableRegistryMessage
14
- } from "./chunk-XYVFPDNU.js";
15
- import "./chunk-AWUZ3AUD.js";
14
+ } from "./chunk-ENHAGQEP.js";
15
+ import "./chunk-IP3XINRB.js";
16
16
  import "./chunk-AWDFDFI3.js";
17
17
  import "./chunk-GMECXFAN.js";
18
- import "./chunk-B25H4M4V.js";
18
+ import "./chunk-FCEFKWPM.js";
19
19
  import "./chunk-UUDQD62L.js";
20
20
  import "./chunk-DPVXBVLL.js";
21
- import "./chunk-YLVI7VL5.js";
21
+ import "./chunk-C6AIZOQN.js";
22
22
  import "./chunk-VC76R6W2.js";
23
23
  import "./chunk-OFQWTKPW.js";
24
24
  import "./chunk-TQFG7HTI.js";
@@ -8,12 +8,12 @@ import {
8
8
  isDegradableEvaluateTimeoutError
9
9
  } from "./chunk-AWNBM3MZ.js";
10
10
  import {
11
+ ensureCaptureDirSync,
11
12
  writeCaptureFileSync
12
- } from "./chunk-5GQAJ43Q.js";
13
+ } from "./chunk-MRF4AMKD.js";
13
14
  import "./chunk-M2WBOQ2Q.js";
14
15
 
15
16
  // src/capture/screenshotCapture.ts
16
- import { mkdirSync } from "fs";
17
17
  import { join } from "path";
18
18
  var MAX_PLATE_HEIGHT_PX = 16384;
19
19
  function pngHeight(buf) {
@@ -56,7 +56,7 @@ async function captureFullPagePlate(page, screenshotsDir, budget = {}) {
56
56
  }
57
57
  async function captureScrollScreenshots(page, outputDir, budget = {}) {
58
58
  const screenshotsDir = join(outputDir, "screenshots");
59
- mkdirSync(screenshotsDir, { recursive: true });
59
+ ensureCaptureDirSync(outputDir, screenshotsDir);
60
60
  const MAX_SCREENSHOTS = 20;
61
61
  const filePaths = [];
62
62
  if ((budget.remainingMs?.() ?? 1) <= 0) return filePaths;
@@ -11,26 +11,26 @@ import "./chunk-WEATBQTR.js";
11
11
  import {
12
12
  getPreparedWavDurationSeconds,
13
13
  prepareWav
14
- } from "./chunk-I5WWEBDG.js";
14
+ } from "./chunk-HTQR7SUZ.js";
15
15
  import "./chunk-OAF4XJOW.js";
16
16
  import "./chunk-X5HWXQPU.js";
17
17
  import "./chunk-TVCRUG2S.js";
18
18
  import {
19
19
  stoppedByCancelSignal
20
- } from "./chunk-JTTAS7N6.js";
20
+ } from "./chunk-7543YIMQ.js";
21
21
  import "./chunk-AMKC3AXA.js";
22
- import "./chunk-OF3RKOPU.js";
23
- import "./chunk-B25H4M4V.js";
22
+ import "./chunk-G2T2X6FZ.js";
23
+ import "./chunk-FCEFKWPM.js";
24
24
  import "./chunk-UUDQD62L.js";
25
25
  import "./chunk-DPVXBVLL.js";
26
- import "./chunk-U4TDAJZE.js";
27
- import "./chunk-YLVI7VL5.js";
26
+ import "./chunk-OCNCK5FQ.js";
27
+ import "./chunk-C6AIZOQN.js";
28
28
  import "./chunk-VC76R6W2.js";
29
29
  import "./chunk-OFQWTKPW.js";
30
30
  import "./chunk-LAOCA3MQ.js";
31
31
  import "./chunk-LCSMOLGX.js";
32
32
  import "./chunk-TWWSYAKJ.js";
33
- import "./chunk-BAVM2XBR.js";
33
+ import "./chunk-YJEGT5L6.js";
34
34
  import "./chunk-HBBJFK6I.js";
35
35
  import "./chunk-PJ3HDUCY.js";
36
36
  import "./chunk-TQFG7HTI.js";
@@ -17,9 +17,9 @@ You build the frame composition file(s) assigned in your dispatch and nothing el
17
17
  - `blueprint:` — an id (or the literal `compose`): the shot template this frame instantiates — the overall shape + its signature move. Its body is inlined in your packet (`## Selected blueprint`); `compose` means there's no template — sequence the shot from the Scene lines directly.
18
18
  - `focal:` / `roles:` — which element is the hero and what each element is. **Semantics are workflow-specific — see the delta.**
19
19
  - `sfx:` — the orchestrator's; you mount no audio.
20
- - The packet also inlines the **rule recipe** (`## Selected motion rule: <id>`) for each named motion the Scene lines cite — the mechanics for that motion, which you reproduce, **never name-guess** (a guess loses the signature move). If a cited motion's recipe is missing from your packet, read `RULES_DIR/<id>.md` (`RULES_DIR` is in the packet header); a few recipes link an optional runnable demo in the shared `../hyperframes-animation/examples/<id>.html` — open it only when a recipe is unclear.
20
+ - The packet also inlines the **rule recipe** (`## Selected motion rule: <id>`) for each named motion the Scene lines cite — the mechanics for that motion, which you reproduce, **never name-guess** (a guess loses the signature move). If a cited motion's recipe is missing from your packet, read `RULES_DIR/<id>.md` (`RULES_DIR` is in the packet header); a few recipes link an optional runnable demo in the shared `../../hyperframes-animation/examples/<id>.html` — open it only when a recipe is unclear.
21
21
  - `frame.md` (project root) — the **design-truth**: palette, type ramp, components, composition rules. The LOOK. Pull every visual token from here. This is the one file you read outside your packet.
22
- - `../references/cut-catalog.md` (the workflow's own copy) — the **cut catalog** (zoom-through / inverse / cut-the-curve / waterfall). When a Scene seam is a within-scene swap, a scene-to-scene cut, or a text-to-text line change, build it INSIDE your composition per this catalog (Z-scale + blur + opacity, or per-word x-staggers). You never author the between-frame transition — story's `transition_in` + the injector own that.
22
+ - `references/cut-catalog.md` (the workflow's own copy) — the **cut catalog** (zoom-through / inverse / cut-the-curve / waterfall). When a Scene seam is a within-scene swap, a scene-to-scene cut, or a text-to-text line change, build it INSIDE your composition per this catalog (Z-scale + blur + opacity, or per-word x-staggers). You never author the between-frame transition — story's `transition_in` + the injector own that.
23
23
  - Canvas `<width>×<height>` and `Captions: <enabled | disabled>` (+ the keep-out cutoff when enabled).
24
24
 
25
25
  **Retry** — if your context carries `lint` / `check` feedback from a prior pass, read it first and re-author so none of those findings recur; treat each as a hard constraint.
@@ -30,7 +30,7 @@ Lints `index.html` and all files in `compositions/`. Reports errors (must fix),
30
30
  ```bash
31
31
  npx hyperframes check # current directory: the full browser gate
32
32
  npx hyperframes check ./my-project # specific project
33
- npx hyperframes check --json # agent-readable envelope {ok, lint, runtime, layout, motion, contrast, hdr, snapshots}
33
+ npx hyperframes check --json # agent-readable envelope {ok, browserSkipped, lint, runtime, layout, motion, contrast, hdr, snapshots}
34
34
  npx hyperframes check --snapshots # also write overview frames (annotated) + per-finding crops
35
35
  npx hyperframes check --samples 15 # denser timeline sweep (default 9)
36
36
  npx hyperframes check --at 1.5,4,7.25 # explicit hero-frame timestamps
@@ -41,7 +41,7 @@ npx hyperframes check --no-contrast # skip the WCAG audit while iterating
41
41
  npx hyperframes check --strict # exit non-zero on warnings too (default: only errors)
42
42
  ```
43
43
 
44
- One command, one Chrome boot. `check` runs the linter first and skips the browser entirely when lint reports errors. Then it loads the bundled composition once, wires runtime listeners before navigation, and sweeps one seek grid running every audit per sample:
44
+ One command, one Chrome boot. `check` runs the linter first and skips the browser entirely when lint reports errors. When the browser never ran (lint errors, a linter crash, or a browser launch failure), `browserSkipped` is `true` and the `layout`, `motion` and `contrast` sections are empty, not clean. Otherwise it loads the bundled composition once, wires runtime listeners before navigation, and sweeps one seek grid running every audit per sample:
45
45
 
46
46
  - **Runtime**: JavaScript console errors, unhandled exceptions, failed network requests (media-file `ERR_ABORTED` filtered out), HTTP 4xx/5xx.
47
47
  - **Layout**: text extending outside its container or the canvas, text clipped by its own box, held text overlaps and occlusion (with an approximate covered fraction), children escaping clipping containers.
@@ -5,7 +5,7 @@ One music bed per composition, produced by the shared audio engine (`scripts/aud
5
5
  - **HeyGen retrieval — the default when credentialed.** Search HeyGen's music catalog by mood, download the top track. No generation; same `~/.heygen` / `$HEYGEN_API_KEY` credential as TTS.
6
6
  - **Local generation (Lyria → MusicGen) — the fallback when there is no credential** (or when asked for explicitly). Generate a WAV from a mood prompt. There is **no `npx hyperframes bgm` command**; the engine spawns `scripts/lyria-recipe.py` or an inline MusicGen script directly.
7
7
 
8
- > **Run the Preflight first — no credential is not a green light to silently generate locally.** Before generating, complete the sign-in **Preflight** (see `../SKILL.md` → Preflight): run `npx hyperframes auth status`, recommend signing in, and **STOP for the user's choice** (sign in for HeyGen's music library, or continue offline with local generation). This applies to a one-off "generate a BGM" request just as much as inside a full workflow.
8
+ > **Run the Preflight first — no credential is not a green light to silently generate locally.** Before generating, complete the sign-in **Preflight** (see `../../SKILL.md` → Preflight): run `npx hyperframes auth status`, recommend signing in, and **STOP for the user's choice** (sign in for HeyGen's music library, or continue offline with local generation). This applies to a one-off "generate a BGM" request just as much as inside a full workflow.
9
9
 
10
10
  ## Driving it from the request
11
11
 
@@ -4,7 +4,7 @@
4
4
  `--provider` or `--words` flag. For HeyGen audio plus word timestamps, use the
5
5
  bundled `heygen-tts.mjs` script below.
6
6
 
7
- > **Run the Preflight first — no credential is not a green light to silently use the local voice.** Before generating a voiceover, complete the sign-in **Preflight** (see `../SKILL.md` → Preflight): run `npx hyperframes auth status`, recommend signing in, and **STOP for the user's choice** (sign in for HeyGen voices, or continue offline with local Kokoro). This applies to a one-off "generate a voiceover" request just as much as inside a full workflow.
7
+ > **Run the Preflight first — no credential is not a green light to silently use the local voice.** Before generating a voiceover, complete the sign-in **Preflight** (see `../../SKILL.md` → Preflight): run `npx hyperframes auth status`, recommend signing in, and **STOP for the user's choice** (sign in for HeyGen voices, or continue offline with local Kokoro). This applies to a one-off "generate a voiceover" request just as much as inside a full workflow.
8
8
 
9
9
  ## Narrating a HyperFrames docs video
10
10
 
@@ -11,12 +11,20 @@
11
11
  // Resolve once, per process: probe the platform's candidates in order and take
12
12
  // the first that actually runs. `py` is the launcher, so it needs a `-3` arg to
13
13
  // select Python 3 — hence candidates are argv PREFIXES, not bare names.
14
+ //
15
+ // `HYPERFRAMES_PYTHON` (the documented PEP 668 venv setup) wins over the PATH probe, matching
16
+ // the CLI's `findPython()`; ignoring it made BGM silently disable itself (#4614).
14
17
 
15
18
  import { spawnSync } from "node:child_process";
16
19
 
17
- function defaultProbe(cmd, args) {
20
+ // Accept only an interpreter whose `--version` reports Python 3, as the CLI's
21
+ // `validatePythonOverride()` does. Exit status alone would take a Python 2
22
+ // `python` (or any executable that exits 0) that `doctor` rejects. Python 2
23
+ // prints its version to stderr, so read both streams.
24
+ export function defaultProbe(cmd, args) {
18
25
  try {
19
- return spawnSync(cmd, args, { stdio: "ignore" }).status === 0;
26
+ const result = spawnSync(cmd, args, { encoding: "utf-8", timeout: 5000 });
27
+ return result.status === 0 && /Python 3/.test(`${result.stdout}${result.stderr}`);
20
28
  } catch {
21
29
  return false;
22
30
  }
@@ -26,12 +34,18 @@ function defaultProbe(cmd, args) {
26
34
  * Pick the argv prefix that launches Python 3 on this platform.
27
35
  * Returns e.g. `["python3"]`, `["python"]`, or `["py", "-3"]`.
28
36
  *
29
- * Pure except for `probe` (which runs `<cmd> … --version`); both `platform`
30
- * and `probe` are injectable so every branch is unit-testable without spawning.
37
+ * Pure except for `probe` (which runs `<cmd> … --version`); `platform`, `probe`
38
+ * and `env` are injectable so every branch is unit-testable without spawning.
31
39
  * If nothing probes OK, falls back to the canonical name for the platform so
32
40
  * the eventual spawn fails loudly exactly as it did before — never worse.
33
41
  */
34
- export function resolvePythonCommand(platform = process.platform, probe = defaultProbe) {
42
+ export function resolvePythonCommand(
43
+ platform = process.platform,
44
+ probe = defaultProbe,
45
+ env = process.env,
46
+ ) {
47
+ const override = env.HYPERFRAMES_PYTHON;
48
+ if (override && probe(override, ["--version"])) return [override];
35
49
  const candidates =
36
50
  platform === "win32" ? [["python3"], ["python"], ["py", "-3"]] : [["python3"], ["python"]];
37
51
  for (const prefix of candidates) {
@@ -1,6 +1,9 @@
1
1
  import { test } from "node:test";
2
2
  import assert from "node:assert/strict";
3
- import { resolvePythonCommand, pythonInvocation } from "./python.mjs";
3
+ import { chmodSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
4
+ import { tmpdir } from "node:os";
5
+ import { join } from "node:path";
6
+ import { defaultProbe, resolvePythonCommand, pythonInvocation } from "./python.mjs";
4
7
 
5
8
  // Regression: on Windows a standard python.org install has no `python3.exe`
6
9
  // (only `python.exe` + the `py` launcher), so `spawn("python3", …)` ENOENTs and
@@ -55,6 +58,71 @@ test("falls back to the canonical name (loud failure, unchanged) when nothing ru
55
58
  );
56
59
  });
57
60
 
61
+ // Regression (#4614): on PEP 668 systems the documented setup is a venv named
62
+ // by HYPERFRAMES_PYTHON; the audio engine ignored it and probed the bare
63
+ // system python3, so MusicGen BGM was skipped while `doctor` said installed.
64
+ const VENV = "/home/u/.venvs/hf/bin/python";
65
+
66
+ test("HYPERFRAMES_PYTHON wins over python3 on PATH when it runs", () => {
67
+ const env = { HYPERFRAMES_PYTHON: VENV };
68
+ assert.deepEqual(resolvePythonCommand("darwin", probeFor(VENV, "python3"), env), [VENV]);
69
+ assert.deepEqual(resolvePythonCommand("win32", probeFor(VENV, "python", "py"), env), [VENV]);
70
+ });
71
+
72
+ test("a HYPERFRAMES_PYTHON that doesn't run falls through to the PATH probe", () => {
73
+ const env = { HYPERFRAMES_PYTHON: "/nope/python" };
74
+ assert.deepEqual(resolvePythonCommand("linux", probeFor("python3"), env), ["python3"]);
75
+ });
76
+
77
+ test("an empty HYPERFRAMES_PYTHON is ignored without being probed", () => {
78
+ const seen = [];
79
+ const probe = (cmd) => {
80
+ seen.push(cmd);
81
+ return cmd === "python3";
82
+ };
83
+ assert.deepEqual(resolvePythonCommand("linux", probe, { HYPERFRAMES_PYTHON: "" }), ["python3"]);
84
+ assert.deepEqual(seen, ["python3"]);
85
+ });
86
+
87
+ // defaultProbe must match the CLI's validatePythonOverride(): exiting 0 is not
88
+ // enough, `--version` has to report Python 3. Stubs are shell scripts, so
89
+ // these run on POSIX only.
90
+ function withStub(script, fn) {
91
+ const dir = mkdtempSync(join(tmpdir(), "hf-python-probe-"));
92
+ try {
93
+ const stub = join(dir, "python");
94
+ writeFileSync(stub, `#!/bin/sh\n${script}\n`);
95
+ chmodSync(stub, 0o755);
96
+ fn(stub);
97
+ } finally {
98
+ rmSync(dir, { recursive: true, force: true });
99
+ }
100
+ }
101
+
102
+ const posixOnly = { skip: process.platform === "win32" && "stub scripts need a POSIX shell" };
103
+
104
+ test("defaultProbe accepts an interpreter reporting Python 3", posixOnly, () => {
105
+ withStub('echo "Python 3.12.4"', (stub) => assert.equal(defaultProbe(stub, ["--version"]), true));
106
+ });
107
+
108
+ test("defaultProbe rejects Python 2, which prints its version to stderr", posixOnly, () => {
109
+ withStub('echo "Python 2.7.18" >&2', (stub) =>
110
+ assert.equal(defaultProbe(stub, ["--version"]), false),
111
+ );
112
+ });
113
+
114
+ test(
115
+ "defaultProbe rejects an executable that exits 0 without a Python 3 version",
116
+ posixOnly,
117
+ () => {
118
+ withStub("exit 0", (stub) => assert.equal(defaultProbe(stub, ["--version"]), false));
119
+ },
120
+ );
121
+
122
+ test("defaultProbe rejects a command that doesn't exist", () => {
123
+ assert.equal(defaultProbe("/nonexistent/hf-python", ["--version"]), false);
124
+ });
125
+
58
126
  test("pythonInvocation prepends the resolved prefix ahead of caller args", () => {
59
127
  assert.deepEqual(pythonInvocation(["-c", "import x"], ["python"]), {
60
128
  cmd: "python",