@reddoorla/maintenance 0.58.0 → 0.60.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/dist/airtable-YZ6VMSQZ.js +9 -0
  2. package/dist/{announce-JO67XZLZ.js → announce-Q2DXP5OO.js} +3 -3
  3. package/dist/{bump-deps-6D4VCAFQ.js → bump-deps-RYHQIKW4.js} +2 -2
  4. package/dist/{chunk-4PY4I5OR.js → chunk-5PHCZ6L5.js} +11 -2
  5. package/dist/chunk-5PHCZ6L5.js.map +1 -0
  6. package/dist/{chunk-IDRBAF2H.js → chunk-6CSCLBAA.js} +2 -2
  7. package/dist/{chunk-MKSZBODM.js → chunk-D3LFQNJK.js} +2 -2
  8. package/dist/{chunk-XO2RUYVM.js → chunk-HB7QPECR.js} +2 -2
  9. package/dist/{chunk-RYECSIEA.js → chunk-HPSGCDWY.js} +3 -3
  10. package/dist/chunk-HPSGCDWY.js.map +1 -0
  11. package/dist/{chunk-HPNGCRTK.js → chunk-KC4HU7BC.js} +2 -2
  12. package/dist/{chunk-PKIYAWA4.js → chunk-L4ULXHIN.js} +7 -2
  13. package/dist/chunk-L4ULXHIN.js.map +1 -0
  14. package/dist/{chunk-IJW4DS2S.js → chunk-LMXIZITU.js} +3 -3
  15. package/dist/chunk-LMXIZITU.js.map +1 -0
  16. package/dist/{chunk-5E3OW6YN.js → chunk-TLZ4V2BE.js} +2 -2
  17. package/dist/{chunk-S7WKPRID.js → chunk-TZN2G6FD.js} +2 -2
  18. package/dist/{chunk-J4ECCFRT.js → chunk-XB6T4ETK.js} +1 -1
  19. package/dist/chunk-XB6T4ETK.js.map +1 -0
  20. package/dist/cli/bin.js +13 -13
  21. package/dist/cli/commands/audit.js +6 -6
  22. package/dist/{convert-to-pnpm-JYUUUDDP.js → convert-to-pnpm-KNCXU6FM.js} +2 -2
  23. package/dist/{digest-RUQ42QXL.js → digest-RVIOHUXR.js} +2 -2
  24. package/dist/{github-signals-JXHRHDAG.js → github-signals-UL2BBS3Q.js} +5 -5
  25. package/dist/index.js +208 -17
  26. package/dist/index.js.map +1 -1
  27. package/dist/{init-6LJU72F2.js → init-KD56UENX.js} +4 -4
  28. package/dist/{launch-6ZB3QA2I.js → launch-UWCI3JRM.js} +15 -9
  29. package/dist/launch-UWCI3JRM.js.map +1 -0
  30. package/dist/{lighthouse-airtable-FSGOUVMQ.js → lighthouse-airtable-N3KCBPVA.js} +3 -3
  31. package/dist/{onboard-UM6UKX2V.js → onboard-SCZ3UKZ2.js} +2 -2
  32. package/dist/{orchestrate-GEHLKE64.js → orchestrate-D72PB6NG.js} +3 -3
  33. package/dist/{renovate-dispatch-L5HWCNRY.js → renovate-dispatch-NG5KUQKY.js} +3 -3
  34. package/dist/{report-3YVSMRFE.js → report-CN56TGMK.js} +5 -5
  35. package/dist/{self-updating-J7U7WIP3.js → self-updating-CFHXJSAX.js} +4 -4
  36. package/dist/{svelte-codemods-BW4M4CDF.js → svelte-codemods-HNITLWQM.js} +2 -2
  37. package/dist/{sync-configs-ZYKZCP4C.js → sync-configs-BZXBYKTI.js} +2 -2
  38. package/dist/{upgrade-UAXREMED.js → upgrade-6YDUELFA.js} +2 -2
  39. package/dist/{websites-EEZVZXQT.js → websites-IYP7IGLU.js} +6 -4
  40. package/dist/{write-audits-to-airtable-LUFY424L.js → write-audits-to-airtable-VDGHCZGQ.js} +4 -4
  41. package/package.json +1 -1
  42. package/dist/airtable-E5F5FLGD.js +0 -9
  43. package/dist/chunk-4PY4I5OR.js.map +0 -1
  44. package/dist/chunk-IJW4DS2S.js.map +0 -1
  45. package/dist/chunk-J4ECCFRT.js.map +0 -1
  46. package/dist/chunk-PKIYAWA4.js.map +0 -1
  47. package/dist/chunk-RYECSIEA.js.map +0 -1
  48. package/dist/launch-6ZB3QA2I.js.map +0 -1
  49. /package/dist/{airtable-E5F5FLGD.js.map → airtable-YZ6VMSQZ.js.map} +0 -0
  50. /package/dist/{announce-JO67XZLZ.js.map → announce-Q2DXP5OO.js.map} +0 -0
  51. /package/dist/{bump-deps-6D4VCAFQ.js.map → bump-deps-RYHQIKW4.js.map} +0 -0
  52. /package/dist/{chunk-IDRBAF2H.js.map → chunk-6CSCLBAA.js.map} +0 -0
  53. /package/dist/{chunk-MKSZBODM.js.map → chunk-D3LFQNJK.js.map} +0 -0
  54. /package/dist/{chunk-XO2RUYVM.js.map → chunk-HB7QPECR.js.map} +0 -0
  55. /package/dist/{chunk-HPNGCRTK.js.map → chunk-KC4HU7BC.js.map} +0 -0
  56. /package/dist/{chunk-5E3OW6YN.js.map → chunk-TLZ4V2BE.js.map} +0 -0
  57. /package/dist/{chunk-S7WKPRID.js.map → chunk-TZN2G6FD.js.map} +0 -0
  58. /package/dist/{convert-to-pnpm-JYUUUDDP.js.map → convert-to-pnpm-KNCXU6FM.js.map} +0 -0
  59. /package/dist/{digest-RUQ42QXL.js.map → digest-RVIOHUXR.js.map} +0 -0
  60. /package/dist/{github-signals-JXHRHDAG.js.map → github-signals-UL2BBS3Q.js.map} +0 -0
  61. /package/dist/{init-6LJU72F2.js.map → init-KD56UENX.js.map} +0 -0
  62. /package/dist/{lighthouse-airtable-FSGOUVMQ.js.map → lighthouse-airtable-N3KCBPVA.js.map} +0 -0
  63. /package/dist/{onboard-UM6UKX2V.js.map → onboard-SCZ3UKZ2.js.map} +0 -0
  64. /package/dist/{orchestrate-GEHLKE64.js.map → orchestrate-D72PB6NG.js.map} +0 -0
  65. /package/dist/{renovate-dispatch-L5HWCNRY.js.map → renovate-dispatch-NG5KUQKY.js.map} +0 -0
  66. /package/dist/{report-3YVSMRFE.js.map → report-CN56TGMK.js.map} +0 -0
  67. /package/dist/{self-updating-J7U7WIP3.js.map → self-updating-CFHXJSAX.js.map} +0 -0
  68. /package/dist/{svelte-codemods-BW4M4CDF.js.map → svelte-codemods-HNITLWQM.js.map} +0 -0
  69. /package/dist/{sync-configs-ZYKZCP4C.js.map → sync-configs-BZXBYKTI.js.map} +0 -0
  70. /package/dist/{upgrade-UAXREMED.js.map → upgrade-6YDUELFA.js.map} +0 -0
  71. /package/dist/{websites-EEZVZXQT.js.map → websites-IYP7IGLU.js.map} +0 -0
  72. /package/dist/{write-audits-to-airtable-LUFY424L.js.map → write-audits-to-airtable-VDGHCZGQ.js.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/audits/a11y-airtable.ts","../src/audits/deps-airtable.ts","../src/audits/security-airtable.ts","../src/audits/domain-airtable.ts","../src/audits/browser-airtable.ts","../src/audits/write-audits-to-airtable.ts"],"sourcesContent":["import type { AuditResult } from \"../types.js\";\n\ntype A11yDetails = {\n totalViolations: number;\n byImpact: Partial<Record<\"minor\" | \"moderate\" | \"serious\" | \"critical\", number>>;\n};\n\n/** True when an a11y AuditResult carries real counts worth persisting.\n * Mirrors the `hasRealScores` policy on lighthouse: write whenever real\n * data exists, regardless of status (a \"warn\" or \"fail\" with concrete\n * violation counts is exactly what the dashboard needs to track). */\nexport function hasA11yCounts(result: AuditResult): boolean {\n if (result.audit !== \"a11y\") return false;\n const details = result.details as A11yDetails | undefined;\n return typeof details?.totalViolations === \"number\";\n}\n\nexport function a11yCountsFromResult(result: AuditResult): { violations: number } {\n if (result.audit !== \"a11y\") {\n throw new Error(`Expected an 'a11y' AuditResult, got '${result.audit}'`);\n }\n const details = result.details as A11yDetails | undefined;\n return { violations: details?.totalViolations ?? 0 };\n}\n","import type { AuditResult } from \"../types.js\";\nimport type { DepsDetails, DepsDriftEntry } from \"./deps.js\";\n\n/** True when a deps AuditResult carries the structured details (an entries\n * array, per {@link DepsDetails}). */\nexport function hasDepsCounts(result: AuditResult): boolean {\n if (result.audit !== \"deps\") return false;\n const d = result.details as Partial<DepsDetails> | undefined;\n return Array.isArray(d?.entries);\n}\n\nexport function depsCountsFromResult(result: AuditResult): {\n drifted: number;\n majorBehind: number;\n outdated: number | null;\n} {\n if (result.audit !== \"deps\") {\n throw new Error(`Expected a 'deps' AuditResult, got '${result.audit}'`);\n }\n const details = (result.details ?? {}) as Partial<DepsDetails>;\n const entries = (details.entries ?? []) as DepsDriftEntry[];\n // \"drifted\" = drift !== \"same\", which intentionally includes \"newer\" (ahead of\n // baseline) — parity with the deps audit summary text.\n const drifted = entries.filter((e) => e.drift !== \"same\").length;\n const majorBehind = entries.filter((e) => e.drift === \"major\").length;\n // The real installed-version drift, distinct from declared-range drift. Null\n // when the audit couldn't determine it (no/stale lockfile) — kept null (not 0)\n // so the dashboard shows \"—\" rather than a misleading \"clean\".\n const outdated = details.outdated?.outdated ?? null;\n return { drifted, majorBehind, outdated };\n}\n","import type { AuditResult } from \"../types.js\";\nimport { normalizeSecurityAdvisory, type SecurityAdvisory } from \"../reports/airtable/websites.js\";\n\ntype SecurityDetails = {\n counts: { low: number; moderate: number; high: number; critical: number };\n advisories?: unknown;\n};\n\n/** True when a security AuditResult carries a counts object. Skipped runs\n * (no pnpm + no npm) have no details and return false. */\nexport function hasSecurityCounts(result: AuditResult): boolean {\n if (result.audit !== \"security\") return false;\n const details = result.details as SecurityDetails | undefined;\n return !!details && typeof details.counts === \"object\";\n}\n\nexport function securityCountsFromResult(result: AuditResult): {\n critical: number;\n high: number;\n moderate: number;\n low: number;\n} {\n if (result.audit !== \"security\") {\n throw new Error(`Expected a 'security' AuditResult, got '${result.audit}'`);\n }\n const details = result.details as SecurityDetails | undefined;\n const c = details?.counts ?? { low: 0, moderate: 0, high: 0, critical: 0 };\n return { critical: c.critical, high: c.high, moderate: c.moderate, low: c.low };\n}\n\n/** The known advisories behind the counts, normalized for persistence. Empty when the\n * run was clean or carried no advisory detail (npm/pnpm sometimes omit it). Malformed\n * entries are dropped via the shared `normalizeSecurityAdvisory`. */\nexport function advisoriesFromResult(result: AuditResult): SecurityAdvisory[] {\n if (result.audit !== \"security\") {\n throw new Error(`Expected a 'security' AuditResult, got '${result.audit}'`);\n }\n const details = result.details as SecurityDetails | undefined;\n const raw = details?.advisories;\n if (!Array.isArray(raw)) return [];\n return raw.map(normalizeSecurityAdvisory).filter((a): a is SecurityAdvisory => a !== null);\n}\n","import type { AuditResult } from \"../types.js\";\nimport type { DomainResult } from \"../reports/airtable/websites.js\";\n\ntype DomainDetails = { resolved: boolean; certDaysRemaining: number | null; checkedAt: string };\n\n/** True when an AuditResult is a `domain` audit carrying a usable details payload (i.e. it\n * actually ran — a \"skip\" for a site with no deployed URL has no details). */\nexport function hasDomainResult(result: AuditResult): boolean {\n if (result.audit !== \"domain\") return false;\n const d = result.details as DomainDetails | undefined;\n return !!d && typeof d.checkedAt === \"string\";\n}\n\n/** Extract the Airtable-writable domain result (cert days + checked-at) from a `domain` audit. */\nexport function domainResultFromAudit(result: AuditResult): DomainResult {\n if (result.audit !== \"domain\") {\n throw new Error(`Expected a 'domain' AuditResult, got '${result.audit}'`);\n }\n const d = result.details as DomainDetails | undefined;\n return {\n certDaysRemaining: typeof d?.certDaysRemaining === \"number\" ? d.certDaysRemaining : null,\n checkedAt: typeof d?.checkedAt === \"string\" ? d.checkedAt : new Date().toISOString(),\n };\n}\n","import type { AuditResult } from \"../types.js\";\nimport type { BrowserAuditFields } from \"../reports/airtable/websites.js\";\n\ntype BrowserDetails = {\n desktopOk: boolean;\n mobileOk: boolean;\n linksOk: boolean;\n brokenLinks: number;\n checkedAt: string;\n};\n\n/** True when an AuditResult is a `browser` audit that actually ran (has a details payload — a\n * \"skip\" for a site with no deployed URL has none). */\nexport function hasBrowserResult(result: AuditResult): boolean {\n if (result.audit !== \"browser\") return false;\n const d = result.details as BrowserDetails | undefined;\n return !!d && typeof d.checkedAt === \"string\";\n}\n\n/** Extract the Airtable-writable browser verdicts from a `browser` audit. */\nexport function browserFieldsFromAudit(result: AuditResult): BrowserAuditFields {\n if (result.audit !== \"browser\") {\n throw new Error(`Expected a 'browser' AuditResult, got '${result.audit}'`);\n }\n const d = result.details as BrowserDetails | undefined;\n return {\n desktopOk: d?.desktopOk === true,\n mobileOk: d?.mobileOk === true,\n linksOk: d?.linksOk === true,\n brokenLinks: typeof d?.brokenLinks === \"number\" ? d.brokenLinks : 0,\n checkedAt: typeof d?.checkedAt === \"string\" ? d.checkedAt : new Date().toISOString(),\n };\n}\n","import type { AuditResult } from \"../types.js\";\nimport type { AirtableBase } from \"../reports/airtable/client.js\";\nimport { type WebsiteRow, siteSlug, updateAuditFields } from \"../reports/airtable/websites.js\";\nimport type {\n A11yCounts,\n DepsCounts,\n SecurityCounts,\n SecurityAdvisory,\n DomainResult,\n BrowserAuditFields,\n} from \"../reports/airtable/websites.js\";\nimport type { LighthouseScoreWriteback } from \"../reports/types.js\";\nimport { hasRealScores, lighthouseScoresFromResult } from \"./lighthouse-airtable.js\";\nimport { hasA11yCounts, a11yCountsFromResult } from \"./a11y-airtable.js\";\nimport { hasDepsCounts, depsCountsFromResult } from \"./deps-airtable.js\";\nimport {\n hasSecurityCounts,\n securityCountsFromResult,\n advisoriesFromResult,\n} from \"./security-airtable.js\";\nimport { hasDomainResult, domainResultFromAudit } from \"./domain-airtable.js\";\nimport { hasBrowserResult, browserFieldsFromAudit } from \"./browser-airtable.js\";\n\ntype WriteSummary = {\n siteName: string;\n writes: Array<{\n audit: \"lighthouse\" | \"a11y\" | \"deps\" | \"security\" | \"github-signals\" | \"domain\" | \"browser\";\n counts: object;\n }>;\n};\n\n/** Orchestrates the per-audit Airtable writes for `audit --write-airtable`.\n * Extracted from the CLI command so it can be unit-tested with a fake base\n * and so adding new audit types is a one-line addition here rather than\n * growing the CLI handler.\n *\n * Throws (with .exitCode set) on the failure modes the CLI surfaces today:\n * - 2: --only ran without lighthouse, or no Websites row matched the slug\n * - 1: lighthouse ran but produced no real scores (infrastructure failure).\n * The a11y/deps/security writes still complete FIRST — a Lighthouse\n * miss flags the site without discarding its other audit data.\n *\n * Precedence note: the Websites-row lookup (exitCode 2) is checked BEFORE the\n * no-scores gate (exitCode 1), so the rare no-row + no-scores combo surfaces\n * as exitCode 2. */\nexport async function writeAuditsToAirtable(args: {\n base: AirtableBase;\n websites: WebsiteRow[];\n slug: string;\n results: AuditResult[];\n}): Promise<WriteSummary> {\n const { base, websites, slug, results } = args;\n\n // Lighthouse is OPTIONAL. The checkout-free `--only lighthouse,domain,browser` nightly includes\n // it, but a standalone `--only security` (checkout-ful) sweep legitimately has none. We write\n // whatever audits produced values; only the lighthouse-MISS flag below is lighthouse-specific\n // (so a real Lighthouse infra failure still reds the run without discarding other audit data).\n const lhResult = results.find((r) => r.audit === \"lighthouse\");\n const target = websites.find((w) => siteSlug(w.name) === slug);\n if (!target) {\n throw Object.assign(new Error(`No Websites row matched slug \"${slug}\"`), { exitCode: 2 });\n }\n\n const writes: WriteSummary[\"writes\"] = [];\n const audits: {\n scores?: LighthouseScoreWriteback;\n a11y?: A11yCounts;\n deps?: DepsCounts;\n security?: SecurityCounts;\n securityAdvisories?: SecurityAdvisory[];\n domain?: DomainResult;\n browser?: BrowserAuditFields;\n } = {};\n\n // Collect every audit that produced real values into ONE merged input, then do a\n // SINGLE atomic Airtable update (was: up to four sequential updates on the same\n // row — a mid-sequence failure left it half-written yet reported fully failed, at\n // 4× the request volume). Lighthouse is the most timeout-prone audit: a Lighthouse\n // miss must NOT discard the site's valid a11y/deps/security results (morning-brief\n // 2026-06-10 MEDIUM-E). So include Lighthouse scores only when real, include the\n // other audits whenever present, write all of them in one update, then — if\n // Lighthouse missed — throw AFTER that atomic write so the site is still flagged\n // (exitCode 1 / collected in FleetWriteResult.failed) without losing its other data.\n const lhHasScores = lhResult ? hasRealScores(lhResult) : false;\n if (lhResult && lhHasScores) {\n const scores = lighthouseScoresFromResult(lhResult);\n audits.scores = scores;\n writes.push({ audit: \"lighthouse\", counts: scores });\n }\n\n const a11y = results.find((r) => r.audit === \"a11y\");\n if (a11y && hasA11yCounts(a11y)) {\n const counts = a11yCountsFromResult(a11y);\n audits.a11y = counts;\n writes.push({ audit: \"a11y\", counts });\n }\n\n const deps = results.find((r) => r.audit === \"deps\");\n if (deps && hasDepsCounts(deps)) {\n const counts = depsCountsFromResult(deps);\n audits.deps = counts;\n writes.push({ audit: \"deps\", counts });\n }\n\n const sec = results.find((r) => r.audit === \"security\");\n if (sec && hasSecurityCounts(sec)) {\n const counts = securityCountsFromResult(sec);\n audits.security = counts;\n // Persist the advisory list alongside the counts so the dashboard can show which packages\n // are vulnerable. An empty array (clean run) clears any stale list.\n audits.securityAdvisories = advisoriesFromResult(sec);\n writes.push({ audit: \"security\", counts });\n }\n\n const dom = results.find((r) => r.audit === \"domain\");\n if (dom && hasDomainResult(dom)) {\n const result = domainResultFromAudit(dom);\n audits.domain = result;\n writes.push({ audit: \"domain\", counts: result });\n }\n\n const browser = results.find((r) => r.audit === \"browser\");\n if (browser && hasBrowserResult(browser)) {\n const fields = browserFieldsFromAudit(browser);\n audits.browser = fields;\n writes.push({ audit: \"browser\", counts: fields });\n }\n\n // One atomic write of everything that ran. Skip the call only if there is nothing\n // to write at all (no real scores AND no other audit produced values) — an empty\n // update is a wasted request.\n if (Object.keys(audits).length > 0) {\n await updateAuditFields(base, target.id, audits);\n }\n\n // Lighthouse-miss flag: only when lighthouse WAS requested (in results) but produced no scores —\n // an infra failure worth reding the run, AFTER persisting the other audits. A sweep that never\n // ran lighthouse (e.g. `--only security`) skips this entirely.\n if (lhResult && !lhHasScores) {\n // Enumerate what WAS persisted so the failure (surfaced to the single-site\n // CLI operator via console.error) reads as a partial write, not a total one.\n const persisted = writes.map((w) => w.audit);\n throw Object.assign(\n new Error(\n `Lighthouse audit produced no scores; ${\n persisted.length ? `wrote ${persisted.join(\"/\")} but refused Lighthouse` : \"wrote nothing\"\n }. Summary: ${lhResult.summary}`,\n ),\n { exitCode: 1 },\n );\n }\n\n return { siteName: target.name, writes };\n}\n\nexport type FleetWriteResult = {\n written: WriteSummary[];\n failed: Array<{ slug: string; error: string }>;\n};\n\n/** Render the fleet write-back outcome for the CLI/CI. Beyond the human-readable\n * lines, it emits a single deterministic, machine-parseable line —\n * `FLEET_WRITE_SUMMARY wrote=N failed=M total=T` — that the nightly workflow\n * greps to decide pass/fail. Keying CI on this line (not the prose, and not a\n * \"wrote ≥ 1\" heuristic) lets the gate tolerate a single known flake while\n * still reding on a total or mass write-back failure. */\nexport function formatFleetWriteSummary(result: FleetWriteResult): string {\n const wrote = result.written.length;\n const failed = result.failed.length;\n const total = wrote + failed;\n let out = `→ wrote ${wrote} site(s) to Airtable`;\n if (failed > 0) {\n out += `\\n⚠ ${failed} site(s) not written: ${result.failed\n .map((f) => `${f.slug} (${f.error})`)\n .join(\"; \")}`;\n }\n out += `\\nFLEET_WRITE_SUMMARY wrote=${wrote} failed=${failed} total=${total}`;\n return out;\n}\n\n/** Write each site's pooled audit results back to its own Websites row,\n * best-effort. Results are grouped by `result.site` (the slug the fleet\n * inventory stamped as Site.name). A per-site failure (no scores, no matching\n * row) is collected — not thrown — so one bad site never aborts the batch. */\nexport async function writeFleetAuditsToAirtable(args: {\n base: AirtableBase;\n websites: WebsiteRow[];\n results: AuditResult[];\n}): Promise<FleetWriteResult> {\n const { base, websites, results } = args;\n\n const bySlug = new Map<string, AuditResult[]>();\n for (const r of results) {\n const arr = bySlug.get(r.site) ?? [];\n arr.push(r);\n bySlug.set(r.site, arr);\n }\n\n const written: WriteSummary[] = [];\n const failed: FleetWriteResult[\"failed\"] = [];\n // Serial on purpose: even at one (now atomic) update call per site, Airtable's\n // ~5 req/sec limit means a Promise.all fan-out across the fleet would burst and\n // trip 429s (silently filed as failures). Below a few dozen sites, serial trades\n // wall-clock for safety. (morning-brief 2026-06-09 MEDIUM-3.) Add a bounded pool\n // when the fleet grows.\n for (const [slug, siteResults] of bySlug) {\n try {\n written.push(await writeAuditsToAirtable({ base, websites, slug, results: siteResults }));\n } catch (e) {\n failed.push({ slug, error: (e as Error).message });\n }\n }\n return { written, failed };\n}\n"],"mappings":"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","names":[]}
@@ -5,7 +5,7 @@ import {
5
5
  ACTIVE_STATUSES,
6
6
  listWebsites,
7
7
  siteSlug
8
- } from "./chunk-PKIYAWA4.js";
8
+ } from "./chunk-L4ULXHIN.js";
9
9
 
10
10
  // src/inventory/airtable.ts
11
11
  function fromAirtableBase(base, opts = {}) {
@@ -46,4 +46,4 @@ function fromAirtableBase(base, opts = {}) {
46
46
  export {
47
47
  fromAirtableBase
48
48
  };
49
- //# sourceMappingURL=chunk-5E3OW6YN.js.map
49
+ //# sourceMappingURL=chunk-TLZ4V2BE.js.map
@@ -17,7 +17,7 @@ import {
17
17
  import {
18
18
  siteSlug,
19
19
  updateAnalyticsHealth
20
- } from "./chunk-PKIYAWA4.js";
20
+ } from "./chunk-L4ULXHIN.js";
21
21
  import {
22
22
  defaultCredentialsPath
23
23
  } from "./chunk-6VAL7XJT.js";
@@ -441,4 +441,4 @@ export {
441
441
  fetchGaUsers,
442
442
  fetchSearch
443
443
  };
444
- //# sourceMappingURL=chunk-S7WKPRID.js.map
444
+ //# sourceMappingURL=chunk-TZN2G6FD.js.map
@@ -218,4 +218,4 @@ function makeGitHub(deps) {
218
218
  export {
219
219
  makeGitHub
220
220
  };
221
- //# sourceMappingURL=chunk-J4ECCFRT.js.map
221
+ //# sourceMappingURL=chunk-XB6T4ETK.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/github/gh.ts"],"sourcesContent":["import { defaultSpawn, type SpawnFn } from \"../audits/util/spawn.js\";\n\n/** Aggregate CI state of a PR's head commit, normalized from GitHub's rollup. */\nexport type CiState = \"passing\" | \"failing\" | \"pending\" | \"none\";\n\n/** GitHub's computed mergeability of a PR. `UNKNOWN` is transient — GitHub is\n * still computing it (e.g. right after a push) — so it should be read as \"not\n * known to conflict\", never as conflicting. */\nexport type PrMergeable = \"MERGEABLE\" | \"CONFLICTING\" | \"UNKNOWN\";\n\n/** A minimal open-PR summary with its head-commit CI rollup state + mergeability. */\nexport type PullRequestSummary = {\n number: number;\n title: string;\n url: string;\n headRef: string;\n ciState: CiState;\n mergeable: PrMergeable;\n};\n\n/**\n * Reject a value before it's interpolated into a `gh api` URL path. The\n * `owner/repo` split methods already validate shape; this is the defense-in-depth\n * guard for the `branch` and file-`path` segments. An unexpected value (`..`, a\n * leading `/`, whitespace, or a URL-structural char like `?#%` or a backslash)\n * could otherwise retarget the endpoint (escape the intended path, smuggle a\n * query string, or traverse). Conservative by design — legit branch names like\n * `maint/self-updating-x` and paths like `.github/workflows/ci.yml` pass.\n *\n * Both branch refs (`maint/self-updating-x`) and file paths\n * (`.github/workflows/ci.yml`) legitimately contain `/`, so a single slash is\n * allowed; what's rejected is `..`, a leading `/`, whitespace, or a\n * URL-structural char (`?`, `#`, `%`, backslash) that could escape or retarget\n * the endpoint.\n */\nexport function assertUrlSegment(kind: \"branch\" | \"path\", value: string): void {\n const structural = /[\\s?#%\\\\]|\\.\\./;\n if (value.length === 0 || value.startsWith(\"/\") || structural.test(value)) {\n throw new Error(\n `unsafe ${kind} for gh api path (illegal characters or traversal): ${JSON.stringify(value)}`,\n );\n }\n}\n\n/** Map GitHub's `statusCheckRollup.state` enum to our normalized CiState. */\nfunction mapRollupState(state: string | null | undefined): CiState {\n switch (state) {\n case \"SUCCESS\":\n return \"passing\";\n case \"FAILURE\":\n case \"ERROR\":\n return \"failing\";\n case \"PENDING\":\n case \"EXPECTED\":\n return \"pending\";\n default:\n return \"none\"; // null/undefined = no checks reported\n }\n}\n\n/** Coerce GitHub's `mergeable` enum to our PrMergeable. Anything unexpected\n * (including the literal `UNKNOWN` GitHub returns while still computing) maps to\n * `UNKNOWN` — i.e. \"not known to conflict\". Only an explicit `CONFLICTING` is. */\nfunction mapMergeable(state: string | null | undefined): PrMergeable {\n return state === \"MERGEABLE\" || state === \"CONFLICTING\" ? state : \"UNKNOWN\";\n}\n\nexport type GitHub = {\n openPullRequest: (\n repo: string,\n pr: { head: string; base: string; title: string; body: string },\n ) => Promise<{ url: string }>;\n enableRepoAutoMerge: (repo: string) => Promise<void>;\n protectBranch: (repo: string, branch: string, requiredChecks: string[]) => Promise<void>;\n setRepoSecret: (repo: string, name: string, value: string) => Promise<void>;\n repoExists: (repo: string) => Promise<boolean>;\n defaultBranch: (repo: string) => Promise<string>;\n filesOnBranch: (repo: string, branch: string, paths: string[]) => Promise<string[]>;\n branchProtectionContexts: (repo: string, branch: string) => Promise<string[]>;\n secretExists: (repo: string, name: string) => Promise<boolean>;\n autoMergeEnabled: (repo: string) => Promise<boolean>;\n findOpenSelfUpdatingPR: (repo: string) => Promise<string | null>;\n /** All open PRs on a repo with each head commit's normalized CI rollup state. */\n openPullRequests: (repo: string) => Promise<PullRequestSummary[]>;\n /** The default branch's latest-commit date + normalized CI rollup, one query. */\n defaultBranchStatus: (repo: string) => Promise<{ ciState: CiState; lastCommitAt: string | null }>;\n /** Fire a `workflow_dispatch` for `<workflow>` (a filename like `renovate.yml`)\n * on `ref`. Requires the token's `actions:write` scope; a 404 (no such\n * workflow) or 403 (missing scope) surfaces as a thrown error. */\n dispatchWorkflow: (repo: string, workflow: string, ref: string) => Promise<void>;\n};\n\nexport function makeGitHub(deps: { token: string; spawn?: SpawnFn }): GitHub {\n const spawn = deps.spawn ?? defaultSpawn;\n const env = { ...process.env, GH_TOKEN: deps.token };\n\n async function gh(args: string[]): Promise<string> {\n const r = await spawn(\"gh\", args, { env, timeoutMs: 60_000 });\n if (r.code !== 0) throw new Error(`gh ${args[0]} failed (code ${r.code}): ${r.stderr.trim()}`);\n return r.stdout;\n }\n\n return {\n async openPullRequest(repo, pr) {\n const out = await gh([\n \"pr\",\n \"create\",\n \"--repo\",\n repo,\n \"--head\",\n pr.head,\n \"--base\",\n pr.base,\n \"--title\",\n pr.title,\n \"--body\",\n pr.body,\n ]);\n return { url: out.trim() };\n },\n async enableRepoAutoMerge(repo) {\n await gh([\"api\", \"-X\", \"PATCH\", `repos/${repo}`, \"-F\", \"allow_auto_merge=true\"]);\n },\n async protectBranch(repo, branch, requiredChecks) {\n assertUrlSegment(\"branch\", branch);\n const args = [\n \"api\",\n \"-X\",\n \"PUT\",\n `repos/${repo}/branches/${branch}/protection`,\n \"-H\",\n \"Accept: application/vnd.github+json\",\n \"-F\",\n \"required_status_checks[strict]=true\",\n ...requiredChecks.flatMap((c) => [\"-f\", `required_status_checks[contexts][]=${c}`]),\n \"-F\",\n \"enforce_admins=true\",\n \"-F\",\n \"required_pull_request_reviews=null\",\n \"-F\",\n \"restrictions=null\",\n ];\n await gh(args);\n },\n async setRepoSecret(repo, name, value) {\n await gh([\"secret\", \"set\", name, \"--repo\", repo, \"--body\", value]);\n },\n async repoExists(repo) {\n const r = await spawn(\"gh\", [\"api\", `repos/${repo}`], { env, timeoutMs: 60_000 });\n return r.code === 0;\n },\n async defaultBranch(repo) {\n const out = await gh([\"api\", `repos/${repo}`, \"--jq\", \".default_branch\"]);\n return out.trim();\n },\n // filesOnBranch and branchProtectionContexts call `spawn` directly (not the\n // throwing `gh()` helper) because a 404 is an expected, meaningful answer —\n // \"file/protection absent\" — not an error. The remaining readers use `gh()`\n // since a non-200 there is a genuine failure (e.g. missing token scope).\n async filesOnBranch(repo, branch, paths) {\n assertUrlSegment(\"branch\", branch);\n const present: string[] = [];\n for (const p of paths) {\n assertUrlSegment(\"path\", p);\n const r = await spawn(\"gh\", [`api`, `repos/${repo}/contents/${p}?ref=${branch}`], {\n env,\n timeoutMs: 60_000,\n });\n if (r.code === 0) present.push(p);\n }\n return present;\n },\n async branchProtectionContexts(repo, branch) {\n assertUrlSegment(\"branch\", branch);\n const r = await spawn(\n \"gh\",\n [\n \"api\",\n `repos/${repo}/branches/${branch}/protection`,\n \"--jq\",\n \".required_status_checks.contexts[]?\",\n ],\n { env, timeoutMs: 60_000 },\n );\n if (r.code !== 0) return []; // 404 = no protection configured\n return r.stdout\n .split(\"\\n\")\n .map((l) => l.trim())\n .filter((l) => l.length > 0);\n },\n async secretExists(repo, name) {\n // per_page=100: the REST default of 30 would false-negative on a repo with >30 secrets,\n // wrongly reporting an existing secret absent (→ a needless overwrite).\n const out = await gh([\n \"api\",\n `repos/${repo}/actions/secrets?per_page=100`,\n \"--jq\",\n \".secrets[].name\",\n ]);\n return out\n .split(\"\\n\")\n .map((l) => l.trim())\n .includes(name);\n },\n async autoMergeEnabled(repo) {\n const out = await gh([\"api\", `repos/${repo}`, \"--jq\", \".allow_auto_merge\"]);\n return out.trim() === \"true\";\n },\n async findOpenSelfUpdatingPR(repo) {\n // per_page=100: with the REST default of 30, a repo with >30 open PRs (plausible under\n // Renovate) could page past the existing self-updating PR and open a duplicate.\n const out = await gh([\n \"api\",\n `repos/${repo}/pulls?state=open&per_page=100`,\n \"--jq\",\n '.[] | select(.head.ref | startswith(\"maint/self-updating-\")) | .html_url',\n ]);\n const first = out\n .split(\"\\n\")\n .map((l) => l.trim())\n .find((l) => l.length > 0);\n return first ?? null;\n },\n async openPullRequests(repo) {\n const [owner, name, ...rest] = repo.split(\"/\");\n if (!owner || !name || rest.length > 0) {\n throw new Error(`openPullRequests: expected \"owner/repo\", got \"${repo}\"`);\n }\n const query =\n \"query($owner:String!,$name:String!){repository(owner:$owner,name:$name){\" +\n \"pullRequests(states:OPEN,first:100,orderBy:{field:CREATED_AT,direction:DESC}){nodes{number title url headRefName mergeable \" +\n \"commits(last:1){nodes{commit{statusCheckRollup{state}}}}}}}}\";\n const out = await gh([\n \"api\",\n \"graphql\",\n \"-f\",\n `query=${query}`,\n \"-F\",\n `owner=${owner}`,\n \"-F\",\n `name=${name}`,\n ]);\n const parsed = JSON.parse(out) as {\n data?: {\n repository?: {\n pullRequests?: {\n nodes?: Array<{\n number: number;\n title: string;\n url: string;\n headRefName: string;\n mergeable?: string;\n commits?: {\n nodes?: Array<{ commit?: { statusCheckRollup?: { state?: string } } }>;\n };\n }>;\n };\n };\n };\n };\n const nodes = parsed.data?.repository?.pullRequests?.nodes ?? [];\n return nodes.map((n) => ({\n number: n.number,\n title: n.title,\n url: n.url,\n headRef: n.headRefName,\n ciState: mapRollupState(n.commits?.nodes?.[0]?.commit?.statusCheckRollup?.state),\n mergeable: mapMergeable(n.mergeable),\n }));\n },\n async defaultBranchStatus(repo) {\n const [owner, name, ...rest] = repo.split(\"/\");\n if (!owner || !name || rest.length > 0) {\n throw new Error(`defaultBranchStatus: expected \"owner/repo\", got \"${repo}\"`);\n }\n const query =\n \"query($owner:String!,$name:String!){repository(owner:$owner,name:$name){\" +\n \"defaultBranchRef{target{... on Commit{committedDate statusCheckRollup{state}}}}}}\";\n const out = await gh([\n \"api\",\n \"graphql\",\n \"-f\",\n `query=${query}`,\n \"-F\",\n `owner=${owner}`,\n \"-F\",\n `name=${name}`,\n ]);\n const parsed = JSON.parse(out) as {\n data?: {\n repository?: {\n defaultBranchRef?: {\n target?: { committedDate?: string; statusCheckRollup?: { state?: string } | null };\n } | null;\n };\n };\n };\n const target = parsed.data?.repository?.defaultBranchRef?.target;\n return {\n ciState: mapRollupState(target?.statusCheckRollup?.state),\n lastCommitAt: target?.committedDate ?? null,\n };\n },\n async dispatchWorkflow(repo, workflow, ref) {\n const [owner, name, ...rest] = repo.split(\"/\");\n if (!owner || !name || rest.length > 0) {\n throw new Error(`dispatchWorkflow: expected \"owner/repo\", got \"${repo}\"`);\n }\n // Every segment interpolates into the API path, so guard them all like the\n // other write methods do (defense in depth). `owner`/`name` are the most\n // operator-controlled (typed into Airtable's \"Git repo\"); `workflow` is a\n // constant today; `ref` is repo-sourced. A junk value like `repo?x=1` would\n // otherwise smuggle a query string past the bare two-part shape check.\n assertUrlSegment(\"path\", owner);\n assertUrlSegment(\"path\", name);\n assertUrlSegment(\"path\", workflow);\n assertUrlSegment(\"branch\", ref);\n await gh([\n \"api\",\n \"-X\",\n \"POST\",\n `repos/${owner}/${name}/actions/workflows/${workflow}/dispatches`,\n \"-f\",\n `ref=${ref}`,\n ]);\n },\n };\n}\n"],"mappings":";;;;;AAmCO,SAAS,iBAAiB,MAAyB,OAAqB;AAC7E,QAAM,aAAa;AACnB,MAAI,MAAM,WAAW,KAAK,MAAM,WAAW,GAAG,KAAK,WAAW,KAAK,KAAK,GAAG;AACzE,UAAM,IAAI;AAAA,MACR,UAAU,IAAI,uDAAuD,KAAK,UAAU,KAAK,CAAC;AAAA,IAC5F;AAAA,EACF;AACF;AAGA,SAAS,eAAe,OAA2C;AACjE,UAAQ,OAAO;AAAA,IACb,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EACX;AACF;AAKA,SAAS,aAAa,OAA+C;AACnE,SAAO,UAAU,eAAe,UAAU,gBAAgB,QAAQ;AACpE;AA2BO,SAAS,WAAW,MAAkD;AAC3E,QAAM,QAAQ,KAAK,SAAS;AAC5B,QAAM,MAAM,EAAE,GAAG,QAAQ,KAAK,UAAU,KAAK,MAAM;AAEnD,iBAAe,GAAG,MAAiC;AACjD,UAAM,IAAI,MAAM,MAAM,MAAM,MAAM,EAAE,KAAK,WAAW,IAAO,CAAC;AAC5D,QAAI,EAAE,SAAS,EAAG,OAAM,IAAI,MAAM,MAAM,KAAK,CAAC,CAAC,iBAAiB,EAAE,IAAI,MAAM,EAAE,OAAO,KAAK,CAAC,EAAE;AAC7F,WAAO,EAAE;AAAA,EACX;AAEA,SAAO;AAAA,IACL,MAAM,gBAAgB,MAAM,IAAI;AAC9B,YAAM,MAAM,MAAM,GAAG;AAAA,QACnB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,GAAG;AAAA,QACH;AAAA,QACA,GAAG;AAAA,QACH;AAAA,QACA,GAAG;AAAA,QACH;AAAA,QACA,GAAG;AAAA,MACL,CAAC;AACD,aAAO,EAAE,KAAK,IAAI,KAAK,EAAE;AAAA,IAC3B;AAAA,IACA,MAAM,oBAAoB,MAAM;AAC9B,YAAM,GAAG,CAAC,OAAO,MAAM,SAAS,SAAS,IAAI,IAAI,MAAM,uBAAuB,CAAC;AAAA,IACjF;AAAA,IACA,MAAM,cAAc,MAAM,QAAQ,gBAAgB;AAChD,uBAAiB,UAAU,MAAM;AACjC,YAAM,OAAO;AAAA,QACX;AAAA,QACA;AAAA,QACA;AAAA,QACA,SAAS,IAAI,aAAa,MAAM;AAAA,QAChC;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,GAAG,eAAe,QAAQ,CAAC,MAAM,CAAC,MAAM,sCAAsC,CAAC,EAAE,CAAC;AAAA,QAClF;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA,YAAM,GAAG,IAAI;AAAA,IACf;AAAA,IACA,MAAM,cAAc,MAAM,MAAM,OAAO;AACrC,YAAM,GAAG,CAAC,UAAU,OAAO,MAAM,UAAU,MAAM,UAAU,KAAK,CAAC;AAAA,IACnE;AAAA,IACA,MAAM,WAAW,MAAM;AACrB,YAAM,IAAI,MAAM,MAAM,MAAM,CAAC,OAAO,SAAS,IAAI,EAAE,GAAG,EAAE,KAAK,WAAW,IAAO,CAAC;AAChF,aAAO,EAAE,SAAS;AAAA,IACpB;AAAA,IACA,MAAM,cAAc,MAAM;AACxB,YAAM,MAAM,MAAM,GAAG,CAAC,OAAO,SAAS,IAAI,IAAI,QAAQ,iBAAiB,CAAC;AACxE,aAAO,IAAI,KAAK;AAAA,IAClB;AAAA;AAAA;AAAA;AAAA;AAAA,IAKA,MAAM,cAAc,MAAM,QAAQ,OAAO;AACvC,uBAAiB,UAAU,MAAM;AACjC,YAAM,UAAoB,CAAC;AAC3B,iBAAW,KAAK,OAAO;AACrB,yBAAiB,QAAQ,CAAC;AAC1B,cAAM,IAAI,MAAM,MAAM,MAAM,CAAC,OAAO,SAAS,IAAI,aAAa,CAAC,QAAQ,MAAM,EAAE,GAAG;AAAA,UAChF;AAAA,UACA,WAAW;AAAA,QACb,CAAC;AACD,YAAI,EAAE,SAAS,EAAG,SAAQ,KAAK,CAAC;AAAA,MAClC;AACA,aAAO;AAAA,IACT;AAAA,IACA,MAAM,yBAAyB,MAAM,QAAQ;AAC3C,uBAAiB,UAAU,MAAM;AACjC,YAAM,IAAI,MAAM;AAAA,QACd;AAAA,QACA;AAAA,UACE;AAAA,UACA,SAAS,IAAI,aAAa,MAAM;AAAA,UAChC;AAAA,UACA;AAAA,QACF;AAAA,QACA,EAAE,KAAK,WAAW,IAAO;AAAA,MAC3B;AACA,UAAI,EAAE,SAAS,EAAG,QAAO,CAAC;AAC1B,aAAO,EAAE,OACN,MAAM,IAAI,EACV,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,EACnB,OAAO,CAAC,MAAM,EAAE,SAAS,CAAC;AAAA,IAC/B;AAAA,IACA,MAAM,aAAa,MAAM,MAAM;AAG7B,YAAM,MAAM,MAAM,GAAG;AAAA,QACnB;AAAA,QACA,SAAS,IAAI;AAAA,QACb;AAAA,QACA;AAAA,MACF,CAAC;AACD,aAAO,IACJ,MAAM,IAAI,EACV,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,EACnB,SAAS,IAAI;AAAA,IAClB;AAAA,IACA,MAAM,iBAAiB,MAAM;AAC3B,YAAM,MAAM,MAAM,GAAG,CAAC,OAAO,SAAS,IAAI,IAAI,QAAQ,mBAAmB,CAAC;AAC1E,aAAO,IAAI,KAAK,MAAM;AAAA,IACxB;AAAA,IACA,MAAM,uBAAuB,MAAM;AAGjC,YAAM,MAAM,MAAM,GAAG;AAAA,QACnB;AAAA,QACA,SAAS,IAAI;AAAA,QACb;AAAA,QACA;AAAA,MACF,CAAC;AACD,YAAM,QAAQ,IACX,MAAM,IAAI,EACV,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,EACnB,KAAK,CAAC,MAAM,EAAE,SAAS,CAAC;AAC3B,aAAO,SAAS;AAAA,IAClB;AAAA,IACA,MAAM,iBAAiB,MAAM;AAC3B,YAAM,CAAC,OAAO,MAAM,GAAG,IAAI,IAAI,KAAK,MAAM,GAAG;AAC7C,UAAI,CAAC,SAAS,CAAC,QAAQ,KAAK,SAAS,GAAG;AACtC,cAAM,IAAI,MAAM,iDAAiD,IAAI,GAAG;AAAA,MAC1E;AACA,YAAM,QACJ;AAGF,YAAM,MAAM,MAAM,GAAG;AAAA,QACnB;AAAA,QACA;AAAA,QACA;AAAA,QACA,SAAS,KAAK;AAAA,QACd;AAAA,QACA,SAAS,KAAK;AAAA,QACd;AAAA,QACA,QAAQ,IAAI;AAAA,MACd,CAAC;AACD,YAAM,SAAS,KAAK,MAAM,GAAG;AAkB7B,YAAM,QAAQ,OAAO,MAAM,YAAY,cAAc,SAAS,CAAC;AAC/D,aAAO,MAAM,IAAI,CAAC,OAAO;AAAA,QACvB,QAAQ,EAAE;AAAA,QACV,OAAO,EAAE;AAAA,QACT,KAAK,EAAE;AAAA,QACP,SAAS,EAAE;AAAA,QACX,SAAS,eAAe,EAAE,SAAS,QAAQ,CAAC,GAAG,QAAQ,mBAAmB,KAAK;AAAA,QAC/E,WAAW,aAAa,EAAE,SAAS;AAAA,MACrC,EAAE;AAAA,IACJ;AAAA,IACA,MAAM,oBAAoB,MAAM;AAC9B,YAAM,CAAC,OAAO,MAAM,GAAG,IAAI,IAAI,KAAK,MAAM,GAAG;AAC7C,UAAI,CAAC,SAAS,CAAC,QAAQ,KAAK,SAAS,GAAG;AACtC,cAAM,IAAI,MAAM,oDAAoD,IAAI,GAAG;AAAA,MAC7E;AACA,YAAM,QACJ;AAEF,YAAM,MAAM,MAAM,GAAG;AAAA,QACnB;AAAA,QACA;AAAA,QACA;AAAA,QACA,SAAS,KAAK;AAAA,QACd;AAAA,QACA,SAAS,KAAK;AAAA,QACd;AAAA,QACA,QAAQ,IAAI;AAAA,MACd,CAAC;AACD,YAAM,SAAS,KAAK,MAAM,GAAG;AAS7B,YAAM,SAAS,OAAO,MAAM,YAAY,kBAAkB;AAC1D,aAAO;AAAA,QACL,SAAS,eAAe,QAAQ,mBAAmB,KAAK;AAAA,QACxD,cAAc,QAAQ,iBAAiB;AAAA,MACzC;AAAA,IACF;AAAA,IACA,MAAM,iBAAiB,MAAM,UAAU,KAAK;AAC1C,YAAM,CAAC,OAAO,MAAM,GAAG,IAAI,IAAI,KAAK,MAAM,GAAG;AAC7C,UAAI,CAAC,SAAS,CAAC,QAAQ,KAAK,SAAS,GAAG;AACtC,cAAM,IAAI,MAAM,iDAAiD,IAAI,GAAG;AAAA,MAC1E;AAMA,uBAAiB,QAAQ,KAAK;AAC9B,uBAAiB,QAAQ,IAAI;AAC7B,uBAAiB,QAAQ,QAAQ;AACjC,uBAAiB,UAAU,GAAG;AAC9B,YAAM,GAAG;AAAA,QACP;AAAA,QACA;AAAA,QACA;AAAA,QACA,SAAS,KAAK,IAAI,IAAI,sBAAsB,QAAQ;AAAA,QACpD;AAAA,QACA,OAAO,GAAG;AAAA,MACZ,CAAC;AAAA,IACH;AAAA,EACF;AACF;","names":[]}
package/dist/cli/bin.js CHANGED
@@ -104,7 +104,7 @@ cli.command("sync-configs [site]", "Sync canonical configs into a site.").option
104
104
  'Inventory file (.json or .mjs/.js), or "airtable" to read from Websites table'
105
105
  ).option("--workdir <path>", "Clone target for fleet mode (default ~/.reddoor-maint/sites)").action(
106
106
  async (site, opts) => runOrExit(
107
- async () => (await import("../sync-configs-ZYKZCP4C.js")).runSyncConfigsCommand(site, opts),
107
+ async () => (await import("../sync-configs-BZXBYKTI.js")).runSyncConfigsCommand(site, opts),
108
108
  opts
109
109
  )
110
110
  );
@@ -113,7 +113,7 @@ cli.command("bump-deps [site]", "Bump dependencies.").option("--group <group>",
113
113
  'Inventory file (.json or .mjs/.js), or "airtable" to read from Websites table'
114
114
  ).option("--workdir <path>", "Clone target for fleet mode (default ~/.reddoor-maint/sites)").action(
115
115
  async (site, opts) => runOrExit(
116
- async () => (await import("../bump-deps-6D4VCAFQ.js")).runBumpDepsCommand(site, opts),
116
+ async () => (await import("../bump-deps-RYHQIKW4.js")).runBumpDepsCommand(site, opts),
117
117
  opts
118
118
  )
119
119
  );
@@ -122,7 +122,7 @@ cli.command(
122
122
  "Bootstrap a repo to keep itself updated (CI + Renovate + auto-merge)."
123
123
  ).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(
124
124
  async (site, opts) => runOrExit(
125
- async () => (await import("../self-updating-J7U7WIP3.js")).runSelfUpdatingCommand(site, opts),
125
+ async () => (await import("../self-updating-CFHXJSAX.js")).runSelfUpdatingCommand(site, opts),
126
126
  opts
127
127
  )
128
128
  );
@@ -131,7 +131,7 @@ cli.command("upgrade <upgrade> [site]", "Run a named upgrade recipe (svelte-4-to
131
131
  'Inventory file (.json or .mjs/.js), or "airtable" to read from Websites table'
132
132
  ).option("--workdir <path>", "Clone target for fleet mode (default ~/.reddoor-maint/sites)").action(
133
133
  async (upgrade, site, opts) => runOrExit(
134
- async () => (await import("../upgrade-UAXREMED.js")).runUpgradeCommand(upgrade, site, opts),
134
+ async () => (await import("../upgrade-6YDUELFA.js")).runUpgradeCommand(upgrade, site, opts),
135
135
  opts
136
136
  )
137
137
  );
@@ -143,7 +143,7 @@ cli.command(
143
143
  'Inventory file (.json or .mjs/.js), or "airtable" to read from Websites table'
144
144
  ).option("--workdir <path>", "Clone target for fleet mode (default ~/.reddoor-maint/sites)").action(
145
145
  async (site, opts) => runOrExit(
146
- async () => (await import("../convert-to-pnpm-JYUUUDDP.js")).runConvertToPnpmCommand(site, opts),
146
+ async () => (await import("../convert-to-pnpm-KNCXU6FM.js")).runConvertToPnpmCommand(site, opts),
147
147
  opts
148
148
  )
149
149
  );
@@ -152,7 +152,7 @@ cli.command("svelte-codemods [site]", "Apply Svelte 5 gotcha codemods to an alre
152
152
  'Inventory file (.json or .mjs/.js), or "airtable" to read from Websites table'
153
153
  ).option("--workdir <path>", "Clone target for fleet mode (default ~/.reddoor-maint/sites)").action(
154
154
  async (site, opts) => runOrExit(
155
- async () => (await import("../svelte-codemods-BW4M4CDF.js")).runSvelteCodemodsCommand(site, opts),
155
+ async () => (await import("../svelte-codemods-HNITLWQM.js")).runSvelteCodemodsCommand(site, opts),
156
156
  opts
157
157
  )
158
158
  );
@@ -164,7 +164,7 @@ cli.command(
164
164
  'Inventory file (.json or .mjs/.js), or "airtable" to read from Websites table'
165
165
  ).option("--workdir <path>", "Clone target for fleet mode (default ~/.reddoor-maint/sites)").action(
166
166
  async (site, opts) => runOrExit(
167
- async () => (await import("../onboard-UM6UKX2V.js")).runOnboardCommand(site, opts),
167
+ async () => (await import("../onboard-SCZ3UKZ2.js")).runOnboardCommand(site, opts),
168
168
  opts
169
169
  )
170
170
  );
@@ -175,14 +175,14 @@ cli.command(
175
175
  "--fleet <inventory>",
176
176
  'Inventory file (.json or .mjs/.js), or "airtable" to read from Websites table'
177
177
  ).option("--workdir <path>", "Clone target for fleet mode (default ~/.reddoor-maint/sites)").action(
178
- async (site, opts) => runOrExit(async () => (await import("../init-6LJU72F2.js")).runInitCommand(site, opts), opts)
178
+ async (site, opts) => runOrExit(async () => (await import("../init-KD56UENX.js")).runInitCommand(site, opts), opts)
179
179
  );
180
180
  cli.command(
181
181
  "launch <site>",
182
182
  "Bootstrap + first-audit a site, then draft its launch email for approval."
183
183
  ).action(
184
184
  async (site, opts) => runOrExit(
185
- async () => (await import("../launch-6ZB3QA2I.js")).runLaunchCommand(site, opts),
185
+ async () => (await import("../launch-UWCI3JRM.js")).runLaunchCommand(site, opts),
186
186
  opts
187
187
  )
188
188
  );
@@ -191,7 +191,7 @@ cli.command(
191
191
  "Draft the monthly-report announcement email for maintenance sites (all, or one) for approval."
192
192
  ).action(
193
193
  async (site, opts) => runOrExit(
194
- async () => (await import("../announce-JO67XZLZ.js")).runAnnounceCommand(site, opts),
194
+ async () => (await import("../announce-Q2DXP5OO.js")).runAnnounceCommand(site, opts),
195
195
  opts
196
196
  )
197
197
  );
@@ -206,7 +206,7 @@ cli.command("report [site]", "Draft or send maintenance/testing reports.").optio
206
206
  "Email the operator one daily digest of reports ready for approval (skips when empty)."
207
207
  ).action(
208
208
  async (site, opts) => runOrExit(
209
- async () => (await import("../report-3YVSMRFE.js")).runReportCommand(site, opts),
209
+ async () => (await import("../report-CN56TGMK.js")).runReportCommand(site, opts),
210
210
  opts
211
211
  )
212
212
  );
@@ -215,7 +215,7 @@ cli.command(
215
215
  "Sweep the fleet for GitHub signals (Renovate-failing/CI/last-commit) and write Airtable."
216
216
  ).option("--fleet", "Run across every site in the Airtable inventory.").option("--write-airtable", "Write each site's signals back to its Websites row.").action(
217
217
  async (opts) => runOrExit(
218
- async () => (await import("../github-signals-JXHRHDAG.js")).runGitHubSignalsCommand({
218
+ async () => (await import("../github-signals-UL2BBS3Q.js")).runGitHubSignalsCommand({
219
219
  fleet: opts.fleet,
220
220
  writeAirtable: opts.writeAirtable
221
221
  }),
@@ -233,7 +233,7 @@ cli.command(
233
233
  "Trigger Renovate on fleet sites the security sweep flagged with critical/high vulns."
234
234
  ).option("--fleet", "Run across every active, repo-backed site in the Airtable inventory.").action(
235
235
  async (opts) => runOrExit(
236
- async () => (await import("../renovate-dispatch-L5HWCNRY.js")).runRenovateDispatchCommand({
236
+ async () => (await import("../renovate-dispatch-NG5KUQKY.js")).runRenovateDispatchCommand({
237
237
  fleet: opts.fleet
238
238
  }),
239
239
  opts
@@ -5,11 +5,11 @@ import {
5
5
  } from "../../chunk-4NAOR44V.js";
6
6
  import {
7
7
  resolveSites
8
- } from "../../chunk-IDRBAF2H.js";
8
+ } from "../../chunk-6CSCLBAA.js";
9
9
  import {
10
10
  ALL_AUDIT_NAMES,
11
11
  runOneAudit
12
- } from "../../chunk-4PY4I5OR.js";
12
+ } from "../../chunk-5PHCZ6L5.js";
13
13
  import "../../chunk-LKGVSM2O.js";
14
14
  import "../../chunk-FDIFTIXC.js";
15
15
  import "../../chunk-HVOOCK6L.js";
@@ -215,9 +215,9 @@ ${skipNotice}`;
215
215
  let writeBackFailed = false;
216
216
  if (opts.writeAirtable !== void 0) {
217
217
  const { openBase, readAirtableConfig } = await import("../../client-EPVO3FEH.js");
218
- const { listWebsites } = await import("../../websites-EEZVZXQT.js");
218
+ const { listWebsites } = await import("../../websites-IYP7IGLU.js");
219
219
  if (opts.fleet !== void 0) {
220
- const { writeFleetAuditsToAirtable, formatFleetWriteSummary } = await import("../../write-audits-to-airtable-LUFY424L.js");
220
+ const { writeFleetAuditsToAirtable, formatFleetWriteSummary } = await import("../../write-audits-to-airtable-VDGHCZGQ.js");
221
221
  const base = openBase(readAirtableConfig());
222
222
  const websites = await listWebsites(base);
223
223
  const fleetWrite = await writeFleetAuditsToAirtable({ base, websites, results });
@@ -226,8 +226,8 @@ ${skipNotice}`;
226
226
 
227
227
  ${formatFleetWriteSummary(fleetWrite)}`;
228
228
  } else {
229
- const { resolveSlugFromCwd } = await import("../../lighthouse-airtable-FSGOUVMQ.js");
230
- const { writeAuditsToAirtable } = await import("../../write-audits-to-airtable-LUFY424L.js");
229
+ const { resolveSlugFromCwd } = await import("../../lighthouse-airtable-N3KCBPVA.js");
230
+ const { writeAuditsToAirtable } = await import("../../write-audits-to-airtable-VDGHCZGQ.js");
231
231
  const slug = typeof opts.writeAirtable === "string" && opts.writeAirtable.length > 0 ? opts.writeAirtable : await resolveSlugFromCwd(cwd);
232
232
  let writeSummary = null;
233
233
  await new Listr(
@@ -5,7 +5,7 @@ import {
5
5
  } from "./chunk-4NAOR44V.js";
6
6
  import {
7
7
  resolveSites
8
- } from "./chunk-IDRBAF2H.js";
8
+ } from "./chunk-6CSCLBAA.js";
9
9
  import {
10
10
  convertToPnpm
11
11
  } from "./chunk-2X322ZES.js";
@@ -48,4 +48,4 @@ async function runConvertToPnpmCommand(site, opts) {
48
48
  export {
49
49
  runConvertToPnpmCommand
50
50
  };
51
- //# sourceMappingURL=convert-to-pnpm-JYUUUDDP.js.map
51
+ //# sourceMappingURL=convert-to-pnpm-KNCXU6FM.js.map
@@ -9,7 +9,7 @@ import {
9
9
  import {
10
10
  listWebsites,
11
11
  siteSlug
12
- } from "./chunk-PKIYAWA4.js";
12
+ } from "./chunk-L4ULXHIN.js";
13
13
  import {
14
14
  openBase,
15
15
  readAirtableConfig
@@ -410,4 +410,4 @@ export {
410
410
  renderDigestHtml,
411
411
  runDigest
412
412
  };
413
- //# sourceMappingURL=digest-RUQ42QXL.js.map
413
+ //# sourceMappingURL=digest-RVIOHUXR.js.map
@@ -3,17 +3,17 @@ import {
3
3
  } from "./chunk-PZQ3WED2.js";
4
4
  import {
5
5
  formatFleetWriteSummary
6
- } from "./chunk-IJW4DS2S.js";
7
- import "./chunk-RYECSIEA.js";
6
+ } from "./chunk-LMXIZITU.js";
7
+ import "./chunk-HPSGCDWY.js";
8
8
  import {
9
9
  makeGitHub
10
- } from "./chunk-J4ECCFRT.js";
10
+ } from "./chunk-XB6T4ETK.js";
11
11
  import "./chunk-HVOOCK6L.js";
12
12
  import {
13
13
  listWebsites,
14
14
  siteSlug,
15
15
  updateGitHubSignals
16
- } from "./chunk-PKIYAWA4.js";
16
+ } from "./chunk-L4ULXHIN.js";
17
17
  import {
18
18
  openBase,
19
19
  readAirtableConfig
@@ -113,4 +113,4 @@ export {
113
113
  githubSignalsExitCode,
114
114
  runGitHubSignalsCommand
115
115
  };
116
- //# sourceMappingURL=github-signals-JXHRHDAG.js.map
116
+ //# sourceMappingURL=github-signals-UL2BBS3Q.js.map