@reddoorla/maintenance 0.95.1 → 0.96.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (268) hide show
  1. package/README.md +37 -2
  2. package/dist/airtable-SJV4ZSMS.js +9 -0
  3. package/dist/{announce-CLQYX5I4.js → announce-45HVP4J4.js} +7 -7
  4. package/dist/{blux-4KNXUP2K.js → blux-RUFMNOUJ.js} +5 -5
  5. package/dist/{bump-deps-C5G2EFBB.js → bump-deps-EL3TKMIL.js} +6 -6
  6. package/dist/{chunk-XN37VTDB.js → chunk-37B4LVB3.js} +2 -2
  7. package/dist/{chunk-BVEDKMNG.js → chunk-3EA43S3R.js} +28 -10
  8. package/dist/chunk-3EA43S3R.js.map +1 -0
  9. package/dist/{chunk-XHHMM5HX.js → chunk-43SW3FGW.js} +63 -1
  10. package/dist/chunk-43SW3FGW.js.map +1 -0
  11. package/dist/{chunk-WMBLR5VA.js → chunk-44SDGPGQ.js} +3 -3
  12. package/dist/chunk-4UTJ4G6P.js +52 -0
  13. package/dist/chunk-4UTJ4G6P.js.map +1 -0
  14. package/dist/{chunk-R53VL3RI.js → chunk-5CJVUPJU.js} +1 -1
  15. package/dist/{chunk-R53VL3RI.js.map → chunk-5CJVUPJU.js.map} +1 -1
  16. package/dist/{chunk-KJRVMMM3.js → chunk-62YWOFVN.js} +36 -5
  17. package/dist/chunk-62YWOFVN.js.map +1 -0
  18. package/dist/{chunk-VSGMCCGQ.js → chunk-6INOBNRO.js} +2 -2
  19. package/dist/{chunk-BYGPUUCT.js → chunk-72FJZ6LO.js} +43 -11
  20. package/dist/chunk-72FJZ6LO.js.map +1 -0
  21. package/dist/{chunk-5GUJ36TL.js → chunk-74QRWE6G.js} +2 -2
  22. package/dist/chunk-A5QKNOXW.js +72 -0
  23. package/dist/chunk-A5QKNOXW.js.map +1 -0
  24. package/dist/{chunk-2NQUCS7O.js → chunk-BIYQN7FH.js} +3 -1
  25. package/dist/{chunk-2NQUCS7O.js.map → chunk-BIYQN7FH.js.map} +1 -1
  26. package/dist/{chunk-S7RYFUIK.js → chunk-CA6ADGOC.js} +2 -2
  27. package/dist/chunk-CGQZFQAY.js +38 -0
  28. package/dist/chunk-CGQZFQAY.js.map +1 -0
  29. package/dist/{chunk-YLYXW5PH.js → chunk-CXICCLNM.js} +34 -4
  30. package/dist/chunk-CXICCLNM.js.map +1 -0
  31. package/dist/{chunk-KZRR4NFG.js → chunk-D3CTOCUR.js} +3 -3
  32. package/dist/{chunk-CWXTNPNZ.js → chunk-DVJNYPFR.js} +3 -3
  33. package/dist/chunk-DVJNYPFR.js.map +1 -0
  34. package/dist/{chunk-AVEQUR44.js → chunk-EASYCD6F.js} +60 -17
  35. package/dist/chunk-EASYCD6F.js.map +1 -0
  36. package/dist/{chunk-BCKEP5S6.js → chunk-ECDJDHKT.js} +2 -2
  37. package/dist/{chunk-BI2VI6EM.js → chunk-EQQ4H6L3.js} +2 -2
  38. package/dist/{chunk-WVNDEYXL.js → chunk-GEUC5VGM.js} +11 -5
  39. package/dist/chunk-GEUC5VGM.js.map +1 -0
  40. package/dist/{chunk-Z2K4JPQ3.js → chunk-H445EH33.js} +2 -2
  41. package/dist/chunk-IHHAYXKY.js +351 -0
  42. package/dist/chunk-IHHAYXKY.js.map +1 -0
  43. package/dist/{chunk-FUWFLAWQ.js → chunk-IMYL67JV.js} +3 -3
  44. package/dist/{chunk-3Z6X3BHU.js → chunk-KN52PM63.js} +7 -2
  45. package/dist/{chunk-3Z6X3BHU.js.map → chunk-KN52PM63.js.map} +1 -1
  46. package/dist/{chunk-WJMPCVOR.js → chunk-LAJ3FF54.js} +12 -4
  47. package/dist/chunk-LAJ3FF54.js.map +1 -0
  48. package/dist/{chunk-5UINJNAJ.js → chunk-MZZDMBDT.js} +16 -3
  49. package/dist/chunk-MZZDMBDT.js.map +1 -0
  50. package/dist/{chunk-DFKBTBO3.js → chunk-NVLREB5R.js} +35 -6
  51. package/dist/chunk-NVLREB5R.js.map +1 -0
  52. package/dist/{chunk-R5IMFAFR.js → chunk-OTEVKRAH.js} +3 -3
  53. package/dist/{chunk-2ZAZ7ETT.js → chunk-P4A6D6HO.js} +4 -4
  54. package/dist/{chunk-XPJQXSC4.js → chunk-P7323YVW.js} +27 -5
  55. package/dist/chunk-P7323YVW.js.map +1 -0
  56. package/dist/{chunk-4763KQ6O.js → chunk-PXRN2MER.js} +2 -2
  57. package/dist/{chunk-TR3HFH6J.js → chunk-QFSL2L2B.js} +67 -10
  58. package/dist/chunk-QFSL2L2B.js.map +1 -0
  59. package/dist/{chunk-2LYOAB2E.js → chunk-RRE74VWI.js} +2 -2
  60. package/dist/{chunk-LM2NHRCJ.js → chunk-SHGIDTYF.js} +4 -4
  61. package/dist/chunk-SHGIDTYF.js.map +1 -0
  62. package/dist/{chunk-ZQV7UQNE.js → chunk-SQ4FSNYL.js} +2 -2
  63. package/dist/{chunk-C3IQQKXL.js → chunk-T76MA2FH.js} +110 -1
  64. package/dist/{chunk-C3IQQKXL.js.map → chunk-T76MA2FH.js.map} +1 -1
  65. package/dist/{chunk-6R56OKJZ.js → chunk-UIITN37J.js} +2 -2
  66. package/dist/{chunk-CJ2RMTT7.js → chunk-VEIIUCYL.js} +2 -2
  67. package/dist/{chunk-SVAAONYB.js → chunk-WQLNUEZL.js} +12 -2
  68. package/dist/{chunk-SVAAONYB.js.map → chunk-WQLNUEZL.js.map} +1 -1
  69. package/dist/{chunk-WSJ7RO54.js → chunk-XED2DNAI.js} +23 -5
  70. package/dist/chunk-XED2DNAI.js.map +1 -0
  71. package/dist/{chunk-FSGICFXB.js → chunk-XG2A6GIG.js} +17 -5
  72. package/dist/chunk-XG2A6GIG.js.map +1 -0
  73. package/dist/{chunk-TO7DJYLZ.js → chunk-XY7YV2YQ.js} +178 -39
  74. package/dist/chunk-XY7YV2YQ.js.map +1 -0
  75. package/dist/{chunk-HTABUCF4.js → chunk-Y5BVR4HW.js} +3 -3
  76. package/dist/{chunk-ZCL7C5LH.js → chunk-Y6FCXRIC.js} +1661 -387
  77. package/dist/chunk-Y6FCXRIC.js.map +1 -0
  78. package/dist/{chunk-2SLED3NB.js → chunk-YDZ7XGPZ.js} +1 -1
  79. package/dist/{chunk-2SLED3NB.js.map → chunk-YDZ7XGPZ.js.map} +1 -1
  80. package/dist/{chunk-QF6IQQFP.js → chunk-Z7FDJ35L.js} +18 -12
  81. package/dist/chunk-Z7FDJ35L.js.map +1 -0
  82. package/dist/{chunk-5EEMTJMT.js → chunk-ZH5LOQET.js} +4 -4
  83. package/dist/cli/bin.js +49 -31
  84. package/dist/cli/bin.js.map +1 -1
  85. package/dist/cli/commands/audit.js +18 -18
  86. package/dist/client-L7NAUG6J.js +11 -0
  87. package/dist/configs/playwright-a11y.d.ts +11 -1
  88. package/dist/configs/playwright-a11y.js +3 -1
  89. package/dist/{convert-to-pnpm-YTFREUJK.js → convert-to-pnpm-4DON7IFS.js} +6 -6
  90. package/dist/{db-XKZYDCKM.js → db-5K4CDEGJ.js} +45 -20
  91. package/dist/db-5K4CDEGJ.js.map +1 -0
  92. package/dist/deadletter-G4M3HSVM.js +17 -0
  93. package/dist/{digest-7UBGUBRK.js → digest-5AJGWS33.js} +45 -22
  94. package/dist/digest-5AJGWS33.js.map +1 -0
  95. package/dist/{digest-collectors-DJFN5ZDK.js → digest-collectors-MC5NWEUA.js} +12 -10
  96. package/dist/{digest-state-3KHZF7GD.js → digest-state-ZDPKR7MW.js} +18 -2
  97. package/dist/digest-state-ZDPKR7MW.js.map +1 -0
  98. package/dist/{ensure-site-OAAE5YE2.js → ensure-site-XESZHZEB.js} +39 -11
  99. package/dist/ensure-site-XESZHZEB.js.map +1 -0
  100. package/dist/{fleet-state-UEVZ3X3J.js → fleet-state-GJWGKTLD.js} +6 -4
  101. package/dist/{forms-notify-target-UC6PF3AE.js → forms-notify-target-4NPLX2UG.js} +5 -5
  102. package/dist/{freeze-A6MUCZU4.js → freeze-GUQ43EAU.js} +2 -2
  103. package/dist/{github-signals-TX5FPYP6.js → github-signals-DMU74SAX.js} +10 -10
  104. package/dist/{header-image-PSPT7CUM.js → header-image-BRTOLHJF.js} +6 -5
  105. package/dist/header-image-BRTOLHJF.js.map +1 -0
  106. package/dist/{health-endpoint-KVCJYWET.js → health-endpoint-UCLMSSCN.js} +8 -7
  107. package/dist/{health-endpoint-KVCJYWET.js.map → health-endpoint-UCLMSSCN.js.map} +1 -1
  108. package/dist/{health-mirror-XJAKA3EY.js → health-mirror-ONRT4DQ5.js} +7 -7
  109. package/dist/{import-airtable-TAKSN4NV.js → import-airtable-IIK2QUUF.js} +3 -3
  110. package/dist/index.d.ts +135 -4
  111. package/dist/index.js +68 -34
  112. package/dist/index.js.map +1 -1
  113. package/dist/{init-FFE4FCO2.js → init-3LMZTCVD.js} +19 -18
  114. package/dist/{init-FFE4FCO2.js.map → init-3LMZTCVD.js.map} +1 -1
  115. package/dist/{launch-UD36AHUN.js → launch-XTDMC6LD.js} +209 -61
  116. package/dist/launch-XTDMC6LD.js.map +1 -0
  117. package/dist/{lighthouse-VHI77PFB.js → lighthouse-52WSPZ5D.js} +2 -2
  118. package/dist/{lighthouse-airtable-YMH4UA7R.js → lighthouse-airtable-3NOFB42B.js} +3 -3
  119. package/dist/{match-harness-QRG6XZAR.js → match-harness-OW45CB5H.js} +14 -7
  120. package/dist/match-harness-OW45CB5H.js.map +1 -0
  121. package/dist/migrate-NE3DUMTM.js +7 -0
  122. package/dist/{notify-IISTHNBR.js → notify-K3WVH3DM.js} +3 -3
  123. package/dist/{onboard-TM2KESGF.js → onboard-CZYBWVWH.js} +6 -6
  124. package/dist/{orchestrate-HYVQPRCE.js → orchestrate-TGDFGY52.js} +8 -8
  125. package/dist/{parity-CAJ477PS.js → parity-AEKYSLN6.js} +5 -5
  126. package/dist/{pipeline-YROAY6DT.js → pipeline-UUPXOS2J.js} +3 -3
  127. package/dist/{preflight-RYIP54NY.js → preflight-POZZI3GN.js} +9 -9
  128. package/dist/{prismic-ci-6GKKZGB5.js → prismic-ci-AHY5ULJR.js} +38 -8
  129. package/dist/prismic-ci-AHY5ULJR.js.map +1 -0
  130. package/dist/{prismic-models-P6FWWVRS.js → prismic-models-URYGODNY.js} +9 -9
  131. package/dist/prospect/types.d.ts +72 -0
  132. package/dist/prospect/types.js +1 -1
  133. package/dist/{prospect-audit-PRHU53HS.js → prospect-audit-AJEE3Z4L.js} +16 -7
  134. package/dist/prospect-audit-AJEE3Z4L.js.map +1 -0
  135. package/dist/{prospect-audits-R3LWF6U7.js → prospect-audits-IZVQY3OQ.js} +4 -2
  136. package/dist/protection-audit-3J3UEOVT.js +413 -0
  137. package/dist/protection-audit-3J3UEOVT.js.map +1 -0
  138. package/dist/recipes/sync-configs.js +3 -3
  139. package/dist/{render-YGNGTX3W.js → render-MHUUHPLN.js} +36 -9
  140. package/dist/render-MHUUHPLN.js.map +1 -0
  141. package/dist/{render-from-row-IFSBHWDH.js → render-from-row-65DC6ZP3.js} +4 -4
  142. package/dist/{renovate-dispatch-U5Q52SKT.js → renovate-dispatch-ONJMBUHJ.js} +3 -3
  143. package/dist/{replay-PCSQOGCZ.js → replay-4FVFOMHH.js} +10 -23
  144. package/dist/replay-4FVFOMHH.js.map +1 -0
  145. package/dist/{report-LQS4ECTM.js → report-RC5LGPU3.js} +22 -20
  146. package/dist/report-RC5LGPU3.js.map +1 -0
  147. package/dist/{report-mirror-HDTOJE64.js → report-mirror-KKZZ6RMZ.js} +13 -9
  148. package/dist/{report-mirror-HDTOJE64.js.map → report-mirror-KKZZ6RMZ.js.map} +1 -1
  149. package/dist/{schema-A4WCPIF4.js → schema-KWUQEZ5O.js} +1 -1
  150. package/dist/schema-KWUQEZ5O.js.map +1 -0
  151. package/dist/{self-updating-MWXIZLL7.js → self-updating-RKKIYNV4.js} +8 -7
  152. package/dist/{self-updating-MWXIZLL7.js.map → self-updating-RKKIYNV4.js.map} +1 -1
  153. package/dist/{selftest-VXTHRPRN.js → selftest-AFLR7YV7.js} +10 -10
  154. package/dist/site-lookup-DTOLJ4EA.js +27 -0
  155. package/dist/site-lookup-DTOLJ4EA.js.map +1 -0
  156. package/dist/{site-mirror-WON4FTJ2.js → site-mirror-H2FYMN55.js} +23 -9
  157. package/dist/site-mirror-H2FYMN55.js.map +1 -0
  158. package/dist/{smoke-suite-7DGITCTZ.js → smoke-suite-BWHR3XX5.js} +8 -7
  159. package/dist/{smoke-suite-7DGITCTZ.js.map → smoke-suite-BWHR3XX5.js.map} +1 -1
  160. package/dist/{submissions-OVZPVBYG.js → submissions-II5J35QM.js} +4 -4
  161. package/dist/{submissions-3I3GAQAX.js → submissions-JDZP35JM.js} +49 -9
  162. package/dist/submissions-JDZP35JM.js.map +1 -0
  163. package/dist/{svelte-codemods-WSV2FGNG.js → svelte-codemods-QWGIRNN6.js} +6 -6
  164. package/dist/{sync-K3PKHVLH.js → sync-NKPDCMYW.js} +5 -5
  165. package/dist/{sync-configs-RRIHNLIJ.js → sync-configs-HGLQV55H.js} +6 -6
  166. package/dist/{upgrade-VTD6V4HS.js → upgrade-WZ44IARG.js} +6 -6
  167. package/dist/util/git.d.ts +48 -9
  168. package/dist/util/git.js +1 -1
  169. package/dist/{webflow-IRKOIT7S.js → webflow-624FEBFD.js} +4 -4
  170. package/dist/{websites-TB4TCAWM.js → websites-6DHIHJ2D.js} +4 -2
  171. package/dist/{write-audits-to-airtable-53EVXKMU.js → write-audits-to-airtable-BIK6LNVC.js} +5 -5
  172. package/dist/write-audits-to-airtable-BIK6LNVC.js.map +1 -0
  173. package/package.json +3 -2
  174. package/dist/airtable-JGCPS7JH.js +0 -9
  175. package/dist/chunk-5UINJNAJ.js.map +0 -1
  176. package/dist/chunk-AVEQUR44.js.map +0 -1
  177. package/dist/chunk-BVEDKMNG.js.map +0 -1
  178. package/dist/chunk-BYGPUUCT.js.map +0 -1
  179. package/dist/chunk-CWXTNPNZ.js.map +0 -1
  180. package/dist/chunk-DFKBTBO3.js.map +0 -1
  181. package/dist/chunk-FSGICFXB.js.map +0 -1
  182. package/dist/chunk-GASBX52O.js +0 -12
  183. package/dist/chunk-GASBX52O.js.map +0 -1
  184. package/dist/chunk-KJRVMMM3.js.map +0 -1
  185. package/dist/chunk-LM2NHRCJ.js.map +0 -1
  186. package/dist/chunk-QF6IQQFP.js.map +0 -1
  187. package/dist/chunk-TO7DJYLZ.js.map +0 -1
  188. package/dist/chunk-TR3HFH6J.js.map +0 -1
  189. package/dist/chunk-WJMPCVOR.js.map +0 -1
  190. package/dist/chunk-WSJ7RO54.js.map +0 -1
  191. package/dist/chunk-WVNDEYXL.js.map +0 -1
  192. package/dist/chunk-XHHMM5HX.js.map +0 -1
  193. package/dist/chunk-XPJQXSC4.js.map +0 -1
  194. package/dist/chunk-YLYXW5PH.js.map +0 -1
  195. package/dist/chunk-ZCL7C5LH.js.map +0 -1
  196. package/dist/client-G2WGWPCA.js +0 -11
  197. package/dist/db-XKZYDCKM.js.map +0 -1
  198. package/dist/digest-7UBGUBRK.js.map +0 -1
  199. package/dist/digest-state-3KHZF7GD.js.map +0 -1
  200. package/dist/ensure-site-OAAE5YE2.js.map +0 -1
  201. package/dist/header-image-PSPT7CUM.js.map +0 -1
  202. package/dist/launch-UD36AHUN.js.map +0 -1
  203. package/dist/match-harness-QRG6XZAR.js.map +0 -1
  204. package/dist/migrate-Y7R4CESL.js +0 -7
  205. package/dist/prismic-ci-6GKKZGB5.js.map +0 -1
  206. package/dist/prospect-audit-PRHU53HS.js.map +0 -1
  207. package/dist/protection-audit-SJO53MEQ.js +0 -168
  208. package/dist/protection-audit-SJO53MEQ.js.map +0 -1
  209. package/dist/render-YGNGTX3W.js.map +0 -1
  210. package/dist/replay-PCSQOGCZ.js.map +0 -1
  211. package/dist/report-LQS4ECTM.js.map +0 -1
  212. package/dist/schema-A4WCPIF4.js.map +0 -1
  213. package/dist/site-mirror-WON4FTJ2.js.map +0 -1
  214. package/dist/submissions-3I3GAQAX.js.map +0 -1
  215. /package/dist/{airtable-JGCPS7JH.js.map → airtable-SJV4ZSMS.js.map} +0 -0
  216. /package/dist/{announce-CLQYX5I4.js.map → announce-45HVP4J4.js.map} +0 -0
  217. /package/dist/{blux-4KNXUP2K.js.map → blux-RUFMNOUJ.js.map} +0 -0
  218. /package/dist/{bump-deps-C5G2EFBB.js.map → bump-deps-EL3TKMIL.js.map} +0 -0
  219. /package/dist/{chunk-XN37VTDB.js.map → chunk-37B4LVB3.js.map} +0 -0
  220. /package/dist/{chunk-WMBLR5VA.js.map → chunk-44SDGPGQ.js.map} +0 -0
  221. /package/dist/{chunk-VSGMCCGQ.js.map → chunk-6INOBNRO.js.map} +0 -0
  222. /package/dist/{chunk-5GUJ36TL.js.map → chunk-74QRWE6G.js.map} +0 -0
  223. /package/dist/{chunk-S7RYFUIK.js.map → chunk-CA6ADGOC.js.map} +0 -0
  224. /package/dist/{chunk-KZRR4NFG.js.map → chunk-D3CTOCUR.js.map} +0 -0
  225. /package/dist/{chunk-BCKEP5S6.js.map → chunk-ECDJDHKT.js.map} +0 -0
  226. /package/dist/{chunk-BI2VI6EM.js.map → chunk-EQQ4H6L3.js.map} +0 -0
  227. /package/dist/{chunk-Z2K4JPQ3.js.map → chunk-H445EH33.js.map} +0 -0
  228. /package/dist/{chunk-FUWFLAWQ.js.map → chunk-IMYL67JV.js.map} +0 -0
  229. /package/dist/{chunk-R5IMFAFR.js.map → chunk-OTEVKRAH.js.map} +0 -0
  230. /package/dist/{chunk-2ZAZ7ETT.js.map → chunk-P4A6D6HO.js.map} +0 -0
  231. /package/dist/{chunk-4763KQ6O.js.map → chunk-PXRN2MER.js.map} +0 -0
  232. /package/dist/{chunk-2LYOAB2E.js.map → chunk-RRE74VWI.js.map} +0 -0
  233. /package/dist/{chunk-ZQV7UQNE.js.map → chunk-SQ4FSNYL.js.map} +0 -0
  234. /package/dist/{chunk-6R56OKJZ.js.map → chunk-UIITN37J.js.map} +0 -0
  235. /package/dist/{chunk-CJ2RMTT7.js.map → chunk-VEIIUCYL.js.map} +0 -0
  236. /package/dist/{chunk-HTABUCF4.js.map → chunk-Y5BVR4HW.js.map} +0 -0
  237. /package/dist/{chunk-5EEMTJMT.js.map → chunk-ZH5LOQET.js.map} +0 -0
  238. /package/dist/{client-G2WGWPCA.js.map → client-L7NAUG6J.js.map} +0 -0
  239. /package/dist/{convert-to-pnpm-YTFREUJK.js.map → convert-to-pnpm-4DON7IFS.js.map} +0 -0
  240. /package/dist/{digest-collectors-DJFN5ZDK.js.map → deadletter-G4M3HSVM.js.map} +0 -0
  241. /package/dist/{fleet-state-UEVZ3X3J.js.map → digest-collectors-MC5NWEUA.js.map} +0 -0
  242. /package/dist/{freeze-A6MUCZU4.js.map → fleet-state-GJWGKTLD.js.map} +0 -0
  243. /package/dist/{forms-notify-target-UC6PF3AE.js.map → forms-notify-target-4NPLX2UG.js.map} +0 -0
  244. /package/dist/{import-airtable-TAKSN4NV.js.map → freeze-GUQ43EAU.js.map} +0 -0
  245. /package/dist/{github-signals-TX5FPYP6.js.map → github-signals-DMU74SAX.js.map} +0 -0
  246. /package/dist/{health-mirror-XJAKA3EY.js.map → health-mirror-ONRT4DQ5.js.map} +0 -0
  247. /package/dist/{lighthouse-VHI77PFB.js.map → import-airtable-IIK2QUUF.js.map} +0 -0
  248. /package/dist/{lighthouse-airtable-YMH4UA7R.js.map → lighthouse-52WSPZ5D.js.map} +0 -0
  249. /package/dist/{migrate-Y7R4CESL.js.map → lighthouse-airtable-3NOFB42B.js.map} +0 -0
  250. /package/dist/{notify-IISTHNBR.js.map → migrate-NE3DUMTM.js.map} +0 -0
  251. /package/dist/{orchestrate-HYVQPRCE.js.map → notify-K3WVH3DM.js.map} +0 -0
  252. /package/dist/{onboard-TM2KESGF.js.map → onboard-CZYBWVWH.js.map} +0 -0
  253. /package/dist/{parity-CAJ477PS.js.map → orchestrate-TGDFGY52.js.map} +0 -0
  254. /package/dist/{pipeline-YROAY6DT.js.map → parity-AEKYSLN6.js.map} +0 -0
  255. /package/dist/{prospect-audits-R3LWF6U7.js.map → pipeline-UUPXOS2J.js.map} +0 -0
  256. /package/dist/{preflight-RYIP54NY.js.map → preflight-POZZI3GN.js.map} +0 -0
  257. /package/dist/{prismic-models-P6FWWVRS.js.map → prismic-models-URYGODNY.js.map} +0 -0
  258. /package/dist/{render-from-row-IFSBHWDH.js.map → prospect-audits-IZVQY3OQ.js.map} +0 -0
  259. /package/dist/{websites-TB4TCAWM.js.map → render-from-row-65DC6ZP3.js.map} +0 -0
  260. /package/dist/{renovate-dispatch-U5Q52SKT.js.map → renovate-dispatch-ONJMBUHJ.js.map} +0 -0
  261. /package/dist/{selftest-VXTHRPRN.js.map → selftest-AFLR7YV7.js.map} +0 -0
  262. /package/dist/{submissions-OVZPVBYG.js.map → submissions-II5J35QM.js.map} +0 -0
  263. /package/dist/{svelte-codemods-WSV2FGNG.js.map → svelte-codemods-QWGIRNN6.js.map} +0 -0
  264. /package/dist/{sync-K3PKHVLH.js.map → sync-NKPDCMYW.js.map} +0 -0
  265. /package/dist/{sync-configs-RRIHNLIJ.js.map → sync-configs-HGLQV55H.js.map} +0 -0
  266. /package/dist/{upgrade-VTD6V4HS.js.map → upgrade-WZ44IARG.js.map} +0 -0
  267. /package/dist/{webflow-IRKOIT7S.js.map → webflow-624FEBFD.js.map} +0 -0
  268. /package/dist/{write-audits-to-airtable-53EVXKMU.js.map → websites-6DHIHJ2D.js.map} +0 -0
