@reddoorla/maintenance 0.85.1 → 0.86.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 (252) hide show
  1. package/README.md +8 -0
  2. package/dist/airtable-G7WBQQMI.js +9 -0
  3. package/dist/{announce-GIAYN67S.js → announce-MXTUQ6C7.js} +26 -19
  4. package/dist/announce-MXTUQ6C7.js.map +1 -0
  5. package/dist/{bump-deps-SWJB6H5V.js → bump-deps-EC74CPLS.js} +9 -9
  6. package/dist/chunk-2EVEFOZY.js +129 -0
  7. package/dist/chunk-2EVEFOZY.js.map +1 -0
  8. package/dist/{chunk-COZPL62X.js → chunk-2NDRHXMR.js} +25 -17
  9. package/dist/chunk-2NDRHXMR.js.map +1 -0
  10. package/dist/{chunk-SDUJIANJ.js → chunk-2NJQLSEU.js} +3 -3
  11. package/dist/chunk-2NQUCS7O.js +243 -0
  12. package/dist/chunk-2NQUCS7O.js.map +1 -0
  13. package/dist/{chunk-QRDB4NLB.js → chunk-2ZPT7GLV.js} +43 -404
  14. package/dist/chunk-2ZPT7GLV.js.map +1 -0
  15. package/dist/{chunk-ZTPPCHDB.js → chunk-3G25KIWW.js} +4 -4
  16. package/dist/chunk-3SF7D4DY.js +359 -0
  17. package/dist/chunk-3SF7D4DY.js.map +1 -0
  18. package/dist/{chunk-Q276MZ7E.js → chunk-3VQWSE3F.js} +4 -4
  19. package/dist/{chunk-37S6L6G4.js → chunk-5UINJNAJ.js} +72 -2
  20. package/dist/chunk-5UINJNAJ.js.map +1 -0
  21. package/dist/{chunk-THEFTZ7F.js → chunk-62CMMGEO.js} +5 -5
  22. package/dist/{chunk-FDIFTIXC.js → chunk-6TWWY7ZU.js} +2 -2
  23. package/dist/{chunk-UYCAF77E.js → chunk-7RJ2HMMJ.js} +3 -3
  24. package/dist/chunk-ACBRLLFT.js +198 -0
  25. package/dist/chunk-ACBRLLFT.js.map +1 -0
  26. package/dist/chunk-BNM5POSJ.js +284 -0
  27. package/dist/chunk-BNM5POSJ.js.map +1 -0
  28. package/dist/{chunk-R6FPFMOS.js → chunk-BQRFQSGY.js} +3 -3
  29. package/dist/{chunk-MGR2H7F4.js → chunk-BYK66EWO.js} +19 -12
  30. package/dist/chunk-BYK66EWO.js.map +1 -0
  31. package/dist/{chunk-N4MOEF32.js → chunk-C6B4RHXR.js} +36 -8
  32. package/dist/chunk-C6B4RHXR.js.map +1 -0
  33. package/dist/{chunk-6QRLRT3P.js → chunk-CQR4LIM7.js} +12 -265
  34. package/dist/chunk-CQR4LIM7.js.map +1 -0
  35. package/dist/{chunk-SEEA6RXF.js → chunk-DJZWYIPP.js} +2 -2
  36. package/dist/chunk-DJZWYIPP.js.map +1 -0
  37. package/dist/chunk-EVBCK2KC.js +68 -0
  38. package/dist/chunk-EVBCK2KC.js.map +1 -0
  39. package/dist/{chunk-TP5M2NQB.js → chunk-F5KM4LEQ.js} +3 -3
  40. package/dist/{chunk-62VF32IC.js → chunk-ILUNZHYV.js} +2 -2
  41. package/dist/chunk-ITIOFN7A.js +396 -0
  42. package/dist/chunk-ITIOFN7A.js.map +1 -0
  43. package/dist/{chunk-LS6QPANO.js → chunk-IYSEC543.js} +2 -2
  44. package/dist/{chunk-DC5H7KEQ.js → chunk-JHGHLKFS.js} +2 -2
  45. package/dist/{chunk-PBWDDDQH.js → chunk-KTH5ZODA.js} +2 -2
  46. package/dist/{chunk-4DHQCN5H.js → chunk-LBYOLBW7.js} +17 -2
  47. package/dist/chunk-LBYOLBW7.js.map +1 -0
  48. package/dist/{chunk-577HCGZO.js → chunk-LDWZSLSU.js} +38 -23
  49. package/dist/chunk-LDWZSLSU.js.map +1 -0
  50. package/dist/{chunk-LTB6KVJW.js → chunk-N45M3FDK.js} +13 -11
  51. package/dist/{chunk-LTB6KVJW.js.map → chunk-N45M3FDK.js.map} +1 -1
  52. package/dist/chunk-NYUYNYQL.js +48 -0
  53. package/dist/chunk-NYUYNYQL.js.map +1 -0
  54. package/dist/{chunk-7J53SUT6.js → chunk-P2FE5AI6.js} +4 -4
  55. package/dist/{chunk-3YXDSCM6.js → chunk-PPE5KZJK.js} +29 -11
  56. package/dist/chunk-PPE5KZJK.js.map +1 -0
  57. package/dist/chunk-PTDMVGKL.js +31 -0
  58. package/dist/chunk-PTDMVGKL.js.map +1 -0
  59. package/dist/{chunk-D4FVAIEJ.js → chunk-PZR4EBPY.js} +5 -2
  60. package/dist/chunk-PZR4EBPY.js.map +1 -0
  61. package/dist/{chunk-NWB4O5EY.js → chunk-SLUQ7R6I.js} +3 -3
  62. package/dist/chunk-SLUQ7R6I.js.map +1 -0
  63. package/dist/{chunk-GZNBCHAZ.js → chunk-TERE5SDF.js} +4 -4
  64. package/dist/{chunk-ZMIPG6TR.js → chunk-TVL5MVUF.js} +4 -4
  65. package/dist/chunk-UDRHAQT7.js +172 -0
  66. package/dist/chunk-UDRHAQT7.js.map +1 -0
  67. package/dist/chunk-VAD43MOR.js +72 -0
  68. package/dist/chunk-VAD43MOR.js.map +1 -0
  69. package/dist/chunk-VSBFM7DS.js +229 -0
  70. package/dist/chunk-VSBFM7DS.js.map +1 -0
  71. package/dist/chunk-W7Z3BGCI.js +274 -0
  72. package/dist/chunk-W7Z3BGCI.js.map +1 -0
  73. package/dist/chunk-X3B723J4.js +1209 -0
  74. package/dist/chunk-X3B723J4.js.map +1 -0
  75. package/dist/{chunk-VRWUL4TR.js → chunk-XHHMM5HX.js} +2 -2
  76. package/dist/{chunk-RJB3QUSP.js → chunk-XIDUYLSR.js} +3 -3
  77. package/dist/{chunk-QG6OSL4M.js → chunk-XUGSZP7Z.js} +2 -2
  78. package/dist/{chunk-R4AB6GCT.js → chunk-Y53WOQIJ.js} +7 -4
  79. package/dist/{chunk-R4AB6GCT.js.map → chunk-Y53WOQIJ.js.map} +1 -1
  80. package/dist/{chunk-ICXV25N7.js → chunk-Z3KYFUN6.js} +3 -3
  81. package/dist/{chunk-MPBXOJ3N.js → chunk-Z7AXYKQB.js} +33 -2
  82. package/dist/chunk-Z7AXYKQB.js.map +1 -0
  83. package/dist/{chunk-6V7565O2.js → chunk-ZKXSX4LO.js} +11 -11
  84. package/dist/cli/bin.js +46 -28
  85. package/dist/cli/bin.js.map +1 -1
  86. package/dist/cli/commands/audit.d.ts +30 -1
  87. package/dist/cli/commands/audit.js +63 -31
  88. package/dist/cli/commands/audit.js.map +1 -1
  89. package/dist/client-AUE3XUPO.js +11 -0
  90. package/dist/configs/playwright-a11y.js +1 -1
  91. package/dist/configs/svelte.d.ts +30 -1
  92. package/dist/configs/svelte.js +9 -1
  93. package/dist/configs/svelte.js.map +1 -1
  94. package/dist/{convert-to-pnpm-AT52NWZB.js → convert-to-pnpm-6L6P74WR.js} +9 -9
  95. package/dist/db-B35OGV3G.js +217 -0
  96. package/dist/db-B35OGV3G.js.map +1 -0
  97. package/dist/{digest-UVHYZUYE.js → digest-BL6UJYKH.js} +23 -20
  98. package/dist/{digest-UVHYZUYE.js.map → digest-BL6UJYKH.js.map} +1 -1
  99. package/dist/dump-P6EBSIOH.js +68 -0
  100. package/dist/dump-P6EBSIOH.js.map +1 -0
  101. package/dist/email-VTTTKKL5.js +195 -0
  102. package/dist/email-VTTTKKL5.js.map +1 -0
  103. package/dist/{ensure-site-S25MDDHW.js → ensure-site-DFTB7MN3.js} +8 -7
  104. package/dist/ensure-site-DFTB7MN3.js.map +1 -0
  105. package/dist/fleet-events-cF2Om88w.d.ts +24 -0
  106. package/dist/{forms-notify-target-TWN4EH6K.js → forms-notify-target-75U6OU7L.js} +38 -132
  107. package/dist/forms-notify-target-75U6OU7L.js.map +1 -0
  108. package/dist/{github-signals-G4ILZAJ6.js → github-signals-IJUPGCUX.js} +40 -19
  109. package/dist/github-signals-IJUPGCUX.js.map +1 -0
  110. package/dist/{header-image-T7XD37JL.js → header-image-AWLLQA4L.js} +34 -11
  111. package/dist/header-image-AWLLQA4L.js.map +1 -0
  112. package/dist/header-images-335L2AKB.js +68 -0
  113. package/dist/header-images-335L2AKB.js.map +1 -0
  114. package/dist/{health-endpoint-242WG2OJ.js → health-endpoint-WJC2UMYS.js} +9 -9
  115. package/dist/health-mirror-4B2L7T2Y.js +75 -0
  116. package/dist/health-mirror-4B2L7T2Y.js.map +1 -0
  117. package/dist/import-airtable-HE43FB4H.js +35 -0
  118. package/dist/index.d.ts +175 -21
  119. package/dist/index.js +116 -74
  120. package/dist/index.js.map +1 -1
  121. package/dist/{init-TFVAN5OY.js → init-NJEOEO7I.js} +21 -18
  122. package/dist/{init-TFVAN5OY.js.map → init-NJEOEO7I.js.map} +1 -1
  123. package/dist/{launch-DWY2MF54.js → launch-XNAX427U.js} +32 -26
  124. package/dist/{launch-DWY2MF54.js.map → launch-XNAX427U.js.map} +1 -1
  125. package/dist/lighthouse-VHI77PFB.js +11 -0
  126. package/dist/{lighthouse-airtable-BIPM26SZ.js → lighthouse-airtable-LBVIYYP5.js} +3 -3
  127. package/dist/mailchimp-XYCTEEJY.js +72 -0
  128. package/dist/mailchimp-XYCTEEJY.js.map +1 -0
  129. package/dist/migrate-GQH237A6.js +7 -0
  130. package/dist/notify-C645PGD5.js +22 -0
  131. package/dist/{onboard-53CITIM7.js → onboard-GK4PHPNI.js} +9 -9
  132. package/dist/orchestrate-77UO4BYJ.js +30 -0
  133. package/dist/orchestrate-77UO4BYJ.js.map +1 -0
  134. package/dist/parity-MWS24A3H.js +12 -0
  135. package/dist/parity-MWS24A3H.js.map +1 -0
  136. package/dist/pipeline-S6CVHDGB.js +12 -0
  137. package/dist/pipeline-S6CVHDGB.js.map +1 -0
  138. package/dist/{preflight-3XPDUHFJ.js → preflight-6WBNU2GZ.js} +16 -13
  139. package/dist/{preflight-3XPDUHFJ.js.map → preflight-6WBNU2GZ.js.map} +1 -1
  140. package/dist/{prismic-ci-UTQ6LRR3.js → prismic-ci-3RHOZUUT.js} +15 -15
  141. package/dist/{prismic-models-PVES6R5V.js → prismic-models-QBGUT2Q3.js} +10 -10
  142. package/dist/prospect-audit-IUNCJ2LV.js +174 -0
  143. package/dist/prospect-audit-IUNCJ2LV.js.map +1 -0
  144. package/dist/prospect-audits-3PMIO73D.js +19 -0
  145. package/dist/prospect-audits-3PMIO73D.js.map +1 -0
  146. package/dist/{protection-audit-64PLLBLI.js → protection-audit-SJO53MEQ.js} +3 -3
  147. package/dist/recipes/sync-configs.js +3 -3
  148. package/dist/render-AQAVQDPZ.js +10 -0
  149. package/dist/render-AQAVQDPZ.js.map +1 -0
  150. package/dist/{renovate-dispatch-ICJGSFCE.js → renovate-dispatch-QJY75ODR.js} +8 -8
  151. package/dist/replay-C2LXMJZP.js +66 -0
  152. package/dist/replay-C2LXMJZP.js.map +1 -0
  153. package/dist/{report-6CKSWJNG.js → report-4EVNDHOZ.js} +55 -29
  154. package/dist/report-4EVNDHOZ.js.map +1 -0
  155. package/dist/reports/header-image/assets/headline-announcement.png +0 -0
  156. package/dist/reports/header-image/assets/headline-launch.png +0 -0
  157. package/dist/reports/header-image/assets/headline-maintenance.png +0 -0
  158. package/dist/reports/header-image/assets/headline-testing.png +0 -0
  159. package/dist/reports/header-image/assets/plate-clean.png +0 -0
  160. package/dist/{self-updating-PPQVV6UA.js → self-updating-6DWI2Z56.js} +9 -9
  161. package/dist/{selftest-CQ6NOX52.js → selftest-RC36MTKP.js} +25 -20
  162. package/dist/selftest-RC36MTKP.js.map +1 -0
  163. package/dist/smoke-B2GQOSIZ.js +20 -0
  164. package/dist/smoke-B2GQOSIZ.js.map +1 -0
  165. package/dist/{smoke-suite-OBWNPALQ.js → smoke-suite-VYY2LXM2.js} +9 -9
  166. package/dist/{submissions-GJ6ITBRH.js → submissions-Q7DRFOCD.js} +3 -3
  167. package/dist/{svelte-codemods-ZOBDHIES.js → svelte-codemods-25J2FO22.js} +9 -9
  168. package/dist/sync-34HNZZ56.js +44 -0
  169. package/dist/sync-34HNZZ56.js.map +1 -0
  170. package/dist/{sync-configs-CJXUX6MD.js → sync-configs-3SE6PSCO.js} +9 -9
  171. package/dist/{upgrade-WLX27UPC.js → upgrade-WBRQ62FX.js} +9 -9
  172. package/dist/{webflow-624FEBFD.js → webflow-IRKOIT7S.js} +4 -4
  173. package/dist/webhook-VOGOW3W6.js +38 -0
  174. package/dist/webhook-VOGOW3W6.js.map +1 -0
  175. package/dist/{websites-SADZR4XQ.js → websites-SXWTP72S.js} +6 -2
  176. package/dist/websites-SXWTP72S.js.map +1 -0
  177. package/dist/{write-audits-to-airtable-7PH75YWY.js → write-audits-to-airtable-MBEILLPU.js} +4 -4
  178. package/dist/write-audits-to-airtable-MBEILLPU.js.map +1 -0
  179. package/package.json +5 -2
  180. package/dist/airtable-HRKSA7V4.js +0 -9
  181. package/dist/announce-GIAYN67S.js.map +0 -1
  182. package/dist/chunk-37S6L6G4.js.map +0 -1
  183. package/dist/chunk-3YXDSCM6.js.map +0 -1
  184. package/dist/chunk-4DHQCN5H.js.map +0 -1
  185. package/dist/chunk-4SOCPK7A.js +0 -108
  186. package/dist/chunk-4SOCPK7A.js.map +0 -1
  187. package/dist/chunk-577HCGZO.js.map +0 -1
  188. package/dist/chunk-6QRLRT3P.js.map +0 -1
  189. package/dist/chunk-COZPL62X.js.map +0 -1
  190. package/dist/chunk-D4FVAIEJ.js.map +0 -1
  191. package/dist/chunk-MGR2H7F4.js.map +0 -1
  192. package/dist/chunk-MPBXOJ3N.js.map +0 -1
  193. package/dist/chunk-N4MOEF32.js.map +0 -1
  194. package/dist/chunk-NWB4O5EY.js.map +0 -1
  195. package/dist/chunk-QRDB4NLB.js.map +0 -1
  196. package/dist/chunk-SEEA6RXF.js.map +0 -1
  197. package/dist/chunk-U5SZ4FOP.js +0 -26
  198. package/dist/chunk-U5SZ4FOP.js.map +0 -1
  199. package/dist/client-X5WUJWDE.js +0 -11
  200. package/dist/db-JSIZYT23.js +0 -23
  201. package/dist/db-JSIZYT23.js.map +0 -1
  202. package/dist/ensure-site-S25MDDHW.js.map +0 -1
  203. package/dist/forms-notify-target-TWN4EH6K.js.map +0 -1
  204. package/dist/github-signals-G4ILZAJ6.js.map +0 -1
  205. package/dist/header-image-T7XD37JL.js.map +0 -1
  206. package/dist/migrate-LJUFGXQZ.js +0 -7
  207. package/dist/orchestrate-KDNXZQX7.js +0 -27
  208. package/dist/report-6CKSWJNG.js.map +0 -1
  209. package/dist/reports/header-image/assets/plate.png +0 -0
  210. package/dist/selftest-CQ6NOX52.js.map +0 -1
  211. /package/dist/{airtable-HRKSA7V4.js.map → airtable-G7WBQQMI.js.map} +0 -0
  212. /package/dist/{bump-deps-SWJB6H5V.js.map → bump-deps-EC74CPLS.js.map} +0 -0
  213. /package/dist/{chunk-SDUJIANJ.js.map → chunk-2NJQLSEU.js.map} +0 -0
  214. /package/dist/{chunk-ZTPPCHDB.js.map → chunk-3G25KIWW.js.map} +0 -0
  215. /package/dist/{chunk-Q276MZ7E.js.map → chunk-3VQWSE3F.js.map} +0 -0
  216. /package/dist/{chunk-THEFTZ7F.js.map → chunk-62CMMGEO.js.map} +0 -0
  217. /package/dist/{chunk-FDIFTIXC.js.map → chunk-6TWWY7ZU.js.map} +0 -0
  218. /package/dist/{chunk-UYCAF77E.js.map → chunk-7RJ2HMMJ.js.map} +0 -0
  219. /package/dist/{chunk-R6FPFMOS.js.map → chunk-BQRFQSGY.js.map} +0 -0
  220. /package/dist/{chunk-TP5M2NQB.js.map → chunk-F5KM4LEQ.js.map} +0 -0
  221. /package/dist/{chunk-62VF32IC.js.map → chunk-ILUNZHYV.js.map} +0 -0
  222. /package/dist/{chunk-LS6QPANO.js.map → chunk-IYSEC543.js.map} +0 -0
  223. /package/dist/{chunk-DC5H7KEQ.js.map → chunk-JHGHLKFS.js.map} +0 -0
  224. /package/dist/{chunk-PBWDDDQH.js.map → chunk-KTH5ZODA.js.map} +0 -0
  225. /package/dist/{chunk-7J53SUT6.js.map → chunk-P2FE5AI6.js.map} +0 -0
  226. /package/dist/{chunk-GZNBCHAZ.js.map → chunk-TERE5SDF.js.map} +0 -0
  227. /package/dist/{chunk-ZMIPG6TR.js.map → chunk-TVL5MVUF.js.map} +0 -0
  228. /package/dist/{chunk-VRWUL4TR.js.map → chunk-XHHMM5HX.js.map} +0 -0
  229. /package/dist/{chunk-RJB3QUSP.js.map → chunk-XIDUYLSR.js.map} +0 -0
  230. /package/dist/{chunk-QG6OSL4M.js.map → chunk-XUGSZP7Z.js.map} +0 -0
  231. /package/dist/{chunk-ICXV25N7.js.map → chunk-Z3KYFUN6.js.map} +0 -0
  232. /package/dist/{chunk-6V7565O2.js.map → chunk-ZKXSX4LO.js.map} +0 -0
  233. /package/dist/{client-X5WUJWDE.js.map → client-AUE3XUPO.js.map} +0 -0
  234. /package/dist/{convert-to-pnpm-AT52NWZB.js.map → convert-to-pnpm-6L6P74WR.js.map} +0 -0
  235. /package/dist/{health-endpoint-242WG2OJ.js.map → health-endpoint-WJC2UMYS.js.map} +0 -0
  236. /package/dist/{lighthouse-airtable-BIPM26SZ.js.map → import-airtable-HE43FB4H.js.map} +0 -0
  237. /package/dist/{migrate-LJUFGXQZ.js.map → lighthouse-VHI77PFB.js.map} +0 -0
  238. /package/dist/{orchestrate-KDNXZQX7.js.map → lighthouse-airtable-LBVIYYP5.js.map} +0 -0
  239. /package/dist/{websites-SADZR4XQ.js.map → migrate-GQH237A6.js.map} +0 -0
  240. /package/dist/{write-audits-to-airtable-7PH75YWY.js.map → notify-C645PGD5.js.map} +0 -0
  241. /package/dist/{onboard-53CITIM7.js.map → onboard-GK4PHPNI.js.map} +0 -0
  242. /package/dist/{prismic-ci-UTQ6LRR3.js.map → prismic-ci-3RHOZUUT.js.map} +0 -0
  243. /package/dist/{prismic-models-PVES6R5V.js.map → prismic-models-QBGUT2Q3.js.map} +0 -0
  244. /package/dist/{protection-audit-64PLLBLI.js.map → protection-audit-SJO53MEQ.js.map} +0 -0
  245. /package/dist/{renovate-dispatch-ICJGSFCE.js.map → renovate-dispatch-QJY75ODR.js.map} +0 -0
  246. /package/dist/{self-updating-PPQVV6UA.js.map → self-updating-6DWI2Z56.js.map} +0 -0
  247. /package/dist/{smoke-suite-OBWNPALQ.js.map → smoke-suite-VYY2LXM2.js.map} +0 -0
  248. /package/dist/{submissions-GJ6ITBRH.js.map → submissions-Q7DRFOCD.js.map} +0 -0
  249. /package/dist/{svelte-codemods-ZOBDHIES.js.map → svelte-codemods-25J2FO22.js.map} +0 -0
  250. /package/dist/{sync-configs-CJXUX6MD.js.map → sync-configs-3SE6PSCO.js.map} +0 -0
  251. /package/dist/{upgrade-WLX27UPC.js.map → upgrade-WBRQ62FX.js.map} +0 -0
  252. /package/dist/{webflow-624FEBFD.js.map → webflow-IRKOIT7S.js.map} +0 -0
