From c12ad504d4124e847e1e9b962d0b49b12eb3f517 Mon Sep 17 00:00:00 2001 From: protosphinx <133899485+protosphinx@users.noreply.github.com> Date: Mon, 25 May 2026 16:12:51 +0000 Subject: [PATCH] fix(sarif): register duplicate-name in the static RULES catalog The duplicate-name rule was added to checks.ts but never registered in sarif.ts RULES, so GitHub Code Scanning received a synthetic entry with just the rule ID as its short description. Add the proper entry with camelCase name and a human-readable description. Add three tests: verify the rule appears in the catalog, verify the description is not just the bare id, and verify ruleIndex resolves to the registered entry rather than a fallback. --- src/sarif.ts | 8 ++++++++ test/sarif.test.ts | 28 ++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/src/sarif.ts b/src/sarif.ts index 8ebc224..997c520 100644 --- a/src/sarif.ts +++ b/src/sarif.ts @@ -99,6 +99,14 @@ export const RULES: readonly SarifRule[] = [ helpUri: HELP_BASE, defaultLevel: "warning", }, + { + id: "duplicate-name", + name: "duplicateName", + shortDescription: + "Two or more skills share the same name value; resolution is ambiguous.", + helpUri: HELP_BASE, + defaultLevel: "warning", + }, ]; const SEVERITY_TO_LEVEL: Record = { diff --git a/test/sarif.test.ts b/test/sarif.test.ts index 0fc7b82..cdfd702 100644 --- a/test/sarif.test.ts +++ b/test/sarif.test.ts @@ -21,9 +21,37 @@ describe("reportSarif", () => { expect(ruleIds).toContain("tool-unknown"); expect(ruleIds).toContain("description-collision"); expect(ruleIds).toContain("tools-overloaded"); + expect(ruleIds).toContain("duplicate-name"); expect(out.runs[0].results).toEqual([]); }); + it("includes duplicate-name in the catalog with a proper description", () => { + const out = JSON.parse(reportSarif([], "/test", opts)); + const rule = out.runs[0].tool.driver.rules.find( + (r: { id: string }) => r.id === "duplicate-name", + ); + expect(rule).toBeDefined(); + expect(rule.name).toBe("duplicateName"); + expect(rule.defaultConfiguration.level).toBe("warning"); + expect(rule.shortDescription.text).not.toBe("duplicate-name"); + }); + + it("ruleIndex for duplicate-name points to the registered entry, not a fallback", () => { + const diagnostics: Diagnostic[] = [ + { + severity: "warn", + rule: "duplicate-name", + message: "skill name 'foo' is also declared in '/b.md'", + file: "/test/a.md", + }, + ]; + const out = JSON.parse(reportSarif(diagnostics, "/test", opts)); + const idx = out.runs[0].results[0].ruleIndex; + const rule = out.runs[0].tool.driver.rules[idx]; + expect(rule.id).toBe("duplicate-name"); + expect(rule.name).toBe("duplicateName"); + }); + it("emits tools-overloaded at warning level with correct ruleIndex", () => { const diagnostics: Diagnostic[] = [ {