@@ -2,30 +2,31 @@ import {
2
2
  appendSkipNotice,
3
3
  fleetWorkdir,
4
4
  prepareFleetSites
5
- } from "./chunk-LM2NHRCJ.js";
5
+ } from "./chunk-SHGIDTYF.js";
6
6
  import {
7
7
  resolveSites
8
- } from "./chunk-Z2K4JPQ3.js";
8
+ } from "./chunk-H445EH33.js";
9
9
  import {
10
10
  init
11
- } from "./chunk-BVEDKMNG.js";
12
- import "./chunk-S7RYFUIK.js";
13
- import "./chunk-CWXTNPNZ.js";
14
- import "./chunk-2LYOAB2E.js";
11
+ } from "./chunk-3EA43S3R.js";
12
+ import "./chunk-CA6ADGOC.js";
13
+ import "./chunk-DVJNYPFR.js";
14
+ import "./chunk-RRE74VWI.js";
15
15
  import "./chunk-J7SZQUCW.js";
16
- import "./chunk-WSJ7RO54.js";
17
- import "./chunk-DFKBTBO3.js";
18
- import "./chunk-R53VL3RI.js";
19
- import "./chunk-FUWFLAWQ.js";
20
- import "./chunk-ZQV7UQNE.js";
16
+ import "./chunk-XED2DNAI.js";
17
+ import "./chunk-NVLREB5R.js";
18
+ import "./chunk-5CJVUPJU.js";
19
+ import "./chunk-4UTJ4G6P.js";
20
+ import "./chunk-IMYL67JV.js";
21
+ import "./chunk-SQ4FSNYL.js";
21
22
  import "./chunk-SLFG7Y76.js";