@@ -2,39 +2,42 @@ import {
2
2
  appendSkipNotice,
3
3
  fleetWorkdir,
4
4
  prepareFleetSites
5
- } from "./chunk-ZMIPG6TR.js";
5
+ } from "./chunk-TVL5MVUF.js";
6
6
  import {
7
7
  resolveSites
8
- } from "./chunk-7J53SUT6.js";
8
+ } from "./chunk-P2FE5AI6.js";
9
9
  import {
10
10
  init
11
- } from "./chunk-6V7565O2.js";
12
- import "./chunk-UYCAF77E.js";
13
- import "./chunk-RJB3QUSP.js";
14
- import "./chunk-LS6QPANO.js";
11
+ } from "./chunk-ZKXSX4LO.js";
12
+ import "./chunk-XIDUYLSR.js";
13
+ import "./chunk-IYSEC543.js";
15
14
  import "./chunk-J7SZQUCW.js";
16
- import "./chunk-R6FPFMOS.js";
17
- import "./chunk-R4AB6GCT.js";
15
+ import "./chunk-BQRFQSGY.js";
16
+ import "./chunk-Y53WOQIJ.js";
17
+ import "./chunk-7RJ2HMMJ.js";
18
18
  import "./chunk-R53VL3RI.js";
19
- import "./chunk-Q276MZ7E.js";
19
+ import "./chunk-3VQWSE3F.js";
20
+ import "./chunk-3G25KIWW.js";
20
21
  import "./chunk-73UFRZKY.js";
