diff --git a/reviewer.test.ts b/reviewer.test.ts new file mode 100644 index 0000000..bbec3fc --- /dev/null +++ b/reviewer.test.ts @@ -0,0 +1,46 @@ +import { describe, it, expect } from "vitest"; +import { parseVerdict, cleanReviewText, isLgtmResult } from "./reviewer"; + +describe("reviewer verdict parsing", () => { + it("parseVerdict extracts LGTM", () => { + expect(parseVerdict("some text LGTM more")).toBe("lgtm"); + }); + + it("parseVerdict extracts ISSUES_FOUND", () => { + expect(parseVerdict("ISSUES_FOUND")).toBe("issues"); + }); + + it("parseVerdict returns null when no tag", () => { + expect(parseVerdict("no verdict here")).toBeNull(); + }); + + it("isLgtmResult returns true for empty text", () => { + expect(isLgtmResult("")).toBe(true); + expect(isLgtmResult(" ")).toBe(true); + }); + + it("isLgtmResult returns false when severity markers present", () => { + expect(isLgtmResult("- **High:** something bad")).toBe(false); + expect(isLgtmResult("- **Medium:** fix this")).toBe(false); + }); + + it("isLgtmResult returns true for explicit LGTM text", () => { + expect(isLgtmResult("LGTM — looks good")).toBe(true); + }); + + it("cleanReviewText strips verdict tags", () => { + const raw = "Some findings\nISSUES_FOUND"; + expect(cleanReviewText(raw)).toBe("Some findings"); + }); + + it("empty cleanedText with ISSUES_FOUND verdict should be treated as LGTM", () => { + // This tests the bug where model returns ISSUES_FOUND + // with no actual findings text — resulting in confusing "found potential issues:" + nothing + const raw = "ISSUES_FOUND"; + const cleaned = cleanReviewText(raw); + expect(cleaned).toBe(""); + // The fix: verdict=issues + empty cleaned = treat as LGTM + // (tested at integration level in reviewer.ts line ~395) + expect(isLgtmResult(cleaned)).toBe(true); + }); +}); diff --git a/reviewer.ts b/reviewer.ts index 45cbe88..72d5f74 100644 --- a/reviewer.ts +++ b/reviewer.ts @@ -392,7 +392,8 @@ export async function runReviewSession(prompt: string, opts: ReviewOptions): Pro } const cleanedText = cleanReviewText(reviewText); - const isLgtm = verdict === "lgtm"; + // If model said ISSUES_FOUND but produced no actual findings text, treat as LGTM + const isLgtm = verdict === "lgtm" || (verdict === "issues" && !cleanedText.trim()); const durationMs = Date.now() - startTime; rlog(