Skip to content

feat(execution): execution_approved wake reason + self-approval fallback#4429

Open
ramonmatias19 wants to merge 1 commit intopaperclipai:masterfrom
ramonmatias19:feature/execution-approved-wake
Open

feat(execution): execution_approved wake reason + self-approval fallback#4429
ramonmatias19 wants to merge 1 commit intopaperclipai:masterfrom
ramonmatias19:feature/execution-approved-wake

Conversation

@ramonmatias19
Copy link
Copy Markdown

Summary

  • Emit an execution_approved wake for the return-assignee agent when the execution workflow completes, so the executor gets a clean acknowledgement cycle instead of silently leaving the issue done
  • Update renderPaperclipWakePrompt to produce a distinct prompt when lastDecisionOutcome === 'approved' (tell the agent the work was accepted and to wrap up handoff notes)
  • Add execution_approved to shouldResetTaskSessionForWake and describeSessionResetReason so the new wake type resets the task session consistently with other workflow transitions
  • Fix selectStageParticipant to fall back to the full participant pool when excluding the return assignee would produce an empty set — lets an executor self-approve when the execution policy lists only that participant on the stage
  • Regression test for the self-approval fallback

Test plan

  • Approve an execution stage — verify the executor receives an execution_approved heartbeat with the new prompt
  • Configure a single-participant stage whose only participant is also the return assignee — verify approval transitions in_review without error

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Apr 24, 2026

Greptile Summary

This PR adds an execution_approved wake cycle so the return-assignee agent receives a clean acknowledgement when the execution workflow completes, and fixes a self-approval crash when a stage's only participant is also the return assignee.

The PR description does not follow the required template from CONTRIBUTING.md. The Thinking Path, Model Used, and Risks sections are all absent. Please fill out the PR template fully — including a blockquote thinking path, the model and version used to produce this change, and a risks assessment — before requesting merge.

Confidence Score: 4/5

Code logic is correct and well-tested; blocked on PR template compliance required before merge per CONTRIBUTING.md

All code-level findings are P2 (the approved-prompt coupling to lastDecisionOutcome alone and the missing heartbeat test). The blocking concern is the missing PR template sections (Thinking Path, Model Used, Risks) which are hard requirements per CONTRIBUTING.md before a 5/5 can be granted.

packages/adapter-utils/src/server-utils.ts — the executor prompt branch should be tied to the wake reason, not just lastDecisionOutcome

Important Files Changed

Filename Overview
packages/adapter-utils/src/server-utils.ts Adds a distinct executor prompt for lastDecisionOutcome === "approved"; prompt branch may fire on non-execution_approved wakes if the outcome field is already set
server/src/routes/issues.ts New completed state branch in buildExecutionStageWakeup correctly emits execution_approved wakeup with deduplication guard; mirrors the existing changes_requested pattern cleanly
server/src/services/heartbeat.ts Adds execution_approved to shouldResetTaskSessionForWake and describeSessionResetReason, consistent with all other execution wake reasons
server/src/services/issue-execution-policy.ts Self-approval fallback in selectStageParticipant is minimal and correct; falls back to full participant pool only when excluding the return assignee would empty the set
server/src/tests/issue-execution-policy.test.ts Two well-structured regression tests cover both the single-participant bootstrap and the mid-workflow advance for the self-approval fallback; shouldResetTaskSessionForWake test for execution_approved is missing
Prompt To Fix All With AI
This is a comment left during a code review.
Path: server/src/__tests__/issue-execution-policy.test.ts
Line: 1261

Comment:
**Missing test for `shouldResetTaskSessionForWake` with new wake reason**

The existing test suite in `heartbeat-workspace-session.test.ts` has explicit cases for `execution_review_requested`, `execution_approval_requested`, and `execution_changes_requested`, but no case for the newly added `execution_approved` reason. Adding a parallel test there would ensure consistency and guard against regressions if the function is refactored.

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: packages/adapter-utils/src/server-utils.ts
Line: 691-704

Comment:
**Approved-prompt fires on `lastDecisionOutcome` alone, not tied to wake reason**

The condition `executionStage.lastDecisionOutcome === "approved"` is used to decide which executor prompt to show, but the `buildCompletedState` function sets `lastDecisionOutcome: "approved"` as a permanent field even if the state later transitions elsewhere. If an executor receives a non-`execution_approved` wake while the last decision happens to be `"approved"` (e.g. a liveness / comment wake during a completed-but-not-yet-acknowledged window), they will see the completion prompt instead of a general-purpose one.