21
- import "./chunk-ZTPPCHDB.js";
22
22
  import "./chunk-OTGB6YQO.js";
23
- import "./chunk-QRDB4NLB.js";
23
+ import "./chunk-2ZPT7GLV.js";
24
24
  import "./chunk-LKGVSM2O.js";
25
25
  import "./chunk-GASBX52O.js";
26
- import "./chunk-VRWUL4TR.js";
27
- import "./chunk-FDIFTIXC.js";
28
- import "./chunk-4DHQCN5H.js";
26
+ import "./chunk-XHHMM5HX.js";
27
+ import "./chunk-6TWWY7ZU.js";
28
+ import "./chunk-EVBCK2KC.js";
29
29
  import "./chunk-A3WDWNN5.js";
30
30
  import "./chunk-2OP4JKIQ.js";
31
+ import "./chunk-XTK5VIQB.js";
32
+ import "./chunk-2NQUCS7O.js";
33
+ import "./chunk-UDRHAQT7.js";
34
+ import "./chunk-PTDMVGKL.js";
35
+ import "./chunk-LBYOLBW7.js";
31
36
  import {
32
37
  siteLabel
33
38
  } from "./chunk-XXTZBPUY.js";
34
- import "./chunk-XTK5VIQB.js";
35
- import "./chunk-U5SZ4FOP.js";
36
39
  import "./chunk-NMAWXBJA.js";
