@reddoorla/maintenance 0.94.1 → 0.95.1

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 (150) hide show
  1. package/README.md +31 -0
  2. package/dist/{announce-PGT4SZZB.js → announce-CLQYX5I4.js} +4 -4
  3. package/dist/{blux-NXQLMS4W.js → blux-4KNXUP2K.js} +1 -1
  4. package/dist/{bump-deps-6OR7LL4E.js → bump-deps-C5G2EFBB.js} +6 -6
  5. package/dist/{chunk-LS6QPANO.js → chunk-2LYOAB2E.js} +2 -2
  6. package/dist/{chunk-KQB2BX4V.js → chunk-2ZAZ7ETT.js} +2 -2
  7. package/dist/{chunk-XTK5VIQB.js → chunk-AVEQUR44.js} +48 -1
  8. package/dist/chunk-AVEQUR44.js.map +1 -0
  9. package/dist/{chunk-B6NUZ2ZX.js → chunk-BCKEP5S6.js} +2 -2
  10. package/dist/{chunk-DMPHP7UP.js → chunk-BI2VI6EM.js} +2 -2
  11. package/dist/{chunk-5FCBYK6L.js → chunk-BVEDKMNG.js} +10 -10
  12. package/dist/{chunk-OCNSIBMP.js → chunk-C3IQQKXL.js} +26 -1
  13. package/dist/{chunk-OCNSIBMP.js.map → chunk-C3IQQKXL.js.map} +1 -1
  14. package/dist/{chunk-PPIZHDJL.js → chunk-CJ2RMTT7.js} +2 -2
  15. package/dist/{chunk-7CJ3DVZW.js → chunk-CWXTNPNZ.js} +2 -2
  16. package/dist/{chunk-TGUESYGF.js → chunk-DFKBTBO3.js} +2 -2
  17. package/dist/{chunk-WHWVYL7B.js → chunk-FSGICFXB.js} +7 -32
  18. package/dist/chunk-FSGICFXB.js.map +1 -0
  19. package/dist/{chunk-3HS6LPFX.js → chunk-FUWFLAWQ.js} +4 -4
  20. package/dist/{chunk-4AIYWWKV.js → chunk-KJRVMMM3.js} +2 -2
  21. package/dist/{chunk-TCF6S7AD.js → chunk-LM2NHRCJ.js} +2 -2
  22. package/dist/{chunk-AEUABPAJ.js → chunk-R5IMFAFR.js} +2 -2
  23. package/dist/{chunk-NTLSMJHW.js → chunk-S7RYFUIK.js} +2 -2
  24. package/dist/{chunk-MLT4QY5X.js → chunk-SLFG7Y76.js} +1 -1
  25. package/dist/chunk-SLFG7Y76.js.map +1 -0
  26. package/dist/{chunk-REJCSA4H.js → chunk-TR3HFH6J.js} +4 -3
  27. package/dist/chunk-TR3HFH6J.js.map +1 -0
  28. package/dist/{chunk-22GKJO5F.js → chunk-VSGMCCGQ.js} +2 -2
  29. package/dist/{chunk-4R3YAQNV.js → chunk-WSJ7RO54.js} +2 -2
  30. package/dist/chunk-XPJQXSC4.js +112 -0
  31. package/dist/chunk-XPJQXSC4.js.map +1 -0
  32. package/dist/chunk-ZCL7C5LH.js +2698 -0
  33. package/dist/chunk-ZCL7C5LH.js.map +1 -0
  34. package/dist/{chunk-ZTPPCHDB.js → chunk-ZQV7UQNE.js} +2 -2
  35. package/dist/cli/bin.js +39 -26
  36. package/dist/cli/bin.js.map +1 -1
  37. package/dist/cli/commands/audit.d.ts +1 -1
  38. package/dist/cli/commands/audit.js +8 -8
  39. package/dist/client-G2WGWPCA.js +11 -0
  40. package/dist/configs/eslint.js +27 -1
  41. package/dist/configs/eslint.js.map +1 -1
  42. package/dist/{convert-to-pnpm-3RVGUBBR.js → convert-to-pnpm-YTFREUJK.js} +6 -6
  43. package/dist/{db-FL7ZBF6H.js → db-XKZYDCKM.js} +9 -9
  44. package/dist/{digest-TZ3QQOSF.js → digest-7UBGUBRK.js} +14 -14
  45. package/dist/{digest-collectors-EHFY2OQC.js → digest-collectors-DJFN5ZDK.js} +8 -8
  46. package/dist/{ensure-site-WIDO6LGU.js → ensure-site-OAAE5YE2.js} +2 -2
  47. package/dist/{forms-notify-target-2LWF5C5B.js → forms-notify-target-UC6PF3AE.js} +2 -2
  48. package/dist/{github-signals-GAHNOAHS.js → github-signals-TX5FPYP6.js} +5 -5
  49. package/dist/{header-image-YN3AQRY3.js → header-image-PSPT7CUM.js} +2 -2
  50. package/dist/{health-endpoint-XLNBWVHK.js → health-endpoint-KVCJYWET.js} +6 -6
  51. package/dist/{health-mirror-EB76EERV.js → health-mirror-XJAKA3EY.js} +3 -3
  52. package/dist/index.d.ts +2 -2
  53. package/dist/index.js +31 -29
  54. package/dist/index.js.map +1 -1
  55. package/dist/{init-YCLSGIEP.js → init-FFE4FCO2.js} +13 -13
  56. package/dist/{launch-FSHDTXSM.js → launch-UD36AHUN.js} +221 -7
  57. package/dist/launch-UD36AHUN.js.map +1 -0
  58. package/dist/match-harness-QRG6XZAR.js +70 -0
  59. package/dist/match-harness-QRG6XZAR.js.map +1 -0
  60. package/dist/migrate-Y7R4CESL.js +7 -0
  61. package/dist/{onboard-NKE6GZKL.js → onboard-TM2KESGF.js} +6 -6
  62. package/dist/{orchestrate-MWXENQOS.js → orchestrate-HYVQPRCE.js} +6 -6
  63. package/dist/{pipeline-MATFYQRC.js → pipeline-YROAY6DT.js} +2 -2
  64. package/dist/{preflight-4VQP7JJL.js → preflight-RYIP54NY.js} +7 -7
  65. package/dist/{prismic-ci-DM352L2Q.js → prismic-ci-6GKKZGB5.js} +13 -11
  66. package/dist/prismic-ci-6GKKZGB5.js.map +1 -0
  67. package/dist/{prismic-models-Q32ARSYS.js → prismic-models-P6FWWVRS.js} +5 -5
  68. package/dist/prospect/types.d.ts +1 -1
  69. package/dist/{prospect-audit-MT6RGMOY.js → prospect-audit-PRHU53HS.js} +5 -5
  70. package/dist/{prospect-audits-RVYEA4KH.js → prospect-audits-R3LWF6U7.js} +10 -4
  71. package/dist/recipes/sync-configs.d.ts +1 -1
  72. package/dist/recipes/sync-configs.js +4 -4
  73. package/dist/{render-JE5P26H5.js → render-YGNGTX3W.js} +2 -2
  74. package/dist/render-from-row-IFSBHWDH.js +1 -1
  75. package/dist/{report-6FFHGUUS.js → report-LQS4ECTM.js} +12 -12
  76. package/dist/{report-mirror-IP64R7B3.js → report-mirror-HDTOJE64.js} +3 -3
  77. package/dist/{schema-2V7BGYVT.js → schema-A4WCPIF4.js} +1 -1
  78. package/dist/{schema-2V7BGYVT.js.map → schema-A4WCPIF4.js.map} +1 -1
  79. package/dist/{self-updating-5DVDIEHB.js → self-updating-MWXIZLL7.js} +6 -6
  80. package/dist/{selftest-LJYXBIO5.js → selftest-VXTHRPRN.js} +9 -9
  81. package/dist/{site-mirror-UKHREAD6.js → site-mirror-WON4FTJ2.js} +3 -3
  82. package/dist/{smoke-suite-NUTC7IUK.js → smoke-suite-7DGITCTZ.js} +6 -6
  83. package/dist/{submissions-5GKJPCIH.js → submissions-OVZPVBYG.js} +2 -2
  84. package/dist/{svelte-codemods-U4NIT6CV.js → svelte-codemods-WSV2FGNG.js} +6 -6
  85. package/dist/{sync-configs-S2JYY6QU.js → sync-configs-RRIHNLIJ.js} +7 -7
  86. package/dist/{types-OIQZ5hWN.d.ts → types-D_bpy89i.d.ts} +1 -1
  87. package/dist/{upgrade-YFZCMUPE.js → upgrade-VTD6V4HS.js} +6 -6
  88. package/dist/util/git.d.ts +46 -1
  89. package/dist/util/git.js +7 -1
  90. package/package.json +1 -1
  91. package/dist/chunk-7MKT4I5T.js +0 -62
  92. package/dist/chunk-7MKT4I5T.js.map +0 -1
  93. package/dist/chunk-MLT4QY5X.js.map +0 -1
  94. package/dist/chunk-REJCSA4H.js.map +0 -1
  95. package/dist/chunk-WHWVYL7B.js.map +0 -1
  96. package/dist/chunk-XTK5VIQB.js.map +0 -1
  97. package/dist/client-M2V6FHH5.js +0 -11
  98. package/dist/launch-FSHDTXSM.js.map +0 -1
  99. package/dist/migrate-K4JETR36.js +0 -7
  100. package/dist/prismic-ci-DM352L2Q.js.map +0 -1
  101. /package/dist/{announce-PGT4SZZB.js.map → announce-CLQYX5I4.js.map} +0 -0
  102. /package/dist/{blux-NXQLMS4W.js.map → blux-4KNXUP2K.js.map} +0 -0
  103. /package/dist/{bump-deps-6OR7LL4E.js.map → bump-deps-C5G2EFBB.js.map} +0 -0
  104. /package/dist/{chunk-LS6QPANO.js.map → chunk-2LYOAB2E.js.map} +0 -0
  105. /package/dist/{chunk-KQB2BX4V.js.map → chunk-2ZAZ7ETT.js.map} +0 -0
  106. /package/dist/{chunk-B6NUZ2ZX.js.map → chunk-BCKEP5S6.js.map} +0 -0
  107. /package/dist/{chunk-DMPHP7UP.js.map → chunk-BI2VI6EM.js.map} +0 -0
  108. /package/dist/{chunk-5FCBYK6L.js.map → chunk-BVEDKMNG.js.map} +0 -0
  109. /package/dist/{chunk-PPIZHDJL.js.map → chunk-CJ2RMTT7.js.map} +0 -0
  110. /package/dist/{chunk-7CJ3DVZW.js.map → chunk-CWXTNPNZ.js.map} +0 -0
  111. /package/dist/{chunk-TGUESYGF.js.map → chunk-DFKBTBO3.js.map} +0 -0
  112. /package/dist/{chunk-3HS6LPFX.js.map → chunk-FUWFLAWQ.js.map} +0 -0
  113. /package/dist/{chunk-4AIYWWKV.js.map → chunk-KJRVMMM3.js.map} +0 -0
  114. /package/dist/{chunk-TCF6S7AD.js.map → chunk-LM2NHRCJ.js.map} +0 -0
  115. /package/dist/{chunk-AEUABPAJ.js.map → chunk-R5IMFAFR.js.map} +0 -0
  116. /package/dist/{chunk-NTLSMJHW.js.map → chunk-S7RYFUIK.js.map} +0 -0
  117. /package/dist/{chunk-22GKJO5F.js.map → chunk-VSGMCCGQ.js.map} +0 -0
  118. /package/dist/{chunk-4R3YAQNV.js.map → chunk-WSJ7RO54.js.map} +0 -0
  119. /package/dist/{chunk-ZTPPCHDB.js.map → chunk-ZQV7UQNE.js.map} +0 -0
  120. /package/dist/{client-M2V6FHH5.js.map → client-G2WGWPCA.js.map} +0 -0
  121. /package/dist/{convert-to-pnpm-3RVGUBBR.js.map → convert-to-pnpm-YTFREUJK.js.map} +0 -0
  122. /package/dist/{db-FL7ZBF6H.js.map → db-XKZYDCKM.js.map} +0 -0
  123. /package/dist/{digest-TZ3QQOSF.js.map → digest-7UBGUBRK.js.map} +0 -0
  124. /package/dist/{digest-collectors-EHFY2OQC.js.map → digest-collectors-DJFN5ZDK.js.map} +0 -0
  125. /package/dist/{ensure-site-WIDO6LGU.js.map → ensure-site-OAAE5YE2.js.map} +0 -0
  126. /package/dist/{forms-notify-target-2LWF5C5B.js.map → forms-notify-target-UC6PF3AE.js.map} +0 -0
  127. /package/dist/{github-signals-GAHNOAHS.js.map → github-signals-TX5FPYP6.js.map} +0 -0
  128. /package/dist/{header-image-YN3AQRY3.js.map → header-image-PSPT7CUM.js.map} +0 -0
  129. /package/dist/{health-endpoint-XLNBWVHK.js.map → health-endpoint-KVCJYWET.js.map} +0 -0
  130. /package/dist/{health-mirror-EB76EERV.js.map → health-mirror-XJAKA3EY.js.map} +0 -0
  131. /package/dist/{init-YCLSGIEP.js.map → init-FFE4FCO2.js.map} +0 -0
  132. /package/dist/{migrate-K4JETR36.js.map → migrate-Y7R4CESL.js.map} +0 -0
  133. /package/dist/{onboard-NKE6GZKL.js.map → onboard-TM2KESGF.js.map} +0 -0
  134. /package/dist/{orchestrate-MWXENQOS.js.map → orchestrate-HYVQPRCE.js.map} +0 -0
  135. /package/dist/{pipeline-MATFYQRC.js.map → pipeline-YROAY6DT.js.map} +0 -0
  136. /package/dist/{preflight-4VQP7JJL.js.map → preflight-RYIP54NY.js.map} +0 -0
  137. /package/dist/{prismic-models-Q32ARSYS.js.map → prismic-models-P6FWWVRS.js.map} +0 -0
  138. /package/dist/{prospect-audit-MT6RGMOY.js.map → prospect-audit-PRHU53HS.js.map} +0 -0
  139. /package/dist/{prospect-audits-RVYEA4KH.js.map → prospect-audits-R3LWF6U7.js.map} +0 -0
  140. /package/dist/{render-JE5P26H5.js.map → render-YGNGTX3W.js.map} +0 -0
  141. /package/dist/{report-6FFHGUUS.js.map → report-LQS4ECTM.js.map} +0 -0
  142. /package/dist/{report-mirror-IP64R7B3.js.map → report-mirror-HDTOJE64.js.map} +0 -0
  143. /package/dist/{self-updating-5DVDIEHB.js.map → self-updating-MWXIZLL7.js.map} +0 -0
  144. /package/dist/{selftest-LJYXBIO5.js.map → selftest-VXTHRPRN.js.map} +0 -0
  145. /package/dist/{site-mirror-UKHREAD6.js.map → site-mirror-WON4FTJ2.js.map} +0 -0
  146. /package/dist/{smoke-suite-NUTC7IUK.js.map → smoke-suite-7DGITCTZ.js.map} +0 -0
  147. /package/dist/{submissions-5GKJPCIH.js.map → submissions-OVZPVBYG.js.map} +0 -0
  148. /package/dist/{svelte-codemods-U4NIT6CV.js.map → svelte-codemods-WSV2FGNG.js.map} +0 -0
  149. /package/dist/{sync-configs-S2JYY6QU.js.map → sync-configs-RRIHNLIJ.js.map} +0 -0
  150. /package/dist/{upgrade-YFZCMUPE.js.map → upgrade-VTD6V4HS.js.map} +0 -0