22
23
  import "./chunk-OTGB6YQO.js";
23
- import "./chunk-TO7DJYLZ.js";
24
+ import "./chunk-XY7YV2YQ.js";
24
25
  import "./chunk-LKGVSM2O.js";
25
- import "./chunk-GASBX52O.js";
26
- import "./chunk-XHHMM5HX.js";
26
+ import "./chunk-CGQZFQAY.js";
27
+ import "./chunk-43SW3FGW.js";
27
28
  import "./chunk-Z3JXLULD.js";
28
- import "./chunk-2NQUCS7O.js";
29
+ import "./chunk-BIYQN7FH.js";
29
30
  import "./chunk-UDRHAQT7.js";
30
31
  import "./chunk-PTDMVGKL.js";
31
32
  import "./chunk-LBYOLBW7.js";
@@ -35,9 +36,9 @@ import "./chunk-RARREDQE.js";
35
36
  import {
36
37
  siteLabel
37
38
  } from "./chunk-XXTZBPUY.js";
38
- import "./chunk-AVEQUR44.js";
39
+ import "./chunk-EASYCD6F.js";
39
40
  import "./chunk-NMAWXBJA.js";
40
- import "./chunk-YLYXW5PH.js";
41
+ import "./chunk-CXICCLNM.js";
41
42
 
42
43
  // src/cli/commands/init.ts
43
44
  import { resolve } from "path";
@@ -110,4 +111,4 @@ async function runInitCommand(site, opts) {
110
111
  export {
111
112
  runInitCommand
112
113
  };
113
- //# sourceMappingURL=init-FFE4FCO2.js.map
114
+ //# sourceMappingURL=init-3LMZTCVD.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli/commands/init.ts"],"sourcesContent":["import { resolve } from \"node:path\";\nimport { init, type InitResult, type InitStepResult } from \"../../recipes/init.js\";\nimport { resolveSites } from \"../fleet/resolve-sites.js\";\nimport { prepareFleetSites, appendSkipNotice, type SkippedSite } from \"../fleet/prepare-sites.js\";\nimport { fleetWorkdir } from \"../../util/fleet-workdir.js\";\nimport { siteLabel } from \"../../util/site.js\";\n\nexport type InitCommandOptions = {\n fleet?: string;\n workdir?: string;\n cwd?: string;\n};\n\nfunction formatStep(name: string, r: InitStepResult): string {\n if (r.kind === \"error\") return `${name.padEnd(20)} error: ${r.message}`;\n if (r.kind === \"audit\") {\n const lines = r.results.map(\n (a) => ` ${a.audit.padEnd(12)} ${a.status.padEnd(5)} ${a.summary}`,\n );\n return `${name.padEnd(20)} ${r.results.length} audit(s):\\n${lines.join(\"\\n\")}`;\n }\n const rec = r.result;\n if (rec.status === \"noop\") return `${name.padEnd(20)} noop${rec.notes ? ` — ${rec.notes}` : \"\"}`;\n if (rec.status === \"failed\")\n return `${name.padEnd(20)} failed${rec.notes ? ` — ${rec.notes}` : \"\"}`;\n return `${name.padEnd(20)} applied (${rec.commits.length} commit${rec.commits.length === 1 ? \"\" : \"s\"})${rec.notes ? ` — ${rec.notes}` : \"\"}`;\n}\n\nfunction formatResult(r: InitResult): string {\n const header = `[${r.site}] init — ${r.complete ? \"complete\" : \"STOPPED\"}`;\n const body = r.steps.map((s) => formatStep(s.name, s.result)).join(\"\\n\");\n return `${header}\\n${body}`;\n}\n\nfunction exitCodeFor(r: InitResult): number {\n if (!r.complete) return 1;\n // A complete chain can still surface a failing audit at the end. Treat\n // any `fail`-status audit as exit 1 so CI signals a regression even when\n // every recipe applied cleanly.\n for (const step of r.steps) {\n if (step.result.kind === \"audit\" && step.result.results.some((a) => a.status === \"fail\")) {\n return 1;\n }\n }\n return 0;\n}\n\nexport async function runInitCommand(\n site: string | undefined,\n opts: InitCommandOptions,\n): Promise<{ output: string; code: number }> {\n const cwd = opts.cwd ? resolve(opts.cwd) : process.cwd();\n\n let sites = await resolveSites({\n ...(site !== undefined ? { site } : {}),\n ...(opts.fleet !== undefined ? { fleet: opts.fleet } : {}),\n ...(opts.workdir !== undefined ? { workdir: opts.workdir } : {}),\n cwd,\n });\n\n let skipped: SkippedSite[] = [];\n if (opts.fleet) {\n const workdir = opts.workdir ?? fleetWorkdir();\n const prep = await prepareFleetSites(sites, { workdir });\n sites = prep.prepared;\n skipped = prep.skipped;\n }\n\n const results: InitResult[] = [];\n for (const s of sites) {\n try {\n results.push(await init(s));\n } catch (err) {\n // Isolate a per-site throw (e.g. a transient git error) so the rest of the\n // fleet still runs — the same guarantee `runRecipeOverSites` gives the other\n // fleet commands, but `init` returns an `InitResult`, so synthesize a stopped\n // one here rather than reuse the shared helper.\n results.push({\n site: siteLabel(s),\n steps: [\n {\n name: \"init\",\n result: { kind: \"error\", message: err instanceof Error ? err.message : String(err) },\n },\n ],\n complete: false,\n });\n }\n }\n\n const output = results.map(formatResult).join(\"\\n\\n\");\n const code = results.some((r) => exitCodeFor(r) !== 0) ? 1 : 0;\n return { output: appendSkipNotice(output, skipped), code };\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/cli/commands/init.ts"],"sourcesContent":["import { resolve } from \"node:path\";\nimport { init, type InitResult, type InitStepResult } from \"../../recipes/init.js\";\nimport { resolveSites } from \"../fleet/resolve-sites.js\";\nimport { prepareFleetSites, appendSkipNotice, type SkippedSite } from \"../fleet/prepare-sites.js\";\nimport { fleetWorkdir } from \"../../util/fleet-workdir.js\";\nimport { siteLabel } from \"../../util/site.js\";\n\nexport type InitCommandOptions = {\n fleet?: string;\n workdir?: string;\n cwd?: string;\n};\n\nfunction formatStep(name: string, r: InitStepResult): string {\n if (r.kind === \"error\") return `${name.padEnd(20)} error: ${r.message}`;\n if (r.kind === \"audit\") {\n const lines = r.results.map(\n (a) => ` ${a.audit.padEnd(12)} ${a.status.padEnd(5)} ${a.summary}`,\n );\n return `${name.padEnd(20)} ${r.results.length} audit(s):\\n${lines.join(\"\\n\")}`;\n }\n const rec = r.result;\n if (rec.status === \"noop\") return `${name.padEnd(20)} noop${rec.notes ? ` — ${rec.notes}` : \"\"}`;\n if (rec.status === \"failed\")\n return `${name.padEnd(20)} failed${rec.notes ? ` — ${rec.notes}` : \"\"}`;\n return `${name.padEnd(20)} applied (${rec.commits.length} commit${rec.commits.length === 1 ? \"\" : \"s\"})${rec.notes ? ` — ${rec.notes}` : \"\"}`;\n}\n\nfunction formatResult(r: InitResult): string {\n const header = `[${r.site}] init — ${r.complete ? \"complete\" : \"STOPPED\"}`;\n const body = r.steps.map((s) => formatStep(s.name, s.result)).join(\"\\n\");\n return `${header}\\n${body}`;\n}\n\nfunction exitCodeFor(r: InitResult): number {\n if (!r.complete) return 1;\n // A complete chain can still surface a failing audit at the end. Treat\n // any `fail`-status audit as exit 1 so CI signals a regression even when\n // every recipe applied cleanly.\n for (const step of r.steps) {\n if (step.result.kind === \"audit\" && step.result.results.some((a) => a.status === \"fail\")) {\n return 1;\n }\n }\n return 0;\n}\n\nexport async function runInitCommand(\n site: string | undefined,\n opts: InitCommandOptions,\n): Promise<{ output: string; code: number }> {\n const cwd = opts.cwd ? resolve(opts.cwd) : process.cwd();\n\n let sites = await resolveSites({\n ...(site !== undefined ? { site } : {}),\n ...(opts.fleet !== undefined ? { fleet: opts.fleet } : {}),\n ...(opts.workdir !== undefined ? { workdir: opts.workdir } : {}),\n cwd,\n });\n\n let skipped: SkippedSite[] = [];\n if (opts.fleet) {\n const workdir = opts.workdir ?? fleetWorkdir();\n const prep = await prepareFleetSites(sites, { workdir });\n sites = prep.prepared;\n skipped = prep.skipped;\n }\n\n const results: InitResult[] = [];\n for (const s of sites) {\n try {\n results.push(await init(s));\n } catch (err) {\n // Isolate a per-site throw (e.g. a transient git error) so the rest of the\n // fleet still runs — the same guarantee `runRecipeOverSites` gives the other\n // fleet commands, but `init` returns an `InitResult`, so synthesize a stopped\n // one here rather than reuse the shared helper.\n results.push({\n site: siteLabel(s),\n steps: [\n {\n name: \"init\",\n result: { kind: \"error\", message: err instanceof Error ? err.message : String(err) },\n },\n ],\n complete: false,\n });\n }\n }\n\n const output = results.map(formatResult).join(\"\\n\\n\");\n const code = results.some((r) => exitCodeFor(r) !== 0) ? 1 : 0;\n return { output: appendSkipNotice(output, skipped), code };\n}\n"],"mappings":"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","names":[]}
@@ -1,22 +1,27 @@
1
1
  import {
2
2
  writeAuditsToAirtable
3
- } from "./chunk-5EEMTJMT.js";
3
+ } from "./chunk-ZH5LOQET.js";
4
4
  import {
5
5
  selfUpdating
6
- } from "./chunk-FSGICFXB.js";
6
+ } from "./chunk-XG2A6GIG.js";
7
7
  import "./chunk-MNDIED4M.js";