37
- import "./chunk-N4MOEF32.js";
40
+ import "./chunk-C6B4RHXR.js";
38
41
 
39
42
  // src/cli/commands/init.ts
40
43
  import { resolve } from "path";
@@ -107,4 +110,4 @@ async function runInitCommand(site, opts) {
107
110
  export {
108
111
  runInitCommand
109
112
  };
110
- //# sourceMappingURL=init-TFVAN5OY.js.map
113
+ //# sourceMappingURL=init-NJEOEO7I.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,59 +1,65 @@
1
+ import {
2
+ writeAuditsToAirtable
3
+ } from "./chunk-PPE5KZJK.js";
1
4
  import {
2
5
  selfUpdating
3
- } from "./chunk-THEFTZ7F.js";
6
+ } from "./chunk-62CMMGEO.js";
4
7
  import "./chunk-MNDIED4M.js";
5
- import {
6
- writeAuditsToAirtable
7
- } from "./chunk-3YXDSCM6.js";
8
8
  import {
9
9
  hasRealScores,
10
10
  lighthouseScoresFromResult
11
- } from "./chunk-PBWDDDQH.js";
11
+ } from "./chunk-KTH5ZODA.js";
12
12
  import "./chunk-5L3FPQIJ.js";
13
13
  import {
14
14
  resolveSites
15
- } from "./chunk-7J53SUT6.js";
15
+ } from "./chunk-P2FE5AI6.js";
16
16
  import {
17
17
  queueDraft
18
- } from "./chunk-62VF32IC.js";
18
+ } from "./chunk-ILUNZHYV.js";
19
+ import {
20
+ renderReportHtml,
21
+ resolveCopy
22
+ } from "./chunk-CQR4LIM7.js";
23
+ import {
24
+ uploadAttachment
25
+ } from "./chunk-Z7AXYKQB.js";
26
+ import "./chunk-DJZWYIPP.js";
19
27
  import {
20
28
  createDraft,
21
29
  findReportByPeriod,
22
- renderReportHtml,
23
- resolveCopy,
24
30
  updateReportScores
25
- } from "./chunk-6QRLRT3P.js";
31
+ } from "./chunk-ACBRLLFT.js";
32
+ import "./chunk-VAD43MOR.js";
26
33
  import {
27
- uploadAttachment
28
- } from "./chunk-MPBXOJ3N.js";
29
- import "./chunk-SEEA6RXF.js";
34
+ openBase,
35
+ readAirtableConfig
36
+ } from "./chunk-HN6I2XWI.js";
30
37
  import "./chunk-73UFRZKY.js";
31
38
  import {
32
39
  runAudits
33
- } from "./chunk-QRDB4NLB.js";
40
+ } from "./chunk-2ZPT7GLV.js";
34
41
  import "./chunk-LKGVSM2O.js";
35
42
  import "./chunk-GASBX52O.js";
36
- import "./chunk-VRWUL4TR.js";
37
- import "./chunk-FDIFTIXC.js";
38
- import "./chunk-4DHQCN5H.js";
43
+ import "./chunk-XHHMM5HX.js";
44
+ import "./chunk-6TWWY7ZU.js";
45
+ import "./chunk-EVBCK2KC.js";
39
46
  import "./chunk-A3WDWNN5.js";
40
47
  import "./chunk-2OP4JKIQ.js";
48
+ import "./chunk-XTK5VIQB.js";
49
+ import "./chunk-2NQUCS7O.js";
50
+ import "./chunk-UDRHAQT7.js";
51
+ import "./chunk-PTDMVGKL.js";
52
+ import "./chunk-LBYOLBW7.js";
41
53
  import {
42
54
  siteLabel
43
55
  } from "./chunk-XXTZBPUY.js";
44
- import "./chunk-XTK5VIQB.js";
45
- import "./chunk-U5SZ4FOP.js";
46
56
  import {
47
57
  listWebsites,
48
58
  siteSlug
49
- } from "./chunk-577HCGZO.js";
50
- import {
51
- openBase,
52
- readAirtableConfig
53
- } from "./chunk-HN6I2XWI.js";
59
+ } from "./chunk-LDWZSLSU.js";
54
60
  import "./chunk-6VAL7XJT.js";
55
61
  import "./chunk-NMAWXBJA.js";
56
- import "./chunk-N4MOEF32.js";
62
+ import "./chunk-C6B4RHXR.js";
57
63
 
58
64
  // src/cli/commands/launch.ts
59
65
  import { resolve } from "path";
@@ -216,4 +222,4 @@ async function runLaunchCommand(site, opts) {
216
222
  export {
217
223
  runLaunchCommand
218
224
  };
219
- //# sourceMappingURL=launch-DWY2MF54.js.map
225
+ //# sourceMappingURL=launch-XNAX427U.js.map
@@ -1 +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\nfunction 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 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 const result = await launch(target);\n return { output: formatResult(result), code: result.complete ? 0 : 1 };\n}\n","import type { AuditResult, RecipeResult, Site } from \"../types.js\";\nimport { siteLabel } from \"../util/site.js\";\nimport { selfUpdating } from \"./self-updating/index.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 { 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: \"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};\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 * Step-chain (mirrors `init`), stopping on the first error or `failed` recipe:\n * 1. selfUpdating — Renovate + protection (platform auto-merge OFF; ci.yml is the starter's).\n * 2. runAudits + write the scores to the site's Websites row (reuses the\n * `audit --write-airtable` writer); the Lighthouse scores feed the draft.\n * 3. createDraft — reportType \"Launch\", today's period, the audited scores.\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\n const steps: Array<{ name: string; result: LaunchStepResult }> = [];\n const stop = (): LaunchResult => ({ site: label, steps, complete: false });\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 try {\n await writeAuditsToAirtable({ base, websites, slug: siteSlug(target.name), results });\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 report = existing;\n } else {\n report = await createDraft(base, draftInputFor(target, scores, today, period));\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 } 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(base, { id: report.id, siteId: target.id, reportType: \"Launch\" });\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":[]}
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\nfunction 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 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 const result = await launch(target);\n return { output: formatResult(result), code: result.complete ? 0 : 1 };\n}\n","import type { AuditResult, RecipeResult, Site } from \"../types.js\";\nimport { siteLabel } from \"../util/site.js\";\nimport { selfUpdating } from \"./self-updating/index.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 { 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: \"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};\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 * Step-chain (mirrors `init`), stopping on the first error or `failed` recipe:\n * 1. selfUpdating — Renovate + protection (platform auto-merge OFF; ci.yml is the starter's).\n * 2. runAudits + write the scores to the site's Websites row (reuses the\n * `audit --write-airtable` writer); the Lighthouse scores feed the draft.\n * 3. createDraft — reportType \"Launch\", today's period, the audited scores.\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\n const steps: Array<{ name: string; result: LaunchStepResult }> = [];\n const stop = (): LaunchResult => ({ site: label, steps, complete: false });\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 try {\n await writeAuditsToAirtable({ base, websites, slug: siteSlug(target.name), results });\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 report = existing;\n } else {\n report = await createDraft(base, draftInputFor(target, scores, today, period));\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 } 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(base, { id: report.id, siteId: target.id, reportType: \"Launch\" });\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":[]}
@@ -0,0 +1,11 @@
1
+ import {
2
+ lighthouseAudit
3
+ } from "./chunk-2NQUCS7O.js";
4
+ import "./chunk-PTDMVGKL.js";
5
+ import "./chunk-LBYOLBW7.js";
6
+ import "./chunk-XXTZBPUY.js";
7
+ import "./chunk-NMAWXBJA.js";
8
+ export {
9
+ lighthouseAudit
10
+ };
11
+ //# sourceMappingURL=lighthouse-VHI77PFB.js.map
@@ -2,11 +2,11 @@ import {
2
2
  hasRealScores,
3
3
  lighthouseScoresFromResult,
4
4
  resolveSlugFromCwd
5
- } from "./chunk-PBWDDDQH.js";
6
- import "./chunk-577HCGZO.js";
5
+ } from "./chunk-KTH5ZODA.js";
6
+ import "./chunk-LDWZSLSU.js";
7
7
  export {
8
8
  hasRealScores,
9
9
  lighthouseScoresFromResult,
10
10
  resolveSlugFromCwd
11
11
  };
