@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
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/reports/airtable/ensure-site.ts","../src/cli/commands/ensure-site.ts"],"sourcesContent":["import type { FieldSet, Records } from \"airtable\";\nimport type { AirtableBase } from \"./client.js\";\nimport { WEBSITES_TABLE, mapRow, siteSlug, type WebsiteRow } from \"./websites.js\";\nimport { toAirtableStatus } from \"./site-status.js\";\n\nexport type EnsureSiteInput = {\n /** Canonical slug — matches by siteSlug(Name); the Name on create when no displayName given. */\n slug: string;\n /** Human display name written to Name on create, and — unlike every other\n * input — UPDATED on an existing row when it differs (#664). Name is\n * consumed VERBATIM in client-facing copy (forms auto-reply intro, report\n * subjects), so a bare machine slug there reads as \"Thanks for reaching out\n * to acme-co.\" — and the row that has it is exactly the one created before\n * the name was settled, which only this command re-run can fix. Must\n * slugify to the same slug or the row wouldn't be found on re-run. */\n displayName?: string;\n url?: string;\n pointOfContact?: string;\n /** owner/repo. Default on create: `reddoorla/<slug>`. */\n gitRepo?: string;\n};\n\n/** #539 Phase 5. Structurally typed rather than importing the db layer's\n * `SiteMirror`, so this module stays the leaf it has always been — a real\n * `SiteMirror` satisfies it. Two ops because `ensureSite` has two write paths,\n * and the create one is the reason this exists: every other site mirror is an\n * UPDATE, which does nothing for a row that does not exist yet. */\nexport type EnsureSiteMirror = {\n created: (rec: { id: string; fields: Record<string, unknown> }) => Promise<void>;\n site: (siteId: string, fields: Record<string, unknown>) => Promise<void>;\n /** #645. Does Turso hold a row for this site id? Optional so every pre-#645\n * caller (and every hand-built test mirror) is byte-for-byte unchanged —\n * absent means the heal below never runs. */\n hasRow?: (siteId: string) => Promise<boolean>;\n};\n\nexport type EnsureSiteResult = {\n status: \"created\" | \"exists\";\n siteId: string;\n /** Airtable column names written on the exists path (create path writes all). */\n updatedFields: string[];\n /** Inputs that DIFFERED from an existing non-blank cell and were left\n * untouched (fill-blanks-only) — surfaced so a resumed bootstrap with a\n * corrected value doesn't silently discard it. */\n skippedMismatches: string[];\n /** #645. True when the site existed in Airtable but had NO Turso row and this\n * run inserted one. Surfaced rather than logged-only because it is the\n * difference between \"nothing to do\" and \"this site's leads were being\n * dropped until just now\". */\n healedDbRow: boolean;\n};\n\n/** Column-name map (load-bearing magic strings — see websites.ts's mapRow header). */\nconst COLS = {\n url: \"url\",\n pointOfContact: \"point of contact\",\n gitRepo: \"Git repo\",\n} as const;\n\n/**\n * Find-or-create the Websites row for a slug so a new site exists in the fleet\n * inventory (audits, form-ingest slug resolution, reports) from day one.\n *\n * Fill-blanks-only on the exists path: this command runs from a bootstrap skill\n * that may be re-run to resume — it must never clobber operator-edited cells.\n * The one exception is `displayName` (#664): `--name` targets Name and nothing\n * else, so a differing value IS the operator's edit, and the create message\n * sends them back here to make it. Frequencies are deliberately NOT set\n * (launch flips the lifecycle); Status is only written on create (\"building\" —\n * Airtable's \"in development\" until the stage-2 vocabulary switch flips).\n */\nexport async function ensureSite(\n base: AirtableBase,\n input: EnsureSiteInput,\n mirror?: EnsureSiteMirror,\n): Promise<EnsureSiteResult> {\n const slug = siteSlug(input.slug);\n if (!slug) throw new Error(`ensure-site: '${input.slug}' does not slugify to a usable slug`);\n if (input.displayName && siteSlug(input.displayName) !== slug)\n throw new Error(\n `ensure-site: display name '${input.displayName}' slugifies to '${siteSlug(input.displayName)}', not '${slug}' — the row would not be found on re-run`,\n );\n\n // Paged inline rather than through `listWebsites` so the RAW stored record\n // survives alongside the mapped row: the #645 heal below re-inserts what\n // Airtable STORED (the same contract as the create path's mirror), and a\n // mapped `WebsiteRow` cannot be turned back into a FieldSet. Same single\n // select `listWebsites` issues — no extra Airtable read.\n const raw: Array<{ id: string; fields: Record<string, unknown> }> = [];\n await base(WEBSITES_TABLE)\n .select({ pageSize: 100 })\n .eachPage((records, fetchNextPage) => {\n for (const rec of records) raw.push({ id: rec.id, fields: rec.fields });\n fetchNextPage();\n });\n let existing: WebsiteRow | undefined;\n let existingRaw: { id: string; fields: Record<string, unknown> } | undefined;\n for (const rec of raw) {\n const row = mapRow(rec);\n if (siteSlug(row.name) === slug) {\n existing = row;\n existingRaw = rec;\n break;\n }\n }\n\n if (!existing || !existingRaw) {\n const fields: FieldSet = {\n Name: input.displayName ?? slug,\n Status: toAirtableStatus(\"building\"),\n [COLS.gitRepo]: input.gitRepo ?? `reddoorla/${slug}`,\n };\n if (input.url) fields[COLS.url] = input.url;\n if (input.pointOfContact) fields[COLS.pointOfContact] = input.pointOfContact;\n const created = (await base(WEBSITES_TABLE).create([{ fields }])) as Records<FieldSet>;\n const rec = created[0]!;\n // The mirror gets what Airtable STORED, never the `fields` we sent: parity\n // diffs Turso against the stored record, so mapping our own payload would\n // diverge the moment Airtable normalises a value.\n await mirror?.created({ id: rec.id, fields: rec.fields as Record<string, unknown> });\n return {\n status: \"created\",\n siteId: rec.id,\n updatedFields: [],\n skippedMismatches: [],\n // The create path just inserted the row; there is nothing to heal, and a\n // `hasRow` probe here would be a round-trip whose answer is already known.\n healedDbRow: false,\n };\n }\n\n // #645. THE gap: before this, `exists` meant \"Airtable has it\" and said nothing\n // about Turso. Post-flip (#643) the form-ingest lookup reads Turso ONLY, so a\n // site with an Airtable row and no Turso row has every lead answered\n // `unknown-site` — silently, permanently, and with no alarm once Phase 6 (#646)\n // deletes `mirror_missed`. `ensure-site` is the command an operator already\n // re-runs to finish a half-created site, so the heal belongs here.\n //\n // FIRST, before the fill-blanks update below: `mirror.site` is an UPDATE, and\n // under the freeze a no-match THROWS (`SITE_MIRROR … no such row in Turso`).\n // Healing second would abort ensure-site on exactly the site it exists to\n // repair. `mirrorSiteInsert` is an upsert, so a lost race just re-writes.\n let healedDbRow = false;\n if (mirror?.hasRow && !(await mirror.hasRow(existingRaw.id))) {\n await mirror.created(existingRaw);\n healedDbRow = true;\n }\n\n const updates: FieldSet = {};\n const skippedMismatches: string[] = [];\n const blank = (v: unknown) => v === null || v === undefined || v === \"\";\n const consider = (column: string, provided: string | undefined, current: unknown) => {\n if (!provided) return;\n if (blank(current)) updates[column] = provided;\n else if (current !== provided) skippedMismatches.push(column);\n };\n consider(COLS.url, input.url, existing.url || null);\n consider(COLS.pointOfContact, input.pointOfContact, existing.pointOfContact);\n consider(COLS.gitRepo, input.gitRepo, existing.gitRepo);\n // #664: Name is NOT fill-blanks. It is never blank (the slug match found it),\n // and `--name` is the only way to retitle a row created before the display\n // name was settled — the slugify guard above already proved the new value\n // resolves to the same row. Goes through the same update + mirror below, so\n // Turso gets it too.\n if (input.displayName && existing.name !== input.displayName) {\n updates[\"Name\"] = input.displayName;\n }\n\n const updatedFields = Object.keys(updates);\n if (updatedFields.length > 0) {\n await base(WEBSITES_TABLE).update([{ id: existing.id, fields: updates }]);\n // The fill-blanks path writes real cells too — a resumed bootstrap that only\n // filled a blank `url` would otherwise leave Turso stale until the sync.\n await mirror?.site(existing.id, updates);\n }\n return { status: \"exists\", siteId: existing.id, updatedFields, skippedMismatches, healedDbRow };\n}\n","import { openBase, readAirtableConfig } from \"../../reports/airtable/client.js\";\nimport { ensureSite } from \"../../reports/airtable/ensure-site.js\";\n\nexport type EnsureSiteCommandOptions = {\n name?: string;\n url?: string;\n contact?: string;\n gitRepo?: string;\n cwd?: string;\n};\n\n/**\n * `ensure-site <slug>` — create/verify the fleet-inventory row for a new site.\n * Day-one step of the /new-site bootstrap skill. Fill-blanks-only; safe to re-run.\n */\nexport async function runEnsureSiteCommand(\n slug: string | undefined,\n opts: EnsureSiteCommandOptions,\n): Promise<{ output: string; code: number }> {\n if (!slug) return { output: \"Provide a <slug> (e.g. `ensure-site roalson`).\", code: 2 };\n try {\n const base = openBase(readAirtableConfig());\n // #539 Phase 5: bootstrapping a site CREATES the Websites row, so this is\n // the one site path that needs an INSERT mirror — every other one updates.\n const { makeSiteMirror } = await import(\"../../db/site-mirror.js\");\n const result = await ensureSite(\n base,\n {\n slug,\n ...(opts.name ? { displayName: opts.name } : {}),\n ...(opts.url ? { url: opts.url } : {}),\n ...(opts.contact ? { pointOfContact: opts.contact } : {}),\n ...(opts.gitRepo ? { gitRepo: opts.gitRepo } : {}),\n },\n await makeSiteMirror(),\n );\n // #664: a Name change on the exists path is a rename the operator asked\n // for with --name, not a blank the bootstrap filled — say so.\n const renamed = result.updatedFields.includes(\"Name\") ? ` — Name set to \"${opts.name}\"` : \"\";\n const blanks = result.updatedFields.filter((f) => f !== \"Name\");\n const filled = blanks.length > 0 ? ` — filled blank field(s): ${blanks.join(\", \")}` : \"\";\n const skipped =\n result.skippedMismatches.length > 0\n ? ` — differs from existing, left untouched (edit in Airtable): ${result.skippedMismatches.join(\", \")}`\n : \"\";\n // #645. Loud, and its own clause: a healed row means this site's leads were\n // being answered `unknown-site` and dropped until this run.\n const healed = result.healedDbRow\n ? ` — HEALED: the Turso row was MISSING and has been inserted; leads for this slug were being dropped (run \\`db replay-deadletters\\`)`\n : \"\";\n const nameNote =\n result.status === \"created\" && !opts.name\n ? ` — Name set to \"${slug}\"; retitle in Airtable before forms/announce go live (or re-run with --name)`\n : \"\";\n return {\n output: `[${slug}] ${result.status} (${result.siteId})${healed}${renamed}${filled}${skipped}${nameNote}`,\n code: 0,\n };\n } catch (err) {\n const e = err as { message?: string; exitCode?: number };\n return { output: e.message ?? String(err), code: e.exitCode ?? 1 };\n }\n}\n"],"mappings":"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","names":[]}
@@ -14,12 +14,13 @@ import {
14
14
  mirrorSiteField,
15
15
  mirrorSiteFields,
16
16
  mirrorSiteInsert,
17
+ siteRowExists,
17
18
  storeRenderedHtml
18
- } from "./chunk-WVNDEYXL.js";
19
- import "./chunk-6R56OKJZ.js";
19
+ } from "./chunk-GEUC5VGM.js";
20
+ import "./chunk-UIITN37J.js";
20
21
  import "./chunk-F3JWOPTG.js";