8
8
  import {
9
9
  hasRealScores,
10
10
  lighthouseScoresFromResult
11
- } from "./chunk-XN37VTDB.js";
12
- import "./chunk-SVAAONYB.js";
11
+ } from "./chunk-37B4LVB3.js";
12
+ import "./chunk-WQLNUEZL.js";
13
13
  import "./chunk-5L3FPQIJ.js";
14
14
  import {
15
15
  resolveSites
16
- } from "./chunk-Z2K4JPQ3.js";
16
+ } from "./chunk-H445EH33.js";
17
17
  import {
18
18
  queueDraft
19
19
  } from "./chunk-YFAXOD7Z.js";
20
+ import {
21
+ HARNESS_JSON_RELATIVE,
22
+ UNGUARDED_TWIN_TELL
23
+ } from "./chunk-Y6FCXRIC.js";
24
+ import "./chunk-4UTJ4G6P.js";
20
25
  import {
21
26
  createDraft,
22
27
  findReportByPeriod,
@@ -38,16 +43,16 @@ import "./chunk-BGTYPVLT.js";
38
43
  import {
39
44
  listWebsites,
40
45
  siteSlug
41
- } from "./chunk-3Z6X3BHU.js";
46
+ } from "./chunk-KN52PM63.js";
42
47
  import "./chunk-SLFG7Y76.js";
43
48
  import {
44
49
  runAudits
45
- } from "./chunk-TO7DJYLZ.js";
50
+ } from "./chunk-XY7YV2YQ.js";
46
51
  import "./chunk-LKGVSM2O.js";
47
- import "./chunk-GASBX52O.js";
48
- import "./chunk-XHHMM5HX.js";
52
+ import "./chunk-CGQZFQAY.js";
53
+ import "./chunk-43SW3FGW.js";
49
54
  import "./chunk-Z3JXLULD.js";
50
- import "./chunk-2NQUCS7O.js";
55
+ import "./chunk-BIYQN7FH.js";
51
56
  import "./chunk-UDRHAQT7.js";
52
57
  import "./chunk-PTDMVGKL.js";
53
58
  import "./chunk-LBYOLBW7.js";
@@ -57,27 +62,75 @@ import "./chunk-RARREDQE.js";
57
62
  import {
58
63
  siteLabel
59
64
  } from "./chunk-XXTZBPUY.js";
60
- import "./chunk-AVEQUR44.js";
65
+ import "./chunk-EASYCD6F.js";
61
66
  import "./chunk-6VAL7XJT.js";
62
67
  import "./chunk-NMAWXBJA.js";
63
- import "./chunk-YLYXW5PH.js";
68
+ import "./chunk-CXICCLNM.js";
64
69
 
65
70
  // src/cli/commands/launch.ts
66
71
  import { resolve } from "path";
67
72
 
68
73
  // src/recipes/launch.ts
69
74
  import { existsSync } from "fs";
70
- import { readFile } from "fs/promises";
75
+ import { readFile, readdir } from "fs/promises";
71
76
  import { join } from "path";
72
77
  var SITE_404_MARKER = /<h1[^>]*>\s*404\s*<\/h1>/i;
73
- var UNGUARDED_TWIN_MARKER = /no (matching )?assembly for/i;
78
+ var UNGUARDED_TWIN_MARKER = new RegExp(
79
+ `${UNGUARDED_TWIN_TELL.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}|no (matching )?assembly for`,
80
+ "i"
81
+ );
74
82
  var MATCH_ROUTE_DIR = "src/routes/dev/match";
75
83
  var CHECKOUT_MARKER = "src/routes";
