Archilyzer · Source

archilyzer

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

commit f991e35b2a78ad01740bfb7b4cc8e5225ef9d070
parent 2e6144647711fae5b94c9d2343c795fcc24113f9
Author: I Mean I'm Just Saying <imeanimjustsaying@kiwifarms.st>
Date:   Mon, 28 Sep 2026 19:59:31 -0400

umtool: cwd-derived paths opt out of Turbopack's asset tracing

Slice Q's `path.join(REPO_ROOT, "transcripts", "channels")`, with
REPO_ROOT = findRepoRoot(process.cwd()), was evaluated by Turbopack as a
directory asset reference to the corpus: `next build` in the primary
checkout walked hundreds of GB until the kernel killed it, or died on
the first symlink out of the root. A worktree has no transcripts/ and
built in 30 s, which is how it shipped.

Every path op on a value derived from process.cwd() or import.meta.url
in a module the app imports now opens with the documented per-expression
opt-out, `/* turbopackIgnore: true */`: lib/paths.mjs (findRepoRoot,
CHANNELS_DIR), lib/paths.ts (SONG_CODE, stateFile), lib/tools.mjs,
lib/trim.ts, lib/report/driver.mjs, report-to-video/brand.mjs and
cues.mjs. The values at run time are unchanged. With the corpus linked,
the build under a 5 GB cap succeeds in 24 s at 0.80 GB max RSS, the
same 1,009 files and 28 MB as without it; nothing under transcripts/
is traced. os.homedir() joins are left as they are: the tracer does not
follow them.

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

Diffstat:
Mumtool/lib/paths.mjs | 22++++++++++++++++------
Mumtool/lib/paths.ts | 4++--
Mumtool/lib/report/driver.mjs | 8++++----
Mumtool/lib/tools.mjs | 4++--
Mumtool/lib/trim.ts | 2+-
Mumtool/report-to-video/brand.mjs | 12++++++------
Mumtool/report-to-video/cues.mjs | 4++--
7 files changed, 33 insertions(+), 23 deletions(-)

