mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-11-14 00:26:28 +01:00
fix(heartbeat): deliver a person's answer that waited behind a turn that closed the task
A person can answer an agent's question while the agent's turn is still running. The answer then waits on its own deferred wake. If that turn completed the task, release cancelled every deferred assignee wake on the done task, including the answer, even though the person's own queued messages reopen the task. The answer was dropped without any run receiving it. Treat an undelivered person's answer that was saved before the task was completed as owed input: reopen the done task straight to in_progress (an answer continues the assignee's own execution) and promote the answer wake. Answers saved after completion, tool-action outcomes, already-delivered answers, agent-requested wakes and cancelled tasks keep the old behavior. Eval steering.approval-delivery (oracle v7): also accept Acorn work that the worker's settling turn saved after the answer was saved, while still requiring exactly one later turn bound to the answer. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
42fd790e80
commit
8a4eaab2c0
8 files changed
+238
-9
No files matched your search
@@ -374,6 +374,19 @@ async function promoteDeferredWake(
|
||||
workingCandidate.queuedCommentIds.length > 0));
|
||||
}
|
||||
|
||||
// A person's answer saved while the task was still open is owed input. The
|
||||
// worker may have finished its turn without reading it; closing the task
|
||||
// must not silently drop it. It reopens the task straight to in_progress,
|
||||
// because an answer continues the assignee's own execution.
|
||||
let reopenForAnswer = false;
|
||||
if (
|
||||
!shouldReopen &&
|
||||
currentIssue.status === "done" &&
|
||||
workingCandidate.requestedByActorType === "user" &&
|
||||
workingCandidate.agentId === currentIssue.assigneeAgentId &&
|
||||
await ports.transaction.isOwedInteractionAnswer({ companyId: run.companyId, issueId: currentIssue.id, payload: workingCandidate.payload })
|
||||
) shouldReopen = reopenForAnswer = true;
|
||||
|
||||
// Agent continuations can outlive the work they addressed. Live,
|
||||
// non-self feedback with an explicit resume intent must still be read
|
||||
// after completion; it cannot revive a cancelled task. Other stale
|
||||
@@ -412,6 +425,7 @@ async function promoteDeferredWake(
|
||||
companyId: run.companyId,
|
||||
issueId: currentIssue.id,
|
||||
runId: run.id,
|
||||
...(reopenForAnswer ? { status: "in_progress" as const } : {}),
|
||||
});
|
||||
if (reopened) {
|
||||
postCommitEffects.push({
|
||||
|
||||
Reference in new issue
Block a user