21
22
  import "./chunk-VAD43MOR.js";
22
- import "./chunk-3Z6X3BHU.js";
23
+ import "./chunk-KN52PM63.js";
23
24
  export {
24
25
  REPORT_LIST_COLUMNS,
25
26
  getReportById,
@@ -36,6 +37,7 @@ export {
36
37
  mirrorSiteField,
37
38
  mirrorSiteFields,
38
39
  mirrorSiteInsert,
40
+ siteRowExists,
39
41
  storeRenderedHtml
40
42
  };
41
- //# sourceMappingURL=fleet-state-UEVZ3X3J.js.map
43
+ //# sourceMappingURL=fleet-state-GJWGKTLD.js.map
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  describeNotifyTarget
3
- } from "./chunk-4763KQ6O.js";
4
- import "./chunk-QF6IQQFP.js";
3
+ } from "./chunk-PXRN2MER.js";
4
+ import "./chunk-Z7FDJ35L.js";
5
5
  import "./chunk-5ML7FMBD.js";
6
6
  import "./chunk-NO74DXDP.js";
7
7
  import "./chunk-I7NHLVVI.js";
@@ -16,7 +16,7 @@ import {
16
16
  siteSlug,
17
17
  toAirtableStatus,
18
18
  updateSiteField
19
- } from "./chunk-3Z6X3BHU.js";
19
+ } from "./chunk-KN52PM63.js";
20
20
  import "./chunk-2OP4JKIQ.js";
21
21
  import "./chunk-6VAL7XJT.js";
22
22
 
