Skip to content

Commit bcb6f76

Browse files
fix(miner): fail closed when referencing PR has missing authorLogin (#7794)
Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent a314577 commit bcb6f76

3 files changed

Lines changed: 24 additions & 5 deletions

File tree

packages/loopover-miner/lib/submission-freshness-check.js

Lines changed: 3 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/loopover-miner/lib/submission-freshness-check.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,9 @@ export async function checkSubmissionFreshness(
143143
const minerLoginKey = minerLogin.toLowerCase();
144144
const referencingPrs = Array.isArray(snapshot.referencingPrs) ? snapshot.referencingPrs : [];
145145
const addressedByAnotherAuthor = referencingPrs.some(
146-
(pr) => typeof pr.authorLogin === "string" && pr.authorLogin.trim().toLowerCase() !== minerLoginKey && (pr.state === "merged" || pr.state === "open"),
146+
(pr) =>
147+
(pr.state === "merged" || pr.state === "open") &&
148+
(typeof pr.authorLogin !== "string" || pr.authorLogin.trim().toLowerCase() !== minerLoginKey),
147149
);
148150
if (addressedByAnotherAuthor) {
149151
return abort(eventLedger, repoFullName, candidate.issueNumber, "already_addressed");

test/unit/miner-submission-freshness-check.test.ts

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,23 @@ describe("checkSubmissionFreshness (#3007)", () => {
162162
expect(result).toEqual({ fresh: false, reason: "already_addressed" });
163163
});
164164

165-
it("a referencing PR with a non-string authorLogin is ignored rather than crashing or false-flagging", async () => {
165+
it("REGRESSION: a merged referencing PR with a missing authorLogin counts as already-addressed (fail-closed)", async () => {
166+
const { claimLedger } = stubClaimLedger([activeClaim]);
167+
const { eventLedger } = stubEventLedger();
168+
const fetchLiveIssueSnapshot = vi.fn(async () => ({
169+
state: "open" as const,
170+
referencingPrs: [{ number: 99, state: "merged" as const, authorLogin: null as unknown as string, createdAt: null }],
171+
}));
172+
173+
const result = await checkSubmissionFreshness(
174+
{ repoFullName: "acme/widgets", issueNumber: 42, minerLogin: "miner-bot" },
175+
{ claimLedger, fetchLiveIssueSnapshot, eventLedger },
176+
);
177+
178+
expect(result).toEqual({ fresh: false, reason: "already_addressed" });
179+
});
180+
181+
it("a referencing PR with a non-string authorLogin counts as already-addressed instead of being ignored", async () => {
166182
const { claimLedger } = stubClaimLedger([activeClaim]);
167183
const { eventLedger } = stubEventLedger();
168184
const fetchLiveIssueSnapshot = vi.fn(async () => ({
@@ -175,7 +191,7 @@ describe("checkSubmissionFreshness (#3007)", () => {
175191
{ claimLedger, fetchLiveIssueSnapshot, eventLedger },
176192
);
177193

178-
expect(result).toEqual({ fresh: true });
194+
expect(result).toEqual({ fresh: false, reason: "already_addressed" });
179195
});
180196

181197
it("a CLOSED (not merged) referencing PR from another author does not count as already-addressed", async () => {

0 commit comments

Comments
 (0)