mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-25 09:41:04 +01:00
fix(pr-gardening): report truncated issue matches
Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
1 parent
da549123cc
commit
a8814a87db
2 files changed
+58
-4
No files matched your search
@@ -33,7 +33,7 @@ export async function findCandidates(options) {
|
||||
const matchesPerIssue = 200;
|
||||
const issueMap = new Map();
|
||||
let offset = 0;
|
||||
let truncated = false;
|
||||
const truncatedIssues = [];
|
||||
|
||||
while (true) {
|
||||
const query = new URLSearchParams({
|
||||
@@ -47,12 +47,16 @@ export async function findCandidates(options) {
|
||||
});
|
||||
const page = await getPaperclip(`/companies/${companyId}/search/extract?${query}`, { apiUrl, apiKey });
|
||||
for (const issue of page.results) issueMap.set(issue.issueId, issue);
|
||||
truncated ||= page.results.some((issue) => issue.matchesTruncated);
|
||||
for (const issue of page.results) {
|
||||
if (issue.matchesTruncated) truncatedIssues.push({ issueId: issue.issueId, identifier: issue.identifier });
|
||||
}
|
||||
if (!page.hasMore) break;
|
||||
offset += limit;
|
||||
if (offset > 5000) throw new Error("Extract-search pagination exceeded the supported 5000 issue offset");
|
||||
}
|
||||
if (truncated) throw new Error("Extract-search truncated one or more issue match sets; refusing an incomplete candidate report");
|
||||
if (truncatedIssues.length > 0) {
|
||||
console.warn(`Warning: ${truncatedIssues.length} issue(s) had truncated match sets (>${matchesPerIssue} PR URL matches). These issues may contribute incomplete PR discovery: ${truncatedIssues.map((i) => i.identifier ?? i.issueId).join(", ")}. Proceeding with available data.`);
|
||||
}
|
||||
|
||||
const pullRequests = new Map();
|
||||
for (const issue of issueMap.values()) {
|
||||
@@ -148,7 +152,8 @@ export async function findCandidates(options) {
|
||||
openPullRequestCount: candidates.length,
|
||||
droppedClosedPullRequests: closed,
|
||||
droppedUnavailablePullRequests: unavailable,
|
||||
truncated: false,
|
||||
truncatedIssues,
|
||||
truncated: truncatedIssues.length > 0,
|
||||
},
|
||||
candidates,
|
||||
};
|
||||
|
||||
@@ -94,6 +94,55 @@ test("candidate discovery deduplicates mentions and drops closed PRs", async ()
|
||||
assert.deepEqual(result.source.droppedUnavailablePullRequests.map((pullRequest) => pullRequest.number), [3]);
|
||||
});
|
||||
|
||||
test("candidate discovery reports truncated issue matches without discarding the report", async () => {
|
||||
const warnings = [];
|
||||
const originalWarn = console.warn;
|
||||
console.warn = (message) => warnings.push(message);
|
||||
|
||||
try {
|
||||
const result = await findCandidates({
|
||||
repo: "paperclipai/paperclip",
|
||||
api_url: "http://paperclip.test",
|
||||
api_key: "test-key",
|
||||
company_id: "company-1",
|
||||
paperclip_get: async (path) => {
|
||||
if (path.includes("search/extract")) {
|
||||
return {
|
||||
hasMore: false,
|
||||
results: [
|
||||
{
|
||||
issueId: "issue-truncated",
|
||||
identifier: "PAP-TRUNCATED",
|
||||
title: "Large PR thread",
|
||||
status: "done",
|
||||
assigneeAgentId: "agent-1",
|
||||
updatedAt: "2026-07-13T00:00:00Z",
|
||||
matchesTruncated: true,
|
||||
matches: [],
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
throw new Error(`Unexpected Paperclip path: ${path}`);
|
||||
},
|
||||
gh_json: async () => {
|
||||
throw new Error("GitHub should not be queried without discovered pull requests");
|
||||
},
|
||||
});
|
||||
|
||||
assert.equal(result.source.truncated, true);
|
||||
assert.deepEqual(result.source.truncatedIssues, [
|
||||
{ issueId: "issue-truncated", identifier: "PAP-TRUNCATED" },
|
||||
]);
|
||||
assert.deepEqual(result.candidates, []);
|
||||
assert.equal(warnings.length, 1);
|
||||
assert.match(warnings[0], /PAP-TRUNCATED/);
|
||||
assert.match(warnings[0], /Proceeding with available data/);
|
||||
} finally {
|
||||
console.warn = originalWarn;
|
||||
}
|
||||
});
|
||||
|
||||
test("missing-PR detection matches only deleted/nonexistent PR signals", () => {
|
||||
// gh's real signals for a deleted/nonexistent PR: GraphQL resolution failure and REST 404.
|
||||
assert.equal(isMissingPullRequestError(new Error("GraphQL: Could not resolve to a PullRequest with the number of 3")), true);
|
||||
|
||||
Reference in new issue
Block a user