package/dist/cli/bin.js CHANGED
@@ -61,6 +61,7 @@ var RECIPE_DESCRIPTIONS = {
61
61
  "smoke-suite": "Add the smoke suite (test:smoke + playwright config + /health smoke routes).",
62
62
  "self-updating": "Bootstrap Renovate + repo protection (writes renovate configs via PR, wires ruleset, disables platform auto-merge; ci.yml comes from the starter and is deliberately not managed).",
63
63
  "prismic-ci": "Add the Prismic model delivery workflow to a site via PR (dry delta comment on PRs, push to Prismic on merge to main).",
64
+ "match-harness": "Install the matching-a-page gate harness (dev-guarded /dev/match/[uid] route + matching/ scripts) for a live-reference rebuild.",
64
65
  init: "Run the full onboarding chain (convert-to-pnpm \u2192 onboard \u2192 sync-configs \u2192 svelte-codemods \u2192 a11y-fixtures-page \u2192 health-endpoint \u2192 smoke-suite \u2192 audit)."
65
66
  };
66
67
  async function runOrExit(fn, opts) {
@@ -111,7 +112,7 @@ cli.command("sync-configs [site]", "Sync canonical configs into a site.").option
111
112
  'Inventory file (.json or .mjs/.js), or "airtable" to read from Websites table'
112
113
  ).option("--workdir <path>", "Clone target for fleet mode (default ~/.reddoor-maint/sites)").action(
113
114
  async (site, opts) => runOrExit(
114
- async () => (await import("../sync-configs-S2JYY6QU.js")).runSyncConfigsCommand(site, opts),
115
+ async () => (await import("../sync-configs-RRIHNLIJ.js")).runSyncConfigsCommand(site, opts),
115
116
  opts
116
117
  )
117
118
  );
@@ -120,7 +121,7 @@ cli.command("bump-deps [site]", "Bump dependencies.").option("--group <group>",
120
121
  'Inventory file (.json or .mjs/.js), or "airtable" to read from Websites table'
121
122
  ).option("--workdir <path>", "Clone target for fleet mode (default ~/.reddoor-maint/sites)").action(
122
123
  async (site, opts) => runOrExit(
123
- async () => (await import("../bump-deps-6OR7LL4E.js")).runBumpDepsCommand(site, opts),
124
+ async () => (await import("../bump-deps-C5G2EFBB.js")).runBumpDepsCommand(site, opts),
124
125
  opts
125
126
  )
126
127
  );
@@ -129,7 +130,7 @@ cli.command(
129
130
  "Bootstrap a repo to keep itself updated (Renovate + protection; platform auto-merge off; ci.yml is the starter's, not managed here)."
130
131
  ).option("--dry", "List what would be enabled without writing or opening PRs").option("--fleet <inventory>", 'Inventory file (.json or .mjs/.js), or "airtable"').option("--workdir <path>", "Clone target for fleet mode (default ~/.reddoor-maint/sites)").action(
131
132
  async (site, opts) => runOrExit(
132
- async () => (await import("../self-updating-5DVDIEHB.js")).runSelfUpdatingCommand(site, opts),
133
+ async () => (await import("../self-updating-MWXIZLL7.js")).runSelfUpdatingCommand(site, opts),
133
134
  opts
134
135
  )
135
136
  );
@@ -138,7 +139,7 @@ cli.command(
138
139
  "Add the Prismic model delivery workflow to a site via PR (one PR per repo; never pushes to main)."
139
140
  ).option("--dry", "List the sites that would be offered the workflow, without opening any PR").option("--fleet <inventory>", 'Inventory file (.json or .mjs/.js), or "airtable"').option("--workdir <path>", "Clone target for fleet mode (default ~/.reddoor-maint/sites)").action(
140
141
  async (site, opts) => runOrExit(
141
- async () => (await import("../prismic-ci-DM352L2Q.js")).runPrismicCiCommand(site, opts),
142
+ async () => (await import("../prismic-ci-6GKKZGB5.js")).runPrismicCiCommand(site, opts),
142
143
  opts
143
144
  )
144
145
  );
@@ -153,7 +154,7 @@ cli.command(
153
154
  "Write the report to this file (the CI workflow posts it as a PR comment)"
154
155
  ).action(
155
156
  async (site, opts) => runOrExit(
156
- async () => (await import("../prismic-models-Q32ARSYS.js")).runPrismicModelsCommand(site, opts),
157
+ async () => (await import("../prismic-models-P6FWWVRS.js")).runPrismicModelsCommand(site, opts),
157
158
  opts
158
159
  )
159
160
  );
@@ -162,7 +163,7 @@ cli.command("upgrade <upgrade> [site]", "Run a named upgrade recipe (svelte-4-to
162
163
  'Inventory file (.json or .mjs/.js), or "airtable" to read from Websites table'
163
164
  ).option("--workdir <path>", "Clone target for fleet mode (default ~/.reddoor-maint/sites)").action(
164
165
  async (upgrade, site, opts) => runOrExit(
165
- async () => (await import("../upgrade-YFZCMUPE.js")).runUpgradeCommand(upgrade, site, opts),
166
+ async () => (await import("../upgrade-VTD6V4HS.js")).runUpgradeCommand(upgrade, site, opts),
166
167
  opts
167
168
  )
168
169
  );
@@ -174,7 +175,7 @@ cli.command(
174
175
  'Inventory file (.json or .mjs/.js), or "airtable" to read from Websites table'
175
176
  ).option("--workdir <path>", "Clone target for fleet mode (default ~/.reddoor-maint/sites)").action(
176
177
  async (site, opts) => runOrExit(
177
- async () => (await import("../convert-to-pnpm-3RVGUBBR.js")).runConvertToPnpmCommand(site, opts),
178
+ async () => (await import("../convert-to-pnpm-YTFREUJK.js")).runConvertToPnpmCommand(site, opts),
178
179
  opts
179
180
  )
180
181
  );
@@ -183,7 +184,7 @@ cli.command("svelte-codemods [site]", "Apply Svelte 5 gotcha codemods to an alre
183
184
  'Inventory file (.json or .mjs/.js), or "airtable" to read from Websites table'
184
185
  ).option("--workdir <path>", "Clone target for fleet mode (default ~/.reddoor-maint/sites)").action(
185
186
  async (site, opts) => runOrExit(
186
- async () => (await import("../svelte-codemods-U4NIT6CV.js")).runSvelteCodemodsCommand(site, opts),
187
+ async () => (await import("../svelte-codemods-WSV2FGNG.js")).runSvelteCodemodsCommand(site, opts),
187
188
  opts
188
189
  )
189
190
  );
@@ -195,7 +196,19 @@ cli.command(
195
196
  'Inventory file (.json or .mjs/.js), or "airtable" to read from Websites table'
196
197
  ).option("--workdir <path>", "Clone target for fleet mode (default ~/.reddoor-maint/sites)").action(
197
198
  async (site, opts) => runOrExit(
198
- async () => (await import("../health-endpoint-XLNBWVHK.js")).runHealthEndpointCommand(site, opts),
199
+ async () => (await import("../health-endpoint-KVCJYWET.js")).runHealthEndpointCommand(site, opts),
200
+ opts
201
+ )
202
+ );
203
+ cli.command(
204
+ "match-harness [site]",
205
+ "Install the matching-a-page gate harness (dev-guarded /dev/match/[uid] route + matching/ scripts) for a live-reference rebuild."
206
+ ).option("--ref <url>", "Reference (live) site URL the harness gates against \u2014 required").option("--cand <url>", "Candidate origin (default http://localhost:5173)").option("--matrix <list>", "Breakpoint matrix, comma-separated (default 1440,834,390)").option(
207
+ "--fleet <inventory>",
208
+ 'Inventory file (.json or .mjs/.js), or "airtable" to read from Websites table'
209
+ ).option("--workdir <path>", "Clone target for fleet mode (default ~/.reddoor-maint/sites)").action(
210
+ async (site, opts) => runOrExit(
211
+ async () => (await import("../match-harness-QRG6XZAR.js")).runMatchHarnessCommand(site, opts),
199
212
  opts
200
213
  )
201
214
  );
@@ -207,7 +220,7 @@ cli.command(
207
220
  'Inventory file (.json or .mjs/.js), or "airtable" to read from Websites table'
208
221
  ).option("--workdir <path>", "Clone target for fleet mode (default ~/.reddoor-maint/sites)").action(
209
222
  async (site, opts) => runOrExit(
210
- async () => (await import("../smoke-suite-NUTC7IUK.js")).runSmokeSuiteCommand(site, opts),
223
+ async () => (await import("../smoke-suite-7DGITCTZ.js")).runSmokeSuiteCommand(site, opts),
211
224
  opts
212
225
  )
213
226
  );
@@ -219,7 +232,7 @@ cli.command(
219
232
  'Inventory file (.json or .mjs/.js), or "airtable" to read from Websites table'
220
233
  ).option("--workdir <path>", "Clone target for fleet mode (default ~/.reddoor-maint/sites)").action(
221
234
  async (site, opts) => runOrExit(
222
- async () => (await import("../onboard-NKE6GZKL.js")).runOnboardCommand(site, opts),
235
+ async () => (await import("../onboard-TM2KESGF.js")).runOnboardCommand(site, opts),
223
236
  opts
224
237
  )
225
238
  );
@@ -230,20 +243,20 @@ cli.command(
230
243
  "--fleet <inventory>",
231
244
  'Inventory file (.json or .mjs/.js), or "airtable" to read from Websites table'
232
245
  ).option("--workdir <path>", "Clone target for fleet mode (default ~/.reddoor-maint/sites)").action(
233
- async (site, opts) => runOrExit(async () => (await import("../init-YCLSGIEP.js")).runInitCommand(site, opts), opts)
246
+ async (site, opts) => runOrExit(async () => (await import("../init-FFE4FCO2.js")).runInitCommand(site, opts), opts)
234
247
  );
235
248
  cli.command(
236
249
  "launch <site>",
237
250
  "Bootstrap + first-audit a site, then draft its launch email for approval."
238
251
  ).action(
239
252
  async (site, opts) => runOrExit(
240
- async () => (await import("../launch-FSHDTXSM.js")).runLaunchCommand(site, opts),
253
+ async () => (await import("../launch-UD36AHUN.js")).runLaunchCommand(site, opts),
241
254
  opts
242
255
  )
243
256
  );
244
257
  cli.command("header-image [site]", "Generate a site's report header image from its live homepage.").option("--all", "Every live site with no Header image yet (backfill)").option("--force", "With --all, regenerate sites that already have one").option("--write-airtable", "Upload to the Websites row instead of writing a local file").option("--out-dir <path>", "Directory for local output (default: reports/)").option("--settle-ms <ms>", "Override the post-load settle delay for slow/animated homepages").action(
245
258
  async (site, opts) => runOrExit(
246
- async () => (await import("../header-image-YN3AQRY3.js")).runHeaderImageCommand(site, opts),
259
+ async () => (await import("../header-image-PSPT7CUM.js")).runHeaderImageCommand(site, opts),
247
260
  opts
248
261
  )
249
262
  );
@@ -252,7 +265,7 @@ cli.command(
252
265
  "Draft the monthly-report announcement email for maintenance sites (all, or one) for approval."
253
266
  ).action(
254
267
  async (site, opts) => runOrExit(
255
- async () => (await import("../announce-PGT4SZZB.js")).runAnnounceCommand(site, opts),
268
+ async () => (await import("../announce-CLQYX5I4.js")).runAnnounceCommand(site, opts),
256
269
  opts
257
270
  )
258
271
  );
