Archilyzer · Source

archilyzer

Archilyzer
git clone https://archilyzer.pages.dev/source/archilyzer.git
Log | Files | Refs | README | LICENSE

commit e2de3bafc1eb2b004ecd81e55687e2b5a33fbc94
parent 8c8f80fa87cec78e941aa7dec3fd9dcbc30b245f
Author: I Mean I'm Just Saying <imeanimjustsaying@kiwifarms.st>
Date:   Tue, 29 Sep 2026 22:52:15 -0400

scripts: review L1 + L2 + L3 — only the build's own cache/ and dev/ are left unread (a test pins it); the post-build check's comment says that with the excludes in place it sees such a pattern only through a name they miss; "left 31 of the 68 routes clean"

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

Diffstat:
Mscripts/next-build-trace.test.mjs | 45+++++++++++++++++++++++++++++++++++----------
1 file changed, 35 insertions(+), 10 deletions(-)

diff --git a/scripts/next-build-trace.test.mjs b/scripts/next-build-trace.test.mjs @@ -26,8 +26,8 @@ // ignored either: it is a dynamic part, and a path or fs call on it becomes a // PATTERN over the app's own directory. Measured in umtool (release 15, slice // UT): the path ops on env and home-directory values in its path modules took -// in the app's whole tree outside dot-directories (opting them out cleaned 31 -// of 68 routes), and the clip-audio route's join with a dynamic extension took +// in the app's whole tree outside dot-directories (opting them out left 31 of +// the 68 routes clean), and the clip-audio route's join with a dynamic extension took // in the dot-directories too, the e2e fixture and `.env.local` among them. // Neither walk entered a symlinked directory. No static check here can tell // such a pattern from a harmless one, so the last test reads a build's traces @@ -35,7 +35,8 @@ // // Run with: pnpm test:scripts import assert from "node:assert/strict"; -import { existsSync, readdirSync, readFileSync, statSync } from "node:fs"; +import { existsSync, mkdirSync, mkdtempSync, readdirSync, readFileSync, rmSync, statSync, writeFileSync } from "node:fs"; +import { tmpdir } from "node:os"; import path from "node:path"; import test from "node:test"; import { fileURLToPath } from "node:url"; @@ -382,12 +383,16 @@ test("the scan set follows relative imports out of the listed folders", () => { assert.ok(!apps.has("common/bin/compose-site.ts"), "a common CLI no app imports is scanned"); }); -/** Every `.nft.json` a build wrote under `dir`, its cache and dev-server output aside. */ -function traceFilesUnder(dir, out = []) { +/** + * Every `.nft.json` a build wrote under its directory `dist`, its cache and + * dev-server output (`dist/cache`, `dist/dev`) aside. Only those two: a route + * directory named `cache` or `dev` deeper down is read like any other. + */ +function traceFilesUnder(dist, dir = dist, out = []) { for (const e of readdirSync(dir, { withFileTypes: true })) { const p = path.join(dir, e.name); if (e.isDirectory()) { - if (e.name !== "cache" && e.name !== "dev") traceFilesUnder(p, out); + if (dir !== dist || (e.name !== "cache" && e.name !== "dev")) traceFilesUnder(dist, p, out); } else if (e.name.endsWith(".nft.json")) out.push(p); } return out; @@ -418,6 +423,20 @@ export function forbiddenTrace(abs, dist) { return null; } +test("traceFilesUnder: only the build's own cache/ and dev/ are left out", () => { + const dist = mkdtempSync(path.join(tmpdir(), "next-build-trace-")); + try { + for (const f of ["cache/a.nft.json", "dev/b.nft.json", "server/app/api/cache/route.js.nft.json", "server/app/dev/page.js.nft.json"]) { + mkdirSync(path.dirname(path.join(dist, f)), { recursive: true }); + writeFileSync(path.join(dist, f), '{"files":[]}'); + } + const found = traceFilesUnder(dist).map((f) => path.relative(dist, f)).sort(); + assert.deepEqual(found, ["server/app/api/cache/route.js.nft.json", "server/app/dev/page.js.nft.json"]); + } finally { + rmSync(dist, { recursive: true, force: true }); + } +}); + test("forbiddenTrace: a fixture, another build, a secret, the corpus, outside the repo", () => { const dist = path.join(UMTOOL, ".next"); const at = (p) => forbiddenTrace(path.join(REPO, p), dist); @@ -434,10 +453,16 @@ test("forbiddenTrace: a fixture, another build, a secret, the corpus, outside th // The static checks above cannot see a value Turbopack reads through an // import: `path.join(CACHE_DIR, `${stamp}.${asMp3 ? "mp3" : "wav"}`)` in -// umtool's clip-audio route made every file under umtool/ with a dot in its -// name part of that route's trace, the fixture and the e2e build's directory -// included (plans/release-15.md, slice UT). So the last build's traces are read -// back, when there is one. +// umtool's clip-audio route took umtool's dot-directories into that route's +// trace, the fixture and the e2e build's directory included (plans/release-15.md, +// slice UT). So the last build's traces are read back, when there is one. +// +// What this can see: umtool/next.config.ts now excludes `.e2e-song`, +// `.next-e2e` and `.env*` from every trace, so a pattern like that one shows +// here only through a name the excludes miss -- `test-results/.last-run.json` +// after an e2e run, `.next-shots`, the corpus, a path outside the repo. A +// checkout with no e2e run behind it is blind to it; the fix at the call is +// what keeps the route clean. test("umtool's last build traced no dot-directory, no corpus file and nothing outside the repo", (t) => { const dist = path.join(UMTOOL, ".next"); const id = path.join(dist, "BUILD_ID");