@@ -144,7 +144,7 @@ async function runFormsNotifyTargetCommand(site, opts) {
144
144
  return { output: `--set must be 'on' or 'off' (got '${opts.set}')`, code: 2 };
145
145
  }
146
146
  try {
147
- const { makeSiteMirror } = await import("./site-mirror-WON4FTJ2.js");
147
+ const { makeSiteMirror } = await import("./site-mirror-H2FYMN55.js");
148
148
  const result = await formsNotifyTarget({
149
149
  siteMirror: await makeSiteMirror(),
150
150
  site: site.trim(),
@@ -164,4 +164,4 @@ export {
164
164
  formatNotifyTarget,
165
165
  runFormsNotifyTargetCommand
166
166
  };
167
- //# sourceMappingURL=forms-notify-target-UC6PF3AE.js.map
167
+ //# sourceMappingURL=forms-notify-target-4NPLX2UG.js.map
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  TURSO_IS_AUTHORITATIVE,
3
3
  mirrorWrite
4
- } from "./chunk-SVAAONYB.js";
4
+ } from "./chunk-WQLNUEZL.js";
5
5
  export {
6
6
  TURSO_IS_AUTHORITATIVE,
7
7
  mirrorWrite
8
8
  };
9
- //# sourceMappingURL=freeze-A6MUCZU4.js.map
9
+ //# sourceMappingURL=freeze-GUQ43EAU.js.map
@@ -3,9 +3,9 @@ import {
3
3
  } from "./chunk-PZQ3WED2.js";
4
4
  import {
5
5
  formatFleetWriteSummary
6
- } from "./chunk-5EEMTJMT.js";
7
- import "./chunk-XN37VTDB.js";
8
- import "./chunk-SVAAONYB.js";
6
+ } from "./chunk-ZH5LOQET.js";
7
+ import "./chunk-37B4LVB3.js";
8
+ import "./chunk-WQLNUEZL.js";
9
9
  import {
10
10
  detectSignalEvents,
11
11
  fleetSweptEvent
@@ -18,15 +18,15 @@ import {
18
18
  listWebsites,
19
19
  siteSlug,
20
20
  updateGitHubSignals
21
- } from "./chunk-3Z6X3BHU.js";
21
+ } from "./chunk-KN52PM63.js";
22
22
  import {
23
23
  makeGitHub
24
- } from "./chunk-XHHMM5HX.js";
24
+ } from "./chunk-43SW3FGW.js";
25
25
  import {
26
26
  recordFleetEventsBestEffort
27
- } from "./chunk-BI2VI6EM.js";
28
- import "./chunk-VSGMCCGQ.js";
29
- import "./chunk-C3IQQKXL.js";
27
+ } from "./chunk-EQQ4H6L3.js";
28
+ import "./chunk-6INOBNRO.js";
29
+ import "./chunk-T76MA2FH.js";
30
30
  import "./chunk-LBYOLBW7.js";
31
31
  import "./chunk-6VAL7XJT.js";
32
32
 
@@ -91,7 +91,7 @@ async function runGitHubSignalsCommand(opts, deps = {}) {
91
91
  );
92
92
  const sweptAt = (/* @__PURE__ */ new Date()).toISOString();
93
93
  const makeMirror = deps.makeMirror ?? (async () => {
94
- const { makeHealthMirrorBestEffort } = await import("./health-mirror-XJAKA3EY.js");
94
+ const { makeHealthMirrorBestEffort } = await import("./health-mirror-ONRT4DQ5.js");
95
95
  return makeHealthMirrorBestEffort();
96
96
  });
97
97
  const mirror = await makeMirror();
@@ -156,4 +156,4 @@ export {
156
156
  githubSignalsExitCode,
157
157
  runGitHubSignalsCommand
158
158
  };
159
- //# sourceMappingURL=github-signals-TX5FPYP6.js.map
159
+ //# sourceMappingURL=github-signals-DMU74SAX.js.map
@@ -7,12 +7,12 @@ import {
7
7
  } from "./chunk-HN6I2XWI.js";
8
8
  import {
9
9
  generateHeaderImage
10
- } from "./chunk-5UINJNAJ.js";
10
+ } from "./chunk-MZZDMBDT.js";
11
11
  import {
12
12
  ACTIVE_STATUSES,
13
13
  listWebsites,
14
14
  siteSlug
15
- } from "./chunk-3Z6X3BHU.js";
15
+ } from "./chunk-KN52PM63.js";
16
16
  import "./chunk-6VAL7XJT.js";
17
17
 
18
18
  // src/cli/commands/header-image.ts
@@ -54,7 +54,8 @@ async function generateForTargets(targets, opts, generate = generateHeaderImage)
54
54
  slug: siteSlug(row.name),
55
55
  // `exactOptionalPropertyTypes` rejects an explicit `settleMs: undefined`
56
56
  // against `settleMs?: number`, so omit the key entirely when unset.
57
- ...settleMs === void 0 ? {} : { settleMs }
57
+ ...settleMs === void 0 ? {} : { settleMs },
58
+ ...opts.consentSelector === void 0 ? {} : { consentSelector: opts.consentSelector }
58
59
  });
