From 33840e53ed21b5761eae7e07a48bdfba8599aba3 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 1 Nov 2026 08:56:29 +0000 Subject: [PATCH 1/2] Add make fast for the quickest local check Co-Authored-By: Claude Sonnet 5.5 --- Makefile | 8 +++++++- scripts/fast.test.ts | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 scripts/fast.test.ts diff --git a/Makefile b/Makefile index cf22ffe..70551ae 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: factory-maintain lab next progress prove-homework doctor dev check check-affected prove levels claude smoke hooks eval factory exercise +.PHONY: fast factory-maintain lab next progress prove-homework doctor dev check check-affected prove levels claude smoke hooks eval factory exercise doctor: @node -v | grep -qE '^v2[2-9]' && echo "ok node $$(node -v)" || (echo "need Node 22+" && exit 1) @@ -22,6 +22,12 @@ check: check-affected: npx tsx scripts/check-affected.ts $(if $(BASE),--base $(BASE)) +# Quickest local read on the first red CI step: lint, types, then only the affected checks. make check stays the gate. +fast: + npm run lint + npm run typecheck + npx tsx scripts/check-affected.ts --base origin/main + prove: npm run prove -- $(LEVEL) diff --git a/scripts/fast.test.ts b/scripts/fast.test.ts new file mode 100644 index 0000000..6e7c6f9 --- /dev/null +++ b/scripts/fast.test.ts @@ -0,0 +1,38 @@ +import { readFileSync } from "node:fs"; +import { describe, expect, it } from "vitest"; + +const makefile = readFileSync("Makefile", "utf8"); + +// The tab-indented lines of one target's recipe. +function recipe(target: string): string[] { + const lines = makefile.split("\n"); + const start = lines.indexOf(`${target}:`); + if (start < 0) return []; + const body: string[] = []; + for (const line of lines.slice(start + 1)) { + if (!line.startsWith("\t")) break; + body.push(line.trim()); + } + return body; +} + +describe("make fast", () => { + it("is declared phony", () => { + const phony = makefile.split("\n").find((l) => l.startsWith(".PHONY:")) ?? ""; + expect(phony.split(/\s+/)).toContain("fast"); + }); + + it("runs lint, typecheck, then the affected checks against origin/main", () => { + expect(recipe("fast")).toEqual([ + "npm run lint", + "npm run typecheck", + "npx tsx scripts/check-affected.ts --base origin/main", + ]); + }); + + it("is not called from check, which stays the gate", () => { + const check = recipe("check"); + expect(check.length).toBeGreaterThan(0); + expect(check.join("\n")).not.toMatch(/\bfast\b/); + }); +}); From 619be0172612516324674f05c75f1f23bb78f068 Mon Sep 17 00:00:00 2001 From: Param Harrison Date: Sun, 1 Nov 2026 12:12:35 +0200 Subject: [PATCH 2/2] Give scripts/fast.test.ts an owner Co-Authored-By: Claude Sonnet 5.5 --- levels.json | 1 + 1 file changed, 1 insertion(+) diff --git a/levels.json b/levels.json index 9c18370..c3cef48 100644 --- a/levels.json +++ b/levels.json @@ -168,6 +168,7 @@ "scripts/impact.ts", "scripts/impact.test.ts", "scripts/check-affected.ts", + "scripts/fast.test.ts", "tests/structure/impact.test.ts", "scripts/dependencies.ts", "tests/structure/dependency-drift.test.ts",