From 7ba71a842d10a9265c8726001ceb6088e697348f Mon Sep 17 00:00:00 2001 From: galuis116 Date: Fri, 24 Jul 2026 10:05:31 -0300 Subject: [PATCH] fix(signals): guard focus-manifest's preferred linked-issue nudge on bodyObserved (#8326) buildFocusManifestGuidance's "required" linked-issue branch already carries a bodyObserved guard so a sparse webhook payload (body never observed, so linkedIssueCount === 0 only means "unknown", not "no issue") can't trip a false positive. Its "preferred" sibling immediately below was missing that same guard, so a linkedIssuePolicy: "preferred" repo could surface the "Maintainer prefers a linked issue" nudge for a PR whose body was never actually observed. Adds `&& bodyObserved` to the "preferred" condition, matching the "required" branch. Per the issue, hasNoIssueRationale is intentionally NOT added here -- only the concretely-verified bodyObserved gap. Adds a regression test asserting a preferred-policy repo with bodyObserved: false and linkedIssueCount: 0 does NOT produce the manifest_linked_issue_ preferred finding; the existing "prefers a linked issue" test already covers the bodyObserved: true arm. --- src/signals/focus-manifest.ts | 2 +- test/unit/focus-manifest.test.ts | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/signals/focus-manifest.ts b/src/signals/focus-manifest.ts index 0306bdd53..fe9ca8313 100644 --- a/src/signals/focus-manifest.ts +++ b/src/signals/focus-manifest.ts @@ -780,7 +780,7 @@ export function buildFocusManifestGuidance(args: { action: "Link the relevant issue (for example `Closes #123`) before opening the PR.", }); publicNextSteps.push("Link the relevant tracked issue; the maintainer requires linked issues on PRs."); - } else if (manifest.linkedIssuePolicy === "preferred" && linkedIssueCount === 0) { + } else if (manifest.linkedIssuePolicy === "preferred" && linkedIssueCount === 0 && bodyObserved) { findings.push({ code: "manifest_linked_issue_preferred", severity: "info", diff --git a/test/unit/focus-manifest.test.ts b/test/unit/focus-manifest.test.ts index 08d47b8ae..68b04a52d 100644 --- a/test/unit/focus-manifest.test.ts +++ b/test/unit/focus-manifest.test.ts @@ -701,6 +701,15 @@ describe("buildFocusManifestGuidance", () => { expect(guidance.findings.some((finding) => finding.code === "manifest_linked_issue_preferred")).toBe(true); }); + // #8326: the "preferred" branch was missing the bodyObserved guard its "required" sibling already has (tested + // just above), so a sparse webhook payload (body never observed -> linkedIssueCount === 0 only means "unknown") + // could surface the "prefers a linked issue" nudge as a false positive. + it("does NOT prefer-nudge when the PR body was never observed (bodyObserved: false)", () => { + const manifest = parseFocusManifest({ wantedPaths: ["src/"], linkedIssuePolicy: "preferred" }); + const guidance = buildFocusManifestGuidance({ manifest, changedPaths: ["src/x.ts"], linkedIssueCount: 0, testFileCount: 1, bodyObserved: false }); + expect(guidance.findings.some((finding) => finding.code === "manifest_linked_issue_preferred")).toBe(false); + }); + it("surfaces missing preferred labels and test expectations", () => { const guidance = buildFocusManifestGuidance({ manifest: wanted, changedPaths: ["src/x.ts"], labels: [], linkedIssueCount: 1, testFileCount: 0, passedValidationCount: 0 }); expect(guidance.findings.some((finding) => finding.code === "manifest_missing_preferred_label")).toBe(true);