From e3546c71a1084bfc8d24d3eb8c6510c076923bba Mon Sep 17 00:00:00 2001 From: davion-knight <298846663+davion-knight@users.noreply.github.com> Date: Sun, 5 Jul 2026 07:02:09 -0500 Subject: [PATCH] feat(enrichment): categorize the full binary inventory as assets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit categorizeFile only recognized a narrow hand-listed set of binary extensions (png/jpg/jpeg/gif/webp/pdf/zip/gz/zst) as the `asset` category, so every other binary the shared inventory already knows — mp4, mov, webm, woff2, wasm, node, safetensors, gguf, onnx, and the rest — fell through to `source`, mislabeling a media/font/model-weight change as a source change. Delegate the check to the shared binary-extension inventory (`BINARY_EXT_RE` from analyzers/binary-extensions, the same source asset-weight and provenance use) instead of a duplicated list, matching the #3252 unification. `.svg` is text (deliberately not in the binary inventory) but is still an asset for categorization, so it is kept explicitly. Purely additive — only binaries that were previously `source` become `asset`; no other category changes. --- review-enrichment/src/analysis-context.ts | 11 +++---- .../test/analysis-context.test.ts | 30 +++++++++++++++++++ 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/review-enrichment/src/analysis-context.ts b/review-enrichment/src/analysis-context.ts index 752ef5beec..091664a4b3 100644 --- a/review-enrichment/src/analysis-context.ts +++ b/review-enrichment/src/analysis-context.ts @@ -19,6 +19,7 @@ import { } from "./external-fetch.js"; import { isWorkflowPath } from "./workflow-path.js"; import { isSupportedLockfile } from "./lockfile-path.js"; +import { BINARY_EXT_RE } from "./analyzers/binary-extensions.js"; type ChangedFile = NonNullable[number]; @@ -448,11 +449,11 @@ function categorizeFile(path: string): FileCategory { ) { return { path, extension, category: "docs" }; } - if ( - [".png", ".jpg", ".jpeg", ".gif", ".webp", ".svg", ".pdf", ".zip", ".gz", ".zst"].includes( - extension, - ) - ) { + // Binary assets — delegate to the shared binary-extension inventory (used by asset-weight/provenance) rather + // than a narrow hand-listed set, so media/fonts/archives/model weights (mp4, woff2, wasm, safetensors, …) + // categorize as assets instead of falling through to `source`. `.svg` is text (not in the binary inventory) + // but is still an asset for categorization, so it is kept explicitly. + if (BINARY_EXT_RE.test(path) || extension === ".svg") { return { path, extension, category: "asset" }; } if (extension) return { path, extension, category: "source" }; diff --git a/review-enrichment/test/analysis-context.test.ts b/review-enrichment/test/analysis-context.test.ts index 29a43aef33..dc11a960a9 100644 --- a/review-enrichment/test/analysis-context.test.ts +++ b/review-enrichment/test/analysis-context.test.ts @@ -570,6 +570,36 @@ test("createAnalysisContext classifies long-form doc extensions as docs", () => ); }); +test("createAnalysisContext categorizes the full binary inventory as assets", () => { + const context = createAnalysisContext({ + repoFullName: "JSONbored/gittensory", + prNumber: 3359, + files: [ + // Binaries beyond the original narrow image/archive list — now recognized via the shared inventory. + { path: "media/demo.mp4", patch: null, status: "added" }, + { path: "fonts/Inter.woff2", patch: null, status: "added" }, + { path: "vendor/lib.wasm", patch: null, status: "added" }, + { path: "models/llama.safetensors", patch: null, status: "added" }, + // .svg is text but still an asset for categorization (kept explicitly). + { path: "icons/logo.svg", patch: "@@ -1,0 +1,1 @@\n+" }, + // A real source file is unaffected. + { path: "src/index.ts", patch: "@@ -1,0 +1,1 @@\n+export {};" }, + ], + }); + + assert.deepEqual( + context.fileCategories.map((file) => [file.path, file.category]), + [ + ["media/demo.mp4", "asset"], + ["fonts/Inter.woff2", "asset"], + ["vendor/lib.wasm", "asset"], + ["models/llama.safetensors", "asset"], + ["icons/logo.svg", "asset"], + ["src/index.ts", "source"], + ], + ); +}); + test("createAnalysisContext classifies lockfile paths case-insensitively", () => { const context = createAnalysisContext({ repoFullName: "JSONbored/gittensory",