12
- //# sourceMappingURL=lighthouse-airtable-BIPM26SZ.js.map
12
+ //# sourceMappingURL=lighthouse-airtable-LBVIYYP5.js.map
@@ -0,0 +1,72 @@
1
+ // src/forms/mailchimp.ts
2
+ import { createHash } from "crypto";
3
+ function mailchimpTagsFor(formType) {
4
+ return ["Online Form", `form:${formType}`];
5
+ }
6
+ function splitName(name) {
7
+ const n = (name ?? "").trim();
8
+ if (!n) return {};
9
+ const [first = n, ...rest] = n.split(/\s+/);
10
+ const out = { FNAME: first };
11
+ if (rest.length) out.LNAME = rest.join(" ");
12
+ return out;
13
+ }
14
+ async function addMailchimpMember(input) {
15
+ const doFetch = input.fetch ?? fetch;
16
+ const dash = input.apiKey.lastIndexOf("-");
17
+ const dc = dash >= 0 ? input.apiKey.slice(dash + 1) : "";
18
+ const email = input.email.trim();
19
+ if (!dc || !input.audienceId || !email) {
20
+ console.error("[mailchimp] missing datacenter/audience/email \u2014 skipping");
21
+ return { ok: false, status: 0 };
22
+ }
23
+ const hash = createHash("md5").update(email.toLowerCase()).digest("hex");
24
+ const url = `https://${dc}.api.mailchimp.com/3.0/lists/${encodeURIComponent(
25
+ input.audienceId
26
+ )}/members/${hash}`;
27
+ const body = {
28
+ email_address: email,
29
+ status_if_new: input.status ?? "subscribed"
30
+ };
31
+ const merge = splitName(input.name);
32
+ if (Object.keys(merge).length > 0) body.merge_fields = merge;
33
+ const tags = (input.tags ?? []).map((t) => t.trim()).filter((t) => t.length > 0);
34
+ if (tags.length > 0) body.tags = tags;
35
+ const auth = Buffer.from(`anystring:${input.apiKey}`).toString("base64");
36
+ const headers = { "content-type": "application/json", authorization: `Basic ${auth}` };
37
+ try {
38
+ const res = await doFetch(url, {
39
+ method: "PUT",
40
+ headers,
41
+ body: JSON.stringify(body)
42
+ });
43
+ if (!res.ok) {
44
+ console.error(`[mailchimp] add member \u2192 ${res.status} (audience ${input.audienceId})`);
45
+ return { ok: false, status: res.status };
46
+ }
47
+ if (tags.length === 0) return { ok: true, status: res.status };
48
+ let tagged = false;
49
+ try {
50
+ const tagRes = await doFetch(`${url}/tags`, {
51
+ method: "POST",
52
+ headers,
53
+ body: JSON.stringify({ tags: tags.map((name) => ({ name, status: "active" })) })
54
+ });
55
+ tagged = tagRes.ok;
56
+ if (!tagRes.ok) {
57
+ console.error(`[mailchimp] tag member \u2192 ${tagRes.status} (audience ${input.audienceId})`);
58
+ }
59
+ } catch (err) {
60
+ console.error(`[mailchimp] tag member failed: ${String(err)}`);
61
+ }
62
+ return { ok: true, status: res.status, tagged };
63
+ } catch (err) {
64
+ console.error(`[mailchimp] add member failed: ${String(err)}`);
65
+ return { ok: false, status: 0 };
66
+ }
67
+ }
68
+ export {
69
+ addMailchimpMember,
70
+ mailchimpTagsFor
71
+ };
72
+ //# sourceMappingURL=mailchimp-XYCTEEJY.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/forms/mailchimp.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\nimport type { FormType } from \"./types.js\";\n\nexport type MailchimpResult = {\n ok: boolean;\n status: number;\n /** Whether the requested tags were applied. Present ONLY when tags were asked for\n * and the member add itself succeeded — absent means \"no tags requested\", which is\n * not the same as \"tagging failed\". */\n tagged?: boolean;\n};\n\n/** Tags identifying a member the ingest pipeline added, so form signups are\n * distinguishable from imported/manually-added members inside Mailchimp (the\n * audience is otherwise a flat list — every API write shows the same\n * \"API - Generic\" source). \"Online Form\" is the human-facing segment name the\n * gallery asked for; the `form:` tag keeps the specific form machine-readable\n * for later segmentation. PURE. */\nexport function mailchimpTagsFor(formType: FormType): string[] {\n return [\"Online Form\", `form:${formType}`];\n}\n\nexport type AddMailchimpMemberInput = {\n /** Mailchimp Marketing API key, format `key-dc` (e.g. \"abc123-us21\"). */\n apiKey: string;\n /** Audience (list) ID. */\n audienceId: string;\n email: string;\n name?: string | null;\n /** Status for a NEW member. Default \"subscribed\" (immediate, no double opt-in). */\n status?: \"subscribed\" | \"pending\";\n /** Tags to apply (see mailchimpTagsFor). Blank entries are dropped. */\n tags?: string[];\n /** Injectable fetch for tests. */\n fetch?: typeof fetch;\n};\n\n/** Split a full name into Mailchimp FNAME/LNAME merge fields. */\nfunction splitName(name: string | null | undefined): { FNAME?: string; LNAME?: string } {\n const n = (name ?? \"\").trim();\n if (!n) return {};\n const [first = n, ...rest] = n.split(/\\s+/);\n const out: { FNAME?: string; LNAME?: string } = { FNAME: first };\n if (rest.length) out.LNAME = rest.join(\" \");\n return out;\n}\n\n/**\n * Upsert a subscriber into a Mailchimp audience (PUT /members/{md5(lowercased\n * email)} — idempotent, so a repeat signup is a no-op rather than an error). Uses\n * `status_if_new` only, so an already-unsubscribed member is NOT force-resubscribed\n * (compliance-safe). NEVER throws — a missing datacenter, non-2xx, or network error\n * returns `{ok:false}` so the caller treats it as a swallowed side-effect.\n */\nexport async function addMailchimpMember(input: AddMailchimpMemberInput): Promise<MailchimpResult> {\n const doFetch = input.fetch ?? fetch;\n const dash = input.apiKey.lastIndexOf(\"-\");\n const dc = dash >= 0 ? input.apiKey.slice(dash + 1) : \"\";\n const email = input.email.trim();\n if (!dc || !input.audienceId || !email) {\n console.error(\"[mailchimp] missing datacenter/audience/email — skipping\");\n return { ok: false, status: 0 };\n }\n const hash = createHash(\"md5\").update(email.toLowerCase()).digest(\"hex\");\n const url = `https://${dc}.api.mailchimp.com/3.0/lists/${encodeURIComponent(\n input.audienceId,\n )}/members/${hash}`;\n const body: Record<string, unknown> = {\n email_address: email,\n status_if_new: input.status ?? \"subscribed\",\n };\n const merge = splitName(input.name);\n if (Object.keys(merge).length > 0) body.merge_fields = merge;\n const tags = (input.tags ?? []).map((t) => t.trim()).filter((t) => t.length > 0);\n if (tags.length > 0) body.tags = tags;\n const auth = Buffer.from(`anystring:${input.apiKey}`).toString(\"base64\");\n const headers = { \"content-type\": \"application/json\", authorization: `Basic ${auth}` };\n try {\n const res = await doFetch(url, {\n method: \"PUT\",\n headers,\n body: JSON.stringify(body),\n });\n if (!res.ok) {\n console.error(`[mailchimp] add member → ${res.status} (audience ${input.audienceId})`);\n return { ok: false, status: res.status };\n }\n if (tags.length === 0) return { ok: true, status: res.status };\n // The `tags` in the PUT body above only take effect when the member is CREATED —\n // Mailchimp silently ignores them for an already-existing member, which is exactly\n // the repeat-signup case. The dedicated endpoint is what makes tagging reliable, so\n // both are sent: the body covers a brand-new member if this second call is lost,\n // and this call covers everyone else. Additive and idempotent (re-applying an\n // active tag is a no-op), and NEVER fatal — the member is already in the audience,\n // so a tag failure is reported (tagged:false) rather than failing the add.\n let tagged = false;\n try {\n const tagRes = await doFetch(`${url}/tags`, {\n method: \"POST\",\n headers,\n body: JSON.stringify({ tags: tags.map((name) => ({ name, status: \"active\" })) }),\n });\n tagged = tagRes.ok;\n if (!tagRes.ok) {\n console.error(`[mailchimp] tag member → ${tagRes.status} (audience ${input.audienceId})`);\n }\n } catch (err) {\n console.error(`[mailchimp] tag member failed: ${String(err)}`);\n }\n return { ok: true, status: res.status, tagged };\n } catch (err) {\n console.error(`[mailchimp] add member failed: ${String(err)}`);\n return { ok: false, status: 0 };\n }\n}\n"],"mappings":";AAAA,SAAS,kBAAkB;AAkBpB,SAAS,iBAAiB,UAA8B;AAC7D,SAAO,CAAC,eAAe,QAAQ,QAAQ,EAAE;AAC3C;AAkBA,SAAS,UAAU,MAAqE;AACtF,QAAM,KAAK,QAAQ,IAAI,KAAK;AAC5B,MAAI,CAAC,EAAG,QAAO,CAAC;AAChB,QAAM,CAAC,QAAQ,GAAG,GAAG,IAAI,IAAI,EAAE,MAAM,KAAK;AAC1C,QAAM,MAA0C,EAAE,OAAO,MAAM;AAC/D,MAAI,KAAK,OAAQ,KAAI,QAAQ,KAAK,KAAK,GAAG;AAC1C,SAAO;AACT;AASA,eAAsB,mBAAmB,OAA0D;AACjG,QAAM,UAAU,MAAM,SAAS;AAC/B,QAAM,OAAO,MAAM,OAAO,YAAY,GAAG;AACzC,QAAM,KAAK,QAAQ,IAAI,MAAM,OAAO,MAAM,OAAO,CAAC,IAAI;AACtD,QAAM,QAAQ,MAAM,MAAM,KAAK;AAC/B,MAAI,CAAC,MAAM,CAAC,MAAM,cAAc,CAAC,OAAO;AACtC,YAAQ,MAAM,+DAA0D;AACxE,WAAO,EAAE,IAAI,OAAO,QAAQ,EAAE;AAAA,EAChC;AACA,QAAM,OAAO,WAAW,KAAK,EAAE,OAAO,MAAM,YAAY,CAAC,EAAE,OAAO,KAAK;AACvE,QAAM,MAAM,WAAW,EAAE,gCAAgC;AAAA,IACvD,MAAM;AAAA,EACR,CAAC,YAAY,IAAI;AACjB,QAAM,OAAgC;AAAA,IACpC,eAAe;AAAA,IACf,eAAe,MAAM,UAAU;AAAA,EACjC;AACA,QAAM,QAAQ,UAAU,MAAM,IAAI;AAClC,MAAI,OAAO,KAAK,KAAK,EAAE,SAAS,EAAG,MAAK,eAAe;AACvD,QAAM,QAAQ,MAAM,QAAQ,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,CAAC,MAAM,EAAE,SAAS,CAAC;AAC/E,MAAI,KAAK,SAAS,EAAG,MAAK,OAAO;AACjC,QAAM,OAAO,OAAO,KAAK,aAAa,MAAM,MAAM,EAAE,EAAE,SAAS,QAAQ;AACvE,QAAM,UAAU,EAAE,gBAAgB,oBAAoB,eAAe,SAAS,IAAI,GAAG;AACrF,MAAI;AACF,UAAM,MAAM,MAAM,QAAQ,KAAK;AAAA,MAC7B,QAAQ;AAAA,MACR;AAAA,MACA,MAAM,KAAK,UAAU,IAAI;AAAA,IAC3B,CAAC;AACD,QAAI,CAAC,IAAI,IAAI;AACX,cAAQ,MAAM,iCAA4B,IAAI,MAAM,cAAc,MAAM,UAAU,GAAG;AACrF,aAAO,EAAE,IAAI,OAAO,QAAQ,IAAI,OAAO;AAAA,IACzC;AACA,QAAI,KAAK,WAAW,EAAG,QAAO,EAAE,IAAI,MAAM,QAAQ,IAAI,OAAO;AAQ7D,QAAI,SAAS;AACb,QAAI;AACF,YAAM,SAAS,MAAM,QAAQ,GAAG,GAAG,SAAS;AAAA,QAC1C,QAAQ;AAAA,QACR;AAAA,QACA,MAAM,KAAK,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC,UAAU,EAAE,MAAM,QAAQ,SAAS,EAAE,EAAE,CAAC;AAAA,MACjF,CAAC;AACD,eAAS,OAAO;AAChB,UAAI,CAAC,OAAO,IAAI;AACd,gBAAQ,MAAM,iCAA4B,OAAO,MAAM,cAAc,MAAM,UAAU,GAAG;AAAA,MAC1F;AAAA,IACF,SAAS,KAAK;AACZ,cAAQ,MAAM,kCAAkC,OAAO,GAAG,CAAC,EAAE;AAAA,IAC/D;AACA,WAAO,EAAE,IAAI,MAAM,QAAQ,IAAI,QAAQ,OAAO;AAAA,EAChD,SAAS,KAAK;AACZ,YAAQ,MAAM,kCAAkC,OAAO,GAAG,CAAC,EAAE;AAC7D,WAAO,EAAE,IAAI,OAAO,QAAQ,EAAE;AAAA,EAChC;AACF;","names":[]}
@@ -0,0 +1,7 @@
1
+ import {
2
+ runMigrations
3
+ } from "./chunk-3SF7D4DY.js";
4
+ export {
5
+ runMigrations
6
+ };
7
+ //# sourceMappingURL=migrate-GQH237A6.js.map
@@ -0,0 +1,22 @@
1
+ import {
2
+ buildAutoresponder,
3
+ buildPocNotification,
4
+ describeNotifyTarget,
5
+ makeNotify,
6
+ notifySubmission,
7
+ resolveRecipients
8
+ } from "./chunk-VSBFM7DS.js";
9
+ import "./chunk-BNM5POSJ.js";
10
+ import "./chunk-SNSTJLQW.js";
11
+ import "./chunk-5ML7FMBD.js";
12
+ import "./chunk-DJZWYIPP.js";
13
+ import "./chunk-2OP4JKIQ.js";
14
+ export {
15
+ buildAutoresponder,
16
+ buildPocNotification,
17
+ describeNotifyTarget,
18
+ makeNotify,
19
+ notifySubmission,
20
+ resolveRecipients
21
+ };
22
+ //# sourceMappingURL=notify-C645PGD5.js.map
@@ -5,21 +5,21 @@ import {
5
5
  appendSkipNotice,
6
6
  fleetWorkdir,
7
7
  prepareFleetSites
8
- } from "./chunk-ZMIPG6TR.js";
8
+ } from "./chunk-TVL5MVUF.js";
9
9
  import {
10
10
  resolveSites
11
- } from "./chunk-7J53SUT6.js";
11
+ } from "./chunk-P2FE5AI6.js";
12
12
  import {
13
13
  onboard
14
- } from "./chunk-UYCAF77E.js";
15
- import "./chunk-ZTPPCHDB.js";
14
+ } from "./chunk-7RJ2HMMJ.js";
15
+ import "./chunk-3G25KIWW.js";
16
16
  import "./chunk-OTGB6YQO.js";
