Fix accepted plan wake comment handoff

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
DottaandPaperclip committed 2026-06-07 00:54:53 +00:00
1 parent a5b3db58dc
commit a379a0264d
2 files changed
+43 -17

No files matched your search

@@ -737,6 +737,17 @@ describeEmbeddedPostgres("accepted plan workspace refresh", () => {
createdAt: new Date(),
updatedAt: new Date(),
});
const planCommentId = randomUUID();
await db.insert(issueComments).values({
id: planCommentId,
companyId,
issueId,
authorUserId: "board-user-1",
authorType: "user",
body: "Keep the accepted plan rollout split into separate child tasks.",
createdAt: new Date("2026-06-07T00:00:00.000Z"),
updatedAt: new Date("2026-06-07T00:00:00.000Z"),
});
await seedAcceptedPlanClaim({
companyId,
issueId,
@@ -803,5 +814,14 @@ describeEmbeddedPostgres("accepted plan workspace refresh", () => {
expect(adapterInput.runtime.sessionId).toBe("accepted-plan-retry-session");
expect(adapterInput.context.acceptedPlanWakeRouting).toBeUndefined();
expect(adapterInput.context.paperclipTaskMarkdown).toContain("Create child issues from the approved plan only");
expect(adapterInput.context.paperclipTaskMarkdown).toContain("Comments included with the confirmed plan:");
expect(adapterInput.context.paperclipTaskMarkdown).toContain(planCommentId);
expect(adapterInput.context.paperclipTaskMarkdown).toContain(
"Keep the accepted plan rollout split into separate child tasks.",
);
expect(adapterInput.context.paperclipWake).toEqual(expect.objectContaining({
commentIds: [planCommentId],
commentContextSource: "accepted_plan_confirmation",
}));
}, 20_000);
});
+23 -17
View File
@@ -2291,6 +2291,20 @@ function normalizeInteractionContinuationWakeContext(
clearInteractionContinuationWakeContext(contextSnapshot);
}
function isAcceptedPlanContinuationWakeContext(
contextSnapshot: Record<string, unknown>,
issueWorkMode?: string | null,
) {
return (
readNonEmptyString(contextSnapshot.workspaceRefreshReason) === "accepted_plan_confirmation" ||
(
issueWorkMode === "planning" &&
readNonEmptyString(contextSnapshot.interactionKind) === "request_confirmation" &&
readNonEmptyString(contextSnapshot.interactionStatus) === "accepted"
)
);
}
type AcceptedPlanWakeRoutingDecision = {
otherActiveClaimIssueId: string;
otherActiveClaimIdentifier: string | null;
@@ -2418,13 +2432,10 @@ export async function buildPaperclipWakePayload(input: {
.then((rows) => rows[0] ?? null)
: null);
let acceptedPlanCommentWindowTruncated = false;
const acceptedPlanContinuationWake =
readNonEmptyString(input.contextSnapshot.workspaceRefreshReason) === "accepted_plan_confirmation" ||
(
issueSummary?.workMode === "planning" &&
readNonEmptyString(input.contextSnapshot.interactionKind) === "request_confirmation" &&
readNonEmptyString(input.contextSnapshot.interactionStatus) === "accepted"
);
const acceptedPlanContinuationWake = isAcceptedPlanContinuationWakeContext(
input.contextSnapshot,
issueSummary?.workMode,
);
if (commentIds.length === 0 && acceptedPlanContinuationWake && issueSummary?.id) {
const recentPlanCommentRows = await input.db
.select({ id: issueComments.id })
@@ -2434,7 +2445,7 @@ export async function buildPaperclipWakePayload(input: {
eq(issueComments.issueId, issueSummary.id),
isNull(issueComments.deletedAt),
))
.orderBy(desc(issueComments.createdAt), desc(issueComments.id))
.orderBy(desc(issueComments.createdAt))
.limit(MAX_INLINE_WAKE_COMMENTS + 1);
acceptedPlanCommentWindowTruncated = recentPlanCommentRows.length > MAX_INLINE_WAKE_COMMENTS;
commentIds = recentPlanCommentRows
@@ -7804,13 +7815,7 @@ export function heartbeatService(db: Db, options: HeartbeatServiceOptions = {})
companyId: agent.companyId,
agentId: agent.id,
issueId,
acceptedPlanContinuationWake:
readNonEmptyString(context.workspaceRefreshReason) === "accepted_plan_confirmation"
|| (
issueContext.workMode === "planning"
&& readNonEmptyString(context.interactionKind) === "request_confirmation"
&& readNonEmptyString(context.interactionStatus) === "accepted"
),
acceptedPlanContinuationWake: isAcceptedPlanContinuationWakeContext(context, issueContext.workMode),
contextSnapshot: context,
})
: null;
@@ -7949,9 +7954,10 @@ export function heartbeatService(db: Db, options: HeartbeatServiceOptions = {})
} else {
delete context[PAPERCLIP_WAKE_PAYLOAD_KEY];
}
const acceptedPlanWakeRouting = parseObject(context.acceptedPlanWakeRouting);
const acceptedPlanContinuationForTask =
readNonEmptyString(context.workspaceRefreshReason) === "accepted_plan_confirmation"
&& !parseObject(context.acceptedPlanWakeRouting);
isAcceptedPlanContinuationWakeContext(context, issueRef?.workMode) &&
Object.keys(acceptedPlanWakeRouting).length === 0;
const acceptedPlanCommentsForTask =
acceptedPlanContinuationForTask && Array.isArray(paperclipWakePayload?.comments)
? paperclipWakePayload.comments.map((comment) => ({