59
60
  if (opts.writeAirtable) {
60
61
  await uploadAttachment(row.id, "Header image", gen.bytes, gen.filename, gen.contentType, {
@@ -102,7 +103,7 @@ async function runHeaderImageCommand(site, opts) {
102
103
  }
103
104
  let withStore = opts;
104
105
  if (opts.writeAirtable && !opts.storeDb && process.env.TURSO_DATABASE_URL) {
105
- const { openDb, readDbConfig } = await import("./client-G2WGWPCA.js");
106
+ const { openDb, readDbConfig } = await import("./client-L7NAUG6J.js");
106
107
  const { storeHeaderImage } = await import("./header-images-SQBCE5OD.js");
107
108
  const db = await openDb(readDbConfig());
108
109
  withStore = { ...opts, storeDb: (id, img) => storeHeaderImage(db, id, img) };
@@ -115,4 +116,4 @@ export {
115
116
  resolveTargets,
116
117
  runHeaderImageCommand
117
118
  };
118
- //# sourceMappingURL=header-image-PSPT7CUM.js.map
119
+ //# sourceMappingURL=header-image-BRTOLHJF.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli/commands/header-image.ts"],"sourcesContent":["import { mkdir, writeFile } from \"node:fs/promises\";\nimport { resolve } from \"node:path\";\nimport { openBase, readAirtableConfig } from \"../../reports/airtable/client.js\";\nimport { listWebsites, siteSlug, ACTIVE_STATUSES } from \"../../reports/airtable/websites.js\";\nimport type { WebsiteRow } from \"../../reports/airtable/websites.js\";\nimport { uploadAttachment } from \"../../reports/airtable/attachments.js\";\nimport { generateHeaderImage } from \"../../reports/header-image/index.js\";\nimport type { StoredHeaderImage } from \"../../db/header-images.js\";\n\nexport type HeaderImageOptions = {\n all?: boolean;\n force?: boolean;\n writeAirtable?: boolean;\n outDir?: string;\n settleMs?: string;\n consentSelector?: string;\n /** Injected Turso store for the dual-write (#539, design D5): while Airtable\n * is still written (until the Phase 5 freeze), every upload ALSO lands the\n * bytes in sites.header_image* so the Turso read layer serves a real image.\n * Absent → Airtable-only (a local run without Turso env still works). */\n storeDb?: (siteId: string, img: StoredHeaderImage) => Promise<void>;\n};\n\n/** Which rows this invocation should act on. Pure, so it is unit-tested. */\nexport function resolveTargets(\n rows: readonly WebsiteRow[],\n // `| undefined` spelled out because `exactOptionalPropertyTypes` otherwise\n // rejects the caller passing through possibly-undefined CLI flags.\n opts: { site?: string | undefined; all?: boolean | undefined; force?: boolean | undefined },\n): WebsiteRow[] {\n if (opts.site) {\n const want = siteSlug(opts.site);\n return rows.filter((r) => siteSlug(r.name) === want);\n }\n if (!opts.all) return [];\n return rows.filter((r) => {\n if (!r.url) return false;\n if (r.status === null || !ACTIVE_STATUSES.has(r.status)) return false;\n return opts.force ? true : !r.headerImage;\n });\n}\n\n/** Parse the `--settle-ms <ms>` flag. Unset → undefined (the generator's own\n * default settle). `Number(\"abc\")` is NaN, which would sail through as a NaN\n * timeout and silently skip the settle entirely, so anything non-finite or\n * negative is rejected up front rather than producing a subtly-wrong capture. */\nexport function parseSettleMs(value: string | undefined): number | undefined {\n if (value === undefined) return undefined;\n const n = Number(value);\n if (!Number.isFinite(n) || n < 0) {\n throw Object.assign(\n new Error(`--settle-ms must be a non-negative number of milliseconds, got \"${value}\"`),\n { exitCode: 2 },\n );\n }\n return n;\n}\n\n/** Injected in tests so the file-writing branch can be exercised without\n * driving a real browser (mirrors `GenerateInput.shooter`). */\ntype Generate = typeof generateHeaderImage;\n\n/**\n * Generate a header image per target row and either upload it to Airtable or\n * write it locally for review. Split out of {@link runHeaderImageCommand} so\n * the local-output path is testable without an Airtable base.\n */\nexport async function generateForTargets(\n targets: readonly WebsiteRow[],\n opts: HeaderImageOptions,\n generate: Generate = generateHeaderImage,\n): Promise<{ output: string; code: number }> {\n const outDir = resolve(opts.outDir ?? \"reports\");\n const settleMs = parseSettleMs(opts.settleMs);\n // `reports/` does not exist on a fresh checkout, so the writeFile() below\n // would throw ENOENT for the first operator to run the default (local) path.\n // Create it once, before the loop, rather than per site.\n if (!opts.writeAirtable) await mkdir(outDir, { recursive: true });\n\n const lines: string[] = [];\n let failed = 0;\n\n for (const row of targets) {\n try {\n const gen = await generate({\n url: row.url,\n slug: siteSlug(row.name),\n // `exactOptionalPropertyTypes` rejects an explicit `settleMs: undefined`\n // against `settleMs?: number`, so omit the key entirely when unset.\n ...(settleMs === undefined ? {} : { settleMs }),\n ...(opts.consentSelector === undefined ? {} : { consentSelector: opts.consentSelector }),\n });\n if (opts.writeAirtable) {\n // replaceIn: the field must hold exactly the current header — see\n // uploadAttachment, where appending left readers on a stale [0].\n await uploadAttachment(row.id, \"Header image\", gen.bytes, gen.filename, gen.contentType, {\n replaceIn: \"Websites\",\n });\n let stored = \"\";\n if (opts.storeDb) {\n // Dual-write. A Turso failure must not void the Airtable upload —\n // but it must be VISIBLE, never a silent divergence.\n try {\n await opts.storeDb(row.id, {\n bytes: gen.bytes,\n filename: gen.filename,\n contentType: gen.contentType,\n generatedAt: new Date().toISOString(),\n });\n stored = \" + turso\";\n } catch (err) {\n stored = ` (⚠ turso store FAILED: ${err instanceof Error ? err.message : String(err)})`;\n }\n }\n lines.push(\n `✔ ${row.name} — uploaded ${gen.filename} (${(gen.bytes.byteLength / 1024 / 1024).toFixed(2)} MB)${stored}`,\n );\n } else {\n const path = resolve(outDir, gen.filename);\n await writeFile(path, gen.bytes);\n lines.push(`✔ ${row.name} — wrote ${path} (review, then re-run with --write-airtable)`);\n }\n } catch (err) {\n failed++;\n lines.push(`✖ ${row.name} — ${err instanceof Error ? err.message : String(err)}`);\n }\n }\n\n lines.push(`${targets.length - failed}/${targets.length} generated.`);\n return { output: lines.join(\"\\n\"), code: failed > 0 ? 1 : 0 };\n}\n\n/**\n * `header-image [site]` — capture a site's live homepage and composite its\n * report header image. Defaults to writing the JPEG locally so the operator can\n * eyeball it; `--write-airtable` uploads it to the Websites row's Header image\n * field. `--all` backfills every live site that has no header image yet.\n */\nexport async function runHeaderImageCommand(\n site: string | undefined,\n opts: HeaderImageOptions,\n): Promise<{ output: string; code: number }> {\n const base = openBase(readAirtableConfig());\n const rows = await listWebsites(base);\n const targets = resolveTargets(rows, { site, all: opts.all, force: opts.force });\n if (targets.length === 0) {\n return {\n output: site ? `No site matched \"${site}\".` : \"No sites need a header image.\",\n code: 1,\n };\n }\n // Wire the Turso dual-write when the env is present; a local run without it\n // still works Airtable-only (the store is per-site error-isolated above).\n let withStore = opts;\n if (opts.writeAirtable && !opts.storeDb && process.env.TURSO_DATABASE_URL) {\n const { openDb, readDbConfig } = await import(\"../../db/client.js\");\n const { storeHeaderImage } = await import(\"../../db/header-images.js\");\n const db = await openDb(readDbConfig());\n withStore = { ...opts, storeDb: (id, img) => storeHeaderImage(db, id, img) };\n }\n return generateForTargets(targets, withStore);\n}\n"],"mappings":"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","names":[]}
@@ -5,20 +5,21 @@ import {
5
5
  appendSkipNotice,
6
6
  fleetWorkdir,
7
7
  prepareFleetSites
8
- } from "./chunk-LM2NHRCJ.js";
8
+ } from "./chunk-SHGIDTYF.js";
9
9
  import {
10
10
  resolveSites
11
- } from "./chunk-Z2K4JPQ3.js";
11
+ } from "./chunk-H445EH33.js";
12
12
  import {
13
13
  healthEndpoint
14
- } from "./chunk-WSJ7RO54.js";
15
- import "./chunk-R53VL3RI.js";
16
- import "./chunk-ZQV7UQNE.js";
14
+ } from "./chunk-XED2DNAI.js";
15
+ import "./chunk-5CJVUPJU.js";
16
+ import "./chunk-4UTJ4G6P.js";
17
+ import "./chunk-SQ4FSNYL.js";
17
18
  import "./chunk-Z3JXLULD.js";
18
19
  import "./chunk-LBYOLBW7.js";
19
20
  import "./chunk-RARREDQE.js";
20
21
  import "./chunk-XXTZBPUY.js";
21
- import "./chunk-AVEQUR44.js";
22
+ import "./chunk-EASYCD6F.js";
22
23
 
23
24
  // src/cli/commands/health-endpoint.ts
24
25
  import { resolve } from "path";
@@ -51,4 +52,4 @@ async function runHealthEndpointCommand(site, opts) {
51
52
  export {
52
53
  runHealthEndpointCommand
53
54
  };
54
- //# sourceMappingURL=health-endpoint-KVCJYWET.js.map
55
+ //# sourceMappingURL=health-endpoint-UCLMSSCN.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli/commands/health-endpoint.ts"],"sourcesContent":["import { resolve } from \"node:path\";\nimport { healthEndpoint } from \"../../recipes/health-endpoint/index.js\";\nimport type { RecipeResult } from \"../../types.js\";\nimport { resolveSites } from \"../fleet/resolve-sites.js\";\nimport { prepareFleetSites, appendSkipNotice, type SkippedSite } from \"../fleet/prepare-sites.js\";\nimport { runRecipeOverSites } from \"../fleet/run-recipe-over-sites.js\";\nimport { fleetWorkdir } from \"../../util/fleet-workdir.js\";\n\nexport type HealthEndpointCommandOptions = {\n fleet?: string;\n workdir?: string;\n cwd?: string;\n};\n\nfunction formatResult(r: RecipeResult): string {\n if (r.status === \"noop\") return `[${r.site}] noop: ${r.notes ?? \"\"}`;\n if (r.status === \"failed\") return `[${r.site}] failed: ${r.notes ?? \"\"}`;\n return `[${r.site}] applied: ${r.commits.length} commit(s)\\n${r.notes ?? \"\"}`;\n}\n\nexport async function runHealthEndpointCommand(\n site: string | undefined,\n opts: HealthEndpointCommandOptions,\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 = await runRecipeOverSites(\"health-endpoint\", sites, (s) => healthEndpoint(s));\n\n const output = results.map(formatResult).join(\"\\n\");\n const code = results.some((r) => r.status === \"failed\") ? 1 : 0;\n return { output: appendSkipNotice(output, skipped), code };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAAA,SAAS,eAAe;AAcxB,SAAS,aAAa,GAAyB;AAC7C,MAAI,EAAE,WAAW,OAAQ,QAAO,IAAI,EAAE,IAAI,WAAW,EAAE,SAAS,EAAE;AAClE,MAAI,EAAE,WAAW,SAAU,QAAO,IAAI,EAAE,IAAI,aAAa,EAAE,SAAS,EAAE;AACtE,SAAO,IAAI,EAAE,IAAI,cAAc,EAAE,QAAQ,MAAM;AAAA,EAAe,EAAE,SAAS,EAAE;AAC7E;AAEA,eAAsB,yBACpB,MACA,MAC2C;AAC3C,QAAM,MAAM,KAAK,MAAM,QAAQ,KAAK,GAAG,IAAI,QAAQ,IAAI;AAEvD,MAAI,QAAQ,MAAM,aAAa;AAAA,IAC7B,GAAI,SAAS,SAAY,EAAE,KAAK,IAAI,CAAC;AAAA,IACrC,GAAI,KAAK,UAAU,SAAY,EAAE,OAAO,KAAK,MAAM,IAAI,CAAC;AAAA,IACxD,GAAI,KAAK,YAAY,SAAY,EAAE,SAAS,KAAK,QAAQ,IAAI,CAAC;AAAA,IAC9D;AAAA,EACF,CAAC;AAED,MAAI,UAAyB,CAAC;AAC9B,MAAI,KAAK,OAAO;AACd,UAAM,UAAU,KAAK,WAAW,aAAa;AAC7C,UAAM,OAAO,MAAM,kBAAkB,OAAO,EAAE,QAAQ,CAAC;AACvD,YAAQ,KAAK;AACb,cAAU,KAAK;AAAA,EACjB;AAEA,QAAM,UAAU,MAAM,mBAAmB,mBAAmB,OAAO,CAAC,MAAM,eAAe,CAAC,CAAC;AAE3F,QAAM,SAAS,QAAQ,IAAI,YAAY,EAAE,KAAK,IAAI;AAClD,QAAM,OAAO,QAAQ,KAAK,CAAC,MAAM,EAAE,WAAW,QAAQ,IAAI,IAAI;AAC9D,SAAO,EAAE,QAAQ,iBAAiB,QAAQ,OAAO,GAAG,KAAK;AAC3D;","names":[]}
1
+ {"version":3,"sources":["../src/cli/commands/health-endpoint.ts"],"sourcesContent":["import { resolve } from \"node:path\";\nimport { healthEndpoint } from \"../../recipes/health-endpoint/index.js\";\nimport type { RecipeResult } from \"../../types.js\";\nimport { resolveSites } from \"../fleet/resolve-sites.js\";\nimport { prepareFleetSites, appendSkipNotice, type SkippedSite } from \"../fleet/prepare-sites.js\";\nimport { runRecipeOverSites } from \"../fleet/run-recipe-over-sites.js\";\nimport { fleetWorkdir } from \"../../util/fleet-workdir.js\";\n\nexport type HealthEndpointCommandOptions = {\n fleet?: string;\n workdir?: string;\n cwd?: string;\n};\n\nfunction formatResult(r: RecipeResult): string {\n if (r.status === \"noop\") return `[${r.site}] noop: ${r.notes ?? \"\"}`;\n if (r.status === \"failed\") return `[${r.site}] failed: ${r.notes ?? \"\"}`;\n return `[${r.site}] applied: ${r.commits.length} commit(s)\\n${r.notes ?? \"\"}`;\n}\n\nexport async function runHealthEndpointCommand(\n site: string | undefined,\n opts: HealthEndpointCommandOptions,\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 = await runRecipeOverSites(\"health-endpoint\", sites, (s) => healthEndpoint(s));\n\n const output = results.map(formatResult).join(\"\\n\");\n const code = results.some((r) => r.status === \"failed\") ? 1 : 0;\n return { output: appendSkipNotice(output, skipped), code };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAAA,SAAS,eAAe;AAcxB,SAAS,aAAa,GAAyB;AAC7C,MAAI,EAAE,WAAW,OAAQ,QAAO,IAAI,EAAE,IAAI,WAAW,EAAE,SAAS,EAAE;AAClE,MAAI,EAAE,WAAW,SAAU,QAAO,IAAI,EAAE,IAAI,aAAa,EAAE,SAAS,EAAE;AACtE,SAAO,IAAI,EAAE,IAAI,cAAc,EAAE,QAAQ,MAAM;AAAA,EAAe,EAAE,SAAS,EAAE;AAC7E;AAEA,eAAsB,yBACpB,MACA,MAC2C;AAC3C,QAAM,MAAM,KAAK,MAAM,QAAQ,KAAK,GAAG,IAAI,QAAQ,IAAI;AAEvD,MAAI,QAAQ,MAAM,aAAa;AAAA,IAC7B,GAAI,SAAS,SAAY,EAAE,KAAK,IAAI,CAAC;AAAA,IACrC,GAAI,KAAK,UAAU,SAAY,EAAE,OAAO,KAAK,MAAM,IAAI,CAAC;AAAA,IACxD,GAAI,KAAK,YAAY,SAAY,EAAE,SAAS,KAAK,QAAQ,IAAI,CAAC;AAAA,IAC9D;AAAA,EACF,CAAC;AAED,MAAI,UAAyB,CAAC;AAC9B,MAAI,KAAK,OAAO;AACd,UAAM,UAAU,KAAK,WAAW,aAAa;AAC7C,UAAM,OAAO,MAAM,kBAAkB,OAAO,EAAE,QAAQ,CAAC;AACvD,YAAQ,KAAK;AACb,cAAU,KAAK;AAAA,EACjB;AAEA,QAAM,UAAU,MAAM,mBAAmB,mBAAmB,OAAO,CAAC,MAAM,eAAe,CAAC,CAAC;AAE3F,QAAM,SAAS,QAAQ,IAAI,YAAY,EAAE,KAAK,IAAI;AAClD,QAAM,OAAO,QAAQ,KAAK,CAAC,MAAM,EAAE,WAAW,QAAQ,IAAI,IAAI;AAC9D,SAAO,EAAE,QAAQ,iBAAiB,QAAQ,OAAO,GAAG,KAAK;AAC3D;","names":[]}
@@ -1,19 +1,19 @@
1
1
  import {
2
2
  mirrorHealthFields,
3
3
  mirrorScheduleFields
4
- } from "./chunk-WVNDEYXL.js";
5
- import "./chunk-6R56OKJZ.js";
4
+ } from "./chunk-GEUC5VGM.js";
5
+ import "./chunk-UIITN37J.js";
6
6
  import {
7
7
  TURSO_IS_AUTHORITATIVE
8
- } from "./chunk-SVAAONYB.js";
8
+ } from "./chunk-WQLNUEZL.js";
9
9
  import "./chunk-F3JWOPTG.js";
10
10
  import "./chunk-VAD43MOR.js";
11
- import "./chunk-3Z6X3BHU.js";
11
+ import "./chunk-KN52PM63.js";
12
12
  import {
13
13
  openDb,
14
14
  readDbConfig
15
- } from "./chunk-VSGMCCGQ.js";
16
- import "./chunk-C3IQQKXL.js";
15
+ } from "./chunk-6INOBNRO.js";
16
+ import "./chunk-T76MA2FH.js";
17
17
  import "./chunk-6VAL7XJT.js";
