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
2 changes: 1 addition & 1 deletion packages/loopover-engine/src/objective-anchor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ function kindsFromPath(path: string): ObjectiveAnchorChangeKind[] {
if (CONFIG_FILENAMES.has(filename) || filename.endsWith(".jsonc") || filename.endsWith(".toml")) {
kinds.push("config");
}
if (/package(?:-lock)?\.json$/u.test(filename)) {
if (/^package(?:-lock)?\.json$/u.test(filename)) {
kinds.push("dependency");
}
return kinds;
Expand Down
8 changes: 8 additions & 0 deletions packages/loopover-engine/test/objective-anchor.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,14 @@ test("extractObjectiveAnchorFeatures normalizes paths, derives modules, and clas
]);
});

test("extractObjectiveAnchorFeatures tags only exact package(.-lock).json as a dependency, not a prefixed sibling (#8874)", () => {
const positive = extractObjectiveAnchorFeatures({ paths: ["package.json", "package-lock.json"] });
assert.ok(positive.changeKinds.includes("dependency"));

const negative = extractObjectiveAnchorFeatures({ paths: ["sub-package.json", "mock-package.json"] });
assert.ok(!negative.changeKinds.includes("dependency"));
});

test("scoreObjectiveAnchor returns 1 for full structural overlap", () => {
const result = scoreObjectiveAnchor({ replayed: replay(), revealed: revealed() });

Expand Down
21 changes: 21 additions & 0 deletions test/unit/engine-objective-anchor-config-classification.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,25 @@ describe("loopover-engine objective-anchor config-filename classification", () =
expect(features.changeKinds).toContain("config");
expect(features.paths).toEqual([".loopover.yml"]);
});

// The dependency check must use the same exact-match discipline as the adjacent CONFIG_FILENAMES
// check: an anchored /^package(?:-lock)?\.json$/ so a differently-prefixed sibling is NOT tagged
// "dependency" (#8874). Exercised on the vitest side because Codecov grades this file via vitest.
it("tags only exact package(.-lock).json as a 'dependency' change kind, not a prefixed sibling (#8874)", () => {
const dependency = extractObjectiveAnchorFeatures({
paths: ["package.json", "package-lock.json"],
labels: [],
titles: [],
notes: [],
});
expect(dependency.changeKinds).toContain("dependency");

const notDependency = extractObjectiveAnchorFeatures({
paths: ["sub-package.json", "mock-package.json"],
labels: [],
titles: [],
notes: [],
});
expect(notDependency.changeKinds).not.toContain("dependency");
});
});