17
17
  import "./chunk-LKGVSM2O.js";
18
- import "./chunk-FDIFTIXC.js";
19
- import "./chunk-4DHQCN5H.js";
20
- import "./chunk-XXTZBPUY.js";
18
+ import "./chunk-6TWWY7ZU.js";
19
+ import "./chunk-EVBCK2KC.js";
21
20
  import "./chunk-XTK5VIQB.js";
22
- import "./chunk-U5SZ4FOP.js";
21
+ import "./chunk-LBYOLBW7.js";
22
+ import "./chunk-XXTZBPUY.js";
23
23
 
24
24
  // src/cli/commands/onboard.ts
25
25
  import { resolve } from "path";
@@ -70,4 +70,4 @@ async function runOnboardCommand(site, opts) {
70
70
  export {
71
71
  runOnboardCommand
72
72
  };
73
- //# sourceMappingURL=onboard-53CITIM7.js.map
73
+ //# sourceMappingURL=onboard-GK4PHPNI.js.map
@@ -0,0 +1,30 @@
1
+ import {
2
+ GLOBAL_REPORT_CC,
3
+ isProbablyEmail,
4
+ parseAddresses,
5
+ sendApprovedReports,
6
+ withGlobalCc
7
+ } from "./chunk-2NDRHXMR.js";
8
+ import "./chunk-GECESMVS.js";
9
+ import "./chunk-5UINJNAJ.js";
10
+ import "./chunk-CQR4LIM7.js";
11
+ import "./chunk-Z7AXYKQB.js";
12
+ import "./chunk-DJZWYIPP.js";
13
+ import "./chunk-ACBRLLFT.js";
14
+ import "./chunk-VAD43MOR.js";
15
+ import "./chunk-HN6I2XWI.js";
16
+ import "./chunk-WEKL2HYJ.js";
17
+ import "./chunk-XUGSZP7Z.js";
18
+ import "./chunk-EVBCK2KC.js";
19
+ import "./chunk-JHGHLKFS.js";
20
+ import "./chunk-3SF7D4DY.js";
21
+ import "./chunk-LDWZSLSU.js";
22
+ import "./chunk-6VAL7XJT.js";
23
+ export {
24
+ GLOBAL_REPORT_CC,
25
+ isProbablyEmail,
26
+ parseAddresses,
27
+ sendApprovedReports,
28
+ withGlobalCc
29
+ };
30
+ //# sourceMappingURL=orchestrate-77UO4BYJ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,12 @@
1
+ import {
2
+ checkFleetParity,
3
+ formatParityResult
4
+ } from "./chunk-2EVEFOZY.js";
5
+ import "./chunk-ITIOFN7A.js";
6
+ import "./chunk-VAD43MOR.js";
7
+ import "./chunk-LDWZSLSU.js";
8
+ export {
9
+ checkFleetParity,
10
+ formatParityResult
11
+ };
12
+ //# sourceMappingURL=parity-MWS24A3H.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,12 @@
1
+ import {
2
+ ANALYZE_SKIPPED,
3
+ PROBES_SKIPPED,
4
+ runProspectAudit
5
+ } from "./chunk-X3B723J4.js";
6
+ import "./chunk-EVBCK2KC.js";
7
+ export {
8
+ ANALYZE_SKIPPED,
9
+ PROBES_SKIPPED,
10
+ runProspectAudit
11
+ };
12
+ //# sourceMappingURL=pipeline-S6CVHDGB.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -1,19 +1,22 @@
1
1
  import {
2
2
  preflight
3
- } from "./chunk-LTB6KVJW.js";
4
- import "./chunk-D4FVAIEJ.js";
5
- import "./chunk-COZPL62X.js";
3
+ } from "./chunk-N45M3FDK.js";
4
+ import "./chunk-PZR4EBPY.js";
5
+ import "./chunk-2NDRHXMR.js";
6
6
  import "./chunk-GECESMVS.js";