18
18
 
19
19
  // src/audits/health-mirror.ts
@@ -43,4 +43,4 @@ export {
43
43
  makeHealthMirrorBestEffort,
44
44
  makeScheduleMirrorBestEffort
45
45
  };
46
- //# sourceMappingURL=health-mirror-XJAKA3EY.js.map
46
+ //# sourceMappingURL=health-mirror-ONRT4DQ5.js.map
@@ -14,9 +14,9 @@ import {
14
14
  renderedHtmlUrl,
15
15
  scheduleColumnFor,
16
16
  siteValueFor
17
- } from "./chunk-6R56OKJZ.js";
17
+ } from "./chunk-UIITN37J.js";
18
18
  import "./chunk-VAD43MOR.js";
19
- import "./chunk-3Z6X3BHU.js";
19
+ import "./chunk-KN52PM63.js";
20
20
  export {
21
21
  EXCLUDED_WEBSITE_FIELDS,
22
22
  HEALTH_BOOLEAN,
@@ -34,4 +34,4 @@ export {
34
34
  scheduleColumnFor,
35
35
  siteValueFor
36
36
  };
37
- //# sourceMappingURL=import-airtable-TAKSN4NV.js.map
37
+ //# sourceMappingURL=import-airtable-IIK2QUUF.js.map
package/dist/index.d.ts CHANGED
@@ -315,14 +315,27 @@ type DependabotAlert = {
315
315
  scope: "runtime" | "development" | null;
316
316
  /** Dependency graph relationship (`dependency.relationship`), or null when GitHub reports
317
317
  * "unknown"/nothing. "transitive" means no direct-dep bump can fix it — Renovate's vuln
318
- * alerts have no fix vehicle until the weekly lockfile-maintenance window. */
319
- relationship: "direct" | "transitive" | null;
318
+ * alerts have no fix vehicle until the weekly lockfile-maintenance window. "inconclusive"
319
+ * is what GitHub stamps on an alert filed against a manifest its dependency graph still
320
+ * tracks but the tree no longer holds (#702) — kept, never folded to null, because it is
321
+ * the secondary tell for a ghost alert. */
322
+ relationship: "direct" | "transitive" | "inconclusive" | null;
323
+ /** The manifest the alert was filed against (`dependency.manifest_path`, e.g.
324
+ * `package-lock.json`), or null when absent. GitHub retains a manifest after the file is
325
+ * deleted from the default branch and keeps filing alerts against that frozen snapshot;
326
+ * the audit resolves this path with {@link GitHubRest.manifestExists} to tell a ghost from
327
+ * a live vulnerability (#702). */
328
+ manifestPath: string | null;
320
329
  };
321
330
 
322
331
  /** The Dependabot fetch the security audit needs, injectable for tests. The real default is
323
332
  * built from GITHUB_TOKEN; absent token (or a site with no gitRepo) → pnpm/npm audit fallback. */
324
333
  type DependabotDeps = {
325
334
  listAlerts: (repo: string) => Promise<DependabotAlert[]>;
335
+ /** Whether an alert's `manifestPath` is still on the default branch. Optional: without it
336
+ * every alert counts, which is the loud direction. A lookup that THROWS also counts the
337
+ * alert — an API hiccup must never quietly suppress a real vulnerability (#702). */
338
+ manifestExists?: (repo: string, path: string) => Promise<boolean>;
326
339
  };
327
340
  declare function securityAudit(ctx: AuditContext): Promise<AuditResult>;
328
341
 
@@ -418,6 +431,84 @@ declare function onboard(site: Site, opts?: OnboardOptions): Promise<RecipeResul
418
431
  */
419
432
  declare function a11yFixturesPage(site: Site): Promise<RecipeResult>;
420
433
 
434
+ type HealthEndpointDeps = {
435
+ spawn: SpawnFn;
436
+ /** Resolve the TARGET repo's own prettier. Injected so a test can assert the
437
+ * absolute-path spawn without a populated `node_modules`. */
438
+ resolvePrettier?: (repoRoot: string) => Promise<string | null>;
439
+ };
440
+ /**
441
+ * Writes a resilient `src/routes/health/+server.ts` if the route doesn't already
442
+ * exist. The function-health audit fetches this endpoint; existing sites need it
443
+ * or the Report Health Gate blocks their Maintenance reports on "unknown". Operator
444
+ * edits to an existing endpoint are never clobbered (noop on existing file).
445
+ *
446
+ * Two heterogeneity fixes the fleet rollout exposed: (1) it detects whether the
447
+ * site has a `$lib/prismicio` module and writes the Prismic-free variant when it
448
+ * doesn't (a static import of a missing module fails the build); (2) it runs the
449
+ * SITE's own prettier on the written file before committing, so the file matches
450
+ * that site's formatting config (tabs/spaces, quote style vary fleet-wide) and
451
+ * doesn't red the CI format check. Prettier is best-effort — a site without it
452
+ * installed commits unformatted with a flag note rather than failing the recipe.
453
+ */
454
+ declare function healthEndpoint(site: Site, deps?: HealthEndpointDeps): Promise<RecipeResult>;
455
+
456
+ type SmokeSuiteDeps = {
457
+ spawn: SpawnFn;
458
+ /** Resolve the TARGET repo's own prettier. Injected so a test can assert the
459
+ * absolute-path spawn without a populated `node_modules`. */
460
+ resolvePrettier?: (repoRoot: string) => Promise<string | null>;
461
+ };
462
+ /**
463
+ * Adds the smoke suite to a site: the `tests/smoke/*` specs, a `test:smoke` /
464
+ * `test:unit` script split, `@playwright/test`, and a `playwright.config.ts`
465
+ * that honors `REDDOOR_SMOKE_PORT` (R1.1). Conservative + partial-apply — every
466
+ * file is noop-if-exists, every `package.json` script/dep is add-if-absent, and
467
+ * an existing config that isn't a recognizable shared-base shape is left
468
+ * untouched and flagged for a manual R1.1 patch (never a destructive write).
469
+ * A site with no `package.json` noops (not a node project). Branch+commit per site.
470
+ */
471
+ declare function smokeSuite(site: Site, deps?: SmokeSuiteDeps): Promise<RecipeResult>;
472
+
473
+ type MatchHarnessOptions = {
474
+ /** The live reference URL the harness gates against. Required — a harness
475
+ * with no reference cannot produce evidence, only an absence of errors. */
476
+ ref: string;
477
+ /** Candidate origin. Defaults to the SvelteKit dev server. */
478
+ cand?: string;
479
+ /** Breakpoint matrix. Defaults to the fleet's 1440 / 834 / 390. */
480
+ matrix?: number[];
481
+ };
482
+ type MatchHarnessDeps = {
483
+ spawn: SpawnFn;
484
+ /** Previously shipped renders per relative path; injectable so the
485
+ * safe-replace path is testable before a second version exists. */
486
+ previous?: Readonly<Record<string, readonly string[]>>;
487
+ /** Previously shipped BLOCK bodies per target file; injectable for the same
488
+ * reason, and empty in the shipped table until a body is superseded. */
489
+ blockPrevious?: Readonly<Record<string, readonly string[]>>;
490
+ /** Resolve the TARGET repo's own prettier. Injected so a test can assert the
491
+ * absolute-path spawn without a populated `node_modules`. */
492
+ resolvePrettier?: (repoRoot: string) => Promise<string | null>;
493
+ };
494
+ /**
495
+ * Installs the matching harness into a site: the dev-guarded `/dev/match/[uid]`
496
+ * route, a `site-pages.js` scaffold and its fixture-vs-model test,
497
+ * `matching/harness.json` + the read layer, the round scripts, the site records,
498
+ * and the `.gitignore` / `.prettierignore` / `CLAUDE.md` blocks.
499
+ *
500
+ * Install-if-absent throughout. Files a site edits are never rewritten. A
501
+ * recipe-owned script that matches a previously shipped render is safe-replaced;
502
+ * one that has been hand-edited is FLAGGED in the notes and left alone.
503
+ *
504
+ * ONE EXCEPTION TO PER-FILE INDEPENDENCE: the scripts in MATCH_HARNESS_COUPLED
505
+ * upgrade as a SET. If any one of them is hand-edited, none of them is written,
506
+ * because gate.sh calls `harness.mjs --check-run` and next.mjs imports from
507
+ * harness.mjs — upgrading the others around a pinned one leaves a harness that
508
+ * cannot run at all. See the measurement on MATCH_HARNESS_COUPLED.
509
+ */
510
+ declare function matchHarness(site: Site, opts: MatchHarnessOptions, deps?: MatchHarnessDeps): Promise<RecipeResult>;
511
+
421
512
  type InitStepResult = {
422
513
  kind: "recipe";
423
514
  result: RecipeResult;
@@ -1166,6 +1257,13 @@ type SiteMirror = {
1166
1257
  health: (siteId: string, fields: Record<string, unknown>) => Promise<void>;
1167
1258
  /** Columns that live in `sites`. */
1168
1259
  site: (siteId: string, fields: Record<string, unknown>) => Promise<void>;
1260
+ /** #645. Does Turso hold a row for this site id? A pure READ, so it is the one
1261
+ * op here that neither logs a SITE_MIRROR line nor throws under the freeze —
1262
+ * `ensure-site` uses it to decide whether to heal, and a probe that threw
1263
+ * would sink the very command that repairs the gap. Creds-absent answers
1264
+ * `true` ("assume present"), so a mirror that cannot read can never provoke
1265
+ * a blind insert. */
1266
+ hasRow: (siteId: string) => Promise<boolean>;
1169
1267
  };
1170
1268
 
1171
1269
  type ShootOptions = {
@@ -1174,6 +1272,9 @@ type ShootOptions = {
1174
1272
  height: number;
1175
1273
  deviceScaleFactor: number;
1176
1274
  settleMs: number;
1275
+ /** Extra CSS selector(s) hidden before the shutter, for a site whose consent
1276
+ * or interstitial UI the class/id heuristic misses. */
1277
+ consentSelector?: string;
1177
1278
  };
1178
1279
  /** Injected browser IO. The real impl drives Playwright; tests pass a fake. */
1179
1280
  type Shooter = {
@@ -1187,8 +1288,11 @@ type GenerateInput = {
1187
1288
  slug?: string;
1188
1289
  /** Injected browser IO (tests). */
1189
1290
  shooter?: Shooter;
1190
- /** Per-site settle override for animation-heavy or consent-gated homepages. */
1291
+ /** Per-site settle override for animation-heavy homepages. */
1191
1292
  settleMs?: number;
1293
+ /** Extra CSS selector(s) hidden before the shutter, for consent or
1294
+ * interstitial UI the capture's class/id heuristic misses (#654). */
1295
+ consentSelector?: string;
1192
1296
  };
1193
1297
  type GeneratedHeaderImage = {
1194
1298
  bytes: Uint8Array;
@@ -1452,6 +1556,15 @@ type SubmissionRow = {
1452
1556
  * was attempted: a non-newsletter form, a spam row, a site with no destination
1453
1557
  * configured, or a row written before 0005. See ingest.ts for the token grammar. */
1454
1558
  fanoutStatus?: string | null;
1559
+ /** Resend's bounce classification, kept so a content rejection by the CLIENT's
1560
+ * mail filter can be told apart from a dead mailbox (#783). Null for a
1561
+ * complaint, and for every row written before migration 0018. */
1562
+ bounceType?: string | null;
1563
+ bounceSubType?: string | null;
1564
+ bounceMessage?: string | null;
1565
+ /** ISO-8601 of the operator saying "this address is not dead" (#783). The row
1566
+ * keeps its bounce record and stops counting toward the alarm. */
1567
+ bounceAckAt?: string | null;
1455
1568
  };
1456
1569
 
1457
1570
  type ScreenOutTotals = {
@@ -1474,6 +1587,13 @@ type AttentionItem = {
1474
1587
  /** Stable identity for diffing: `vuln:<siteId>`, `delivery:<reportId>`. */
1475
1588
  key: string;
1476
1589
  kind: "vuln" | "delivery" | "renovate" | "lighthouse" | "ci" | "analytics" | "preflight" | "turnstile" | "notify-bounce"
1590
+ /** #645. Leads captured by the dead-letter because their site could not be
1591
+ * placed — a store outage during the lookup, or (since #645) a slug with no
1592
+ * Turso row at all. Until this kind existed a dropped lead had NO alarm
1593
+ * anywhere: the queue could fill and nothing said so. Keyed by SLUG, not by
1594
+ * site id, because the whole point of the worst case is that the slug
1595
+ * resolves to no site. */
1596
+ | "deadletter"
1477
1597
  /** The nightly Prismic model sweep. THREE item flavors share this kind —
1478
1598
  * `prismic-drift:` (repo and Prismic diverge), `prismic-unknown:` (the check
1479
1599
  * ran and could not answer), `prismic-stale:` (nobody has re-established the
@@ -1612,6 +1732,17 @@ type CockpitModel = {
1612
1732
  * invisible to every fleet op, so the Needs-you feed surfaces them as amber watch
1613
1733
  * rows (optional for back-compat). */
1614
1734
  unrecognizedStatus?: OffFleetSiteEntry[];
1735
+ /** #786. Attention items that belong to NO site card. The grid is built from
1736
+ * the visible sites and items are grouped onto it by `siteName`, so an item
1737
+ * naming a site the fleet does not have matched nothing and was dropped —
1738
+ * silently, on the one surface the operator actually watches.
1739
+ *
1740
+ * The collector that produces them is the one whose entire point is that the
1741
+ * site is missing: a dead letter for a slug resolving to no fleet row means
1742
+ * leads are being dropped RIGHT NOW. Kept general rather than
1743
+ * dead-letter-specific, so a future card-less item lands here instead of
1744
+ * vanishing the same way. Optional for back-compat with hand-built models. */
1745
+ cardless?: AttentionItem[];
1615
1746
  };
1616
1747
  /** The cockpit's alarm verdict for ONE site, for the /s/<slug> page header. */
1617
1748
  type SiteAlarmContext = {
@@ -1702,4 +1833,4 @@ declare function loadPlate(): Promise<Uint8Array>;
1702
1833
  /** Read a headline overlay (transparent PNG, ink-box cropped). */
1703
1834
  declare function loadHeadline(kind: HeadlineKind): Promise<Uint8Array>;
1704
1835
 
1705
- export { ALL_AUDIT_NAMES, ALL_RECIPE_NAMES, type AirtableInventoryOptions, AuditName, AuditResult, BLURRED_CID, type BumpDepsOptions, type BundledImage, CHECK_CID, type ConvertToPnpmOptions, DEFAULT_INIT_STEPS, type DraftOptions, type DraftResult, type DueItem, type GenerateInput, type GeneratedHeaderImage, type HeaderImage, type InitOptions, type InitResult, type InitStep, type InitStepResult, InventoryProvider, type LighthouseScores, type LocalPathOptions, type OnboardAudit, type OnboardOptions, type OrchestrateOptions, RecipeName, RecipeResult, type RefreshHeaderDeps, type RenderResult, type ReportData, type ReportType, Site, type UpgradeSvelte4to5Options, a11yAudit, a11yFixturesPage, bumpDeps, convertToPnpm, depsAudit, domainFromUrl, draftReportForSite, findDueReports, fromAirtableBase, fromJsonFile, generateHeaderImage, init, isRecipeName, lighthouseAudit, lintAudit, loadBundledImages, loadHeadline, loadPlate, localPath, onboard, renderCockpitHtml, renderReportHtml, renderSiteDashboardHtml, runAudits, runAuditsAcross, securityAudit, selfCaretRange, selfPackageVersion, sendApprovedReports, svelteCodemods, upgradeSvelte4to5, verifyBasicAuth };
1836
+ export { ALL_AUDIT_NAMES, ALL_RECIPE_NAMES, type AirtableInventoryOptions, AuditName, AuditResult, BLURRED_CID, type BumpDepsOptions, type BundledImage, CHECK_CID, type ConvertToPnpmOptions, DEFAULT_INIT_STEPS, type DraftOptions, type DraftResult, type DueItem, type GenerateInput, type GeneratedHeaderImage, type HeaderImage, type InitOptions, type InitResult, type InitStep, type InitStepResult, InventoryProvider, type LighthouseScores, type LocalPathOptions, type OnboardAudit, type OnboardOptions, type OrchestrateOptions, RecipeName, RecipeResult, type RefreshHeaderDeps, type RenderResult, type ReportData, type ReportType, Site, type UpgradeSvelte4to5Options, a11yAudit, a11yFixturesPage, bumpDeps, convertToPnpm, depsAudit, domainFromUrl, draftReportForSite, findDueReports, fromAirtableBase, fromJsonFile, generateHeaderImage, healthEndpoint, init, isRecipeName, lighthouseAudit, lintAudit, loadBundledImages, loadHeadline, loadPlate, localPath, matchHarness, onboard, renderCockpitHtml, renderReportHtml, renderSiteDashboardHtml, runAudits, runAuditsAcross, securityAudit, selfCaretRange, selfPackageVersion, sendApprovedReports, smokeSuite, svelteCodemods, upgradeSvelte4to5, verifyBasicAuth };