diff --git a/umtool/lib/paths.mjs b/umtool/lib/paths.mjs @@ -98,13 +98,22 @@ const dedupe = (list) => [...new Set(list.map((p) => path.resolve(p)))]; * all run with cwd inside the checkout (the app at umtool/, which is what the * fallback assumes). report-to-video/cues.mjs keeps its import.meta.url walk: * only its CLI entry points (build-video, resolve-windows) read that default. + * + * EVERY PATH OP ON A cwd-DERIVED VALUE CARRIES `turbopackIgnore`. Turbopack + * evaluates `process.cwd()` statically as the project, so an un-annotated + * `path.join(REPO_ROOT, "transcripts", "channels")` became a DIRECTORY ASSET + * REFERENCE: `next build` walked the whole corpus (hundreds of GB, `data/` + * symlinked to another drive) and was OOM-killed, or died on the first symlink + * out of the root. A worktree with no transcripts/ builds fine, which is how it + * shipped. The comment is the documented per-expression opt-out; the values at + * run time are unchanged. scripts/umtool-build-trace.test.mjs holds the line. */ export function findRepoRoot(start) { - let dir = path.resolve(start); + let dir = path.resolve(/* turbopackIgnore: true */ start); for (;;) { - if (existsSync(path.join(dir, "pnpm-workspace.yaml"))) return dir; - const up = path.dirname(dir); - if (up === dir) return path.resolve(start, ".."); + if (existsSync(path.join(/* turbopackIgnore: true */ dir, "pnpm-workspace.yaml"))) return dir; + const up = path.dirname(/* turbopackIgnore: true */ dir); + if (up === dir) return path.resolve(/* turbopackIgnore: true */ start, ".."); dir = up; } } @@ -112,10 +121,11 @@ export function findRepoRoot(start) { export const REPO_ROOT = findRepoRoot(process.cwd()); export const CHANNELS_DIR = path.resolve( + /* turbopackIgnore: true */ process.env.CHANNELS_DIR ?? (process.env.TRANSCRIPTS_DIR - ? path.join(process.env.TRANSCRIPTS_DIR, "channels") - : path.join(REPO_ROOT, "transcripts", "channels")), + ? path.join(/* turbopackIgnore: true */ process.env.TRANSCRIPTS_DIR, "channels") + : path.join(/* turbopackIgnore: true */ REPO_ROOT, "transcripts", "channels")), ); export const READ_ROOTS = dedupe( diff --git a/umtool/lib/paths.ts b/umtool/lib/paths.ts @@ -39,9 +39,9 @@ export { // cwd at the package root. export const SONG_CODE = process.env.SONG_CODE_DIR ? path.resolve(process.env.SONG_CODE_DIR) - : path.join(process.cwd(), "song"); + : path.join(/* turbopackIgnore: true */ process.cwd(), "song"); -export const stateFile = (name: string) => path.join(SONG_CODE, name); +export const stateFile = (name: string) => path.join(/* turbopackIgnore: true */ SONG_CODE, name); // dataFile needs SONG_DATA at module scope, which the re-export above does not // bind locally -- so it is imported again rather than duplicated. diff --git a/umtool/lib/report/driver.mjs b/umtool/lib/report/driver.mjs @@ -11,9 +11,9 @@ import path from "node:path"; /** Where the pipeline lives. One place, so a move is one edit. */ -export const PIPELINE_DIR = path.resolve(process.cwd(), "report-to-video"); +export const PIPELINE_DIR = path.resolve(/* turbopackIgnore: true */ process.cwd(), "report-to-video"); -const script = (name) => path.join(PIPELINE_DIR, name); +const script = (name) => path.join(/* turbopackIgnore: true */ PIPELINE_DIR, name); /** * Presets, in the order somebody actually works. @@ -322,9 +322,9 @@ export function checkSourcesSteps(projects, env = {}) { // --------------------------------------------------------------------------- /** This package's own root. bin/ lives here, and so does report-to-video/. */ -export const UMTOOL_DIR = path.resolve(process.cwd()); +export const UMTOOL_DIR = path.resolve(/* turbopackIgnore: true */ process.cwd()); -const tool = (name) => path.join(UMTOOL_DIR, "bin", name); +const tool = (name) => path.join(/* turbopackIgnore: true */ UMTOOL_DIR, "bin", name); /** The interpreter a project's own scripts are run with. */ export const PYTHON = process.env.PYTHON_BIN ?? "python3"; diff --git a/umtool/lib/tools.mjs b/umtool/lib/tools.mjs @@ -19,8 +19,8 @@ import { SONG_SCRATCH } from "./paths.mjs"; export const facedetPython = () => process.env.FACEDET_PYTHON ?? path.join(SONG_SCRATCH, "facedet", "bin", "python"); export const songCode = () => - process.env.SONG_CODE_DIR ? path.resolve(process.env.SONG_CODE_DIR) : path.join(process.cwd(), "song"); -export const facecropPy = () => path.join(songCode(), "facecrop.py"); + process.env.SONG_CODE_DIR ? path.resolve(process.env.SONG_CODE_DIR) : path.join(/* turbopackIgnore: true */ process.cwd(), "song"); +export const facecropPy = () => path.join(/* turbopackIgnore: true */ songCode(), "facecrop.py"); /** * The tools, with the env override each pipeline script honours. `required` diff --git a/umtool/lib/trim.ts b/umtool/lib/trim.ts @@ -222,7 +222,7 @@ export function hookRecipe( const trimDir = `mkvocals/hooks-trim-${stamp}`; const takeDir = `mkvocals/hooks-best-${stamp}`; const outOverlays = dataFile(pair.to.replace(/\.json$/, `-${stamp}.json`)); - const cwd = path.join(process.cwd(), "song"); + const cwd = path.join(/* turbopackIgnore: true */ process.cwd(), "song"); const base = { SONG_DIR: SONG_DATA }; return [ diff --git a/umtool/report-to-video/brand.mjs b/umtool/report-to-video/brand.mjs @@ -37,17 +37,17 @@ import { readFileSync } from "node:fs"; import path from "node:path"; import { fileURLToPath } from "node:url"; -const HERE = path.dirname(fileURLToPath(import.meta.url)); +const HERE = path.dirname(/* turbopackIgnore: true */ fileURLToPath(import.meta.url)); import { BRAND_CHOICES, BRAND_IDS } from "./brand-ids.mjs"; import { IBM_PLEX_SANS } from "./svg-faces.mjs"; export { BRAND_CHOICES, BRAND_IDS }; -export const FONTS_DIR = path.join(HERE, "fonts"); -export const FONTCONFIG_FILE = path.join(FONTS_DIR, "fonts.conf"); -export const MONO_FONT_FILE = path.join(FONTS_DIR, "IBMPlexMono-Regular.ttf"); +export const FONTS_DIR = path.join(/* turbopackIgnore: true */ HERE, "fonts"); +export const FONTCONFIG_FILE = path.join(/* turbopackIgnore: true */ FONTS_DIR, "fonts.conf"); +export const MONO_FONT_FILE = path.join(/* turbopackIgnore: true */ FONTS_DIR, "IBMPlexMono-Regular.ttf"); /** Plex Mono's static Bold: `render.fontBold`, which compose-chrome's HyperFrames band sets its bold in. */ -export const MONO_BOLD_FONT_FILE = path.join(FONTS_DIR, "IBMPlexMono-Bold.ttf"); +export const MONO_BOLD_FONT_FILE = path.join(/* turbopackIgnore: true */ FONTS_DIR, "IBMPlexMono-Bold.ttf"); /** The end card's default length: YouTube's end screen runs in the last 5–20 s. */ export const END_CARD_DEFAULT_SECONDS = 20; @@ -79,7 +79,7 @@ export function brandKit(id) { throw new Error(`render.brand "${id}" is not a preset — one of ${BRAND_IDS.join(", ")}`); } if (!kits.has(id)) { - kits.set(id, JSON.parse(readFileSync(path.join(HERE, "brands", `${id}.json`), "utf8"))); + kits.set(id, JSON.parse(readFileSync(path.join(/* turbopackIgnore: true */ HERE, "brands", `${id}.json`), "utf8"))); } return kits.get(id); } diff --git a/umtool/report-to-video/cues.mjs b/umtool/report-to-video/cues.mjs @@ -58,10 +58,10 @@ import { fileURLToPath } from "node:url"; // checkout would have is two levels up. Previously this defaulted to an absolute // path inside the original author's home directory, which meant every other // clone silently looked in a directory that does not exist. -const REPO_ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..", ".."); +const REPO_ROOT = path.resolve(/* turbopackIgnore: true */ path.dirname(/* turbopackIgnore: true */ fileURLToPath(import.meta.url)), "..", ".."); export const DEFAULT_CHANNELS_DIR = - process.env.CHANNELS_DIR ?? path.join(REPO_ROOT, "transcripts", "channels"); + process.env.CHANNELS_DIR ?? path.join(/* turbopackIgnore: true */ REPO_ROOT, "transcripts", "channels"); const DEFAULT_CACHE_DIR = process.env.REPORT_CACHE_DIR ??