Tying this branch to a wake-reason check (`executionStage.wakeRole === "executor" && wakeReason === "execution_approved"`) — or including the wake reason in the `ExecutionStageWakeContext` passed to this renderer — would make the condition explicit and safe.

How can I resolve this? If you propose a fix, please make it concise.

Reviews (1): Last reviewed commit: "feat(execution): execution_approved wake..." | Re-trigger Greptile

@@ -1261,4 +1261,79 @@ describe("issue execution policy transitions", () => {
});
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Missing test for shouldResetTaskSessionForWake with new wake reason

The existing test suite in heartbeat-workspace-session.test.ts has explicit cases for execution_review_requested, execution_approval_requested, and execution_changes_requested, but no case for the newly added execution_approved reason. Adding a parallel test there would ensure consistency and guard against regressions if the function is refactored.

Prompt To Fix With AI
This is a comment left during a code review.
Path: server/src/__tests__/issue-execution-policy.test.ts
Line: 1261

Comment:
**Missing test for `shouldResetTaskSessionForWake` with new wake reason**

The existing test suite in `heartbeat-workspace-session.test.ts` has explicit cases for `execution_review_requested`, `execution_approval_requested`, and `execution_changes_requested`, but no case for the newly added `execution_approved` reason. Adding a parallel test there would ensure consistency and guard against regressions if the function is refactored.

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines 691 to +704
} else if (executionStage.wakeRole === "executor") {
lines.push(
"You are waking because changes were requested in the execution workflow.",
"Address the requested changes on this issue and resubmit when the work is ready.",
"",
);
if (executionStage.lastDecisionOutcome === "approved") {
lines.push(
"Your submitted work on this issue was APPROVED and the execution workflow is complete.",
"Acknowledge the approval, wrap up any remaining handoff notes, and do not continue executor work on this issue.",
"",
);
} else {
lines.push(
"You are waking because changes were requested in the execution workflow.",
"Address the requested changes on this issue and resubmit when the work is ready.",
"",
);
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Approved-prompt fires on lastDecisionOutcome alone, not tied to wake reason

The condition executionStage.lastDecisionOutcome === "approved" is used to decide which executor prompt to show, but the buildCompletedState function sets lastDecisionOutcome: "approved" as a permanent field even if the state later transitions elsewhere. If an executor receives a non-execution_approved wake while the last decision happens to be "approved" (e.g. a liveness / comment wake during a completed-but-not-yet-acknowledged window), they will see the completion prompt instead of a general-purpose one.

Tying this branch to a wake-reason check (executionStage.wakeRole === "executor" && wakeReason === "execution_approved") — or including the wake reason in the ExecutionStageWakeContext passed to this renderer — would make the condition explicit and safe.

Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/adapter-utils/src/server-utils.ts
Line: 691-704

Comment:
**Approved-prompt fires on `lastDecisionOutcome` alone, not tied to wake reason**

The condition `executionStage.lastDecisionOutcome === "approved"` is used to decide which executor prompt to show, but the `buildCompletedState` function sets `lastDecisionOutcome: "approved"` as a permanent field even if the state later transitions elsewhere. If an executor receives a non-`execution_approved` wake while the last decision happens to be `"approved"` (e.g. a liveness / comment wake during a completed-but-not-yet-acknowledged window), they will see the completion prompt instead of a general-purpose one.

Tying this branch to a wake-reason check (`executionStage.wakeRole === "executor" && wakeReason === "execution_approved"`) — or including the wake reason in the `ExecutionStageWakeContext` passed to this renderer — would make the condition explicit and safe.

How can I resolve this? If you propose a fix, please make it concise.

@ramonmatias19 ramonmatias19 force-pushed the feature/execution-approved-wake branch from b03d1c1 to 846eb74 Compare April 24, 2026 20:25
- Emit an 'execution_approved' wake for the return-assignee agent when
  the execution workflow completes, so the executor gets a clean
  acknowledgement cycle instead of silently leaving the issue done
- Update renderPaperclipWakePrompt to produce a distinct prompt when
  lastDecisionOutcome === 'approved' (tell the agent the work was
  accepted and to wrap up handoff notes)
- Add 'execution_approved' to shouldResetTaskSessionForWake and
  describeSessionResetReason so the new wake type resets the task
  session consistently with other workflow transitions
- Fix selectStageParticipant to fall back to the full participant pool
  when excluding the return assignee would produce an empty set — lets
  an executor self-approve when the execution policy lists only that
  participant on the stage
- Add a regression test for the self-approval fallback
@ramonmatias19 ramonmatias19 force-pushed the feature/execution-approved-wake branch from 846eb74 to 024032d Compare April 24, 2026 21:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant