#!/usr/bin/env node /** * run-check.mjs — aggregate quality check runner (M1, S-106) * * Runs every quality gate in sequence and reports a summary. * All steps run even if earlier steps fail, so you get a complete * picture of the repository health in one pass. * * Transitional contract (M1): * This script may exit non-zero. Pre-existing failures are recorded in * docs/CLEANUP-BASELINE.md. Only issues introduced by new changes (not * listed in the baseline) constitute a regression. * * Usage: * node scripts/lib/run-check.mjs # full check * pnpm run check # same, via pnpm */ import { spawnSync } from "node:child_process"; import path from "node:path"; import { fileURLToPath } from "node:url"; const __dirname = path.dirname(fileURLToPath(import.meta.url)); const REPO_ROOT = path.resolve(__dirname, "../.."); // ── Steps ────────────────────────────────────────────────────────────────── const STEPS = [ { label: "lint", cmd: "pnpm", args: ["run", "lint"] }, { label: "typecheck", cmd: "pnpm", args: ["run", "typecheck"] }, { label: "test", cmd: "pnpm", args: ["run", "test"] }, { label: "verify:pi", cmd: "pnpm", args: ["run", "verify:pi"] }, { label: "verify:reviewers", cmd: "pnpm", args: ["run", "verify:reviewers"] }, { label: "verify:docs", cmd: "pnpm", args: ["run", "verify:docs"] }, { label: "verify:generated", cmd: "pnpm", args: ["run", "verify:generated"] }, { label: "verify:ci", cmd: "pnpm", args: ["run", "verify:ci"] }, ]; // ── Runner ───────────────────────────────────────────────────────────────── const RESET = "\x1b[0m"; const GREEN = "\x1b[32m"; const RED = "\x1b[31m"; const BOLD = "\x1b[1m"; const DIM = "\x1b[2m"; function colorize(color, text) { // Respect NO_COLOR env variable if (process.env.NO_COLOR || process.env.CI) return text; return `${color}${text}${RESET}`; } const results = []; for (const step of STEPS) { process.stdout.write(`\n${colorize(BOLD, `=== ${step.label} ===`)}\n`); const result = spawnSync(step.cmd, step.args, { cwd: REPO_ROOT, stdio: "inherit", encoding: "utf8", shell: false, }); const ok = result.status === 0 && !result.error; results.push({ label: step.label, ok, status: result.status ?? -1 }); } // ── Summary ──────────────────────────────────────────────────────────────── process.stdout.write(`\n${colorize(BOLD, "=== check summary ===")}\n`); const failures = []; for (const r of results) { if (r.ok) { process.stdout.write( ` ${colorize(GREEN, "PASS")} ${r.label}\n` ); } else { process.stdout.write( ` ${colorize(RED, "FAIL")} ${r.label} ${colorize(DIM, `(exit ${r.status})`)} — see docs/CLEANUP-BASELINE.md if pre-existing\n` ); failures.push(r.label); } } process.stdout.write("\n"); if (failures.length === 0) { process.stdout.write(colorize(GREEN, "All checks passed.\n")); process.exit(0); } else { process.stdout.write( colorize( RED, `${failures.length} check(s) failed: ${failures.join(", ")}\n` ) ); process.exit(1); }