Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 7 additions & 21 deletions src/signals/local-branch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import { deriveEligibilityPlan } from "../services/eligibility-plan";
import { scenarioInputFromLocalBranchMetadata } from "../scenarios/input-model";
import { renderPublicScenarioSummary, type PublicScenarioSummary, type ScenarioSummaryInput } from "../scenarios/scenario-summary";
import { simulateOpenPrPressure } from "../services/open-pr-pressure-scenarios";
import { isTestPath } from "./test-evidence";
import { isCodeFile, isTestFile } from "./path-matchers";

export type LocalBranchChangedFile = {
path: string;
Expand Down Expand Up @@ -1261,26 +1261,12 @@ function safeRepoPath(path: string): string {
return PUBLIC_LOCAL_PATH_PREFIX_PATTERN.test(String(path).replace(/\\/g, "/")) ? "[local path hidden]" : String(path || "(unknown path)").replace(/\\/g, "/");
}

export function isTestFile(file: string): boolean {
// Keep local scoring aligned with slop/test-evidence matchers (#561 / #1046).
return isTestPath(file);
}

export function isCodeFile(file: string): boolean {
// cs/swift/groovy/php plus C/C++/Objective-C round out the native/JVM/.NET/Swift/PHP set: isTestPath already
// recognizes their `SomethingTest(s)`/`Spec` test files, so their source must
// count as code too — otherwise a C#/Swift/Groovy/PHP/native source file is neither test
// nor code in the local scorer. vue/svelte/astro align with review/rag.ts CODE_EXT_RE,
// review/visual/paths.ts, and rules/advisory.ts isCodePath so every classifier agrees.
// cc/hpp round out the C++ set alongside cpp/c/h (rag.ts already indexes all four).
// dart aligns with rag.ts and test-evidence's *_test.dart convention (hand-authored
// .dart is source; generated .g.dart/.freezed.dart stay non-code via isGeneratedFile).
return (
/\.(ts|tsx|mts|cts|js|jsx|mjs|cjs|py|rb|rs|kt|scala|java|go|sql|cs|swift|groovy|php|cpp|cc|c|h|hpp|m|vue|svelte|astro|dart)$/i.test(
file,
) && !isTestFile(file)
);
}
// isTestFile/isCodeFile now live in path-matchers.ts (#3690-followup: path-matchers.ts must never import
// FROM local-branch.ts -- it is reachable from apps/gittensory-ui/src/lib/registration-workspace.ts via
// focus-manifest.ts, and local-branch.ts pulls in the whole review-scoring/Gittensor-API subsystem, which
// breaks `ui:typecheck` under the UI's tsconfig (no Workers ambient types there). Re-exported here so this
// file's own many existing importers of isTestFile/isCodeFile don't need to change their import path.
export { isCodeFile, isTestFile };

function sameRepo(left: string, right: string): boolean {
return left.toLowerCase() === right.toLowerCase();
Expand Down
26 changes: 25 additions & 1 deletion src/signals/path-matchers.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,34 @@
import { isCodeFile, isTestFile } from "./local-branch";
import { isTestPath } from "./test-evidence";

// Pure, deterministic path matchers for slop classification (#561). Siblings to `isTestFile` /
// `isTestPath`: they identify changed files that are NOT genuine hand-authored effort — machine-
// generated output, vendored/imported third-party code, minified bundles, dependency lockfiles, and
// docs — so slop signals can tell a padded diff from real work. Path-only and side-effect-free.
//
// MUST NOT import from local-branch.ts (#3690-followup): this file is reachable from
// apps/gittensory-ui/src/lib/registration-workspace.ts via focus-manifest.ts, and local-branch.ts pulls in
// the whole review-scoring/Gittensor-API subsystem, which breaks `ui:typecheck` under the UI's tsconfig (no
// Workers ambient types there). local-branch.ts imports isTestFile/isCodeFile back FROM here instead.

/** Keep local scoring aligned with slop/test-evidence matchers (#561 / #1046). */
export function isTestFile(file: string): boolean {
return isTestPath(file);
}

/** cs/swift/groovy/php plus C/C++/Objective-C round out the native/JVM/.NET/Swift/PHP set: isTestPath already
* recognizes their `SomethingTest(s)`/`Spec` test files, so their source must count as code too —
* otherwise a C#/Swift/Groovy/PHP/native source file is neither test nor code in the local scorer.
* vue/svelte/astro align with review/rag.ts CODE_EXT_RE, review/visual/paths.ts, and rules/advisory.ts
* isCodePath so every classifier agrees. cc/hpp round out the C++ set alongside cpp/c/h (rag.ts already
* indexes all four). dart aligns with rag.ts and test-evidence's *_test.dart convention (hand-authored
* .dart is source; generated .g.dart/.freezed.dart stay non-code via isGeneratedFile). */
export function isCodeFile(file: string): boolean {
return (
/\.(ts|tsx|mts|cts|js|jsx|mjs|cjs|py|rb|rs|kt|scala|java|go|sql|cs|swift|groovy|php|cpp|cc|c|h|hpp|m|vue|svelte|astro|dart)$/i.test(
file,
) && !isTestFile(file)
);
}

function normalize(path: string): string {
return String(path ?? "")
Expand Down
15 changes: 15 additions & 0 deletions test/unit/path-matchers.test.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import { readFileSync } from "node:fs";
import { dirname, join } from "node:path";
import { fileURLToPath } from "node:url";
import { describe, expect, it } from "vitest";
import {
classifyChangedFile,
Expand All @@ -11,6 +14,18 @@ import {
isVendoredFile,
} from "../../src/signals/path-matchers";

// Structural guard (#3690-followup): this file is reachable from apps/gittensory-ui/src/lib/
// registration-workspace.ts via focus-manifest.ts's classifyChangedFile import. local-branch.ts pulls in
// the whole review-scoring/Gittensor-API subsystem, so an import from it here breaks `ui:typecheck` under
// the UI's tsconfig (no Workers ambient types there) -- confirmed by a real ~35-file "Cannot find name
// Env/D1Database" break when path-matchers.ts briefly imported isCodeFile/isTestFile from local-branch.ts.
describe("path-matchers.ts never imports from local-branch.ts", () => {
it("has no import statement referencing ./local-branch", () => {
const source = readFileSync(join(dirname(fileURLToPath(import.meta.url)), "../../src/signals/path-matchers.ts"), "utf8");
expect(source).not.toMatch(/from\s+["']\.\/local-branch["']/);
});
});

describe("isGeneratedFile", () => {
it("matches generated output by directory, suffix, codegen, and source maps", () => {
for (const path of [
Expand Down
Loading