From 9dcccc9e4610c8bc9a516fadf03033fbb2000cda Mon Sep 17 00:00:00 2001 From: Dotta Date: Wed, 21 Oct 2026 09:05:47 -0500 Subject: [PATCH] fix: resume pending repository work with an empty work list Co-Authored-By: Paperclip --- .../native-runtime/native-completion-feedback.test.ts | 4 ++++ .../services/native-runtime/native-completion-feedback.ts | 5 +++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/server/src/services/native-runtime/native-completion-feedback.test.ts b/server/src/services/native-runtime/native-completion-feedback.test.ts index 0562482cb15..04452de5cf9 100644 --- a/server/src/services/native-runtime/native-completion-feedback.test.ts +++ b/server/src/services/native-runtime/native-completion-feedback.test.ts @@ -251,6 +251,10 @@ describe("native final-response feedback", () => { scope: "current_track", unblockAction: "Start the next normal admission" }, }; await expect(nativeCompletionFeedback(db, value.runId, report)).rejects.toThrow('paperclip_finish with reportedWorkDisposition="yielded"'); + await expect(nativeCompletionFeedback(db, value.runId, { ...report, completionClaim: { ...report.completionClaim, remainingWork: [] } })) + .rejects.toThrow('paperclip_finish with reportedWorkDisposition="yielded"'); + await expect(nativeCompletionFeedback(db, value.runId, { ...report, completionClaim: { ...report.completionClaim, objectiveSatisfied: true } })) + .rejects.toThrow('paperclip_finish with reportedWorkDisposition="yielded"'); await expect(nativeCompletionFeedback(db, value.runId, { ...report, evidence: [{ ref: `repository-preparation:${randomUUID()}` }] })) .resolves.toContain("Blocker report accepted"); await expect(nativeCompletionFeedback(db, value.runId, { ...report, blocker: { ...report.blocker!, reasonCode: "missing_access" } })) diff --git a/server/src/services/native-runtime/native-completion-feedback.ts b/server/src/services/native-runtime/native-completion-feedback.ts index 0be1b473f26..f69ecdb2d71 100644 --- a/server/src/services/native-runtime/native-completion-feedback.ts +++ b/server/src/services/native-runtime/native-completion-feedback.ts @@ -239,9 +239,10 @@ export async function nativeCompletionFeedback( if (readiness.unresolvedBlockerCount > 0) { return `Completion report accepted; this task still has unresolved dependencies. Explain the blockers on [this task](/issues/${issue.identifier ?? issue.id}); do not say the task is done.`; } + const unfinishedWork = !result.completionClaim.objectiveSatisfied || result.completionClaim.remainingWork.some(work => work.blocksCompletion); if (result.reportedWorkDisposition === "blocked" && result.blocker?.owner.kind === "system" && result.blocker.scope === "current_track" && result.blocker.reasonCode === "repository_checkout_pending" && - !result.completionClaim.objectiveSatisfied && result.completionClaim.remainingWork.some(work => work.blocksCompletion) && + unfinishedWork && signals.actionableAttentionRequests.length === 0 && issue.workMode === "standard" && issue.executionRunId === run.id && run.status === "running") { const repositoryIds = result.evidence.flatMap(evidence => { @@ -262,7 +263,7 @@ export async function nativeCompletionFeedback( !isConversation(issue) && result.reportedWorkDisposition === "yielded" && result.continuation?.kind === "response_wake" && - (!result.completionClaim.objectiveSatisfied || result.completionClaim.remainingWork.some((entry) => entry.blocksCompletion)) && + unfinishedWork && signals.actionableAttentionRequests.length === 0 ) { const pause = await issueTreeControlService(db).getActivePauseHoldGate(