From d0e7daeb45b5f2b5d9f5481e1617ce4d51507115 Mon Sep 17 00:00:00 2001 From: Youngsup Oh Date: Mon, 2 Nov 2026 21:53:02 +0900 Subject: [PATCH 1/2] feat: detect Umi temp directories as safe Node build artifacts Umi generates .umi, .umi-production and .umi-test (entry, routes and webpack cache) under src/ when it exists, else at the project root, and regenerates them on dev, build and test. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_018n8bPcGZaeNmytfiBseBPR --- docs/SPEC.md | 2 ++ internal/scanner/node.go | 8 ++++++++ internal/scanner/node_test.go | 16 ++++++++++++++++ 3 files changed, 26 insertions(+) diff --git a/docs/SPEC.md b/docs/SPEC.md index 30f0e3c..242f629 100644 --- a/docs/SPEC.md +++ b/docs/SPEC.md @@ -370,6 +370,8 @@ Sizes use **decimal SI units** (1 KB = 1000 B). `--min-size` uses the same conve | `.parcel-cache` | cache | safe | Parcel cache | | `coverage` | build | safe | Test coverage reports | | `.svelte-kit` | build | safe | SvelteKit cache | +| `src/.umi`, `src/.umi-production`, `src/.umi-test` | build | safe | Umi temp dirs (generated entry, routes, webpack cache) | +| `.umi`, `.umi-production`, `.umi-test` | build | safe | Umi temp dirs when the project has no `src/` | **pnpm-installed `node_modules`**: pnpm clones (macOS) or hard-links (Linux) pnpm store files into `node_modules` by default, so deleting it alone frees little; running `pnpm store prune` afterwards removes packages no project references. The result carries this note when `node_modules/.modules.yaml` (written by pnpm on install, JSON since pnpm 12; `pnpm-lock.yaml` alone does not prove pnpm populated the folder) names a `storeDir` that exists on the same volume. On macOS its `size` leaves out blocks shared with the store or other projects. A store on another volume forces pnpm to copy, so no note is given. `packageImportMethod: copy` is not recorded in `.modules.yaml`, so such installs still get the note. diff --git a/internal/scanner/node.go b/internal/scanner/node.go index 048049e..f6a74a7 100644 --- a/internal/scanner/node.go +++ b/internal/scanner/node.go @@ -25,6 +25,14 @@ var nodeWalkEcosystem = walkEcosystem{ {RelPath: ".parcel-cache", Category: model.CatCache, Safety: model.SafetySafe}, // Parcel cache {RelPath: "coverage", Category: model.CatBuild, Safety: model.SafetySafe}, // Test coverage reports {RelPath: ".svelte-kit", Category: model.CatBuild, Safety: model.SafetySafe}, // SvelteKit cache + // Umi temp dirs (generated entry, routes and webpack cache), under src/ + // when it exists, else at the project root. + {RelPath: "src/.umi", Category: model.CatBuild, Safety: model.SafetySafe}, + {RelPath: "src/.umi-production", Category: model.CatBuild, Safety: model.SafetySafe}, + {RelPath: "src/.umi-test", Category: model.CatBuild, Safety: model.SafetySafe}, + {RelPath: ".umi", Category: model.CatBuild, Safety: model.SafetySafe}, + {RelPath: ".umi-production", Category: model.CatBuild, Safety: model.SafetySafe}, + {RelPath: ".umi-test", Category: model.CatBuild, Safety: model.SafetySafe}, }, ExtraRules: nodeExtraRules, } diff --git a/internal/scanner/node_test.go b/internal/scanner/node_test.go index 5ff86c5..0ae92d2 100644 --- a/internal/scanner/node_test.go +++ b/internal/scanner/node_test.go @@ -41,6 +41,22 @@ func TestNodeWalk(t *testing.T) { tree: []string{"app/package.json", "app/node_modules/pkg/package.json", "app/node_modules/pkg/node_modules/dep/index.js"}, want: []artifact{safe("app/node_modules", model.CatDeps)}, }, + { + name: "umi temp dirs under src and at the root", + ecos: node, + tree: []string{ + "crm/package.json", "crm/src/pages/index.tsx", + "crm/src/.umi/.cache/0.pack", "crm/src/.umi-production/umi.ts", "crm/src/.umi-test/umi.ts", + "flat/package.json", "flat/.umi/umi.ts", "flat/.umi-production/umi.ts", + }, + want: []artifact{ + safe("crm/src/.umi", model.CatBuild), + safe("crm/src/.umi-production", model.CatBuild), + safe("crm/src/.umi-test", model.CatBuild), + safe("flat/.umi", model.CatBuild), + safe("flat/.umi-production", model.CatBuild), + }, + }, { name: "react native via ios/Podfile", ecos: node, From 8ea03d69ac5b769b31ec7a4e526364d11707d688 Mon Sep 17 00:00:00 2001 From: Youngsup Oh Date: Mon, 2 Nov 2026 22:01:04 +0900 Subject: [PATCH 2/2] fix: state that root Umi temp dirs match even when src/ exists Cover the root .umi of a project with src/ and the root .umi-test in the Umi scanner test. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_018n8bPcGZaeNmytfiBseBPR --- docs/SPEC.md | 2 +- internal/scanner/node.go | 5 +++-- internal/scanner/node_test.go | 5 ++++- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/docs/SPEC.md b/docs/SPEC.md index 242f629..a437781 100644 --- a/docs/SPEC.md +++ b/docs/SPEC.md @@ -371,7 +371,7 @@ Sizes use **decimal SI units** (1 KB = 1000 B). `--min-size` uses the same conve | `coverage` | build | safe | Test coverage reports | | `.svelte-kit` | build | safe | SvelteKit cache | | `src/.umi`, `src/.umi-production`, `src/.umi-test` | build | safe | Umi temp dirs (generated entry, routes, webpack cache) | -| `.umi`, `.umi-production`, `.umi-test` | build | safe | Umi temp dirs when the project has no `src/` | +| `.umi`, `.umi-production`, `.umi-test` | build | safe | Umi temp dirs at the project root (where Umi writes them when the project has no `src/`; also matched when `src/` exists) | **pnpm-installed `node_modules`**: pnpm clones (macOS) or hard-links (Linux) pnpm store files into `node_modules` by default, so deleting it alone frees little; running `pnpm store prune` afterwards removes packages no project references. The result carries this note when `node_modules/.modules.yaml` (written by pnpm on install, JSON since pnpm 12; `pnpm-lock.yaml` alone does not prove pnpm populated the folder) names a `storeDir` that exists on the same volume. On macOS its `size` leaves out blocks shared with the store or other projects. A store on another volume forces pnpm to copy, so no note is given. `packageImportMethod: copy` is not recorded in `.modules.yaml`, so such installs still get the note. diff --git a/internal/scanner/node.go b/internal/scanner/node.go index f6a74a7..ed2d138 100644 --- a/internal/scanner/node.go +++ b/internal/scanner/node.go @@ -25,8 +25,9 @@ var nodeWalkEcosystem = walkEcosystem{ {RelPath: ".parcel-cache", Category: model.CatCache, Safety: model.SafetySafe}, // Parcel cache {RelPath: "coverage", Category: model.CatBuild, Safety: model.SafetySafe}, // Test coverage reports {RelPath: ".svelte-kit", Category: model.CatBuild, Safety: model.SafetySafe}, // SvelteKit cache - // Umi temp dirs (generated entry, routes and webpack cache), under src/ - // when it exists, else at the project root. + // Umi temp dirs (generated entry, routes and webpack cache). Umi writes + // them under src/ when it exists, else at the project root; both + // locations match regardless of src/. {RelPath: "src/.umi", Category: model.CatBuild, Safety: model.SafetySafe}, {RelPath: "src/.umi-production", Category: model.CatBuild, Safety: model.SafetySafe}, {RelPath: "src/.umi-test", Category: model.CatBuild, Safety: model.SafetySafe}, diff --git a/internal/scanner/node_test.go b/internal/scanner/node_test.go index 0ae92d2..01e887e 100644 --- a/internal/scanner/node_test.go +++ b/internal/scanner/node_test.go @@ -47,14 +47,17 @@ func TestNodeWalk(t *testing.T) { tree: []string{ "crm/package.json", "crm/src/pages/index.tsx", "crm/src/.umi/.cache/0.pack", "crm/src/.umi-production/umi.ts", "crm/src/.umi-test/umi.ts", - "flat/package.json", "flat/.umi/umi.ts", "flat/.umi-production/umi.ts", + "crm/.umi/umi.ts", + "flat/package.json", "flat/.umi/umi.ts", "flat/.umi-production/umi.ts", "flat/.umi-test/umi.ts", }, want: []artifact{ + safe("crm/.umi", model.CatBuild), safe("crm/src/.umi", model.CatBuild), safe("crm/src/.umi-production", model.CatBuild), safe("crm/src/.umi-test", model.CatBuild), safe("flat/.umi", model.CatBuild), safe("flat/.umi-production", model.CatBuild), + safe("flat/.umi-test", model.CatBuild), }, }, {