7
- import "./chunk-6QRLRT3P.js";
8
- import "./chunk-MPBXOJ3N.js";
9
- import "./chunk-SEEA6RXF.js";
10
- import "./chunk-WEKL2HYJ.js";
11
- import "./chunk-QG6OSL4M.js";
12
- import "./chunk-DC5H7KEQ.js";
13
- import "./chunk-4SOCPK7A.js";
14
- import "./chunk-U5SZ4FOP.js";
15
- import "./chunk-577HCGZO.js";
7
+ import "./chunk-5UINJNAJ.js";
8
+ import "./chunk-CQR4LIM7.js";
9
+ import "./chunk-Z7AXYKQB.js";
10
+ import "./chunk-DJZWYIPP.js";
11
+ import "./chunk-ACBRLLFT.js";
12
+ import "./chunk-VAD43MOR.js";
16
13
  import "./chunk-HN6I2XWI.js";
14
+ import "./chunk-WEKL2HYJ.js";
15
+ import "./chunk-XUGSZP7Z.js";
16
+ import "./chunk-EVBCK2KC.js";
17
+ import "./chunk-JHGHLKFS.js";
18
+ import "./chunk-3SF7D4DY.js";
19
+ import "./chunk-LDWZSLSU.js";
17
20
  import "./chunk-6VAL7XJT.js";
18
21
 
19
22
  // src/cli/commands/preflight.ts
