fix: isolate feedback delivery roots

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
DottaandPaperclip committed 2026-08-16 21:33:02 +00:00
1 parent b49c032da2
commit 408d9e55ee
4 files changed
+51 -2

No files matched your search

+13 -2
View File
@@ -237,12 +237,14 @@ import {
FEEDBACK_DELIVERY_RETRY_WAKE_REASON,
buildFeedbackDeliveryFingerprint,
buildFeedbackDeliveryRetryIdempotencyKey,
canCoalesceFeedbackDeliveryRetry,
carriesExplicitFeedbackResume,
collectFeedbackDispositionHandledCommentIds,
isEligibleFeedbackDeliveryWake,
isSuccessfulFeedbackDeliveryRecoveryMatch,
remainingFeedbackDispositionCommentIds,
readFeedbackDeliveryRetryGeneration,
readFeedbackDeliveryRunContext,
} from "./recovery/index.js";
import { isAutomaticRecoverySuppressedByPauseHold } from "./recovery/pause-hold-guard.js";
import {
@@ -10483,6 +10485,9 @@ export function heartbeatService(db: Db, options: HeartbeatServiceOptions = {})
};
const liveContext = parseObject(liveRun?.contextSnapshot);
const liveDelivery = liveRun
? readFeedbackDeliveryRunContext({ companyId: input.run.companyId, run: liveRun })
: null;
if (
liveRun &&
readNonEmptyString(liveContext.feedbackDeliveryRootWakeupRequestId) ===
@@ -10498,8 +10503,13 @@ export function heartbeatService(db: Db, options: HeartbeatServiceOptions = {})
if (
liveRun &&
liveRun.agentId === input.run.agentId &&
liveRun.status !== "running"
canCoalesceFeedbackDeliveryRetry({
sourceAgentId: input.run.agentId,
liveAgentId: liveRun.agentId,
liveStatus: liveRun.status,
sourceRootWakeupRequestId: input.delivery.rootWakeupRequestId,
liveRootWakeupRequestId: liveDelivery?.rootWakeupRequestId ?? null,
})
) {
const mergedContext = mergeCoalescedContextSnapshot(retryContext, parseObject(liveRun.contextSnapshot));
const orderedCommentIds = await orderCommentIds(mergeWakeCommentIds(retryContext, liveRun.contextSnapshot));
@@ -10532,6 +10542,7 @@ export function heartbeatService(db: Db, options: HeartbeatServiceOptions = {})
eq(agentWakeupRequests.agentId, input.run.agentId),
eq(agentWakeupRequests.status, "deferred_issue_execution"),
sql`${agentWakeupRequests.payload} ->> 'issueId' = ${input.delivery.issueId}`,
sql`${agentWakeupRequests.payload} -> '_paperclipWakeContext' ->> 'feedbackDeliveryRootWakeupRequestId' = ${input.delivery.rootWakeupRequestId}`,
))
.orderBy(asc(agentWakeupRequests.requestedAt), asc(agentWakeupRequests.id))
.limit(1)
@@ -5,6 +5,7 @@ import {
STRANDED_FEEDBACK_DELIVERY_BACKSTOP_SOURCE,
buildFeedbackDeliveryFingerprint,
buildFeedbackDeliveryRetryIdempotencyKey,
canCoalesceFeedbackDeliveryRetry,
collectFeedbackDispositionHandledCommentIds,
decideStrandedFeedbackDeliveryBackstop,
hasCompleteFeedbackDispositionCoverage,
@@ -243,6 +244,27 @@ describe("manual feedback retry attempts", () => {
});
});
describe("feedback retry coalescing", () => {
const base = {
sourceAgentId: "agent-1",
liveAgentId: "agent-1",
liveStatus: "queued",
sourceRootWakeupRequestId: "wake-root-1",
liveRootWakeupRequestId: "wake-root-1" as string | null,
};
it("coalesces queued work for the same delivery root", () => {
expect(canCoalesceFeedbackDeliveryRetry(base)).toBe(true);
});
it("keeps a different user wake in a separate delivery lane", () => {
expect(canCoalesceFeedbackDeliveryRetry({
...base,
liveRootWakeupRequestId: "wake-root-2",
})).toBe(false);
});
});
describe("stranded feedback delivery backstop", () => {
it("requeues exactly one normal-model recovery for the original assignee", () => {
const decision = decide();
@@ -97,6 +97,21 @@ export function nextFeedbackDeliveryManualRetryAttempt(input: {
return maxAttempt + 1;
}
export function canCoalesceFeedbackDeliveryRetry(input: {
sourceAgentId: string;
liveAgentId: string;
liveStatus: string;
sourceRootWakeupRequestId: string;
liveRootWakeupRequestId: string | null;
}) {
return input.liveAgentId === input.sourceAgentId
&& input.liveStatus !== "running"
&& (
input.liveRootWakeupRequestId === null
|| input.liveRootWakeupRequestId === input.sourceRootWakeupRequestId
);
}
export function hasCompleteFeedbackDispositionCoverage(input: {
deliveryCommentIds: string[];
handledCommentIds: string[];
+1
View File
@@ -39,6 +39,7 @@ export {
STRANDED_FEEDBACK_DELIVERY_BACKSTOP_SOURCE,
buildFeedbackDeliveryFingerprint,
buildFeedbackDeliveryRetryIdempotencyKey,
canCoalesceFeedbackDeliveryRetry,
carriesExplicitFeedbackResume,
collectFeedbackDispositionHandledCommentIds,
decideStrandedFeedbackDeliveryBackstop,