diff --git a/packages/loopover-engine/src/objective-anchor.ts b/packages/loopover-engine/src/objective-anchor.ts index 915d65eff9..e381f3b499 100644 --- a/packages/loopover-engine/src/objective-anchor.ts +++ b/packages/loopover-engine/src/objective-anchor.ts @@ -228,7 +228,10 @@ function kindsFromPath(path: string): ObjectiveAnchorChangeKind[] { if (DOC_EXTENSIONS.has(extensionOf(path)) || segments.includes("docs") || filename.toLowerCase() === "readme.md") { kinds.push("docs"); } - if (segments.some((segment) => CI_SEGMENTS.has(segment)) || filename.endsWith(".yml") || filename.endsWith(".yaml")) { + // "ci" is classified ONLY by a real CI path segment (CI_SEGMENTS), matching the path-segment discipline every + // other kind here uses. The old bare `.yml`/`.yaml` extension fallback tagged any YAML file anywhere (root + // `.loopover.yml`, `docs/mkdocs.yml`) as "ci", diluting the signal scoreObjectiveAnchor relies on (#8873). + if (segments.some((segment) => CI_SEGMENTS.has(segment))) { kinds.push("ci"); } if (CONFIG_FILENAMES.has(filename) || filename.endsWith(".jsonc") || filename.endsWith(".toml")) { diff --git a/test/unit/engine-objective-anchor-config-classification.test.ts b/test/unit/engine-objective-anchor-config-classification.test.ts index f2afafae2f..99f92fed89 100644 --- a/test/unit/engine-objective-anchor-config-classification.test.ts +++ b/test/unit/engine-objective-anchor-config-classification.test.ts @@ -14,6 +14,8 @@ describe("loopover-engine objective-anchor config-filename classification", () = }); expect(features.changeKinds).toContain("config"); + // #8873: a config YAML at the repo root must NOT be tagged "ci" purely by its extension. + expect(features.changeKinds).not.toContain("ci"); expect(features.paths).toEqual([".loopover.yml"]); }); @@ -37,4 +39,14 @@ describe("loopover-engine objective-anchor config-filename classification", () = }); expect(notDependency.changeKinds).not.toContain("dependency"); }); + + it("does NOT tag a non-CI YAML file (docs/mkdocs.yml) as a 'ci' change kind (#8873)", () => { + const features = extractObjectiveAnchorFeatures({ paths: ["docs/mkdocs.yml"], labels: [], titles: [], notes: [] }); + expect(features.changeKinds).not.toContain("ci"); + }); + + it("still tags a YAML under a real CI path segment (.github/workflows/ci.yml) as 'ci' (#8873)", () => { + const features = extractObjectiveAnchorFeatures({ paths: [".github/workflows/ci.yml"], labels: [], titles: [], notes: [] }); + expect(features.changeKinds).toContain("ci"); + }); });