76
- var MATCH_GUARD_FILES = [
77
- "src/routes/dev/+layout.server.ts",
78
- "src/routes/dev/match/+layout.server.ts",
79
- "src/routes/dev/match/[uid]/+page.server.ts"
80
- ];
84
+ var REGEX_PRECEDERS = /[(,=:[!&|?{};+\-*%~^<>]/;
85
+ var REGEX_KEYWORDS = /* @__PURE__ */ new Set([
86
+ "return",
87
+ "typeof",
88
+ "case",
89
+ "in",
90
+ "of",
91
+ "new",
92
+ "delete",
93
+ "void",
94
+ "instanceof",
95
+ "do",
96
+ "else",
97
+ "yield",
98
+ "await"
99
+ ]);
100
+ function opensRegex(prevChar, prevWord) {
101
+ if (prevChar === "") return true;
102
+ if (REGEX_PRECEDERS.test(prevChar)) return true;
103
+ return REGEX_KEYWORDS.has(prevWord);
104
+ }
105
+ function lookback(out) {
106
+ let i = out.length - 1;
107
+ while (i >= 0 && /\s/.test(out[i])) i--;
108
+ if (i < 0) return { char: "", word: "" };
109
+ let j = i;
110
+ while (j >= 0 && /[A-Za-z0-9_$]/.test(out[j])) j--;
111
+ return { char: out[i], word: out.slice(j + 1, i + 1) };
112
+ }
113
+ function regexLiteralEnd(source, at) {
114
+ let inClass = false;
115
+ for (let i = at + 1; i < source.length; i++) {
116
+ const c = source[i];
117
+ if (c === "\\") {
118
+ i++;
119
+ continue;
120
+ }
121
+ if (c === "\n") return -1;
122
+ if (inClass) {
123
+ if (c === "]") inClass = false;
124
+ continue;
125
+ }
126
+ if (c === "[") {
127
+ inClass = true;
128
+ continue;
129
+ }
130
+ if (c === "/") return i;
131
+ }
132
+ return -1;
133
+ }
81
134
  function stripComments(source) {
82
135
  let out = "";
83
136
  for (let i = 0; i < source.length; ) {
@@ -93,6 +146,17 @@ function stripComments(source) {
93
146
  i += 2;
94
147
  continue;
95
148
  }
149
+ if (ch === "/") {
150
+ const { char, word } = lookback(out);
151
+ if (opensRegex(char, word)) {
152
+ const end = regexLiteralEnd(source, i);
153
+ if (end !== -1) {
154
+ out += source.slice(i, end + 1);
155
+ i = end + 1;
156
+ continue;
157
+ }
158
+ }
159
+ }
96
160
  if (ch === '"' || ch === "'" || ch === "`") {
97
161
  out += ch;
98
162
  i++;
@@ -117,6 +181,17 @@ function maskLiterals(code) {
117
181
  let out = "";
118
182
  for (let i = 0; i < code.length; ) {
119
183
  const ch = code[i];
184
+ if (ch === "/") {
185
+ const { char, word } = lookback(out);
186
+ if (opensRegex(char, word)) {
187
+ const end = regexLiteralEnd(code, i);
188
+ if (end !== -1) {
189
+ out += "/" + " ".repeat(end - i - 1) + "/";
190
+ i = end + 1;
191
+ continue;
192
+ }
193
+ }
194
+ }
120
195
  if (ch !== '"' && ch !== "'" && ch !== "`") {
121
196
  out += ch;
122
197
  i++;
@@ -175,6 +250,45 @@ function carriesGuard(source) {
175
250
  }
176
251
  return false;
177
252
  }
253
+ var DEV_ROUTE_DIR = "src/routes/dev";
254
+ async function routeFilesUnder(sitePath, relDir) {
255
+ let entries;
256
+ try {
257
+ entries = await readdir(join(sitePath, relDir), { withFileTypes: true });
258
+ } catch {
259
+ return [];
260
+ }
261
+ const out = [];
262
+ for (const e of entries) {
263
+ const rel = `${relDir}/${e.name}`;
264
+ if (e.isDirectory()) out.push(...await routeFilesUnder(sitePath, rel));
265
+ else if (e.name.startsWith("+")) out.push(rel);
266
+ }
267
+ return out;
268
+ }
269
+ async function guardAt(sitePath, rel, cache) {
270
+ const hit = cache.get(rel);
271
+ if (hit !== void 0) return hit;
272
+ let ok;
273
+ try {
274
+ ok = carriesGuard(await readFile(join(sitePath, rel), "utf-8"));
275
+ } catch {
276
+ ok = false;
277
+ }
278
+ cache.set(rel, ok);
279
+ return ok;
280
+ }
281
+ async function coveringLayout(sitePath, dir, cache) {
282
+ let d = dir;
283
+ for (; ; ) {
284
+ const rel = `${d}/+layout.server.ts`;
285
+ if (await guardAt(sitePath, rel, cache)) return rel;
286
+ if (d === DEV_ROUTE_DIR) return null;
287
+ const up = d.slice(0, d.lastIndexOf("/"));
288
+ if (up.length < DEV_ROUTE_DIR.length) return null;
289
+ d = up;
290
+ }
291
+ }
178
292
  async function matchingDisposition(sitePath) {
179
293
  if (!existsSync(join(sitePath, CHECKOUT_MARKER))) {
180
294
  return {
@@ -188,33 +302,64 @@ async function matchingDisposition(sitePath) {
188
302
  message: `no ${MATCH_ROUTE_DIR} in this checkout (${CHECKOUT_MARKER} is present, so the absence is a real one)`
189
303
  };
190
304
  }
191
- const read = [];
192
- for (const rel of MATCH_GUARD_FILES) {
193
- let source;
194
- try {
195
- source = await readFile(join(sitePath, rel), "utf-8");
196
- } catch {
305
+ const files = await routeFilesUnder(sitePath, MATCH_ROUTE_DIR);
306
+ if (files.length === 0) {
307
+ return {
308
+ ok: false,
309
+ message: `${MATCH_ROUTE_DIR} exists but carries no route files (+page/+server/+layout) \u2014 the twin's disposition cannot be established`
310
+ };
311
+ }
312
+ const cache = /* @__PURE__ */ new Map();
313
+ const unguarded = [];
314
+ const covers = [];
315
+ for (const ep of files.filter((f) => f.endsWith("/+server.ts"))) {
316
+ if (await guardAt(sitePath, ep, cache)) covers.push(ep);
317
+ else
318
+ unguarded.push(
319
+ `${ep} (a \`+server.ts\` endpoint \u2014 layout \`load\` does not run for it, so it needs its own guard)`
320
+ );
321
+ }
322
+ const pageDirs = [
323
+ ...new Set(
324
+ files.filter((f) => /\/\+page\.(server\.ts|ts|svelte)$/.test(f)).map((f) => f.slice(0, f.lastIndexOf("/")))
325
+ )
326
+ ];
327
+ for (const dir of pageDirs) {
328
+ const layout = await coveringLayout(sitePath, dir, cache);
329
+ if (layout) {
330
+ covers.push(layout);
197
331
  continue;
198
332
  }
199
- read.push(rel);
200
- if (carriesGuard(source)) {
201
- return {
202
- ok: true,
203
- message: `${rel} contains dev guard source \u2014 \`if (!dev)\` on \`$app/environment\` whose own branch refuses with a 404/throw (source text only; the deployed build is checked at the dev-guard step)`
204
- };
333
+ const own = `${dir}/+page.server.ts`;
334
+ if (await guardAt(sitePath, own, cache)) {
335
+ covers.push(own);
336
+ continue;
205
337
  }
338
+ unguarded.push(`${dir}/ (no guarded +page.server.ts and no covering +layout.server.ts)`);
206
339
  }
207
- if (read.length === 0) {
340
+ if (unguarded.length > 0) {
208
341
  return {
209
342
  ok: false,
210
- message: `${MATCH_ROUTE_DIR} exists but none of ${MATCH_GUARD_FILES.join(", ")} could be read \u2014 the twin's disposition cannot be established`
343
+ message: `${MATCH_ROUTE_DIR} is not fully guarded \u2014 ${unguarded.join("; ")} \u2014 an \`if (!dev)\` guard on \`$app/environment\` whose own branch refuses (\`error(404\` or \`throw\`) is required, once comments are stripped and string and regex contents masked; the matching twin would ship`
211
344
  };
212
345
  }
213
346
  return {
214
- ok: false,
215
- message: `none of ${read.join(", ")} carries an \`if (!dev)\` guard on \`$app/environment\` whose own branch refuses (\`error(404\` or \`throw\`), once comments are stripped and string contents masked \u2014 the matching twin would ship`
347
+ ok: true,
348
+ message: `every route under ${MATCH_ROUTE_DIR} is covered by dev guard source \u2014 ${[...new Set(covers)].join(", ")} (source text only; the deployed build is checked at the dev-guard step)`
216
349
  };
217
350
  }
351
+ async function twinUids(sitePath) {
352
+ let parsed;
353
+ try {
354
+ parsed = JSON.parse(await readFile(join(sitePath, HARNESS_JSON_RELATIVE), "utf-8"));
355
+ } catch {
356
+ return ["home"];
357
+ }
358
+ const pages = parsed?.pages;
359
+ if (!pages || typeof pages !== "object") return ["home"];
360
+ const uids = Object.values(pages).map((p) => p?.uid).filter((u) => typeof u === "string" && u.length > 0);
361
+ return uids.length > 0 ? [...new Set(uids)] : ["home"];
362
+ }
218
363
  var PROBE_TIMEOUT_MS = 15e3;
219
364
  var defaultProbe = async (url) => {
220
365
  const res = await fetch(url, {
@@ -278,10 +423,11 @@ async function launch(site, deps = {}) {
278
423
  return stop();
279
424
  }
280
425
  const origin = target.url.replace(/\/+$/, "");
281
- let twin;
426
+ const uids = await twinUids(site.path);
427
+ const twins = [];
282
428
  let control;
283
429
  try {
284
- twin = await probe(`${origin}/dev/match/home`);
430
+ for (const uid of uids) twins.push({ uid, res: await probe(`${origin}/dev/match/${uid}`) });
285
431
  control = await probe(`${origin}/health`);
286
432
  } catch (err) {
287
433
  steps.push({ name: "dev-guard", result: errorOf(err) });
@@ -297,32 +443,34 @@ async function launch(site, deps = {}) {
297
443
  });
298
444
  return stop();
299
445
  }
300
- const unguardedTell = twin.body.match(UNGUARDED_TWIN_MARKER);
301
- if (unguardedTell) {
302
- steps.push({
303
- name: "dev-guard",
304
- result: {
305
- kind: "error",
306
- message: `${origin}/dev/match/home answered ${twin.status} carrying the twin route's OWN "${unguardedTell[0]}" message \u2014 the twin is LIVE and merely has no assembly for the uid "home". That is not evidence of a dev guard.`
307
- }
308
- });
309
- return stop();
310
- }
311
- if (twin.status !== 404 || !SITE_404_MARKER.test(twin.body)) {
312
- steps.push({
313
- name: "dev-guard",
314
- result: {
315
- kind: "error",
316
- message: twin.status === 404 ? `${origin}/dev/match/home 404s, but not with this site's own error page \u2014 cannot tell the guard from a dead route` : `${origin}/dev/match/home answered ${twin.status} \u2014 the matching twin is live in production`
317
- }
318
- });
319
- return stop();
446
+ for (const { uid, res } of twins) {
447
+ const unguardedTell = res.body.match(UNGUARDED_TWIN_MARKER);
448
+ if (unguardedTell) {
449
+ steps.push({
450
+ name: "dev-guard",
451
+ result: {
452
+ kind: "error",
453
+ message: `${origin}/dev/match/${uid} answered ${res.status} carrying the twin route's OWN "${unguardedTell[0]}" message \u2014 the twin is LIVE and merely has no assembly for the uid "${uid}". That is not evidence of a dev guard.`
454
+ }
455
+ });
456
+ return stop();
457
+ }
458
+ if (res.status !== 404 || !SITE_404_MARKER.test(res.body)) {
459
+ steps.push({
460
+ name: "dev-guard",
461
+ result: {
462
+ kind: "error",
463
+ message: res.status === 404 ? `${origin}/dev/match/${uid} 404s, but not with this site's own error page \u2014 cannot tell the guard from a dead route` : `${origin}/dev/match/${uid} answered ${res.status} \u2014 the matching twin is live in production`
464
+ }
465
+ });
466
+ return stop();
467
+ }
320
468
  }
321
469
  steps.push({
322
470
  name: "dev-guard",
323
471
  result: {
324
472
  kind: "probe",
325
- message: `${origin}/dev/match/home 404 (site error page), /health 200`
473
+ message: `${uids.map((u) => `${origin}/dev/match/${u}`).join(", ")} 404 (site error page), /health 200`
326
474
  }
327
475
  });
328
476
  try {
@@ -454,8 +602,8 @@ async function runLaunchCommand(site, opts) {
454
602
  if (!target) {
455
603
  return { output: `No site resolved for "${site}".`, code: 1 };
456
604
  }
457
- const { makeReportMirror } = await import("./report-mirror-HDTOJE64.js");
458
- const { makeSiteMirror } = await import("./site-mirror-WON4FTJ2.js");
605
+ const { makeReportMirror } = await import("./report-mirror-KKZZ6RMZ.js");
606
+ const { makeSiteMirror } = await import("./site-mirror-H2FYMN55.js");
459
607
  const result = await launch(target, {
460
608
  reportMirror: await makeReportMirror(),
461
609
  siteMirror: await makeSiteMirror()
@@ -466,4 +614,4 @@ export {
466
614
  formatStep,
467
615
  runLaunchCommand
468
616
  };
469
- //# sourceMappingURL=launch-UD36AHUN.js.map
617
+ //# sourceMappingURL=launch-XTDMC6LD.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli/commands/launch.ts","../src/recipes/launch.ts"],"sourcesContent":["import { resolve } from \"node:path\";\nimport { launch, type LaunchResult, type LaunchStepResult } from \"../../recipes/launch.js\";\nimport { resolveSites } from \"../fleet/resolve-sites.js\";\n\nexport type LaunchCommandOptions = {\n cwd?: string;\n};\n\nexport function formatStep(name: string, r: LaunchStepResult): string {\n if (r.kind === \"error\") return `${name.padEnd(20)} error: ${r.message}`;\n if (r.kind === \"audit\") {\n const s = r.scores;\n return `${name.padEnd(20)} audited (P=${s.performance} A=${s.accessibility} BP=${s.bestPractices} SEO=${s.seo})`;\n }\n if (r.kind === \"draft\") {\n return `${name.padEnd(20)} drafted ${r.report.reportId}`;\n }\n if (r.kind === \"probe\") return `${name.padEnd(20)} ok — ${r.message}`;\n const rec = r.result;\n if (rec.status === \"noop\") return `${name.padEnd(20)} noop${rec.notes ? ` — ${rec.notes}` : \"\"}`;\n if (rec.status === \"failed\")\n return `${name.padEnd(20)} failed${rec.notes ? ` — ${rec.notes}` : \"\"}`;\n return `${name.padEnd(20)} applied (${rec.commits.length} commit${rec.commits.length === 1 ? \"\" : \"s\"})${rec.notes ? ` — ${rec.notes}` : \"\"}`;\n}\n\nfunction formatResult(r: LaunchResult): string {\n const header = `[${r.site}] launch — ${r.complete ? \"drafted (awaiting approval)\" : \"STOPPED\"}`;\n const body = r.steps.map((s) => formatStep(s.name, s.result)).join(\"\\n\");\n return `${header}\\n${body}`;\n}\n\n/**\n * `launch <site>` — single-site only. Bootstrap (Renovate + protection), first-audit\n * the site, and DRAFT its launch email into the M3 approve queue. Never sends;\n * the operator approves the draft and the next send run delivers the go-live\n * email (flipping Status → maintenance + stamping Launched at).\n */\nexport async function runLaunchCommand(\n site: string,\n opts: LaunchCommandOptions,\n): Promise<{ output: string; code: number }> {\n const cwd = opts.cwd ? resolve(opts.cwd) : process.cwd();\n const sites = await resolveSites({ site, cwd });\n const target = sites[0];\n if (!target) {\n return { output: `No site resolved for \"${site}\".`, code: 1 };\n }\n\n // #539 Phase 5: create-side Turso dual-write, wired at the composition root\n // (see runAnnounceCommand for why it is not defaulted inside the recipe).\n const { makeReportMirror } = await import(\"../../reports/report-mirror.js\");\n const { makeSiteMirror } = await import(\"../../db/site-mirror.js\");\n const result = await launch(target, {\n reportMirror: await makeReportMirror(),\n siteMirror: await makeSiteMirror(),\n });\n return { output: formatResult(result), code: result.complete ? 0 : 1 };\n}\n","import { existsSync } from \"node:fs\";\nimport { readFile, readdir } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport type { AuditResult, RecipeResult, Site } from \"../types.js\";\nimport { siteLabel } from \"../util/site.js\";\nimport { selfUpdating } from \"./self-updating/index.js\";\nimport { HARNESS_JSON_RELATIVE, UNGUARDED_TWIN_TELL } from \"./match-harness/template.js\";\nimport { runAudits } from \"../audits/index.js\";\nimport { hasRealScores, lighthouseScoresFromResult } from \"../audits/lighthouse-airtable.js\";\nimport { writeAuditsToAirtable } from \"../audits/write-audits-to-airtable.js\";\nimport { openBase, readAirtableConfig } from \"../reports/airtable/client.js\";\nimport type { AirtableBase } from \"../reports/airtable/client.js\";\nimport { listWebsites, siteSlug } from \"../reports/airtable/websites.js\";\nimport type { WebsiteRow } from \"../reports/airtable/websites.js\";\nimport {\n createDraft,\n findReportByPeriod,\n updateReportScores,\n} from \"../reports/airtable/reports.js\";\nimport type { ReportRow } from \"../reports/airtable/reports.js\";\nimport type { ReportMirror } from \"../reports/report-mirror.js\";\nimport type { SiteMirror } from \"../db/site-mirror.js\";\nimport { queueDraft } from \"../reports/queue.js\";\nimport { uploadAttachment } from \"../reports/airtable/attachments.js\";\nimport { renderReportHtml } from \"../reports/render.js\";\nimport { resolveCopy } from \"../reports/copy.js\";\nimport type { LighthouseScores } from \"../reports/types.js\";\n\nexport type LaunchStepResult =\n | { kind: \"recipe\"; result: RecipeResult }\n | { kind: \"audit\"; results: AuditResult[]; scores: LighthouseScores }\n | { kind: \"draft\"; report: ReportRow }\n | { kind: \"probe\"; message: string }\n | { kind: \"error\"; message: string };\n\nexport type LaunchResult = {\n site: string;\n steps: Array<{ name: string; result: LaunchStepResult }>;\n /** True if every step ran (bootstrap + audit + draft); false if a step\n * errored or a recipe `failed` short-circuited the chain. */\n complete: boolean;\n};\n\nexport type LaunchDeps = {\n /** Bootstrap step (Renovate + protection; ci.yml comes from the starter). Defaults to the real `selfUpdating`. */\n bootstrap?: (site: Site) => Promise<RecipeResult>;\n /** Audit step. Defaults to the real `runAudits`. */\n audit?: (site: Site) => Promise<AuditResult[]>;\n /** Airtable handle. Defaults to opening the live base from credentials. */\n base?: AirtableBase;\n /** #539 Phase 5: Turso write-through for everything this recipe writes — the\n * Launch row (or a re-run's refreshed scores), the rendered body, and the\n * queue flag. Wired at the CLI composition root, never defaulted here — the\n * unit suite calls `launch` with a fake base and must not open a real\n * libSQL handle. */\n reportMirror?: ReportMirror;\n /** #539 Phase 5: the Websites-row twin — launch writes the site's FIRST audit\n * results and (on send) its launched status. Injected at the CLI root. */\n siteMirror?: SiteMirror;\n /** HTTP probe for `dev-guard`. Defaults to global fetch. INJECTED in tests:\n * the suite stubs `global.fetch` for the Airtable attachment upload and that\n * stub answers 200 to everything — which is precisely the state this step\n * exists to fail on. */\n probe?: (url: string) => Promise<{ status: number; body: string }>;\n};\n\n/** The site's OWN 404. `src/routes/+error.svelte` renders `<h1>{page.status}</h1>`,\n * so a real SvelteKit 404 from this app carries an `<h1>404</h1>`; a parked\n * domain, a CDN 404 and a dead host do not. \"The route is gone\" and \"the site\n * is gone\" must not look the same to this gate. */\nconst SITE_404_MARKER = /<h1[^>]*>\\s*404\\s*<\\/h1>/i;\n\n/** The UNGUARDED twin's OWN refusal. `src/routes/dev/match/[uid]/+page.server.ts`\n * 404s for any uid absent from its assembly map — and that message renders\n * through the very same `+error.svelte` the guard's 404 uses, so it carries an\n * `<h1>404</h1>` too. On a site whose uid set lacks \"home\", a LIVE twin and a\n * guarded one are byte-indistinguishable to SITE_404_MARKER, and the check\n * could never fail. Verified on disk: beachfront-dentistry's copy of that route\n * imports `$app/environment` zero times.\n *\n * The contract is the MACHINE tell `UNGUARDED_TWIN_TELL`, imported from the\n * template that installs the route rather than re-typed here: the installed\n * twin puts it ahead of its human-readable message. Matching the prose was\n * the defect of #719 — reword the message (\"no document for\", \"unknown uid\")\n * and the guard silently stopped denying, i.e. failed OPEN with fixtures\n * public. The two prose wordings are STILL accepted, on purpose and for now:\n * beachfront-dentistry's on-disk twin predates the tell and says \"no matching\n * assembly for\", and any site installed before the tell says \"no assembly\n * for\". Drop the prose alternates once beachfront's twin has been\n * re-installed from the harness; until then they only ever widen the deny.\n *\n * This is a DENY clause and only ever a deny — it can refuse a green, never\n * grant one. Widening it can only ever refuse a launch that would otherwise\n * have proceeded, so widening is always the safe direction here. */\nexport const UNGUARDED_TWIN_MARKER = new RegExp(\n `${UNGUARDED_TWIN_TELL.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\")}|no (matching )?assembly for`,\n \"i\",\n);\n\nconst MATCH_ROUTE_DIR = \"src/routes/dev/match\";\n\n/** Positive evidence that `sitePath` is a SvelteKit checkout at all. Without it,\n * the absence of MATCH_ROUTE_DIR is evidence of nothing: a path never cloned, a\n * stale clone, a mistyped site name and the wrong working directory all produce\n * exactly the same `false`, and `resolveSites` builds the path with\n * `localPath(resolve(cwd, site))` and no existence check of its own. This is\n * the filesystem twin of the `/health` control on the deployed gate — an absent\n * error must never be allowed to grant a green. */\nconst CHECKOUT_MARKER = \"src/routes\";\n\n/** Tokens after which a `/` opens a REGEX literal rather than a division. This\n * is the usual JS ambiguity, answered by lookback at the last significant\n * character — a scanner's answer, not a parser's.\n *\n * `)` is deliberately NOT here. `if (x) /re/.test(y)` is legal and is read as\n * division, which costs nothing (the `/` is copied through unchanged, exactly\n * as before this function existed) and keeps `(a + b) / 2` right, which is far\n * commoner in that position. That is the residual: a regex literal opening\n * directly after `)` AND containing a quote falls back to the old behaviour and\n * therefore DENIES. Deny is the safe direction here — see `carriesGuard`. */\nconst REGEX_PRECEDERS = /[(,=:[!&|?{};+\\-*%~^<>]/;\nconst REGEX_KEYWORDS = new Set([\n \"return\",\n \"typeof\",\n \"case\",\n \"in\",\n \"of\",\n \"new\",\n \"delete\",\n \"void\",\n \"instanceof\",\n \"do\",\n \"else\",\n \"yield\",\n \"await\",\n]);\n\nfunction opensRegex(prevChar: string, prevWord: string): boolean {\n if (prevChar === \"\") return true;\n if (REGEX_PRECEDERS.test(prevChar)) return true;\n return REGEX_KEYWORDS.has(prevWord);\n}\n\n/** The last significant character emitted so far, and the identifier ending at\n * it. Both scanners look back over their own OUTPUT, which is why masking is\n * safe to interleave: masked bodies are spaces and the delimiters survive, so\n * the structural lookback reads the same either way. */\nfunction lookback(out: string): { char: string; word: string } {\n let i = out.length - 1;\n while (i >= 0 && /\\s/.test(out[i]!)) i--;\n if (i < 0) return { char: \"\", word: \"\" };\n let j = i;\n while (j >= 0 && /[A-Za-z0-9_$]/.test(out[j]!)) j--;\n return { char: out[i]!, word: out.slice(j + 1, i + 1) };\n}\n\n/** Index of a regex literal's CLOSING `/`, or -1 if `source[at]` does not in\n * fact open one. `[...]` character classes are tracked because a `/` inside one\n * does not close the literal (`/[a-z/]/`). A newline or an unterminated run\n * means this was never a regex, and the caller then treats the `/` as an\n * ordinary character — the behaviour that predates regex-awareness. */\nfunction regexLiteralEnd(source: string, at: number): number {\n let inClass = false;\n for (let i = at + 1; i < source.length; i++) {\n const c = source[i]!;\n if (c === \"\\\\\") {\n i++;\n continue;\n }\n if (c === \"\\n\") return -1;\n if (inClass) {\n if (c === \"]\") inClass = false;\n continue;\n }\n if (c === \"[\") {\n inClass = true;\n continue;\n }\n if (c === \"/\") return i;\n }\n return -1;\n}\n\n/** Strip line and block comments, so the COMMON commented-out guard cannot\n * satisfy the match — an import left in place above `// if (!dev) error(404);`\n * is the likeliest real-world state, and it used to pass. String and template\n * literals are skipped so a `//` inside a URL is not read as a comment.\n *\n * Regex literals are recognised (#726). Without that, a quote character inside\n * one — `/[a-z0-9']+/` — opened a string that never closed, and everything to\n * the next matching quote was preserved as if it were string content. On a\n * CORRECTLY guarded file that swallowed the live `if (!dev) error(404)` and the\n * twin read as unguarded, so a launch was blocked on a site that was fine. The\n * literal is now copied through verbatim, which is what a comment stripper\n * should do with one. */\nfunction stripComments(source: string): string {\n let out = \"\";\n for (let i = 0; i < source.length;) {\n const ch = source[i]!;\n const next = source[i + 1];\n if (ch === \"/\" && next === \"/\") {\n while (i < source.length && source[i] !== \"\\n\") i++;\n continue;\n }\n if (ch === \"/\" && next === \"*\") {\n i += 2;\n while (i < source.length && !(source[i] === \"*\" && source[i + 1] === \"/\")) i++;\n i += 2;\n continue;\n }\n if (ch === \"/\") {\n const { char, word } = lookback(out);\n if (opensRegex(char, word)) {\n const end = regexLiteralEnd(source, i);\n if (end !== -1) {\n out += source.slice(i, end + 1);\n i = end + 1;\n continue;\n }\n }\n }\n if (ch === '\"' || ch === \"'\" || ch === \"`\") {\n out += ch;\n i++;\n while (i < source.length) {\n if (source[i] === \"\\\\\") {\n out += source.slice(i, i + 2);\n i += 2;\n continue;\n }\n out += source[i]!;\n i++;\n if (source[i - 1] === ch) break;\n }\n continue;\n }\n out += ch;\n i++;\n }\n return out;\n}\n\n/** Blank the CONTENTS of string and template literals, keeping the quote\n * characters, the newlines and the overall length. Only the guard scan uses\n * this — never the `$app/environment` check, whose whole subject is an import\n * specifier and therefore is itself a string literal.\n *\n * It exists because `if (!dev) console.warn(\"this should throw error(404)\")`\n * read as a refusal. Masking can only ever REMOVE candidate refusal tokens, so\n * it can only ever deny.\n * Regex BODIES are masked too, for the same reason and with the same effect: a\n * regex is data, so `if (!dev) RE = /throw/` must not be read as a refusal. It\n * was, before #726. */\nfunction maskLiterals(code: string): string {\n let out = \"\";\n for (let i = 0; i < code.length;) {\n const ch = code[i]!;\n if (ch === \"/\") {\n const { char, word } = lookback(out);\n if (opensRegex(char, word)) {\n const end = regexLiteralEnd(code, i);\n if (end !== -1) {\n // Delimiters and length kept, body blanked — exactly the string rule.\n out += \"/\" + \" \".repeat(end - i - 1) + \"/\";\n i = end + 1;\n continue;\n }\n }\n }\n if (ch !== '\"' && ch !== \"'\" && ch !== \"`\") {\n out += ch;\n i++;\n continue;\n }\n out += ch;\n i++;\n while (i < code.length) {\n const c = code[i]!;\n if (c === \"\\\\\") {\n out += \" \";\n i += 2;\n continue;\n }\n i++;\n if (c === ch) {\n out += c;\n break;\n }\n out += c === \"\\n\" ? \"\\n\" : \" \";\n }\n }\n return out;\n}\n\n/** The statement or block the `if (...)` ending at `from` actually governs: a\n * braced block, or the single statement up to its terminating `;` — or, under\n * ASI, the end of its line. Bracket depth is tracked so\n * `error(404, {\\n message: \"…\"\\n});` is ONE statement rather than three\n * fragments. Expects `code` to be comment-stripped and literal-masked, so every\n * bracket it sees is a real one. */\nfunction consequentAt(code: string, from: number): string {\n let i = from;\n while (i < code.length && /\\s/.test(code[i]!)) i++;\n const start = i;\n if (code[i] === \"{\") {\n let depth = 0;\n for (; i < code.length; i++) {\n if (code[i] === \"{\") depth++;\n else if (code[i] === \"}\" && --depth === 0) return code.slice(start, i + 1);\n }\n return code.slice(start);\n }\n let depth = 0;\n for (; i < code.length; i++) {\n const ch = code[i]!;\n if (ch === \"(\" || ch === \"[\" || ch === \"{\") depth++;\n else if (ch === \")\" || ch === \"]\" || ch === \"}\") {\n if (depth === 0) return code.slice(start, i);\n depth--;\n } else if (depth === 0 && (ch === \";\" || ch === \"\\n\")) return code.slice(start, i);\n }\n return code.slice(start);\n}\n\n/** An actual refusal: SvelteKit's `error(404, …)`, or any `throw`. */\nconst REFUSAL = /\\berror\\s*\\(\\s*404|\\bthrow\\b/;\n\n/** A guard is `$app/environment` + an `if (!dev)` **whose own branch refuses**.\n *\n * The three conditions used to be ANDed across the WHOLE file, with nothing\n * tying the refusal to the `if`. Two shapes passed that should not have: a\n * warn-only `if (!dev)` alongside the route's own unrelated `throw` (the exact\n * half-fix this comment used to claim was closed), and a refusal occurring only\n * inside a string. Reading the guard's consequent, on literal-masked source, is\n * strictly narrower than the old whole-file grep — every input it rejects, the\n * old predicate also had to reject on `$app/environment` or `if (!dev)`, or was\n * a false pass. It can therefore only deny, never grant.\n *\n * It is a contract with plan BC's `ROUTE_SERVER` template, which BC installs\n * and this pre-flight must accept; tests/recipes/launch.test.ts lifts that\n * template out of the plan and runs this predicate over it rather than\n * restating the pattern. */\nfunction carriesGuard(source: string): boolean {\n const code = stripComments(source);\n if (!code.includes(\"$app/environment\")) return false;\n const masked = maskLiterals(code);\n const guards = /if\\s*\\(\\s*!\\s*dev\\s*\\)/g;\n for (let m = guards.exec(masked); m; m = guards.exec(masked)) {\n if (REFUSAL.test(consequentAt(masked, m.index + m[0].length))) return true;\n }\n return false;\n}\n\nconst DEV_ROUTE_DIR = \"src/routes/dev\";\n\n/** Every SvelteKit route file at or below `relDir`, site-root-relative. The\n * gates used to read a FIXED list of three paths, which is why a `+server.ts`\n * endpoint and a `/dev/match/frozen` sibling were inspected by neither of them\n * (#723). What exists under the twin is a question for the filesystem, not for\n * a constant. */\nasync function routeFilesUnder(sitePath: string, relDir: string): Promise<string[]> {\n let entries;\n try {\n entries = await readdir(join(sitePath, relDir), { withFileTypes: true });\n } catch {\n return [];\n }\n const out: string[] = [];\n for (const e of entries) {\n const rel = `${relDir}/${e.name}`;\n if (e.isDirectory()) out.push(...(await routeFilesUnder(sitePath, rel)));\n else if (e.name.startsWith(\"+\")) out.push(rel);\n }\n return out;\n}\n\n/** `carriesGuard` for one file, memoised — a layout is asked about once per page\n * directory below it. An unreadable file is not a guard. */\nasync function guardAt(\n sitePath: string,\n rel: string,\n cache: Map<string, boolean>,\n): Promise<boolean> {\n const hit = cache.get(rel);\n if (hit !== undefined) return hit;\n let ok: boolean;\n try {\n ok = carriesGuard(await readFile(join(sitePath, rel), \"utf-8\"));\n } catch {\n ok = false;\n }\n cache.set(rel, ok);\n return ok;\n}\n\n/** The nearest guarded `+layout.server.ts` at or above `dir`, up to and\n * including `src/routes/dev`, or null.\n *\n * `src/routes/dev/+layout.server.ts` is the STRONGEST placement and the\n * fleet-wide class-fix for \"dev routes ship in production\" (#717): one `load`\n * doing `if (!dev) error(404)` runs for every `/dev/*` page, `/dev/match/[uid]`\n * included. An earlier version read only inside `/dev/match` and so reported\n * such a site as \"the matching twin would ship\" — untrue, and it penalised the\n * better fix. It also contradicted the deployed half of this feature, which was\n * deliberately redesigned to survive that class-fix: see the `/health` comment\n * at the dev-guard step for why the 200 control moved off `/dev/a11y-fixtures`.\n *\n * Layouts cover PAGES only. A `+server.ts` endpoint runs no layout `load` at\n * all, which is why `matchingDisposition` checks endpoints separately and never\n * lets a layout vouch for one (#723). */\nasync function coveringLayout(\n sitePath: string,\n dir: string,\n cache: Map<string, boolean>,\n): Promise<string | null> {\n let d = dir;\n for (;;) {\n const rel = `${d}/+layout.server.ts`;\n if (await guardAt(sitePath, rel, cache)) return rel;\n if (d === DEV_ROUTE_DIR) return null;\n const up = d.slice(0, d.lastIndexOf(\"/\"));\n if (up.length < DEV_ROUTE_DIR.length) return null;\n d = up;\n }\n}\n\n/**\n * Pre-flight: a checkout that still carries the matching twin must carry the\n * dev guard the `match-harness` recipe installs with it. Nothing is deleted at\n * launch — the harness stays for the next round — so the guard is the whole\n * mechanism keeping `/dev/match/*` off the production build.\n *\n * Filesystem only, and it runs BEFORE any GitHub write: a site that will fail\n * the deployed check should not first acquire branch protection and an audit.\n *\n * Liveness first. `src/routes` has to be there before a missing\n * `src/routes/dev/match` may be read as \"this site has no twin\" — otherwise the\n * pass is granted by an absence, and four separate operator errors produce that\n * same absence. See CHECKOUT_MARKER.\n */\nexport async function matchingDisposition(\n sitePath: string,\n): Promise<{ ok: boolean; message: string }> {\n if (!existsSync(join(sitePath, CHECKOUT_MARKER))) {\n return {\n ok: false,\n message: `${sitePath} has no ${CHECKOUT_MARKER} — this is not a SvelteKit checkout (never cloned, a stale clone, a mistyped site name, or the wrong working directory), so the twin's disposition cannot be established`,\n };\n }\n if (!existsSync(join(sitePath, MATCH_ROUTE_DIR))) {\n return {\n ok: true,\n message: `no ${MATCH_ROUTE_DIR} in this checkout (${CHECKOUT_MARKER} is present, so the absence is a real one)`,\n };\n }\n const files = await routeFilesUnder(sitePath, MATCH_ROUTE_DIR);\n if (files.length === 0) {\n return {\n ok: false,\n message: `${MATCH_ROUTE_DIR} exists but carries no route files (+page/+server/+layout) — the twin's disposition cannot be established`,\n };\n }\n\n const cache = new Map<string, boolean>();\n const unguarded: string[] = [];\n const covers: string[] = [];\n\n // Endpoints FIRST, and never covered by a layout: SvelteKit layout `load` does\n // not run for `+server.ts`, so the #717 class-fix at src/routes/dev that\n // legitimately covers every page leaves an endpoint fully live (#723).\n for (const ep of files.filter((f) => f.endsWith(\"/+server.ts\"))) {\n if (await guardAt(sitePath, ep, cache)) covers.push(ep);\n else\n unguarded.push(\n `${ep} (a \\`+server.ts\\` endpoint — layout \\`load\\` does not run for it, so it needs its own guard)`,\n );\n }\n\n // Then every directory holding a page, each covered by its own guarded\n // +page.server.ts or by a +layout.server.ts at or above it.\n const pageDirs = [\n ...new Set(\n files\n .filter((f) => /\\/\\+page\\.(server\\.ts|ts|svelte)$/.test(f))\n .map((f) => f.slice(0, f.lastIndexOf(\"/\"))),\n ),\n ];\n for (const dir of pageDirs) {\n const layout = await coveringLayout(sitePath, dir, cache);\n if (layout) {\n covers.push(layout);\n continue;\n }\n const own = `${dir}/+page.server.ts`;\n if (await guardAt(sitePath, own, cache)) {\n covers.push(own);\n continue;\n }\n unguarded.push(`${dir}/ (no guarded +page.server.ts and no covering +layout.server.ts)`);\n }\n\n if (unguarded.length > 0) {\n return {\n ok: false,\n message: `${MATCH_ROUTE_DIR} is not fully guarded — ${unguarded.join(\"; \")} — an \\`if (!dev)\\` guard on \\`$app/environment\\` whose own branch refuses (\\`error(404\\` or \\`throw\\`) is required, once comments are stripped and string and regex contents masked; the matching twin would ship`,\n };\n }\n // Deliberately NOT \"the twin is guarded in production\". This function reads\n // source text on disk; it cannot observe the deployed build, and a field that\n // can only see configuration must not be named after the thing it cannot see.\n // The deployed behaviour is the `dev-guard` step's job.\n return {\n ok: true,\n message: `every route under ${MATCH_ROUTE_DIR} is covered by dev guard source — ${[...new Set(covers)].join(\", \")} (source text only; the deployed build is checked at the dev-guard step)`,\n };\n}\n\n/** The uids whose `/dev/match` twin must be proved dead, read from the harness's\n * OWN page table — the file `match-harness` installs and every gate already\n * reads — so the gate and the harness cannot disagree about which pages exist.\n * Probing a hardcoded \"home\" left every sibling uid unprobed (#723).\n *\n * A page whose `uid` is null has no twin (harness.mjs says so) and is skipped.\n * An absent or unparseable harness.json falls back to \"home\": not every\n * launched site carries the harness, so a missing file must not become a\n * refusal — and must not yield an EMPTY list either, which would prove nothing\n * while looking like a pass. */\nasync function twinUids(sitePath: string): Promise<string[]> {\n let parsed: unknown;\n try {\n parsed = JSON.parse(await readFile(join(sitePath, HARNESS_JSON_RELATIVE), \"utf-8\"));\n } catch {\n return [\"home\"];\n }\n const pages = (parsed as { pages?: Record<string, { uid?: unknown } | null> })?.pages;\n if (!pages || typeof pages !== \"object\") return [\"home\"];\n const uids = Object.values(pages)\n .map((p) => p?.uid)\n .filter((u): u is string => typeof u === \"string\" && u.length > 0);\n return uids.length > 0 ? [...new Set(uids)] : [\"home\"];\n}\n\n/** Undici's defaults are 300s headers + 300s body, and the body timeout is an\n * INACTIVITY timer — so a trickling origin can hold this open for ~10 minutes,\n * AFTER the GitHub writes and a full Lighthouse audit have already run.\n *\n * 15s is NOT the house number, and this comment used to imply it was by citing\n * `audits/function-health.ts`, which is 10s. The 15s call sites are\n * `audits/netlify-deploy.ts`, `github/gh-rest.ts`, `prismic/models/remote.ts`\n * and the inline ones in `prospect/pipeline.ts` and `prospect/http-probes.ts`;\n * `audits/function-health.ts`, `audits/form-e2e.ts`, `audits/browser.ts` and\n * `prospect/dns.ts` are 10s, `prospect/ownership.ts` 12s, `prospect/crawl.ts`\n * 20s. Each is set for its own workload — see the note on PRISMIC_TIMEOUT_MS.\n * 15s here is a bound on a two-request pre-send check, not a convention.\n *\n * An abort rejects, and dev-guard treats a rejection as a refusal, which is the\n * correct reading: an origin that will not answer has proved nothing. */\nconst PROBE_TIMEOUT_MS = 15_000;\n\nconst defaultProbe = async (url: string): Promise<{ status: number; body: string }> => {\n const res = await fetch(url, {\n redirect: \"follow\",\n signal: AbortSignal.timeout(PROBE_TIMEOUT_MS),\n });\n return { status: res.status, body: await res.text() };\n};\n\n/**\n * Launch a site: bootstrap → first-audit → DRAFT a launch email. The M3\n * approve loop is what actually sends; `launch` never sends — it stops at a\n * dashboard-queued draft (`reportType: \"Launch\"`) carrying the just-audited\n * Lighthouse scores, so `sendOne`'s `report.lighthouse` guard passes.\n *\n * EXECUTION order, stopping on the first error or `failed` recipe:\n * 0. matchingDisposition — filesystem pre-flight, BEFORE any GitHub write.\n * 1. selfUpdating — Renovate + protection (platform auto-merge OFF; ci.yml is the starter's).\n * 2. audit — the Lighthouse scores that feed the draft are collected here.\n * 3. the Websites-row lookup, which supplies the url the next step probes.\n * 3b. dev-guard — the same twin, checked against the DEPLOYED url. It sits\n * BETWEEN collecting the scores and writing them, so a site that fails it\n * has been audited but leaves its Websites row untouched.\n * 4. writeAuditsToAirtable — the `audit --write-airtable` writer.\n * 5. createDraft — reportType \"Launch\", today's period, the audited scores.\n *\n * The REPORTED chain is deliberately not that order. The `audit` step is only\n * pushed once its write succeeds (:261), so the emitted steps read\n * `matching-disposition -> self-updating -> dev-guard -> audit -> draft`, which\n * is what the CLI prints and what tests/recipes/launch.test.ts asserts. Do not\n * renumber either list to match the other: one says when work happens, the\n * other says what has been proved. Only step 0 precedes a GitHub write —\n * dev-guard cannot, because it needs the row from step 3 to know the url.\n */\nexport async function launch(site: Site, deps: LaunchDeps = {}): Promise<LaunchResult> {\n const label = siteLabel(site);\n const bootstrap = deps.bootstrap ?? selfUpdating;\n const audit = deps.audit ?? runAudits;\n const base = deps.base ?? openBase(readAirtableConfig());\n const probe = deps.probe ?? defaultProbe;\n\n const steps: Array<{ name: string; result: LaunchStepResult }> = [];\n const stop = (): LaunchResult => ({ site: label, steps, complete: false });\n\n // 0. Matching disposition — filesystem, before any GitHub write.\n const disposition = await matchingDisposition(site.path);\n steps.push({\n name: \"matching-disposition\",\n result: disposition.ok\n ? { kind: \"probe\", message: disposition.message }\n : { kind: \"error\", message: disposition.message },\n });\n if (!disposition.ok) return stop();\n\n // 1. Bootstrap.\n let recipe: RecipeResult;\n try {\n recipe = await bootstrap(site);\n } catch (err) {\n steps.push({ name: \"self-updating\", result: errorOf(err) });\n return stop();\n }\n steps.push({ name: \"self-updating\", result: { kind: \"recipe\", result: recipe } });\n if (recipe.status === \"failed\") return stop();\n\n // 2. Audit + write scores back to Airtable.\n let results: AuditResult[];\n try {\n results = await audit(site);\n } catch (err) {\n steps.push({ name: \"audit\", result: errorOf(err) });\n return stop();\n }\n const lhResult = results.find((r) => r.audit === \"lighthouse\");\n if (!lhResult || !hasRealScores(lhResult)) {\n steps.push({\n name: \"audit\",\n result: { kind: \"error\", message: \"lighthouse audit produced no real scores\" },\n });\n return stop();\n }\n // The launch announcement renders a numeric score per category; a metric that\n // errored this run (now null from lighthouseScoresFromResult) keeps the prior\n // 0 behavior here rather than propagating null into the launch-email path. The\n // Airtable write path (write-audits-to-airtable) keeps the null → shows \"—\".\n const rawScores = lighthouseScoresFromResult(lhResult);\n const scores: LighthouseScores = {\n performance: rawScores.performance ?? 0,\n accessibility: rawScores.accessibility ?? 0,\n bestPractices: rawScores.bestPractices ?? 0,\n seo: rawScores.seo ?? 0,\n };\n\n const websites = await listWebsites(base);\n const target = websites.find((w) => siteSlug(w.name) === siteSlug(label));\n if (!target) {\n steps.push({\n name: \"audit\",\n result: { kind: \"error\", message: `no Websites row matched site \"${label}\"` },\n });\n return stop();\n }\n\n // 2b. The dev guard, on the DEPLOYED build. Two halves, both required:\n // /dev/match/home must 404 WITH this site's own error page, and /health\n // must answer 200. Without the second, a dead host, a wrong url and a\n // parked domain all \"pass\" the first — an absent error granting a green,\n // which is the one shape this fleet does not allow. Reading the deployed\n // url makes this a production-build check by construction; no local build\n // can substitute.\n //\n // The control is /health, NOT a /dev/* route. It used to be\n // /dev/a11y-fixtures, which made this gate require an unguarded dev page\n // to be publicly reachable in production — so the obvious class-fix for\n // \"dev routes ship in production\" (one src/routes/dev/+layout.server.ts\n // doing `if (!dev) error(404)`) would have taken the control down with it\n // and failed every correctly-guarded site. /health is a real production\n // endpoint shipped by the starter and present in all 23 starter-derived\n // repos, each declaring `prerender = false` — so a 200 from it is still a\n // live render/function path, not a static file served by the CDN.\n const origin = target.url.replace(/\\/+$/, \"\");\n const uids = await twinUids(site.path);\n const twins: Array<{ uid: string; res: { status: number; body: string } }> = [];\n let control: { status: number; body: string };\n try {\n for (const uid of uids) twins.push({ uid, res: await probe(`${origin}/dev/match/${uid}`) });\n control = await probe(`${origin}/health`);\n } catch (err) {\n steps.push({ name: \"dev-guard\", result: errorOf(err) });\n return stop();\n }\n if (control.status !== 200) {\n steps.push({\n name: \"dev-guard\",\n result: {\n kind: \"error\",\n message: `${origin}/health answered ${control.status}, not 200 — the twin's 404 proves nothing (host down, wrong url, or the site's /health function is not deploying, in which case the function-health audit is failing too)`,\n },\n });\n return stop();\n }\n for (const { uid, res } of twins) {\n const unguardedTell = res.body.match(UNGUARDED_TWIN_MARKER);\n if (unguardedTell) {\n steps.push({\n name: \"dev-guard\",\n result: {\n kind: \"error\",\n message: `${origin}/dev/match/${uid} answered ${res.status} carrying the twin route's OWN \"${unguardedTell[0]}\" message — the twin is LIVE and merely has no assembly for the uid \"${uid}\". That is not evidence of a dev guard.`,\n },\n });\n return stop();\n }\n if (res.status !== 404 || !SITE_404_MARKER.test(res.body)) {\n steps.push({\n name: \"dev-guard\",\n result: {\n kind: \"error\",\n message:\n res.status === 404\n ? `${origin}/dev/match/${uid} 404s, but not with this site's own error page — cannot tell the guard from a dead route`\n : `${origin}/dev/match/${uid} answered ${res.status} — the matching twin is live in production`,\n },\n });\n return stop();\n }\n }\n steps.push({\n name: \"dev-guard\",\n result: {\n kind: \"probe\",\n message: `${uids.map((u) => `${origin}/dev/match/${u}`).join(\", \")} 404 (site error page), /health 200`,\n },\n });\n\n try {\n const auditWrite = await writeAuditsToAirtable({\n base,\n websites,\n slug: siteSlug(target.name),\n results,\n });\n // #539 Phase 5: mirror the first-audit write-back. Launch is the ONE path\n // that writes a brand-new site's health, so without this its row reads empty\n // in the console until the next hourly sync.\n if (auditWrite.siteId && auditWrite.fields) {\n await deps.siteMirror?.health(auditWrite.siteId, auditWrite.fields);\n }\n } catch (err) {\n steps.push({ name: \"audit\", result: errorOf(err) });\n return stop();\n }\n steps.push({ name: \"audit\", result: { kind: \"audit\", results, scores } });\n\n // 3. Draft the launch email (reuses draft.ts's reportId/period scheme). DRAFTS\n // ONLY — the M3 approve loop sends it and flips Status on send.\n const today = new Date();\n const period = today.toISOString().slice(0, 7);\n const slug = siteSlug(target.name);\n\n let report: ReportRow;\n try {\n // Re-run dedupe: reuse an existing Launch row for this (site, period) instead\n // of stacking a second draft. findReportByPeriod is the same idempotency\n // lookup draft.ts documents (dashboard/digest point lookup).\n const existing = await findReportByPeriod(base, target.id, \"Launch\", period);\n if (existing) {\n // Reuse path: the row was created on a prior run with THAT run's scores. This\n // re-run just produced fresh audit scores AND will re-render the preview from\n // them — so refresh the row's Lighthouse cells (+ Completed on) to match,\n // otherwise the sent email (which reads the row) ships stale scores. The\n // create path already writes fresh scores via createDraft.\n await updateReportScores(base, existing.id, scores, today);\n // Mirror the same refresh — see the announce reuse path for why.\n await deps.reportMirror?.patch(existing.id, {\n lighthouse_performance: scores.performance,\n lighthouse_accessibility: scores.accessibility,\n lighthouse_best_practices: scores.bestPractices,\n lighthouse_seo: scores.seo,\n completed_on: today.toISOString().slice(0, 10),\n });\n report = existing;\n } else {\n report = await createDraft(\n base,\n draftInputFor(target, scores, today, period),\n deps.reportMirror?.created,\n );\n }\n } catch (err) {\n steps.push({ name: \"draft\", result: errorOf(err) });\n return stop();\n }\n\n // Mirror draft.ts:135-154 — render → upload \"Rendered HTML\" preview → flip\n // Draft ready. Without setDraftReady the draft never enters the approve queue\n // (every pending-approval gate requires draftReady true), so it can never be\n // approved or sent. The upload is a review convenience; the ready flag is the\n // critical step.\n try {\n const { html } = await renderReportHtml({\n siteName: target.name,\n siteUrl: target.url,\n reportType: \"Launch\",\n completedOn: today,\n lighthouse: scores,\n lastTestedDate: null,\n commentary: null,\n copy: resolveCopy(target),\n headerImageCid: `${slug}-header`,\n });\n // A preview-upload hiccup must NOT fail the launch — log and continue.\n try {\n await uploadAttachment(\n report.id,\n \"Rendered HTML\",\n html,\n `${slug}-${today.toISOString().slice(0, 10)}.html`,\n \"text/html\",\n );\n // The console preview reads the body from Turso, not the attachment.\n await deps.reportMirror?.body(report.id, html);\n } catch (uploadErr) {\n console.warn(\n `⚠ Launch preview upload skipped for ${target.name}: ${\n uploadErr instanceof Error ? uploadErr.message : String(uploadErr)\n }`,\n );\n }\n // Critical: NOT wrapped — a failure here must surface as a failed launch. queueDraft\n // supersedes any lower-tier (Maintenance/Testing) drafts queued for this site; a Launch is\n // top tier so it only stands down if another Launch/Announcement is already queued.\n await queueDraft(\n base,\n { id: report.id, siteId: target.id, reportType: \"Launch\" },\n deps.reportMirror,\n );\n } catch (err) {\n steps.push({ name: \"draft\", result: errorOf(err) });\n return stop();\n }\n\n steps.push({ name: \"draft\", result: { kind: \"draft\", report } });\n\n return { site: label, steps, complete: true };\n}\n\n/** Build the Launch `DraftInput`. reportId/period mirror `draftReportForSite`\n * (draft.ts) — do not invent a new id scheme. `today`/`period` are threaded in\n * from `launch()` so a single timestamp drives the render, the draft, the\n * dedupe lookup, and the preview filename. Launch reports have no period window\n * and no prior maintenance test, so periodStart/periodEnd/completedOn all\n * collapse to \"today\" and `lastTestedDate` is null. */\nfunction draftInputFor(\n target: WebsiteRow,\n scores: LighthouseScores,\n today: Date,\n period: string,\n): Parameters<typeof createDraft>[1] {\n const reportType = \"Launch\" as const;\n const reportId = `${target.name} — ${reportType} — ${today.toISOString().slice(0, 10)}`;\n return {\n reportId,\n siteId: target.id,\n reportType,\n period,\n periodStart: today,\n periodEnd: today,\n completedOn: today,\n lighthouse: scores,\n lastTestedDate: null,\n };\n}\n\nfunction errorOf(err: unknown): LaunchStepResult {\n return { kind: \"error\", message: err instanceof Error ? err.message : String(err) };\n}\n"],"mappings":"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","names":["depth"]}
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  lighthouseAudit
3
- } from "./chunk-2NQUCS7O.js";
3
+ } from "./chunk-BIYQN7FH.js";
4
4
  import "./chunk-PTDMVGKL.js";
5
5
  import "./chunk-LBYOLBW7.js";
6
6
  import "./chunk-XXTZBPUY.js";
@@ -8,4 +8,4 @@ import "./chunk-NMAWXBJA.js";
8
8
  export {
9
9
  lighthouseAudit
10
10
  };
11
- //# sourceMappingURL=lighthouse-VHI77PFB.js.map
11
+ //# sourceMappingURL=lighthouse-52WSPZ5D.js.map
@@ -2,11 +2,11 @@ import {
2
2
  hasRealScores,
3
3
  lighthouseScoresFromResult,
4
4
  resolveSlugFromCwd
5
- } from "./chunk-XN37VTDB.js";
6
- import "./chunk-3Z6X3BHU.js";
5
+ } from "./chunk-37B4LVB3.js";
6
+ import "./chunk-KN52PM63.js";
7
7
  export {
8
8
  hasRealScores,
9
9
  lighthouseScoresFromResult,
10
10
  resolveSlugFromCwd
11
11
  };
12
- //# sourceMappingURL=lighthouse-airtable-YMH4UA7R.js.map
12
+ //# sourceMappingURL=lighthouse-airtable-3NOFB42B.js.map