From 9e0e9454da7edda0fc425e399946d5b8ee6c9b71 Mon Sep 17 00:00:00 2001 From: ghost <49853598+JSONbored@users.noreply.github.com> Date: Sun, 14 Jun 2026 02:15:43 -0700 Subject: [PATCH] fix: align predicted gate parity --- src/api/routes.ts | 1 + src/rules/predicted-gate.ts | 28 +++++++++++++++------------- test/unit/predicted-gate.test.ts | 6 ++++++ 3 files changed, 22 insertions(+), 13 deletions(-) diff --git a/src/api/routes.ts b/src/api/routes.ts index 2fb245501c..368bda3418 100644 --- a/src/api/routes.ts +++ b/src/api/routes.ts @@ -2100,6 +2100,7 @@ export function createApp() { pullRequests, bounties, issueQuality: issueQuality?.report, + confirmedContributor: Boolean(context.gittensorSnapshot), }); const response = { ...analysis, predictedGate, dataQuality: await loadRepoDataQuality(c.env, parsed.data.repoFullName) }; await persistSignal(c.env, "local-branch-analysis", `${parsed.data.login}:${parsed.data.repoFullName}:${parsed.data.branchName ?? parsed.data.headRef ?? "local"}`, parsed.data.repoFullName, response as unknown as Record, analysis.generatedAt); diff --git a/src/rules/predicted-gate.ts b/src/rules/predicted-gate.ts index d31864b787..6301cdccc3 100644 --- a/src/rules/predicted-gate.ts +++ b/src/rules/predicted-gate.ts @@ -76,19 +76,6 @@ export function buildPredictedGateVerdict(args: { const { input, manifest, repo, issues, pullRequests } = args; const gate = manifest.gate; - // A synthetic open PR from the local branch metadata — fed to the SAME advisory builder as a real PR. - const syntheticPr: PullRequestRecord = { - repoFullName: input.repoFullName, - number: 0, - title: input.title, - state: "open", - authorLogin: input.contributorLogin, - authorAssociation: input.authorAssociation ?? null, - body: input.body ?? null, - labels: input.labels ?? [], - linkedIssues: input.linkedIssues ?? [], - }; - const preflight = buildPreflightResult( { repoFullName: input.repoFullName, @@ -105,6 +92,21 @@ export function buildPredictedGateVerdict(args: { args.bounties ?? [], args.issueQuality, ); + + // A synthetic open PR from the local branch metadata — fed to the SAME advisory builder as a real PR. + // Use preflight's normalized linked issues so body references like "Closes #7" match real PR parity. + const syntheticPr: PullRequestRecord = { + repoFullName: input.repoFullName, + number: 0, + title: input.title, + state: "open", + authorLogin: input.contributorLogin, + authorAssociation: input.authorAssociation ?? null, + body: input.body ?? null, + labels: input.labels ?? [], + linkedIssues: preflight.linkedIssues, + }; + const collisions = buildCollisionReport(input.repoFullName, issues, pullRequests); const queueHealth = buildQueueHealth(repo, issues, pullRequests, collisions); const readiness = buildPublicReadinessScore({ diff --git a/test/unit/predicted-gate.test.ts b/test/unit/predicted-gate.test.ts index e190e7462b..5f4547f7df 100644 --- a/test/unit/predicted-gate.test.ts +++ b/test/unit/predicted-gate.test.ts @@ -66,6 +66,12 @@ describe("buildPredictedGateVerdict", () => { expect(advisory.blockers.some((b) => b.code === "missing_linked_issue")).toBe(false); }); + it("uses linked issues inferred from the body for gate advisory parity", () => { + const result = verdict({ gate: { linkedIssue: "block" }, input: { body: "Closes #7", linkedIssues: [] } }); + expect(result.conclusion).toBe("success"); + expect(result.blockers.some((b) => b.code === "missing_linked_issue")).toBe(false); + }); + it("forces a neutral prediction for a self-declared non-confirmed contributor", () => { const result = buildPredictedGateVerdict({ input: { ...BASE_INPUT, body: "no issue", linkedIssues: [] },