@@ -63,4 +66,4 @@ async function runPreflightCommand(site, opts) {
63
66
  export {
64
67
  runPreflightCommand
65
68
  };
66
- //# sourceMappingURL=preflight-3XPDUHFJ.js.map
69
+ //# sourceMappingURL=preflight-6WBNU2GZ.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli/commands/preflight.ts"],"sourcesContent":["import {\n preflight,\n type PreflightSiteResult,\n type PreflightFinding,\n} from \"../../reports/preflight.js\";\nimport type { ReportType } from \"../../reports/types.js\";\n\nexport type PreflightCommandOptions = {\n type?: string;\n all?: boolean;\n cwd?: string;\n};\n\nconst TYPES: Record<string, ReportType> = {\n announcement: \"Announcement\",\n maintenance: \"Maintenance\",\n testing: \"Testing\",\n};\n\nconst MARK: Record<PreflightFinding[\"level\"], string> = { fail: \"✗\", warn: \"⚠\", info: \"ℹ\" };\n\nfunction formatSite(r: PreflightSiteResult): string {\n if (r.findings.length === 0) return `[${r.site}] ✓ clean`;\n return r.findings.map((f) => `[${r.site}] ${MARK[f.level]} ${f.check}: ${f.message}`).join(\"\\n\");\n}\n\n/**\n * `preflight [site]` — read-only pre-send checks over the live Airtable rows: everything\n * that would make a report send fail, reach the wrong inbox, or surprise the operator.\n * Exit 0 = safe (warnings allowed, printed), 1 = at least one hard failure, 2 = bad args.\n */\nexport async function runPreflightCommand(\n site: string | undefined,\n opts: PreflightCommandOptions,\n): Promise<{ output: string; code: number }> {\n if (Boolean(site) === Boolean(opts.all)) {\n return { output: \"Provide exactly one of <site> or --all.\", code: 2 };\n }\n const typeKey = (opts.type ?? \"announcement\").toLowerCase();\n const type = TYPES[typeKey];\n if (!type) {\n return {\n output: `Unknown --type '${opts.type}'. Supported: ${Object.keys(TYPES).join(\", \")}`,\n code: 2,\n };\n }\n\n try {\n const { results, fleet } = await preflight({\n ...(site ? { site } : {}),\n ...(opts.all ? { all: true } : {}),\n type,\n });\n if (results.length === 0) return { output: \"No matching sites.\", code: 1 };\n\n const lines = results.map(formatSite);\n for (const f of fleet) lines.push(`[fleet] ${MARK[f.level]} ${f.check}: ${f.message}`);\n\n const all = [...results.flatMap((r) => r.findings), ...fleet];\n const fails = all.filter((f) => f.level === \"fail\").length;\n const warns = all.filter((f) => f.level === \"warn\").length;\n lines.push(\n `Preflight: ${results.length} site(s) — ${fails} fail, ${warns} warn. ${\n fails > 0 ? \"NOT safe to send.\" : \"Safe to send (review warnings).\"\n }`,\n );\n return { output: lines.join(\"\\n\"), code: fails > 0 ? 1 : 0 };\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":";;;;;;;;;;;;;;;;;;;AAaA,IAAM,QAAoC;AAAA,EACxC,cAAc;AAAA,EACd,aAAa;AAAA,EACb,SAAS;AACX;AAEA,IAAM,OAAkD,EAAE,MAAM,UAAK,MAAM,UAAK,MAAM,SAAI;AAE1F,SAAS,WAAW,GAAgC;AAClD,MAAI,EAAE,SAAS,WAAW,EAAG,QAAO,IAAI,EAAE,IAAI;AAC9C,SAAO,EAAE,SAAS,IAAI,CAAC,MAAM,IAAI,EAAE,IAAI,KAAK,KAAK,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,KAAK,EAAE,OAAO,EAAE,EAAE,KAAK,IAAI;AACjG;AAOA,eAAsB,oBACpB,MACA,MAC2C;AAC3C,MAAI,QAAQ,IAAI,MAAM,QAAQ,KAAK,GAAG,GAAG;AACvC,WAAO,EAAE,QAAQ,2CAA2C,MAAM,EAAE;AAAA,EACtE;AACA,QAAM,WAAW,KAAK,QAAQ,gBAAgB,YAAY;AAC1D,QAAM,OAAO,MAAM,OAAO;AAC1B,MAAI,CAAC,MAAM;AACT,WAAO;AAAA,MACL,QAAQ,mBAAmB,KAAK,IAAI,iBAAiB,OAAO,KAAK,KAAK,EAAE,KAAK,IAAI,CAAC;AAAA,MAClF,MAAM;AAAA,IACR;AAAA,EACF;AAEA,MAAI;AACF,UAAM,EAAE,SAAS,MAAM,IAAI,MAAM,UAAU;AAAA,MACzC,GAAI,OAAO,EAAE,KAAK,IAAI,CAAC;AAAA,MACvB,GAAI,KAAK,MAAM,EAAE,KAAK,KAAK,IAAI,CAAC;AAAA,MAChC;AAAA,IACF,CAAC;AACD,QAAI,QAAQ,WAAW,EAAG,QAAO,EAAE,QAAQ,sBAAsB,MAAM,EAAE;AAEzE,UAAM,QAAQ,QAAQ,IAAI,UAAU;AACpC,eAAW,KAAK,MAAO,OAAM,KAAK,WAAW,KAAK,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,KAAK,EAAE,OAAO,EAAE;AAErF,UAAM,MAAM,CAAC,GAAG,QAAQ,QAAQ,CAAC,MAAM,EAAE,QAAQ,GAAG,GAAG,KAAK;AAC5D,UAAM,QAAQ,IAAI,OAAO,CAAC,MAAM,EAAE,UAAU,MAAM,EAAE;AACpD,UAAM,QAAQ,IAAI,OAAO,CAAC,MAAM,EAAE,UAAU,MAAM,EAAE;AACpD,UAAM;AAAA,MACJ,cAAc,QAAQ,MAAM,mBAAc,KAAK,UAAU,KAAK,UAC5D,QAAQ,IAAI,sBAAsB,iCACpC;AAAA,IACF;AACA,WAAO,EAAE,QAAQ,MAAM,KAAK,IAAI,GAAG,MAAM,QAAQ,IAAI,IAAI,EAAE;AAAA,EAC7D,SAAS,KAAK;AACZ,UAAM,IAAI;AACV,WAAO,EAAE,QAAQ,EAAE,WAAW,OAAO,GAAG,GAAG,MAAM,EAAE,YAAY,EAAE;AAAA,EACnE;AACF;","names":[]}
1
+ {"version":3,"sources":["../src/cli/commands/preflight.ts"],"sourcesContent":["import {\n preflight,\n type PreflightSiteResult,\n type PreflightFinding,\n} from \"../../reports/preflight.js\";\nimport type { ReportType } from \"../../reports/types.js\";\n\nexport type PreflightCommandOptions = {\n type?: string;\n all?: boolean;\n cwd?: string;\n};\n\nconst TYPES: Record<string, ReportType> = {\n announcement: \"Announcement\",\n maintenance: \"Maintenance\",\n testing: \"Testing\",\n};\n\nconst MARK: Record<PreflightFinding[\"level\"], string> = { fail: \"✗\", warn: \"⚠\", info: \"ℹ\" };\n\nfunction formatSite(r: PreflightSiteResult): string {\n if (r.findings.length === 0) return `[${r.site}] ✓ clean`;\n return r.findings.map((f) => `[${r.site}] ${MARK[f.level]} ${f.check}: ${f.message}`).join(\"\\n\");\n}\n\n/**\n * `preflight [site]` — read-only pre-send checks over the live Airtable rows: everything\n * that would make a report send fail, reach the wrong inbox, or surprise the operator.\n * Exit 0 = safe (warnings allowed, printed), 1 = at least one hard failure, 2 = bad args.\n */\nexport async function runPreflightCommand(\n site: string | undefined,\n opts: PreflightCommandOptions,\n): Promise<{ output: string; code: number }> {\n if (Boolean(site) === Boolean(opts.all)) {\n return { output: \"Provide exactly one of <site> or --all.\", code: 2 };\n }\n const typeKey = (opts.type ?? \"announcement\").toLowerCase();\n const type = TYPES[typeKey];\n if (!type) {\n return {\n output: `Unknown --type '${opts.type}'. Supported: ${Object.keys(TYPES).join(\", \")}`,\n code: 2,\n };\n }\n\n try {\n const { results, fleet } = await preflight({\n ...(site ? { site } : {}),\n ...(opts.all ? { all: true } : {}),\n type,\n });\n if (results.length === 0) return { output: \"No matching sites.\", code: 1 };\n\n const lines = results.map(formatSite);\n for (const f of fleet) lines.push(`[fleet] ${MARK[f.level]} ${f.check}: ${f.message}`);\n\n const all = [...results.flatMap((r) => r.findings), ...fleet];\n const fails = all.filter((f) => f.level === \"fail\").length;\n const warns = all.filter((f) => f.level === \"warn\").length;\n lines.push(\n `Preflight: ${results.length} site(s) — ${fails} fail, ${warns} warn. ${\n fails > 0 ? \"NOT safe to send.\" : \"Safe to send (review warnings).\"\n }`,\n );\n return { output: lines.join(\"\\n\"), code: fails > 0 ? 1 : 0 };\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":";;;;;;;;;;;;;;;;;;;;;;AAaA,IAAM,QAAoC;AAAA,EACxC,cAAc;AAAA,EACd,aAAa;AAAA,EACb,SAAS;AACX;AAEA,IAAM,OAAkD,EAAE,MAAM,UAAK,MAAM,UAAK,MAAM,SAAI;AAE1F,SAAS,WAAW,GAAgC;AAClD,MAAI,EAAE,SAAS,WAAW,EAAG,QAAO,IAAI,EAAE,IAAI;AAC9C,SAAO,EAAE,SAAS,IAAI,CAAC,MAAM,IAAI,EAAE,IAAI,KAAK,KAAK,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,KAAK,EAAE,OAAO,EAAE,EAAE,KAAK,IAAI;AACjG;AAOA,eAAsB,oBACpB,MACA,MAC2C;AAC3C,MAAI,QAAQ,IAAI,MAAM,QAAQ,KAAK,GAAG,GAAG;AACvC,WAAO,EAAE,QAAQ,2CAA2C,MAAM,EAAE;AAAA,EACtE;AACA,QAAM,WAAW,KAAK,QAAQ,gBAAgB,YAAY;AAC1D,QAAM,OAAO,MAAM,OAAO;AAC1B,MAAI,CAAC,MAAM;AACT,WAAO;AAAA,MACL,QAAQ,mBAAmB,KAAK,IAAI,iBAAiB,OAAO,KAAK,KAAK,EAAE,KAAK,IAAI,CAAC;AAAA,MAClF,MAAM;AAAA,IACR;AAAA,EACF;AAEA,MAAI;AACF,UAAM,EAAE,SAAS,MAAM,IAAI,MAAM,UAAU;AAAA,MACzC,GAAI,OAAO,EAAE,KAAK,IAAI,CAAC;AAAA,MACvB,GAAI,KAAK,MAAM,EAAE,KAAK,KAAK,IAAI,CAAC;AAAA,MAChC;AAAA,IACF,CAAC;AACD,QAAI,QAAQ,WAAW,EAAG,QAAO,EAAE,QAAQ,sBAAsB,MAAM,EAAE;AAEzE,UAAM,QAAQ,QAAQ,IAAI,UAAU;AACpC,eAAW,KAAK,MAAO,OAAM,KAAK,WAAW,KAAK,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,KAAK,EAAE,OAAO,EAAE;AAErF,UAAM,MAAM,CAAC,GAAG,QAAQ,QAAQ,CAAC,MAAM,EAAE,QAAQ,GAAG,GAAG,KAAK;AAC5D,UAAM,QAAQ,IAAI,OAAO,CAAC,MAAM,EAAE,UAAU,MAAM,EAAE;AACpD,UAAM,QAAQ,IAAI,OAAO,CAAC,MAAM,EAAE,UAAU,MAAM,EAAE;AACpD,UAAM;AAAA,MACJ,cAAc,QAAQ,MAAM,mBAAc,KAAK,UAAU,KAAK,UAC5D,QAAQ,IAAI,sBAAsB,iCACpC;AAAA,IACF;AACA,WAAO,EAAE,QAAQ,MAAM,KAAK,IAAI,GAAG,MAAM,QAAQ,IAAI,IAAI,EAAE;AAAA,EAC7D,SAAS,KAAK;AACZ,UAAM,IAAI;AACV,WAAO,EAAE,QAAQ,EAAE,WAAW,OAAO,GAAG,GAAG,MAAM,EAAE,YAAY,EAAE;AAAA,EACnE;AACF;","names":[]}