@@ -261,7 +274,7 @@ cli.command(
261
274
  "Show who a form submission would email, and optionally flip the pre-launch guard (read-back confirmed)."
262
275
  ).option("--set <on|off>", "Flip the guard: on = route to operator, off = restore.").option("--restore <status>", "Status to restore with --set off. Required; never inferred.").action(
263
276
  async (site, opts) => runOrExit(
264
- async () => (await import("../forms-notify-target-2LWF5C5B.js")).runFormsNotifyTargetCommand(
277
+ async () => (await import("../forms-notify-target-UC6PF3AE.js")).runFormsNotifyTargetCommand(
265
278
  site,
266
279
  opts
267
280
  ),
@@ -273,7 +286,7 @@ cli.command(
273
286
  "Operator self-tests. kind=email: preview a report email for a site (or --all) to yourself."
274
287
  ).option("--type <type>", "Report type: announcement (default) | maintenance | testing | launch").option("--to <addr>", "Recipient(s), comma-separated. Default: OPERATOR_EMAIL.").option("--all", "Send a preview for every maintenance site (to --to/operator).").option("--dry-run", "Render only; write reports/<slug>/selftest-<type>.html; do not send.").action(
275
288
  async (kind, site, opts) => runOrExit(
276
- async () => (await import("../selftest-LJYXBIO5.js")).runSelftestCommand(kind, site, opts),
289
+ async () => (await import("../selftest-VXTHRPRN.js")).runSelftestCommand(kind, site, opts),
277
290
  opts
278
291
  )
279
292
  );
@@ -285,13 +298,13 @@ cli.command(
285
298
  "Fleet mode: announcement\u2192maintenance sites; maintenance/testing\u2192all schedulable sites."
286
299
  ).action(
287
300
  async (site, opts) => runOrExit(
288
- async () => (await import("../preflight-4VQP7JJL.js")).runPreflightCommand(site, opts),
301
+ async () => (await import("../preflight-RYIP54NY.js")).runPreflightCommand(site, opts),
289
302
  opts
290
303
  )
291
304
  );
292
305
  cli.command("ensure-site <slug>", "Create/verify the Airtable Websites row for a new site.").option("--name <display name>", "Human Name for the row (client-facing copy uses it verbatim).").option("--url <url>", "Deployed URL (e.g. the Netlify site URL).").option("--contact <email>", "point of contact \u2014 the client address reports resolve to.").option("--git-repo <owner/repo>", "GitHub identity. Default on create: reddoorla/<slug>.").action(
293
306
  async (slug, opts) => runOrExit(
294
- async () => (await import("../ensure-site-WIDO6LGU.js")).runEnsureSiteCommand(slug, opts),
307
+ async () => (await import("../ensure-site-OAAE5YE2.js")).runEnsureSiteCommand(slug, opts),
295
308
  opts
296
309
  )
297
310
  );
@@ -312,7 +325,7 @@ cli.command(
312
325
  "Email the internal sheet (scores, what wasn't measured, top fixes, the link) to PROSPECT_AUDIT_RECIPIENTS."
313
326
  ).action(
314
327
  async (url, opts) => runOrExit(
315
- async () => (await import("../prospect-audit-MT6RGMOY.js")).runProspectAuditCommand(url, opts),
328
+ async () => (await import("../prospect-audit-PRHU53HS.js")).runProspectAuditCommand(url, opts),
316
329
  opts
317
330
  )
318
331
  );
@@ -333,7 +346,7 @@ cli.command("report [site]", "Draft or send maintenance/testing reports.").optio
333
346
  "Regenerate one UNSENT report's stored HTML from its current row, so the console preview shows edited commentary. Refuses a sent report."
334
347
  ).action(
335
348
  async (site, opts) => runOrExit(
336
- async () => (await import("../report-6FFHGUUS.js")).runReportCommand(site, opts),
349
+ async () => (await import("../report-LQS4ECTM.js")).runReportCommand(site, opts),
337
350
  opts
338
351
  )
339
352
  );
@@ -342,7 +355,7 @@ cli.command(
342
355
  "Sweep the fleet for GitHub signals (Renovate-failing/CI/last-commit) and write Airtable."
343
356
  ).option("--fleet", "Run across every site in the Airtable inventory.").option("--write-airtable", "Write each site's signals back to its Websites row.").action(
344
357
  async (opts) => runOrExit(
345
- async () => (await import("../github-signals-GAHNOAHS.js")).runGitHubSignalsCommand({
358
+ async () => (await import("../github-signals-TX5FPYP6.js")).runGitHubSignalsCommand({
346
359
  fleet: opts.fleet,
347
360
  writeAirtable: opts.writeAirtable
348
361
  }),
@@ -373,7 +386,7 @@ cli.command(
373
386
  "--force",
374
387
  "import-airtable / sync: run despite the freeze (#643) \u2014 a deliberate rollback-window converge from the frozen Airtable shadow. Without it both refuse while Turso is authoritative, because an import overwrites authoritative rows."
375
388
  ).action(
376
- async (action, opts) => runOrExit(async () => (await import("../db-FL7ZBF6H.js")).runDbCommand(action, opts), opts)
389
+ async (action, opts) => runOrExit(async () => (await import("../db-XKZYDCKM.js")).runDbCommand(action, opts), opts)
377
390
  );
378
391
  cli.command(
379
392
  "submissions <action>",
@@ -383,7 +396,7 @@ cli.command(
383
396
  "Write the re-buckets: status \u2192 spam_auto, spam_score/spam_reason replaced with the new verdict + 'retro-rescore' marker."
384
397
  ).action(
385
398
  async (action, opts) => runOrExit(
386
- async () => (await import("../submissions-5GKJPCIH.js")).runSubmissionsCommand(action, opts),
399
+ async () => (await import("../submissions-OVZPVBYG.js")).runSubmissionsCommand(action, opts),
387
400
  opts
388
401
  )
389
402
  );
@@ -395,7 +408,7 @@ cli.command(
395
408
  async () => (await import("../renovate-dispatch-U5Q52SKT.js")).runRenovateDispatchCommand({
396
409
  fleet: opts.fleet,
397
410
  // #539 Phase 5: mirror the auto-fix counter into site_health.
398
- siteMirror: await (await import("../site-mirror-UKHREAD6.js")).makeSiteMirror()
411
+ siteMirror: await (await import("../site-mirror-WON4FTJ2.js")).makeSiteMirror()
399
412
  }),
400
413
  opts
401
414
  )
@@ -420,7 +433,7 @@ cli.command(
420
433
  "freeze: JSON declaring slots the template has no token for (video poster, a panel rebuilt from a baked image). Keys must start with 'x.'"
421
434
  ).action(
422
435
  async (action, dir, opts) => runOrExit(
423
- async () => (await import("../blux-NXQLMS4W.js")).runBluxCommand(action, dir, opts),
436
+ async () => (await import("../blux-4KNXUP2K.js")).runBluxCommand(action, dir, opts),
424
437
  opts
425
438
  )
426
439
  );
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/cli/bin.ts","../../src/cli/version.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { dirname } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { cac } from \"cac\";\nimport type { AuditName, RecipeName } from \"../types.js\";\nimport { loadCredentialsIntoEnv } from \"../util/credentials.js\";\nimport { resolvePackageVersion } from \"./version.js\";\n\n// Command modules are loaded LAZILY (dynamic `import()` inside each `.action()`),\n// never eagerly at the top. An eager `import { runReportCommand } from\n// \"./commands/report.js\"` would pull EVERY command's transitive dependency chain\n// into the CLI's startup graph — report/announce/launch drag in mjml + resend +\n// @google-analytics/data, `db` drags in the libSQL/kysely stack, etc. Those heavy\n// packages are `devDependencies` (this repo's CLI/functions/audits use them); a\n// consuming fleet site installs @reddoorla/maintenance only for `./forms` +\n// `./configs/*` and runs just `reddoor-maint audit --only a11y` in CI. Lazy\n// loading keeps that path (and `--help`/`--version`) free of the report/db\n// chains, so those packages never land in a consumer's node_modules. The\n// smoke-dist gate asserts bin.js's STATIC import closure stays free of them.\n\n// Load credentials from ~/.config/reddoor-maint/credentials.env before any\n// command runs, so AIRTABLE_PAT/AIRTABLE_BASE_ID/RESEND_API_KEY/etc. are\n// available from any cwd. Shell-exported env vars still win. Silent on\n// missing file — commands that need the credentials will fail with their\n// own clear error.\nloadCredentialsIntoEnv();\n\nconst here = dirname(fileURLToPath(import.meta.url));\nconst version = resolvePackageVersion(here);\n\nconst AUDIT_DESCRIPTIONS: Record<AuditName, string> = {\n deps: \"Diff site package.json against the bundled baseline version map.\",\n lighthouse: \"Run @lhci/cli autorun using the canonical lighthouserc.\",\n a11y: \"Playwright + axe against the canonical a11y routes.\",\n security:\n \"GitHub Dependabot alerts (prod+dev) for repo-backed sites; falls back to pnpm/npm audit (prod-deps) with no repo/token.\",\n lint: \"ESLint + Prettier using the canonical configs.\",\n domain: \"DNS resolve + TLS cert expiry against the deployed URL (checkout-free).\",\n browser:\n \"Playwright across desktop engines + mobile devices + link-check against the deployed URL (checkout-free).\",\n \"netlify-deploy\":\n \"Latest production deploy health via the Netlify API by site id (checkout-free; needs NETLIFY_PAT).\",\n \"function-health\":\n \"GET {deployedUrl}/health and read its ok/prismic/forms status (checkout-free).\",\n smoke: \"Run the site's own `pnpm test:smoke` suite in its checkout (clone-based).\",\n \"form-e2e\":\n \"Submit the real production contact form in test-mode against the deployed URL (checkout-free).\",\n};\n\nconst RECIPE_DESCRIPTIONS: Record<RecipeName, string> = {\n \"sync-configs\": \"Overwrite a site's canonical configs to match @reddoorla/maintenance.\",\n \"bump-deps\": \"Bump dependencies and commit the lockfile change.\",\n \"svelte-4-to-5\": \"Run the 7-commit Svelte 4 → 5 upgrade recipe.\",\n \"svelte-codemods\":\n \"Apply Svelte 5 gotcha codemods to an already-migrated site (state_referenced_locally, etc.).\",\n \"convert-to-pnpm\": \"Convert an npm/yarn site to pnpm (lockfile, packageManager, scripts).\",\n onboard: \"Install @reddoorla/maintenance + audit deps on a site (preferred first step).\",\n \"a11y-fixtures-page\":\n \"Write src/routes/dev/a11y-fixtures/+page.svelte (stub for lhci + axe targets).\",\n \"health-endpoint\":\n \"Write src/routes/health/+server.ts (function-health probe for the report gate).\",\n \"smoke-suite\": \"Add the smoke suite (test:smoke + playwright config + /health smoke routes).\",\n \"self-updating\":\n \"Bootstrap Renovate + repo protection (writes renovate configs via PR, wires ruleset, disables platform auto-merge; ci.yml comes from the starter and is deliberately not managed).\",\n \"prismic-ci\":\n \"Add the Prismic model delivery workflow to a site via PR (dry delta comment on PRs, push to Prismic on merge to main).\",\n init: \"Run the full onboarding chain (convert-to-pnpm → onboard → sync-configs → svelte-codemods → a11y-fixtures-page → health-endpoint → smoke-suite → audit).\",\n};\n\n/** Run a command thunk and surface its result, falling back to a clean error\n * message on throw. Wraps the ~10-line try/catch every `.action()` used to\n * duplicate. `verbose` flips between full stack and message-only.\n *\n * On success it sets `process.exitCode` and RETURNS rather than calling\n * `process.exit()` right after `console.log()`. `process.exit()` does not wait\n * for stdout to flush when stdout is a pipe, so a large `--json` payload piped\n * to another process would get truncated mid-write. Setting `exitCode` and\n * returning lets Node drain stdout and exit naturally with the right code. A\n * non-zero `code` still yields a non-zero process exit.\n *\n * The error path keeps `process.exit()` — error messages are small (one line),\n * always go to stderr, and exiting immediately is the desired fail-fast. */\nexport async function runOrExit(\n fn: () => Promise<{ output: string; code: number }>,\n opts: { verbose?: boolean },\n): Promise<void> {\n try {\n const { output, code } = await fn();\n console.log(output);\n process.exitCode = code;\n return;\n } catch (err) {\n const e = err as { exitCode?: number; message?: string; stack?: string };\n console.error(opts.verbose ? (e.stack ?? e.message) : (e.message ?? String(err)));\n process.exit(e.exitCode ?? 1);\n }\n}\n\nconst cli = cac(\"reddoor-maint\");\n\ncli.option(\"--cwd <path>\", \"Override working directory (default: process.cwd())\");\ncli.option(\"--verbose\", \"Verbose output (full stack on errors)\");\n\ncli.command(\"list-audits\", \"Print the available audits.\").action(() => {\n for (const [name, desc] of Object.entries(AUDIT_DESCRIPTIONS)) {\n console.log(`${name.padEnd(12)} ${desc}`);\n }\n});\n\ncli.command(\"list-recipes\", \"Print the available recipes.\").action(() => {\n for (const [name, desc] of Object.entries(RECIPE_DESCRIPTIONS)) {\n console.log(`${name.padEnd(16)} ${desc}`);\n }\n});\n\ncli\n .command(\"audit [site]\", \"Run audits against a site (default: cwd).\")\n .option(\"--only <names>\", \"Comma-separated audit names (e.g. deps,lighthouse)\")\n .option(\"--json\", \"Machine-readable JSON output\")\n .option(\n \"--fleet <inventory>\",\n 'Inventory file (.json or .mjs/.js), or \"airtable\" to read from Websites table',\n )\n .option(\"--workdir <path>\", \"Clone target for fleet mode (default ~/.reddoor-maint/sites)\")\n .option(\n \"--write-airtable [slug]\",\n \"After lighthouse runs, write pScore/rScore/bpScore/seoScore + timestamp to the matching Websites row. Slug defaults to cwd's package.json#name.\",\n )\n .option(\"--fail-on-violations\", \"Exit non-zero if any a11y violations are found (for CI gates)\")\n .option(\n \"--url <url>\",\n \"Audit this deployed URL with lighthouse (no dev server); single-site. Pair with --only lighthouse — other audits still use the local checkout.\",\n )\n .option(\n \"--concurrency <n>\",\n \"Max sites to audit in parallel in --fleet mode (default: all at once). Use 1 for sequential (CI).\",\n )\n .action(\n async (\n site,\n opts: {\n only?: string;\n json?: boolean;\n fleet?: string;\n workdir?: string;\n cwd?: string;\n verbose?: boolean;\n writeAirtable?: string | boolean;\n failOnViolations?: boolean;\n url?: string;\n concurrency?: string;\n },\n ) =>\n runOrExit(\n async () => (await import(\"./commands/audit.js\")).runAuditCommand(site, opts),\n opts,\n ),\n );\n\ncli\n .command(\"sync-configs [site]\", \"Sync canonical configs into a site.\")\n .option(\"--only <names>\", \"Comma-separated config names (e.g. eslint,prettier)\")\n .option(\"--dry\", \"Print diff without writing\")\n .option(\n \"--fleet <inventory>\",\n 'Inventory file (.json or .mjs/.js), or \"airtable\" to read from Websites table',\n )\n .option(\"--workdir <path>\", \"Clone target for fleet mode (default ~/.reddoor-maint/sites)\")\n .action(\n async (\n site,\n opts: {\n only?: string;\n dry?: boolean;\n fleet?: string;\n workdir?: string;\n cwd?: string;\n verbose?: boolean;\n },\n ) =>\n runOrExit(\n async () => (await import(\"./commands/sync-configs.js\")).runSyncConfigsCommand(site, opts),\n opts,\n ),\n );\n\ncli\n .command(\"bump-deps [site]\", \"Bump dependencies.\")\n .option(\"--group <group>\", \"patch | minor | major\", { default: \"minor\" })\n .option(\n \"--fleet <inventory>\",\n 'Inventory file (.json or .mjs/.js), or \"airtable\" to read from Websites table',\n )\n .option(\"--workdir <path>\", \"Clone target for fleet mode (default ~/.reddoor-maint/sites)\")\n .action(\n async (\n site,\n opts: {\n group?: string;\n fleet?: string;\n workdir?: string;\n cwd?: string;\n verbose?: boolean;\n },\n ) =>\n runOrExit(\n async () => (await import(\"./commands/bump-deps.js\")).runBumpDepsCommand(site, opts),\n opts,\n ),\n );\n\ncli\n .command(\n \"self-updating [site]\",\n \"Bootstrap a repo to keep itself updated (Renovate + protection; platform auto-merge off; ci.yml is the starter's, not managed here).\",\n )\n .option(\"--dry\", \"List what would be enabled without writing or opening PRs\")\n .option(\"--fleet <inventory>\", 'Inventory file (.json or .mjs/.js), or \"airtable\"')\n .option(\"--workdir <path>\", \"Clone target for fleet mode (default ~/.reddoor-maint/sites)\")\n .action(\n async (\n site,\n opts: {\n dry?: boolean;\n fleet?: string;\n workdir?: string;\n cwd?: string;\n verbose?: boolean;\n },\n ) =>\n runOrExit(\n async () =>\n (await import(\"./commands/self-updating.js\")).runSelfUpdatingCommand(site, opts),\n opts,\n ),\n );\n\n// Fleet-wide, this opens ONE PULL REQUEST PER REPOSITORY and never pushes to a\n// client's main. `--dry` exists because that is the only way to see the blast\n// radius before firing it. Both directions of the flag ↔ option link are pinned\n// by tests/cli/prismic-ci-command.test.ts.\ncli\n .command(\n \"prismic-ci [site]\",\n \"Add the Prismic model delivery workflow to a site via PR (one PR per repo; never pushes to main).\",\n )\n .option(\"--dry\", \"List the sites that would be offered the workflow, without opening any PR\")\n .option(\"--fleet <inventory>\", 'Inventory file (.json or .mjs/.js), or \"airtable\"')\n .option(\"--workdir <path>\", \"Clone target for fleet mode (default ~/.reddoor-maint/sites)\")\n .action(\n async (\n site,\n opts: {\n dry?: boolean;\n fleet?: string;\n workdir?: string;\n cwd?: string;\n verbose?: boolean;\n },\n ) =>\n runOrExit(\n async () => (await import(\"./commands/prismic-ci.js\")).runPrismicCiCommand(site, opts),\n opts,\n ),\n );\n\n// EVERY flag below must be one the command actually reads, and every option the\n// command reads must appear below. cac rejects an unknown option outright, so a\n// missing line here is a hard error in whatever workflow types the flag; a line\n// here with no handler is the silent no-op — it parses, it lands in `opts`, and\n// nothing ever looks at it. Both directions are pinned by\n// tests/cli/prismic-models-registration.test.ts, the second one at the type level\n// against `PrismicModelsCommandOptions`.\ncli\n .command(\n \"prismic-models [site]\",\n \"Compare a site's Prismic models against its repo (dry by default).\",\n )\n .option(\n \"--apply\",\n \"Push local models to Prismic. Never deletes — remote-only models are reported.\",\n )\n .option(\"--pull\", \"Write remote-only models into the repo (single-site; review + PR the result).\")\n .option(\"--tokens\", \"Print the per-site write-token doctor: which env var, present?, reads?\")\n .option(\"--fleet <inventory>\", 'Inventory file (.json or .mjs/.js), or \"airtable\". Read-only.')\n .option(\"--workdir <path>\", \"Clone target for fleet mode (default ~/.reddoor-maint/sites)\")\n .option(\"--write-airtable\", \"Fleet mode: persist each site's verdict to its Websites row\")\n .option(\n \"--comment-file <path>\",\n \"Write the report to this file (the CI workflow posts it as a PR comment)\",\n )\n .action(\n async (\n site,\n opts: {\n apply?: boolean;\n pull?: boolean;\n tokens?: boolean;\n fleet?: string;\n workdir?: string;\n writeAirtable?: boolean;\n commentFile?: string;\n cwd?: string;\n verbose?: boolean;\n },\n ) =>\n runOrExit(\n async () =>\n (await import(\"./commands/prismic-models.js\")).runPrismicModelsCommand(site, opts),\n opts,\n ),\n );\n\ncli\n .command(\"upgrade <upgrade> [site]\", \"Run a named upgrade recipe (svelte-4-to-5).\")\n .example(\"reddoor-maint upgrade svelte-4-to-5 ./my-site\")\n .option(\n \"--fleet <inventory>\",\n 'Inventory file (.json or .mjs/.js), or \"airtable\" to read from Websites table',\n )\n .option(\"--workdir <path>\", \"Clone target for fleet mode (default ~/.reddoor-maint/sites)\")\n .action(\n async (\n upgrade: string,\n site: string | undefined,\n opts: { fleet?: string; workdir?: string; cwd?: string; verbose?: boolean },\n ) =>\n runOrExit(\n async () => (await import(\"./commands/upgrade.js\")).runUpgradeCommand(upgrade, site, opts),\n opts,\n ),\n );\n\ncli\n .command(\n \"convert-to-pnpm [site]\",\n \"Convert an npm/yarn site to pnpm (lockfile, packageManager, scripts).\",\n )\n .option(\n \"--fleet <inventory>\",\n 'Inventory file (.json or .mjs/.js), or \"airtable\" to read from Websites table',\n )\n .option(\"--workdir <path>\", \"Clone target for fleet mode (default ~/.reddoor-maint/sites)\")\n .action(\n async (site, opts: { fleet?: string; workdir?: string; cwd?: string; verbose?: boolean }) =>\n runOrExit(\n async () =>\n (await import(\"./commands/convert-to-pnpm.js\")).runConvertToPnpmCommand(site, opts),\n opts,\n ),\n );\n\ncli\n .command(\"svelte-codemods [site]\", \"Apply Svelte 5 gotcha codemods to an already-migrated site.\")\n .option(\n \"--fleet <inventory>\",\n 'Inventory file (.json or .mjs/.js), or \"airtable\" to read from Websites table',\n )\n .option(\"--workdir <path>\", \"Clone target for fleet mode (default ~/.reddoor-maint/sites)\")\n .action(\n async (site, opts: { fleet?: string; workdir?: string; cwd?: string; verbose?: boolean }) =>\n runOrExit(\n async () =>\n (await import(\"./commands/svelte-codemods.js\")).runSvelteCodemodsCommand(site, opts),\n opts,\n ),\n );\n\ncli\n .command(\n \"health-endpoint [site]\",\n \"Write src/routes/health/+server.ts (function-health probe for the report gate).\",\n )\n .option(\n \"--fleet <inventory>\",\n 'Inventory file (.json or .mjs/.js), or \"airtable\" to read from Websites table',\n )\n .option(\"--workdir <path>\", \"Clone target for fleet mode (default ~/.reddoor-maint/sites)\")\n .action(\n async (site, opts: { fleet?: string; workdir?: string; cwd?: string; verbose?: boolean }) =>\n runOrExit(\n async () =>\n (await import(\"./commands/health-endpoint.js\")).runHealthEndpointCommand(site, opts),\n opts,\n ),\n );\n\ncli\n .command(\n \"smoke-suite [site]\",\n \"Add the smoke suite (test:smoke + playwright config + /health smoke routes).\",\n )\n .option(\n \"--fleet <inventory>\",\n 'Inventory file (.json or .mjs/.js), or \"airtable\" to read from Websites table',\n )\n .option(\"--workdir <path>\", \"Clone target for fleet mode (default ~/.reddoor-maint/sites)\")\n .action(\n async (site, opts: { fleet?: string; workdir?: string; cwd?: string; verbose?: boolean }) =>\n runOrExit(\n async () => (await import(\"./commands/smoke-suite.js\")).runSmokeSuiteCommand(site, opts),\n opts,\n ),\n );\n\ncli\n .command(\n \"onboard [site]\",\n \"Install @reddoorla/maintenance + audit deps on a site (run after convert-to-pnpm).\",\n )\n .option(\"--audits <names>\", \"Comma-separated audit subset: lighthouse,a11y (default: both)\")\n .option(\n \"--fleet <inventory>\",\n 'Inventory file (.json or .mjs/.js), or \"airtable\" to read from Websites table',\n )\n .option(\"--workdir <path>\", \"Clone target for fleet mode (default ~/.reddoor-maint/sites)\")\n .action(\n async (\n site,\n opts: {\n audits?: string;\n fleet?: string;\n workdir?: string;\n cwd?: string;\n verbose?: boolean;\n },\n ) =>\n runOrExit(\n async () => (await import(\"./commands/onboard.js\")).runOnboardCommand(site, opts),\n opts,\n ),\n );\n\ncli\n .command(\n \"init [site]\",\n \"One-shot guided onboarding: convert-to-pnpm → onboard → sync-configs → svelte-codemods → a11y-fixtures-page → health-endpoint → smoke-suite → audit.\",\n )\n .option(\n \"--fleet <inventory>\",\n 'Inventory file (.json or .mjs/.js), or \"airtable\" to read from Websites table',\n )\n .option(\"--workdir <path>\", \"Clone target for fleet mode (default ~/.reddoor-maint/sites)\")\n .action(\n async (site, opts: { fleet?: string; workdir?: string; cwd?: string; verbose?: boolean }) =>\n runOrExit(async () => (await import(\"./commands/init.js\")).runInitCommand(site, opts), opts),\n );\n\ncli\n .command(\n \"launch <site>\",\n \"Bootstrap + first-audit a site, then draft its launch email for approval.\",\n )\n .action(async (site: string, opts: { cwd?: string; verbose?: boolean }) =>\n runOrExit(\n async () => (await import(\"./commands/launch.js\")).runLaunchCommand(site, opts),\n opts,\n ),\n );\n\ncli\n .command(\"header-image [site]\", \"Generate a site's report header image from its live homepage.\")\n .option(\"--all\", \"Every live site with no Header image yet (backfill)\")\n .option(\"--force\", \"With --all, regenerate sites that already have one\")\n .option(\"--write-airtable\", \"Upload to the Websites row instead of writing a local file\")\n .option(\"--out-dir <path>\", \"Directory for local output (default: reports/)\")\n .option(\"--settle-ms <ms>\", \"Override the post-load settle delay for slow/animated homepages\")\n .action(\n async (\n site: string | undefined,\n opts: {\n all?: boolean;\n force?: boolean;\n writeAirtable?: boolean;\n outDir?: string;\n settleMs?: string;\n cwd?: string;\n verbose?: boolean;\n },\n ) =>\n runOrExit(\n async () => (await import(\"./commands/header-image.js\")).runHeaderImageCommand(site, opts),\n opts,\n ),\n );\n\ncli\n .command(\n \"announce [site]\",\n \"Draft the monthly-report announcement email for maintenance sites (all, or one) for approval.\",\n )\n .action(async (site: string | undefined, opts: { cwd?: string; verbose?: boolean }) =>\n runOrExit(\n async () => (await import(\"./commands/announce.js\")).runAnnounceCommand(site, opts),\n opts,\n ),\n );\n\ncli\n .command(\n \"forms-notify-target [site]\",\n \"Show who a form submission would email, and optionally flip the pre-launch guard (read-back confirmed).\",\n )\n .option(\"--set <on|off>\", \"Flip the guard: on = route to operator, off = restore.\")\n .option(\"--restore <status>\", \"Status to restore with --set off. Required; never inferred.\")\n .action(\n async (\n site: string | undefined,\n opts: { set?: string; restore?: string; cwd?: string; verbose?: boolean },\n ) =>\n runOrExit(\n async () =>\n (await import(\"./commands/forms-notify-target.js\")).runFormsNotifyTargetCommand(\n site,\n opts,\n ),\n opts,\n ),\n );\n\ncli\n .command(\n \"selftest <kind> [site]\",\n \"Operator self-tests. kind=email: preview a report email for a site (or --all) to yourself.\",\n )\n .option(\"--type <type>\", \"Report type: announcement (default) | maintenance | testing | launch\")\n .option(\"--to <addr>\", \"Recipient(s), comma-separated. Default: OPERATOR_EMAIL.\")\n .option(\"--all\", \"Send a preview for every maintenance site (to --to/operator).\")\n .option(\"--dry-run\", \"Render only; write reports/<slug>/selftest-<type>.html; do not send.\")\n .action(\n async (\n kind: string,\n site: string | undefined,\n opts: {\n type?: string;\n to?: string;\n all?: boolean;\n dryRun?: boolean;\n cwd?: string;\n verbose?: boolean;\n },\n ) =>\n runOrExit(\n async () => (await import(\"./commands/selftest.js\")).runSelftestCommand(kind, site, opts),\n opts,\n ),\n );\n\ncli\n .command(\n \"preflight [site]\",\n \"Read-only pre-send checks: recipients, header image, pending drafts, schedule hygiene.\",\n )\n .option(\"--type <type>\", \"Report type: announcement (default) | maintenance | testing\")\n .option(\n \"--all\",\n \"Fleet mode: announcement→maintenance sites; maintenance/testing→all schedulable sites.\",\n )\n .action(\n async (\n site: string | undefined,\n opts: { type?: string; all?: boolean; cwd?: string; verbose?: boolean },\n ) =>\n runOrExit(\n async () => (await import(\"./commands/preflight.js\")).runPreflightCommand(site, opts),\n opts,\n ),\n );\n\ncli\n .command(\"ensure-site <slug>\", \"Create/verify the Airtable Websites row for a new site.\")\n .option(\"--name <display name>\", \"Human Name for the row (client-facing copy uses it verbatim).\")\n .option(\"--url <url>\", \"Deployed URL (e.g. the Netlify site URL).\")\n .option(\"--contact <email>\", \"point of contact — the client address reports resolve to.\")\n .option(\"--git-repo <owner/repo>\", \"GitHub identity. Default on create: reddoorla/<slug>.\")\n .action(\n async (\n slug: string,\n opts: {\n name?: string;\n url?: string;\n contact?: string;\n gitRepo?: string;\n cwd?: string;\n verbose?: boolean;\n },\n ) =>\n runOrExit(\n async () => (await import(\"./commands/ensure-site.js\")).runEnsureSiteCommand(slug, opts),\n opts,\n ),\n );\n\ncli\n .command(\n \"prospect-audit <url>\",\n \"AEO/SEO audit an external prospect's site and publish the report.\",\n )\n .option(\n \"--business <name>\",\n \"The prospect's business name (defaults to what the model reads off the site).\",\n )\n .option(\n \"--competitors <list>\",\n \"Comma-separated competitor domains to add comparison probes for.\",\n )\n .option(\n \"--goal <goal>\",\n \"What the site should get a visitor to do: book, enquire, call, visit, buy, demo or partner. Defaults to what the model reads off the site.\",\n )\n .option(\"--no-probes\", \"Skip the live AI-visibility probes (tier 3).\")\n .option(\"--out <file>\", \"Also write the rendered report to this file.\")\n .option(\"--json\", \"Print the raw result JSON instead of the report summary.\")\n .option(\n \"--email\",\n \"Email the internal sheet (scores, what wasn't measured, top fixes, the link) to PROSPECT_AUDIT_RECIPIENTS.\",\n )\n .action(\n async (\n url: string,\n opts: {\n business?: string;\n goal?: string;\n competitors?: string;\n probes?: boolean;\n out?: string;\n json?: boolean;\n email?: boolean;\n cwd?: string;\n verbose?: boolean;\n },\n ) =>\n runOrExit(\n async () =>\n (await import(\"./commands/prospect-audit.js\")).runProspectAuditCommand(url, opts),\n opts,\n ),\n );\n\ncli\n .command(\"report [site]\", \"Draft or send maintenance/testing reports.\")\n .option(\"--due\", \"Scan all Websites and draft overdue reports.\")\n .option(\"--type <type>\", \"Single-site draft report type: Maintenance (default) or Testing.\")\n .option(\n \"--preview\",\n \"Single-site dry run; writes reports/<slug>/draft.html, never touches Airtable.\",\n )\n .option(\n \"--enrich\",\n \"With --preview: also fetch GA + Search Console, so the render exercises those credentials for real. Still writes nothing.\",\n )\n .option(\n \"--send-ready\",\n \"Send all Reports with Draft ready=true AND Approved to send=true AND Sent at IS NULL.\",\n )\n .option(\n \"--digest\",\n \"Email the operator one daily digest of reports ready for approval (skips when empty).\",\n )\n .option(\n \"--rerender <reportId>\",\n \"Regenerate one UNSENT report's stored HTML from its current row, so the console preview shows edited commentary. Refuses a sent report.\",\n )\n .action(\n async (\n site,\n opts: {\n due?: boolean;\n type?: string;\n preview?: boolean;\n enrich?: boolean;\n sendReady?: boolean;\n digest?: boolean;\n rerender?: string;\n cwd?: string;\n verbose?: boolean;\n },\n ) =>\n runOrExit(\n async () => (await import(\"./commands/report.js\")).runReportCommand(site, opts),\n opts,\n ),\n );\n\ncli\n .command(\n \"github-signals\",\n \"Sweep the fleet for GitHub signals (Renovate-failing/CI/last-commit) and write Airtable.\",\n )\n .option(\"--fleet\", \"Run across every site in the Airtable inventory.\")\n .option(\"--write-airtable\", \"Write each site's signals back to its Websites row.\")\n .action(\n async (opts: { fleet?: boolean; writeAirtable?: boolean; cwd?: string; verbose?: boolean }) =>\n runOrExit(\n async () =>\n (await import(\"./commands/github-signals.js\")).runGitHubSignalsCommand({\n fleet: opts.fleet,\n writeAirtable: opts.writeAirtable,\n }),\n opts,\n ),\n );\n\ncli\n .command(\n \"protection-audit\",\n \"Verify every public org repo carries a sound branch ruleset (empty bypass, PR-required).\",\n )\n .option(\"--org <org>\", \"GitHub org to sweep (enumerated from the API, never a hand list).\")\n .action(async (opts: { org?: string; cwd?: string; verbose?: boolean }) =>\n runOrExit(\n async () =>\n (await import(\"./commands/protection-audit.js\")).runProtectionAuditCommand({\n org: opts.org,\n }),\n opts,\n ),\n );\n\ncli\n .command(\n \"db <action>\",\n \"Operate the libSQL store (migrate | replay-deadletters | import-airtable | parity | sync | backfill-header-images | backfill-digest-state | dump | verify-dump | restore | usage).\",\n )\n .option(\"--file <path>\", \"verify-dump / restore: the dump file to load\")\n .option(\n \"--org <slug>\",\n \"usage: Turso org slug (default: TURSO_ORG, else discovered from the token). The token itself comes from TURSO_FLEET_USAGE — never a flag, since argv is readable from ps.\",\n )\n .option(\n \"--url <url>\",\n \"restore: the TARGET database to load into. Required, never defaulted — a restore \" +\n \"that could fall back to the ambient TURSO_DATABASE_URL is one keystroke from \" +\n \"overwriting production.\",\n )\n .option(\n \"--force\",\n \"import-airtable / sync: run despite the freeze (#643) — a deliberate rollback-window \" +\n \"converge from the frozen Airtable shadow. Without it both refuse while Turso is \" +\n \"authoritative, because an import overwrites authoritative rows.\",\n )\n .action(\n async (\n action: string,\n opts: {\n file?: string;\n url?: string;\n org?: string;\n force?: boolean;\n cwd?: string;\n verbose?: boolean;\n },\n ) => runOrExit(async () => (await import(\"./commands/db.js\")).runDbCommand(action, opts), opts),\n );\n\ncli\n .command(\n \"submissions <action>\",\n \"Operate on stored form submissions. rescore: re-run the CURRENT spam classifier over the status='new' backlog (dry-run by default; only 'new' rows are ever touched).\",\n )\n .option(\"--dry-run\", \"Print the would-be re-buckets without writing (the default).\")\n .option(\n \"--apply\",\n \"Write the re-buckets: status → spam_auto, spam_score/spam_reason replaced with the new verdict + 'retro-rescore' marker.\",\n )\n .action(\n async (\n action: string,\n opts: { dryRun?: boolean; apply?: boolean; cwd?: string; verbose?: boolean },\n ) =>\n runOrExit(\n async () => (await import(\"./commands/submissions.js\")).runSubmissionsCommand(action, opts),\n opts,\n ),\n );\n\ncli\n .command(\n \"renovate-dispatch\",\n \"Trigger Renovate on fleet sites the security sweep flagged with critical/high vulns.\",\n )\n .option(\"--fleet\", \"Run across every active, repo-backed site in the Airtable inventory.\")\n .action(async (opts: { fleet?: boolean; cwd?: string; verbose?: boolean }) =>\n runOrExit(\n async () =>\n (await import(\"./commands/renovate-dispatch.js\")).runRenovateDispatchCommand({\n fleet: opts.fleet,\n // #539 Phase 5: mirror the auto-fix counter into site_health.\n siteMirror: await (await import(\"../db/site-mirror.js\")).makeSiteMirror(),\n }),\n opts,\n ),\n );\n\ncli\n .command(\n \"blux <action> [dir]\",\n \"Blux conversion pipeline. emit: export dir → migration plan + custom types + theme + review manifest. migrate: emitted plan → live Prismic (needs PRISMIC_REPOSITORY_NAME + PRISMIC_WRITE_TOKEN). validate: content coverage of a rendered site against the export answer key. grid: parse rendered index.html → grid-tree.json (layout tree). convert: parse+classify index.html + assemble IR → migration-plan.json + blux-presentation.json + theme.css (+ map-config.json), offline. catalog: parse each page + classify every band to a blux_section → migration-plan.json only (no sidecar), offline.\",\n )\n .option(\n \"--out <dir>\",\n \"Output directory for emit/grid/convert/catalog (default: <exportDir>/blux-out)\",\n )\n .option(\"--converted-base <url>\", \"Converted-site base URL for the review manifest\")\n .option(\"--blux-base <url>\", \"Original Blux site base URL (default: https://<site.json domain>)\")\n .option(\n \"--probe\",\n \"Reconstruct + HEAD-probe CDN URLs for used assets the HTML scrape missed (network)\",\n )\n .option(\n \"--against <target>\",\n \"validate: rendered HTML of the converted site — a file path or http(s) URL\",\n )\n .option(\n \"--site <slug>\",\n \"freeze/migrate-frozen: site slug naming <slug>.slots.json (default: slugified dir name)\",\n )\n .option(\n \"--extra-slots <path>\",\n \"freeze: JSON declaring slots the template has no token for (video poster, a panel rebuilt from a baked image). Keys must start with 'x.'\",\n )\n .action(\n async (\n action: string,\n dir: string | undefined,\n opts: {\n out?: string;\n convertedBase?: string;\n bluxBase?: string;\n probe?: boolean;\n against?: string;\n site?: string;\n extraSlots?: string;\n cwd?: string;\n verbose?: boolean;\n },\n ) =>\n runOrExit(\n async () => (await import(\"./commands/blux.js\")).runBluxCommand(action, dir, opts),\n opts,\n ),\n );\n\ncli\n .command(\n \"webflow <action> [target]\",\n \"Webflow import pipeline. capture: live-crawl a base url → <out>/ir.json, progress on stderr. docs: convert a saved ir.json → docs.json + assets.json (offline). migrate: push a capture dir's docs.json + assets.json to Prismic via the shared runner (needs PRISMIC_REPOSITORY_NAME + PRISMIC_WRITE_TOKEN).\",\n )\n .option(\n \"--out <dir>\",\n \"Output directory for capture (default: webflow-out) / docs (default: dirname of the ir.json)\",\n )\n .action(\n async (\n action: string,\n target: string | undefined,\n opts: { out?: string; cwd?: string; verbose?: boolean },\n ) =>\n runOrExit(\n async () => (await import(\"./commands/webflow.js\")).runWebflowCommand(action, target, opts),\n opts,\n ),\n );\n\ncli.help();\ncli.version(version);\n\n// A typo'd / unrecognized subcommand (e.g. `reddoor-maint auditt`) otherwise\n// falls through cac with no matched command and exits 0 — a cron/CI typo would\n// \"succeed\" silently. cac emits `command:*` at the end of parse() exactly when\n// a positional arg was given but matched no command (a bare `reddoor-maint`,\n// `--help`, and `--version` do NOT trigger it: they have no leading positional\n// or are handled before this fires). Turn that into a clear stderr error +\n// non-zero exit. process.argv[2] is the first positional, i.e. the bad command.\ncli.on(\"command:*\", () => {\n const unknown = cli.args[0] ?? process.argv[2] ?? \"\";\n console.error(\n `error: unknown command '${unknown}'. Run 'reddoor-maint --help' to see available commands.`,\n );\n process.exit(1);\n});\n\ncli.parse();\n","import { readFileSync, existsSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\n\n/**\n * Read the @reddoorla/maintenance package version, given the directory of a\n * file that lives inside the package. Walks UP looking for the first\n * `package.json` whose `name` matches. Defensive against bundling-layout\n * changes — the older \"two levels up\" assumption held for `dist/cli/bin.js`\n * but would silently mis-read (or return \"unknown\") if tsup ever moved bin\n * to a different depth. Same walk-up pattern as the self-version helper.\n *\n * Returns \"unknown\" when no matching package.json is reachable (Yarn PnP\n * setups stash manifests inside .zip caches; the readFileSync there fails\n * before any name check).\n */\nexport function resolvePackageVersion(fromDir: string): string {\n try {\n let dir = fromDir;\n while (true) {\n const candidate = join(dir, \"package.json\");\n if (existsSync(candidate)) {\n const raw = readFileSync(candidate, \"utf-8\");\n const pkg = JSON.parse(raw) as { name?: string; version?: string };\n if (pkg.name === \"@reddoorla/maintenance\") {\n return pkg.version ?? \"unknown\";\n }\n }\n const parent = dirname(dir);\n if (parent === dir) return \"unknown\";\n dir = parent;\n }\n } catch {\n return \"unknown\";\n }\n}\n"],"mappings":"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","names":["dirname","dirname"]}
1
+ {"version":3,"sources":["../../src/cli/bin.ts","../../src/cli/version.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { dirname } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { cac } from \"cac\";\nimport type { AuditName, RecipeName } from \"../types.js\";\nimport { loadCredentialsIntoEnv } from \"../util/credentials.js\";\nimport { resolvePackageVersion } from \"./version.js\";\n\n// Command modules are loaded LAZILY (dynamic `import()` inside each `.action()`),\n// never eagerly at the top. An eager `import { runReportCommand } from\n// \"./commands/report.js\"` would pull EVERY command's transitive dependency chain\n// into the CLI's startup graph — report/announce/launch drag in mjml + resend +\n// @google-analytics/data, `db` drags in the libSQL/kysely stack, etc. Those heavy\n// packages are `devDependencies` (this repo's CLI/functions/audits use them); a\n// consuming fleet site installs @reddoorla/maintenance only for `./forms` +\n// `./configs/*` and runs just `reddoor-maint audit --only a11y` in CI. Lazy\n// loading keeps that path (and `--help`/`--version`) free of the report/db\n// chains, so those packages never land in a consumer's node_modules. The\n// smoke-dist gate asserts bin.js's STATIC import closure stays free of them.\n\n// Load credentials from ~/.config/reddoor-maint/credentials.env before any\n// command runs, so AIRTABLE_PAT/AIRTABLE_BASE_ID/RESEND_API_KEY/etc. are\n// available from any cwd. Shell-exported env vars still win. Silent on\n// missing file — commands that need the credentials will fail with their\n// own clear error.\nloadCredentialsIntoEnv();\n\nconst here = dirname(fileURLToPath(import.meta.url));\nconst version = resolvePackageVersion(here);\n\nconst AUDIT_DESCRIPTIONS: Record<AuditName, string> = {\n deps: \"Diff site package.json against the bundled baseline version map.\",\n lighthouse: \"Run @lhci/cli autorun using the canonical lighthouserc.\",\n a11y: \"Playwright + axe against the canonical a11y routes.\",\n security:\n \"GitHub Dependabot alerts (prod+dev) for repo-backed sites; falls back to pnpm/npm audit (prod-deps) with no repo/token.\",\n lint: \"ESLint + Prettier using the canonical configs.\",\n domain: \"DNS resolve + TLS cert expiry against the deployed URL (checkout-free).\",\n browser:\n \"Playwright across desktop engines + mobile devices + link-check against the deployed URL (checkout-free).\",\n \"netlify-deploy\":\n \"Latest production deploy health via the Netlify API by site id (checkout-free; needs NETLIFY_PAT).\",\n \"function-health\":\n \"GET {deployedUrl}/health and read its ok/prismic/forms status (checkout-free).\",\n smoke: \"Run the site's own `pnpm test:smoke` suite in its checkout (clone-based).\",\n \"form-e2e\":\n \"Submit the real production contact form in test-mode against the deployed URL (checkout-free).\",\n};\n\nconst RECIPE_DESCRIPTIONS: Record<RecipeName, string> = {\n \"sync-configs\": \"Overwrite a site's canonical configs to match @reddoorla/maintenance.\",\n \"bump-deps\": \"Bump dependencies and commit the lockfile change.\",\n \"svelte-4-to-5\": \"Run the 7-commit Svelte 4 → 5 upgrade recipe.\",\n \"svelte-codemods\":\n \"Apply Svelte 5 gotcha codemods to an already-migrated site (state_referenced_locally, etc.).\",\n \"convert-to-pnpm\": \"Convert an npm/yarn site to pnpm (lockfile, packageManager, scripts).\",\n onboard: \"Install @reddoorla/maintenance + audit deps on a site (preferred first step).\",\n \"a11y-fixtures-page\":\n \"Write src/routes/dev/a11y-fixtures/+page.svelte (stub for lhci + axe targets).\",\n \"health-endpoint\":\n \"Write src/routes/health/+server.ts (function-health probe for the report gate).\",\n \"smoke-suite\": \"Add the smoke suite (test:smoke + playwright config + /health smoke routes).\",\n \"self-updating\":\n \"Bootstrap Renovate + repo protection (writes renovate configs via PR, wires ruleset, disables platform auto-merge; ci.yml comes from the starter and is deliberately not managed).\",\n \"prismic-ci\":\n \"Add the Prismic model delivery workflow to a site via PR (dry delta comment on PRs, push to Prismic on merge to main).\",\n \"match-harness\":\n \"Install the matching-a-page gate harness (dev-guarded /dev/match/[uid] route + matching/ scripts) for a live-reference rebuild.\",\n init: \"Run the full onboarding chain (convert-to-pnpm → onboard → sync-configs → svelte-codemods → a11y-fixtures-page → health-endpoint → smoke-suite → audit).\",\n};\n\n/** Run a command thunk and surface its result, falling back to a clean error\n * message on throw. Wraps the ~10-line try/catch every `.action()` used to\n * duplicate. `verbose` flips between full stack and message-only.\n *\n * On success it sets `process.exitCode` and RETURNS rather than calling\n * `process.exit()` right after `console.log()`. `process.exit()` does not wait\n * for stdout to flush when stdout is a pipe, so a large `--json` payload piped\n * to another process would get truncated mid-write. Setting `exitCode` and\n * returning lets Node drain stdout and exit naturally with the right code. A\n * non-zero `code` still yields a non-zero process exit.\n *\n * The error path keeps `process.exit()` — error messages are small (one line),\n * always go to stderr, and exiting immediately is the desired fail-fast. */\nexport async function runOrExit(\n fn: () => Promise<{ output: string; code: number }>,\n opts: { verbose?: boolean },\n): Promise<void> {\n try {\n const { output, code } = await fn();\n console.log(output);\n process.exitCode = code;\n return;\n } catch (err) {\n const e = err as { exitCode?: number; message?: string; stack?: string };\n console.error(opts.verbose ? (e.stack ?? e.message) : (e.message ?? String(err)));\n process.exit(e.exitCode ?? 1);\n }\n}\n\nconst cli = cac(\"reddoor-maint\");\n\ncli.option(\"--cwd <path>\", \"Override working directory (default: process.cwd())\");\ncli.option(\"--verbose\", \"Verbose output (full stack on errors)\");\n\ncli.command(\"list-audits\", \"Print the available audits.\").action(() => {\n for (const [name, desc] of Object.entries(AUDIT_DESCRIPTIONS)) {\n console.log(`${name.padEnd(12)} ${desc}`);\n }\n});\n\ncli.command(\"list-recipes\", \"Print the available recipes.\").action(() => {\n for (const [name, desc] of Object.entries(RECIPE_DESCRIPTIONS)) {\n console.log(`${name.padEnd(16)} ${desc}`);\n }\n});\n\ncli\n .command(\"audit [site]\", \"Run audits against a site (default: cwd).\")\n .option(\"--only <names>\", \"Comma-separated audit names (e.g. deps,lighthouse)\")\n .option(\"--json\", \"Machine-readable JSON output\")\n .option(\n \"--fleet <inventory>\",\n 'Inventory file (.json or .mjs/.js), or \"airtable\" to read from Websites table',\n )\n .option(\"--workdir <path>\", \"Clone target for fleet mode (default ~/.reddoor-maint/sites)\")\n .option(\n \"--write-airtable [slug]\",\n \"After lighthouse runs, write pScore/rScore/bpScore/seoScore + timestamp to the matching Websites row. Slug defaults to cwd's package.json#name.\",\n )\n .option(\"--fail-on-violations\", \"Exit non-zero if any a11y violations are found (for CI gates)\")\n .option(\n \"--url <url>\",\n \"Audit this deployed URL with lighthouse (no dev server); single-site. Pair with --only lighthouse — other audits still use the local checkout.\",\n )\n .option(\n \"--concurrency <n>\",\n \"Max sites to audit in parallel in --fleet mode (default: all at once). Use 1 for sequential (CI).\",\n )\n .action(\n async (\n site,\n opts: {\n only?: string;\n json?: boolean;\n fleet?: string;\n workdir?: string;\n cwd?: string;\n verbose?: boolean;\n writeAirtable?: string | boolean;\n failOnViolations?: boolean;\n url?: string;\n concurrency?: string;\n },\n ) =>\n runOrExit(\n async () => (await import(\"./commands/audit.js\")).runAuditCommand(site, opts),\n opts,\n ),\n );\n\ncli\n .command(\"sync-configs [site]\", \"Sync canonical configs into a site.\")\n .option(\"--only <names>\", \"Comma-separated config names (e.g. eslint,prettier)\")\n .option(\"--dry\", \"Print diff without writing\")\n .option(\n \"--fleet <inventory>\",\n 'Inventory file (.json or .mjs/.js), or \"airtable\" to read from Websites table',\n )\n .option(\"--workdir <path>\", \"Clone target for fleet mode (default ~/.reddoor-maint/sites)\")\n .action(\n async (\n site,\n opts: {\n only?: string;\n dry?: boolean;\n fleet?: string;\n workdir?: string;\n cwd?: string;\n verbose?: boolean;\n },\n ) =>\n runOrExit(\n async () => (await import(\"./commands/sync-configs.js\")).runSyncConfigsCommand(site, opts),\n opts,\n ),\n );\n\ncli\n .command(\"bump-deps [site]\", \"Bump dependencies.\")\n .option(\"--group <group>\", \"patch | minor | major\", { default: \"minor\" })\n .option(\n \"--fleet <inventory>\",\n 'Inventory file (.json or .mjs/.js), or \"airtable\" to read from Websites table',\n )\n .option(\"--workdir <path>\", \"Clone target for fleet mode (default ~/.reddoor-maint/sites)\")\n .action(\n async (\n site,\n opts: {\n group?: string;\n fleet?: string;\n workdir?: string;\n cwd?: string;\n verbose?: boolean;\n },\n ) =>\n runOrExit(\n async () => (await import(\"./commands/bump-deps.js\")).runBumpDepsCommand(site, opts),\n opts,\n ),\n );\n\ncli\n .command(\n \"self-updating [site]\",\n \"Bootstrap a repo to keep itself updated (Renovate + protection; platform auto-merge off; ci.yml is the starter's, not managed here).\",\n )\n .option(\"--dry\", \"List what would be enabled without writing or opening PRs\")\n .option(\"--fleet <inventory>\", 'Inventory file (.json or .mjs/.js), or \"airtable\"')\n .option(\"--workdir <path>\", \"Clone target for fleet mode (default ~/.reddoor-maint/sites)\")\n .action(\n async (\n site,\n opts: {\n dry?: boolean;\n fleet?: string;\n workdir?: string;\n cwd?: string;\n verbose?: boolean;\n },\n ) =>\n runOrExit(\n async () =>\n (await import(\"./commands/self-updating.js\")).runSelfUpdatingCommand(site, opts),\n opts,\n ),\n );\n\n// Fleet-wide, this opens ONE PULL REQUEST PER REPOSITORY and never pushes to a\n// client's main. `--dry` exists because that is the only way to see the blast\n// radius before firing it. Both directions of the flag ↔ option link are pinned\n// by tests/cli/prismic-ci-command.test.ts.\ncli\n .command(\n \"prismic-ci [site]\",\n \"Add the Prismic model delivery workflow to a site via PR (one PR per repo; never pushes to main).\",\n )\n .option(\"--dry\", \"List the sites that would be offered the workflow, without opening any PR\")\n .option(\"--fleet <inventory>\", 'Inventory file (.json or .mjs/.js), or \"airtable\"')\n .option(\"--workdir <path>\", \"Clone target for fleet mode (default ~/.reddoor-maint/sites)\")\n .action(\n async (\n site,\n opts: {\n dry?: boolean;\n fleet?: string;\n workdir?: string;\n cwd?: string;\n verbose?: boolean;\n },\n ) =>\n runOrExit(\n async () => (await import(\"./commands/prismic-ci.js\")).runPrismicCiCommand(site, opts),\n opts,\n ),\n );\n\n// EVERY flag below must be one the command actually reads, and every option the\n// command reads must appear below. cac rejects an unknown option outright, so a\n// missing line here is a hard error in whatever workflow types the flag; a line\n// here with no handler is the silent no-op — it parses, it lands in `opts`, and\n// nothing ever looks at it. Both directions are pinned by\n// tests/cli/prismic-models-registration.test.ts, the second one at the type level\n// against `PrismicModelsCommandOptions`.\ncli\n .command(\n \"prismic-models [site]\",\n \"Compare a site's Prismic models against its repo (dry by default).\",\n )\n .option(\n \"--apply\",\n \"Push local models to Prismic. Never deletes — remote-only models are reported.\",\n )\n .option(\"--pull\", \"Write remote-only models into the repo (single-site; review + PR the result).\")\n .option(\"--tokens\", \"Print the per-site write-token doctor: which env var, present?, reads?\")\n .option(\"--fleet <inventory>\", 'Inventory file (.json or .mjs/.js), or \"airtable\". Read-only.')\n .option(\"--workdir <path>\", \"Clone target for fleet mode (default ~/.reddoor-maint/sites)\")\n .option(\"--write-airtable\", \"Fleet mode: persist each site's verdict to its Websites row\")\n .option(\n \"--comment-file <path>\",\n \"Write the report to this file (the CI workflow posts it as a PR comment)\",\n )\n .action(\n async (\n site,\n opts: {\n apply?: boolean;\n pull?: boolean;\n tokens?: boolean;\n fleet?: string;\n workdir?: string;\n writeAirtable?: boolean;\n commentFile?: string;\n cwd?: string;\n verbose?: boolean;\n },\n ) =>\n runOrExit(\n async () =>\n (await import(\"./commands/prismic-models.js\")).runPrismicModelsCommand(site, opts),\n opts,\n ),\n );\n\ncli\n .command(\"upgrade <upgrade> [site]\", \"Run a named upgrade recipe (svelte-4-to-5).\")\n .example(\"reddoor-maint upgrade svelte-4-to-5 ./my-site\")\n .option(\n \"--fleet <inventory>\",\n 'Inventory file (.json or .mjs/.js), or \"airtable\" to read from Websites table',\n )\n .option(\"--workdir <path>\", \"Clone target for fleet mode (default ~/.reddoor-maint/sites)\")\n .action(\n async (\n upgrade: string,\n site: string | undefined,\n opts: { fleet?: string; workdir?: string; cwd?: string; verbose?: boolean },\n ) =>\n runOrExit(\n async () => (await import(\"./commands/upgrade.js\")).runUpgradeCommand(upgrade, site, opts),\n opts,\n ),\n );\n\ncli\n .command(\n \"convert-to-pnpm [site]\",\n \"Convert an npm/yarn site to pnpm (lockfile, packageManager, scripts).\",\n )\n .option(\n \"--fleet <inventory>\",\n 'Inventory file (.json or .mjs/.js), or \"airtable\" to read from Websites table',\n )\n .option(\"--workdir <path>\", \"Clone target for fleet mode (default ~/.reddoor-maint/sites)\")\n .action(\n async (site, opts: { fleet?: string; workdir?: string; cwd?: string; verbose?: boolean }) =>\n runOrExit(\n async () =>\n (await import(\"./commands/convert-to-pnpm.js\")).runConvertToPnpmCommand(site, opts),\n opts,\n ),\n );\n\ncli\n .command(\"svelte-codemods [site]\", \"Apply Svelte 5 gotcha codemods to an already-migrated site.\")\n .option(\n \"--fleet <inventory>\",\n 'Inventory file (.json or .mjs/.js), or \"airtable\" to read from Websites table',\n )\n .option(\"--workdir <path>\", \"Clone target for fleet mode (default ~/.reddoor-maint/sites)\")\n .action(\n async (site, opts: { fleet?: string; workdir?: string; cwd?: string; verbose?: boolean }) =>\n runOrExit(\n async () =>\n (await import(\"./commands/svelte-codemods.js\")).runSvelteCodemodsCommand(site, opts),\n opts,\n ),\n );\n\ncli\n .command(\n \"health-endpoint [site]\",\n \"Write src/routes/health/+server.ts (function-health probe for the report gate).\",\n )\n .option(\n \"--fleet <inventory>\",\n 'Inventory file (.json or .mjs/.js), or \"airtable\" to read from Websites table',\n )\n .option(\"--workdir <path>\", \"Clone target for fleet mode (default ~/.reddoor-maint/sites)\")\n .action(\n async (site, opts: { fleet?: string; workdir?: string; cwd?: string; verbose?: boolean }) =>\n runOrExit(\n async () =>\n (await import(\"./commands/health-endpoint.js\")).runHealthEndpointCommand(site, opts),\n opts,\n ),\n );\n\ncli\n .command(\n \"match-harness [site]\",\n \"Install the matching-a-page gate harness (dev-guarded /dev/match/[uid] route + matching/ scripts) for a live-reference rebuild.\",\n )\n .option(\"--ref <url>\", \"Reference (live) site URL the harness gates against — required\")\n .option(\"--cand <url>\", \"Candidate origin (default http://localhost:5173)\")\n .option(\"--matrix <list>\", \"Breakpoint matrix, comma-separated (default 1440,834,390)\")\n .option(\n \"--fleet <inventory>\",\n 'Inventory file (.json or .mjs/.js), or \"airtable\" to read from Websites table',\n )\n .option(\"--workdir <path>\", \"Clone target for fleet mode (default ~/.reddoor-maint/sites)\")\n .action(\n async (\n site,\n opts: {\n ref?: string;\n cand?: string;\n matrix?: string | number;\n fleet?: string;\n workdir?: string;\n cwd?: string;\n verbose?: boolean;\n },\n ) =>\n runOrExit(\n async () =>\n (await import(\"./commands/match-harness.js\")).runMatchHarnessCommand(site, opts),\n opts,\n ),\n );\n\ncli\n .command(\n \"smoke-suite [site]\",\n \"Add the smoke suite (test:smoke + playwright config + /health smoke routes).\",\n )\n .option(\n \"--fleet <inventory>\",\n 'Inventory file (.json or .mjs/.js), or \"airtable\" to read from Websites table',\n )\n .option(\"--workdir <path>\", \"Clone target for fleet mode (default ~/.reddoor-maint/sites)\")\n .action(\n async (site, opts: { fleet?: string; workdir?: string; cwd?: string; verbose?: boolean }) =>\n runOrExit(\n async () => (await import(\"./commands/smoke-suite.js\")).runSmokeSuiteCommand(site, opts),\n opts,\n ),\n );\n\ncli\n .command(\n \"onboard [site]\",\n \"Install @reddoorla/maintenance + audit deps on a site (run after convert-to-pnpm).\",\n )\n .option(\"--audits <names>\", \"Comma-separated audit subset: lighthouse,a11y (default: both)\")\n .option(\n \"--fleet <inventory>\",\n 'Inventory file (.json or .mjs/.js), or \"airtable\" to read from Websites table',\n )\n .option(\"--workdir <path>\", \"Clone target for fleet mode (default ~/.reddoor-maint/sites)\")\n .action(\n async (\n site,\n opts: {\n audits?: string;\n fleet?: string;\n workdir?: string;\n cwd?: string;\n verbose?: boolean;\n },\n ) =>\n runOrExit(\n async () => (await import(\"./commands/onboard.js\")).runOnboardCommand(site, opts),\n opts,\n ),\n );\n\ncli\n .command(\n \"init [site]\",\n \"One-shot guided onboarding: convert-to-pnpm → onboard → sync-configs → svelte-codemods → a11y-fixtures-page → health-endpoint → smoke-suite → audit.\",\n )\n .option(\n \"--fleet <inventory>\",\n 'Inventory file (.json or .mjs/.js), or \"airtable\" to read from Websites table',\n )\n .option(\"--workdir <path>\", \"Clone target for fleet mode (default ~/.reddoor-maint/sites)\")\n .action(\n async (site, opts: { fleet?: string; workdir?: string; cwd?: string; verbose?: boolean }) =>\n runOrExit(async () => (await import(\"./commands/init.js\")).runInitCommand(site, opts), opts),\n );\n\ncli\n .command(\n \"launch <site>\",\n \"Bootstrap + first-audit a site, then draft its launch email for approval.\",\n )\n .action(async (site: string, opts: { cwd?: string; verbose?: boolean }) =>\n runOrExit(\n async () => (await import(\"./commands/launch.js\")).runLaunchCommand(site, opts),\n opts,\n ),\n );\n\ncli\n .command(\"header-image [site]\", \"Generate a site's report header image from its live homepage.\")\n .option(\"--all\", \"Every live site with no Header image yet (backfill)\")\n .option(\"--force\", \"With --all, regenerate sites that already have one\")\n .option(\"--write-airtable\", \"Upload to the Websites row instead of writing a local file\")\n .option(\"--out-dir <path>\", \"Directory for local output (default: reports/)\")\n .option(\"--settle-ms <ms>\", \"Override the post-load settle delay for slow/animated homepages\")\n .action(\n async (\n site: string | undefined,\n opts: {\n all?: boolean;\n force?: boolean;\n writeAirtable?: boolean;\n outDir?: string;\n settleMs?: string;\n cwd?: string;\n verbose?: boolean;\n },\n ) =>\n runOrExit(\n async () => (await import(\"./commands/header-image.js\")).runHeaderImageCommand(site, opts),\n opts,\n ),\n );\n\ncli\n .command(\n \"announce [site]\",\n \"Draft the monthly-report announcement email for maintenance sites (all, or one) for approval.\",\n )\n .action(async (site: string | undefined, opts: { cwd?: string; verbose?: boolean }) =>\n runOrExit(\n async () => (await import(\"./commands/announce.js\")).runAnnounceCommand(site, opts),\n opts,\n ),\n );\n\ncli\n .command(\n \"forms-notify-target [site]\",\n \"Show who a form submission would email, and optionally flip the pre-launch guard (read-back confirmed).\",\n )\n .option(\"--set <on|off>\", \"Flip the guard: on = route to operator, off = restore.\")\n .option(\"--restore <status>\", \"Status to restore with --set off. Required; never inferred.\")\n .action(\n async (\n site: string | undefined,\n opts: { set?: string; restore?: string; cwd?: string; verbose?: boolean },\n ) =>\n runOrExit(\n async () =>\n (await import(\"./commands/forms-notify-target.js\")).runFormsNotifyTargetCommand(\n site,\n opts,\n ),\n opts,\n ),\n );\n\ncli\n .command(\n \"selftest <kind> [site]\",\n \"Operator self-tests. kind=email: preview a report email for a site (or --all) to yourself.\",\n )\n .option(\"--type <type>\", \"Report type: announcement (default) | maintenance | testing | launch\")\n .option(\"--to <addr>\", \"Recipient(s), comma-separated. Default: OPERATOR_EMAIL.\")\n .option(\"--all\", \"Send a preview for every maintenance site (to --to/operator).\")\n .option(\"--dry-run\", \"Render only; write reports/<slug>/selftest-<type>.html; do not send.\")\n .action(\n async (\n kind: string,\n site: string | undefined,\n opts: {\n type?: string;\n to?: string;\n all?: boolean;\n dryRun?: boolean;\n cwd?: string;\n verbose?: boolean;\n },\n ) =>\n runOrExit(\n async () => (await import(\"./commands/selftest.js\")).runSelftestCommand(kind, site, opts),\n opts,\n ),\n );\n\ncli\n .command(\n \"preflight [site]\",\n \"Read-only pre-send checks: recipients, header image, pending drafts, schedule hygiene.\",\n )\n .option(\"--type <type>\", \"Report type: announcement (default) | maintenance | testing\")\n .option(\n \"--all\",\n \"Fleet mode: announcement→maintenance sites; maintenance/testing→all schedulable sites.\",\n )\n .action(\n async (\n site: string | undefined,\n opts: { type?: string; all?: boolean; cwd?: string; verbose?: boolean },\n ) =>\n runOrExit(\n async () => (await import(\"./commands/preflight.js\")).runPreflightCommand(site, opts),\n opts,\n ),\n );\n\ncli\n .command(\"ensure-site <slug>\", \"Create/verify the Airtable Websites row for a new site.\")\n .option(\"--name <display name>\", \"Human Name for the row (client-facing copy uses it verbatim).\")\n .option(\"--url <url>\", \"Deployed URL (e.g. the Netlify site URL).\")\n .option(\"--contact <email>\", \"point of contact — the client address reports resolve to.\")\n .option(\"--git-repo <owner/repo>\", \"GitHub identity. Default on create: reddoorla/<slug>.\")\n .action(\n async (\n slug: string,\n opts: {\n name?: string;\n url?: string;\n contact?: string;\n gitRepo?: string;\n cwd?: string;\n verbose?: boolean;\n },\n ) =>\n runOrExit(\n async () => (await import(\"./commands/ensure-site.js\")).runEnsureSiteCommand(slug, opts),\n opts,\n ),\n );\n\ncli\n .command(\n \"prospect-audit <url>\",\n \"AEO/SEO audit an external prospect's site and publish the report.\",\n )\n .option(\n \"--business <name>\",\n \"The prospect's business name (defaults to what the model reads off the site).\",\n )\n .option(\n \"--competitors <list>\",\n \"Comma-separated competitor domains to add comparison probes for.\",\n )\n .option(\n \"--goal <goal>\",\n \"What the site should get a visitor to do: book, enquire, call, visit, buy, demo or partner. Defaults to what the model reads off the site.\",\n )\n .option(\"--no-probes\", \"Skip the live AI-visibility probes (tier 3).\")\n .option(\"--out <file>\", \"Also write the rendered report to this file.\")\n .option(\"--json\", \"Print the raw result JSON instead of the report summary.\")\n .option(\n \"--email\",\n \"Email the internal sheet (scores, what wasn't measured, top fixes, the link) to PROSPECT_AUDIT_RECIPIENTS.\",\n )\n .action(\n async (\n url: string,\n opts: {\n business?: string;\n goal?: string;\n competitors?: string;\n probes?: boolean;\n out?: string;\n json?: boolean;\n email?: boolean;\n cwd?: string;\n verbose?: boolean;\n },\n ) =>\n runOrExit(\n async () =>\n (await import(\"./commands/prospect-audit.js\")).runProspectAuditCommand(url, opts),\n opts,\n ),\n );\n\ncli\n .command(\"report [site]\", \"Draft or send maintenance/testing reports.\")\n .option(\"--due\", \"Scan all Websites and draft overdue reports.\")\n .option(\"--type <type>\", \"Single-site draft report type: Maintenance (default) or Testing.\")\n .option(\n \"--preview\",\n \"Single-site dry run; writes reports/<slug>/draft.html, never touches Airtable.\",\n )\n .option(\n \"--enrich\",\n \"With --preview: also fetch GA + Search Console, so the render exercises those credentials for real. Still writes nothing.\",\n )\n .option(\n \"--send-ready\",\n \"Send all Reports with Draft ready=true AND Approved to send=true AND Sent at IS NULL.\",\n )\n .option(\n \"--digest\",\n \"Email the operator one daily digest of reports ready for approval (skips when empty).\",\n )\n .option(\n \"--rerender <reportId>\",\n \"Regenerate one UNSENT report's stored HTML from its current row, so the console preview shows edited commentary. Refuses a sent report.\",\n )\n .action(\n async (\n site,\n opts: {\n due?: boolean;\n type?: string;\n preview?: boolean;\n enrich?: boolean;\n sendReady?: boolean;\n digest?: boolean;\n rerender?: string;\n cwd?: string;\n verbose?: boolean;\n },\n ) =>\n runOrExit(\n async () => (await import(\"./commands/report.js\")).runReportCommand(site, opts),\n opts,\n ),\n );\n\ncli\n .command(\n \"github-signals\",\n \"Sweep the fleet for GitHub signals (Renovate-failing/CI/last-commit) and write Airtable.\",\n )\n .option(\"--fleet\", \"Run across every site in the Airtable inventory.\")\n .option(\"--write-airtable\", \"Write each site's signals back to its Websites row.\")\n .action(\n async (opts: { fleet?: boolean; writeAirtable?: boolean; cwd?: string; verbose?: boolean }) =>\n runOrExit(\n async () =>\n (await import(\"./commands/github-signals.js\")).runGitHubSignalsCommand({\n fleet: opts.fleet,\n writeAirtable: opts.writeAirtable,\n }),\n opts,\n ),\n );\n\ncli\n .command(\n \"protection-audit\",\n \"Verify every public org repo carries a sound branch ruleset (empty bypass, PR-required).\",\n )\n .option(\"--org <org>\", \"GitHub org to sweep (enumerated from the API, never a hand list).\")\n .action(async (opts: { org?: string; cwd?: string; verbose?: boolean }) =>\n runOrExit(\n async () =>\n (await import(\"./commands/protection-audit.js\")).runProtectionAuditCommand({\n org: opts.org,\n }),\n opts,\n ),\n );\n\ncli\n .command(\n \"db <action>\",\n \"Operate the libSQL store (migrate | replay-deadletters | import-airtable | parity | sync | backfill-header-images | backfill-digest-state | dump | verify-dump | restore | usage).\",\n )\n .option(\"--file <path>\", \"verify-dump / restore: the dump file to load\")\n .option(\n \"--org <slug>\",\n \"usage: Turso org slug (default: TURSO_ORG, else discovered from the token). The token itself comes from TURSO_FLEET_USAGE — never a flag, since argv is readable from ps.\",\n )\n .option(\n \"--url <url>\",\n \"restore: the TARGET database to load into. Required, never defaulted — a restore \" +\n \"that could fall back to the ambient TURSO_DATABASE_URL is one keystroke from \" +\n \"overwriting production.\",\n )\n .option(\n \"--force\",\n \"import-airtable / sync: run despite the freeze (#643) — a deliberate rollback-window \" +\n \"converge from the frozen Airtable shadow. Without it both refuse while Turso is \" +\n \"authoritative, because an import overwrites authoritative rows.\",\n )\n .action(\n async (\n action: string,\n opts: {\n file?: string;\n url?: string;\n org?: string;\n force?: boolean;\n cwd?: string;\n verbose?: boolean;\n },\n ) => runOrExit(async () => (await import(\"./commands/db.js\")).runDbCommand(action, opts), opts),\n );\n\ncli\n .command(\n \"submissions <action>\",\n \"Operate on stored form submissions. rescore: re-run the CURRENT spam classifier over the status='new' backlog (dry-run by default; only 'new' rows are ever touched).\",\n )\n .option(\"--dry-run\", \"Print the would-be re-buckets without writing (the default).\")\n .option(\n \"--apply\",\n \"Write the re-buckets: status → spam_auto, spam_score/spam_reason replaced with the new verdict + 'retro-rescore' marker.\",\n )\n .action(\n async (\n action: string,\n opts: { dryRun?: boolean; apply?: boolean; cwd?: string; verbose?: boolean },\n ) =>\n runOrExit(\n async () => (await import(\"./commands/submissions.js\")).runSubmissionsCommand(action, opts),\n opts,\n ),\n );\n\ncli\n .command(\n \"renovate-dispatch\",\n \"Trigger Renovate on fleet sites the security sweep flagged with critical/high vulns.\",\n )\n .option(\"--fleet\", \"Run across every active, repo-backed site in the Airtable inventory.\")\n .action(async (opts: { fleet?: boolean; cwd?: string; verbose?: boolean }) =>\n runOrExit(\n async () =>\n (await import(\"./commands/renovate-dispatch.js\")).runRenovateDispatchCommand({\n fleet: opts.fleet,\n // #539 Phase 5: mirror the auto-fix counter into site_health.\n siteMirror: await (await import(\"../db/site-mirror.js\")).makeSiteMirror(),\n }),\n opts,\n ),\n );\n\ncli\n .command(\n \"blux <action> [dir]\",\n \"Blux conversion pipeline. emit: export dir → migration plan + custom types + theme + review manifest. migrate: emitted plan → live Prismic (needs PRISMIC_REPOSITORY_NAME + PRISMIC_WRITE_TOKEN). validate: content coverage of a rendered site against the export answer key. grid: parse rendered index.html → grid-tree.json (layout tree). convert: parse+classify index.html + assemble IR → migration-plan.json + blux-presentation.json + theme.css (+ map-config.json), offline. catalog: parse each page + classify every band to a blux_section → migration-plan.json only (no sidecar), offline.\",\n )\n .option(\n \"--out <dir>\",\n \"Output directory for emit/grid/convert/catalog (default: <exportDir>/blux-out)\",\n )\n .option(\"--converted-base <url>\", \"Converted-site base URL for the review manifest\")\n .option(\"--blux-base <url>\", \"Original Blux site base URL (default: https://<site.json domain>)\")\n .option(\n \"--probe\",\n \"Reconstruct + HEAD-probe CDN URLs for used assets the HTML scrape missed (network)\",\n )\n .option(\n \"--against <target>\",\n \"validate: rendered HTML of the converted site — a file path or http(s) URL\",\n )\n .option(\n \"--site <slug>\",\n \"freeze/migrate-frozen: site slug naming <slug>.slots.json (default: slugified dir name)\",\n )\n .option(\n \"--extra-slots <path>\",\n \"freeze: JSON declaring slots the template has no token for (video poster, a panel rebuilt from a baked image). Keys must start with 'x.'\",\n )\n .action(\n async (\n action: string,\n dir: string | undefined,\n opts: {\n out?: string;\n convertedBase?: string;\n bluxBase?: string;\n probe?: boolean;\n against?: string;\n site?: string;\n extraSlots?: string;\n cwd?: string;\n verbose?: boolean;\n },\n ) =>\n runOrExit(\n async () => (await import(\"./commands/blux.js\")).runBluxCommand(action, dir, opts),\n opts,\n ),\n );\n\ncli\n .command(\n \"webflow <action> [target]\",\n \"Webflow import pipeline. capture: live-crawl a base url → <out>/ir.json, progress on stderr. docs: convert a saved ir.json → docs.json + assets.json (offline). migrate: push a capture dir's docs.json + assets.json to Prismic via the shared runner (needs PRISMIC_REPOSITORY_NAME + PRISMIC_WRITE_TOKEN).\",\n )\n .option(\n \"--out <dir>\",\n \"Output directory for capture (default: webflow-out) / docs (default: dirname of the ir.json)\",\n )\n .action(\n async (\n action: string,\n target: string | undefined,\n opts: { out?: string; cwd?: string; verbose?: boolean },\n ) =>\n runOrExit(\n async () => (await import(\"./commands/webflow.js\")).runWebflowCommand(action, target, opts),\n opts,\n ),\n );\n\ncli.help();\ncli.version(version);\n\n// A typo'd / unrecognized subcommand (e.g. `reddoor-maint auditt`) otherwise\n// falls through cac with no matched command and exits 0 — a cron/CI typo would\n// \"succeed\" silently. cac emits `command:*` at the end of parse() exactly when\n// a positional arg was given but matched no command (a bare `reddoor-maint`,\n// `--help`, and `--version` do NOT trigger it: they have no leading positional\n// or are handled before this fires). Turn that into a clear stderr error +\n// non-zero exit. process.argv[2] is the first positional, i.e. the bad command.\ncli.on(\"command:*\", () => {\n const unknown = cli.args[0] ?? process.argv[2] ?? \"\";\n console.error(\n `error: unknown command '${unknown}'. Run 'reddoor-maint --help' to see available commands.`,\n );\n process.exit(1);\n});\n\ncli.parse();\n","import { readFileSync, existsSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\n\n/**\n * Read the @reddoorla/maintenance package version, given the directory of a\n * file that lives inside the package. Walks UP looking for the first\n * `package.json` whose `name` matches. Defensive against bundling-layout\n * changes — the older \"two levels up\" assumption held for `dist/cli/bin.js`\n * but would silently mis-read (or return \"unknown\") if tsup ever moved bin\n * to a different depth. Same walk-up pattern as the self-version helper.\n *\n * Returns \"unknown\" when no matching package.json is reachable (Yarn PnP\n * setups stash manifests inside .zip caches; the readFileSync there fails\n * before any name check).\n */\nexport function resolvePackageVersion(fromDir: string): string {\n try {\n let dir = fromDir;\n while (true) {\n const candidate = join(dir, \"package.json\");\n if (existsSync(candidate)) {\n const raw = readFileSync(candidate, \"utf-8\");\n const pkg = JSON.parse(raw) as { name?: string; version?: string };\n if (pkg.name === \"@reddoorla/maintenance\") {\n return pkg.version ?? \"unknown\";\n }\n }\n const parent = dirname(dir);\n if (parent === dir) return \"unknown\";\n dir = parent;\n }\n } catch {\n return \"unknown\";\n }\n}\n"],"mappings":"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","names":["dirname","dirname"]}
@@ -1,4 +1,4 @@
1
- import { S as Site, a as AuditResult, A as AuditName } from '../../types-OIQZ5hWN.js';
1
+ import { S as Site, a as AuditResult, A as AuditName } from '../../types-D_bpy89i.js';
2
2
  import { A as AirtableBase, F as FleetEvent } from '../../fleet-events-cF2Om88w.js';
3
3
  import 'airtable/lib/airtable_base.js';
4
4
 
@@ -5,7 +5,7 @@ import {
5
5
  fleetWorkdir,
6
6
  formatSkippedNotice,
7
7
  prepareFleetSites
8
- } from "../../chunk-TCF6S7AD.js";
8
+ } from "../../chunk-LM2NHRCJ.js";
9
9
  import {
10
10
  resolveSites
11
11
  } from "../../chunk-Z2K4JPQ3.js";
@@ -19,20 +19,20 @@ import "../../chunk-XHHMM5HX.js";
19
19
  import "../../chunk-Z3JXLULD.js";
20
20
  import {
21
21
  recordFleetEventsBestEffort
22
- } from "../../chunk-DMPHP7UP.js";
23
- import "../../chunk-22GKJO5F.js";
24
- import "../../chunk-OCNSIBMP.js";
22
+ } from "../../chunk-BI2VI6EM.js";
23
+ import "../../chunk-VSGMCCGQ.js";
24
+ import "../../chunk-C3IQQKXL.js";
25
25
  import "../../chunk-2NQUCS7O.js";
26
26
  import "../../chunk-UDRHAQT7.js";
27
27
  import "../../chunk-PTDMVGKL.js";
28
28
  import "../../chunk-LBYOLBW7.js";
29
29
  import "../../chunk-A3WDWNN5.js";
30
30
  import "../../chunk-2OP4JKIQ.js";
31
- import "../../chunk-XXTZBPUY.js";
32
31
  import {
33
32
  isHttpUrl
34
33
  } from "../../chunk-RARREDQE.js";
35
- import "../../chunk-XTK5VIQB.js";
34
+ import "../../chunk-XXTZBPUY.js";
35
+ import "../../chunk-AVEQUR44.js";
36
36
  import "../../chunk-6VAL7XJT.js";
37
37
  import "../../chunk-NMAWXBJA.js";
38
38
  import "../../chunk-YLYXW5PH.js";
@@ -267,7 +267,7 @@ ${wb.summary}`;
267
267
  task.output = "writing scores\u2026";
268
268
  writeSummary = await writeAuditsToAirtable({ base, websites, slug, results });
269
269
  if (writeSummary.siteId && writeSummary.fields) {
270
- const { makeSiteMirror } = await import("../../site-mirror-UKHREAD6.js");
270
+ const { makeSiteMirror } = await import("../../site-mirror-WON4FTJ2.js");
271
271
  await (await makeSiteMirror()).health(writeSummary.siteId, writeSummary.fields);
272
272
  }
273
273
  task.title = `Wrote to Websites[${writeSummary.siteName}] (${writeSummary.writes.length} audit type${writeSummary.writes.length === 1 ? "" : "s"})`;
@@ -304,7 +304,7 @@ async function runFleetWriteBack(args) {
304
304
  const { listWebsites } = await import("../../websites-TB4TCAWM.js");
305
305
  const websites = await listWebsites(base);
306
306
  const makeMirror = deps.makeMirror ?? (async () => {
307
- const { makeHealthMirrorBestEffort } = await import("../../health-mirror-EB76EERV.js");
307
+ const { makeHealthMirrorBestEffort } = await import("../../health-mirror-XJAKA3EY.js");
308
308
  return makeHealthMirrorBestEffort();
309
309
  });
310
310
  const mirror = await makeMirror();
@@ -0,0 +1,11 @@
1
+ import {
2
+ openDb,
3
+ readDbConfig
4
+ } from "./chunk-VSGMCCGQ.js";
5
+ import "./chunk-C3IQQKXL.js";
6
+ import "./chunk-6VAL7XJT.js";
7
+ export {
8
+ openDb,
9
+ readDbConfig
10
+ };
11
+ //# sourceMappingURL=client-G2WGWPCA.js.map
@@ -68,7 +68,33 @@ function createEslintConfig(opts) {
68
68
  // Agency process artifacts: git-ignored in every repo, but present on
69
69
  // disk locally, so `pnpm lint` would otherwise try to parse them.
70
70
  "docs/superpowers/",
71
- "scratchpad/"
71
+ "scratchpad/",
72
+ // Third member of that class: the match-harness Phase 0 reference
73
+ // capture. `matching/capture-reference.mjs` downloads the live site's
74
+ // own HTML/CSS/JS byte-for-byte into a fixed `matching/spec` (line 31,
75
+ // `const OUT = "matching/spec"` — a const, not configurable), so eslint
76
+ // gets handed third-party minified bundles. Measured on 29 Navy's first
77
+ // capture: 745 errors, `pnpm verify` red — Webflow's two chunks 377 and
78
+ // 78, jQuery 3.5.1 290.
79
+ //
80
+ // `prettier --check .` survives the same files, but only by accident of
81
+ // prettier 3 defaulting --ignore-path to `.gitignore`, which the recipe's
82
+ // block fills with `matching/*`. Eslint flat config reads no ignore file
83
+ // at all, and `.prettierignore` does NOT list the capture: measured,
84
+ // `prettier --check matching/spec --ignore-path .prettierignore` flags
85
+ // five files. That asymmetry is the whole bug.
86
+ //
87
+ // SCOPED TO `matching/spec/`, deliberately NOT `matching/`. The probes,
88
+ // gate scripts and site records under `matching/` are ours and must stay
89
+ // linted — beachfront-dentistry ignores `matching/` wholesale and has
90
+ // un-linted its own `adv-verify-svc*.mjs` that way. The narrowness cuts
91
+ // both ways: `matching/spec*` also swallows the TRACKED
92
+ // `matching/spec-sections/`.
93
+ "matching/spec/",
94
+ // Same class, same generated .gitignore block: the harness's scratch
95
+ // diff workspace. Included on class grounds, NOT on a reproduced signal
96
+ // — nothing in the harness writes it and no clone has one on disk.
97
+ "scratch-diff*/"
72
98
  ]
73
99
  }
74
100
  ];
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/configs/eslint.ts"],"sourcesContent":["import js from \"@eslint/js\";\nimport ts from \"typescript-eslint\";\nimport svelte from \"eslint-plugin-svelte\";\nimport prettier from \"eslint-config-prettier\";\nimport globals from \"globals\";\nimport type { Linter } from \"eslint\";\n\nexport type CreateEslintConfigOptions = {\n svelteConfig: unknown;\n};\n\nexport function createEslintConfig(opts: CreateEslintConfigOptions): Linter.Config[] {\n return [\n js.configs.recommended,\n ...ts.configs.recommended,\n ...svelte.configs.recommended,\n prettier,\n ...svelte.configs.prettier,\n {\n languageOptions: {\n globals: {\n ...globals.browser,\n ...globals.node,\n },\n },\n rules: {\n \"@typescript-eslint/no-unused-vars\": [\n \"error\",\n {\n argsIgnorePattern: \"^_\",\n varsIgnorePattern: \"^_\",\n caughtErrorsIgnorePattern: \"^_\",\n },\n ],\n \"svelte/no-navigation-without-resolve\": \"off\",\n },\n },\n {\n files: [\"**/*.svelte\", \"**/*.svelte.js\", \"**/*.svelte.ts\"],\n languageOptions: {\n parserOptions: {\n parser: ts.parser,\n svelteConfig: opts.svelteConfig,\n },\n },\n },\n {\n // eslint-plugin-svelte 3.20+ allows only an `error` prop in +error.svelte,\n // but SvelteKit really does pass merged layout `data` to error pages\n // (typed by hand since kit generates no ./$types for +error). The rule\n // takes no options (schema: []), so scope it off for error pages only.\n files: [\"**/+error.svelte\"],\n rules: {\n \"svelte/valid-prop-names-in-kit-pages\": \"off\",\n },\n },\n {\n files: [\"**/*.d.ts\"],\n rules: {\n \"no-var\": \"off\",\n \"@typescript-eslint/no-unused-vars\": \"off\",\n },\n },\n {\n ignores: [\n \"build/\",\n \".svelte-kit/\",\n \".netlify/\",\n \"node_modules/\",\n \"static/\",\n \"customtypes/\",\n \"src/lib/slices/**/index.js\",\n // Agency process artifacts: git-ignored in every repo, but present on\n // disk locally, so `pnpm lint` would otherwise try to parse them.\n \"docs/superpowers/\",\n \"scratchpad/\",\n ],\n },\n ] as Linter.Config[];\n}\n\nexport default createEslintConfig;\n"],"mappings":";AAAA,OAAO,QAAQ;AACf,OAAO,QAAQ;AACf,OAAO,YAAY;AACnB,OAAO,cAAc;AACrB,OAAO,aAAa;AAOb,SAAS,mBAAmB,MAAkD;AACnF,SAAO;AAAA,IACL,GAAG,QAAQ;AAAA,IACX,GAAG,GAAG,QAAQ;AAAA,IACd,GAAG,OAAO,QAAQ;AAAA,IAClB;AAAA,IACA,GAAG,OAAO,QAAQ;AAAA,IAClB;AAAA,MACE,iBAAiB;AAAA,QACf,SAAS;AAAA,UACP,GAAG,QAAQ;AAAA,UACX,GAAG,QAAQ;AAAA,QACb;AAAA,MACF;AAAA,MACA,OAAO;AAAA,QACL,qCAAqC;AAAA,UACnC;AAAA,UACA;AAAA,YACE,mBAAmB;AAAA,YACnB,mBAAmB;AAAA,YACnB,2BAA2B;AAAA,UAC7B;AAAA,QACF;AAAA,QACA,wCAAwC;AAAA,MAC1C;AAAA,IACF;AAAA,IACA;AAAA,MACE,OAAO,CAAC,eAAe,kBAAkB,gBAAgB;AAAA,MACzD,iBAAiB;AAAA,QACf,eAAe;AAAA,UACb,QAAQ,GAAG;AAAA,UACX,cAAc,KAAK;AAAA,QACrB;AAAA,MACF;AAAA,IACF;AAAA,IACA;AAAA;AAAA;AAAA;AAAA;AAAA,MAKE,OAAO,CAAC,kBAAkB;AAAA,MAC1B,OAAO;AAAA,QACL,wCAAwC;AAAA,MAC1C;AAAA,IACF;AAAA,IACA;AAAA,MACE,OAAO,CAAC,WAAW;AAAA,MACnB,OAAO;AAAA,QACL,UAAU;AAAA,QACV,qCAAqC;AAAA,MACvC;AAAA,IACF;AAAA,IACA;AAAA,MACE,SAAS;AAAA,QACP;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA;AAAA;AAAA,QAGA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAEA,IAAO,iBAAQ;","names":[]}
1
+ {"version":3,"sources":["../../src/configs/eslint.ts"],"sourcesContent":["import js from \"@eslint/js\";\nimport ts from \"typescript-eslint\";\nimport svelte from \"eslint-plugin-svelte\";\nimport prettier from \"eslint-config-prettier\";\nimport globals from \"globals\";\nimport type { Linter } from \"eslint\";\n\nexport type CreateEslintConfigOptions = {\n svelteConfig: unknown;\n};\n\nexport function createEslintConfig(opts: CreateEslintConfigOptions): Linter.Config[] {\n return [\n js.configs.recommended,\n ...ts.configs.recommended,\n ...svelte.configs.recommended,\n prettier,\n ...svelte.configs.prettier,\n {\n languageOptions: {\n globals: {\n ...globals.browser,\n ...globals.node,\n },\n },\n rules: {\n \"@typescript-eslint/no-unused-vars\": [\n \"error\",\n {\n argsIgnorePattern: \"^_\",\n varsIgnorePattern: \"^_\",\n caughtErrorsIgnorePattern: \"^_\",\n },\n ],\n \"svelte/no-navigation-without-resolve\": \"off\",\n },\n },\n {\n files: [\"**/*.svelte\", \"**/*.svelte.js\", \"**/*.svelte.ts\"],\n languageOptions: {\n parserOptions: {\n parser: ts.parser,\n svelteConfig: opts.svelteConfig,\n },\n },\n },\n {\n // eslint-plugin-svelte 3.20+ allows only an `error` prop in +error.svelte,\n // but SvelteKit really does pass merged layout `data` to error pages\n // (typed by hand since kit generates no ./$types for +error). The rule\n // takes no options (schema: []), so scope it off for error pages only.\n files: [\"**/+error.svelte\"],\n rules: {\n \"svelte/valid-prop-names-in-kit-pages\": \"off\",\n },\n },\n {\n files: [\"**/*.d.ts\"],\n rules: {\n \"no-var\": \"off\",\n \"@typescript-eslint/no-unused-vars\": \"off\",\n },\n },\n {\n ignores: [\n \"build/\",\n \".svelte-kit/\",\n \".netlify/\",\n \"node_modules/\",\n \"static/\",\n \"customtypes/\",\n \"src/lib/slices/**/index.js\",\n // Agency process artifacts: git-ignored in every repo, but present on\n // disk locally, so `pnpm lint` would otherwise try to parse them.\n \"docs/superpowers/\",\n \"scratchpad/\",\n // Third member of that class: the match-harness Phase 0 reference\n // capture. `matching/capture-reference.mjs` downloads the live site's\n // own HTML/CSS/JS byte-for-byte into a fixed `matching/spec` (line 31,\n // `const OUT = \"matching/spec\"` — a const, not configurable), so eslint\n // gets handed third-party minified bundles. Measured on 29 Navy's first\n // capture: 745 errors, `pnpm verify` red — Webflow's two chunks 377 and\n // 78, jQuery 3.5.1 290.\n //\n // `prettier --check .` survives the same files, but only by accident of\n // prettier 3 defaulting --ignore-path to `.gitignore`, which the recipe's\n // block fills with `matching/*`. Eslint flat config reads no ignore file\n // at all, and `.prettierignore` does NOT list the capture: measured,\n // `prettier --check matching/spec --ignore-path .prettierignore` flags\n // five files. That asymmetry is the whole bug.\n //\n // SCOPED TO `matching/spec/`, deliberately NOT `matching/`. The probes,\n // gate scripts and site records under `matching/` are ours and must stay\n // linted — beachfront-dentistry ignores `matching/` wholesale and has\n // un-linted its own `adv-verify-svc*.mjs` that way. The narrowness cuts\n // both ways: `matching/spec*` also swallows the TRACKED\n // `matching/spec-sections/`.\n \"matching/spec/\",\n // Same class, same generated .gitignore block: the harness's scratch\n // diff workspace. Included on class grounds, NOT on a reproduced signal\n // — nothing in the harness writes it and no clone has one on disk.\n \"scratch-diff*/\",\n ],\n },\n ] as Linter.Config[];\n}\n\nexport default createEslintConfig;\n"],"mappings":";AAAA,OAAO,QAAQ;AACf,OAAO,QAAQ;AACf,OAAO,YAAY;AACnB,OAAO,cAAc;AACrB,OAAO,aAAa;AAOb,SAAS,mBAAmB,MAAkD;AACnF,SAAO;AAAA,IACL,GAAG,QAAQ;AAAA,IACX,GAAG,GAAG,QAAQ;AAAA,IACd,GAAG,OAAO,QAAQ;AAAA,IAClB;AAAA,IACA,GAAG,OAAO,QAAQ;AAAA,IAClB;AAAA,MACE,iBAAiB;AAAA,QACf,SAAS;AAAA,UACP,GAAG,QAAQ;AAAA,UACX,GAAG,QAAQ;AAAA,QACb;AAAA,MACF;AAAA,MACA,OAAO;AAAA,QACL,qCAAqC;AAAA,UACnC;AAAA,UACA;AAAA,YACE,mBAAmB;AAAA,YACnB,mBAAmB;AAAA,YACnB,2BAA2B;AAAA,UAC7B;AAAA,QACF;AAAA,QACA,wCAAwC;AAAA,MAC1C;AAAA,IACF;AAAA,IACA;AAAA,MACE,OAAO,CAAC,eAAe,kBAAkB,gBAAgB;AAAA,MACzD,iBAAiB;AAAA,QACf,eAAe;AAAA,UACb,QAAQ,GAAG;AAAA,UACX,cAAc,KAAK;AAAA,QACrB;AAAA,MACF;AAAA,IACF;AAAA,IACA;AAAA;AAAA;AAAA;AAAA;AAAA,MAKE,OAAO,CAAC,kBAAkB;AAAA,MAC1B,OAAO;AAAA,QACL,wCAAwC;AAAA,MAC1C;AAAA,IACF;AAAA,IACA;AAAA,MACE,OAAO,CAAC,WAAW;AAAA,MACnB,OAAO;AAAA,QACL,UAAU;AAAA,QACV,qCAAqC;AAAA,MACvC;AAAA,IACF;AAAA,IACA;AAAA,MACE,SAAS;AAAA,QACP;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA;AAAA;AAAA,QAGA;AAAA,QACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAsBA;AAAA;AAAA;AAAA;AAAA,QAIA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAEA,IAAO,iBAAQ;","names":[]}