From 06cddb456d063ee917aef93def69f04dfd04ada4 Mon Sep 17 00:00:00 2001 From: openhands Date: Mon, 23 Mar 2026 07:24:04 +0000 Subject: [PATCH] =?UTF-8?q?fix:=20investigate:=20PreToolUse=20guard=20bloc?= =?UTF-8?q?ks=20do=5Fmerge()=20in=20dev-agent=20=E2=80=94=20every=20disint?= =?UTF-8?q?o=20PR=20escalates=20on=20merge=20(#568)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Root cause: two code paths injected merge curl commands into Claude's session (review-poll.sh APPROVE injection and dev-agent.sh prompt instructions). The PreToolUse guard correctly blocked these, causing Claude to write PHASE:escalate instead of merging. The bash phase handler already handles merging via do_merge() — which runs outside Claude tool use and is not subject to the guard. Remove the merge/close curl instructions from both Claude-facing prompts so the bash orchestrator handles merges as intended. Co-Authored-By: Claude Opus 4.6 (1M context) --- dev/dev-agent.sh | 23 ++--------------------- review/review-poll.sh | 19 ++----------------- 2 files changed, 4 insertions(+), 38 deletions(-) diff --git a/dev/dev-agent.sh b/dev/dev-agent.sh index 5a46499..56a63c8 100755 --- a/dev/dev-agent.sh +++ b/dev/dev-agent.sh @@ -579,27 +579,8 @@ echo \"PHASE:awaiting_ci\" > \"${PHASE_FILE}\" (CI runs again after each push — always write awaiting_ci, not awaiting_review) **When you receive an \"Approved\" injection:** -The injection includes exact API commands. Merge the PR and close the issue directly: -\`\`\`bash -# Merge (replace NNN with the actual PR number from the injection): -curl -sf -X POST \\ - -H \"Authorization: token \${CODEBERG_TOKEN}\" \\ - -H 'Content-Type: application/json' \\ - \"${API}/pulls/NNN/merge\" \\ - -d '{\"Do\":\"merge\",\"delete_branch_after_merge\":true}' - -# Close the issue: -curl -sf -X PATCH \\ - -H \"Authorization: token \${CODEBERG_TOKEN}\" \\ - -H 'Content-Type: application/json' \\ - \"${API}/issues/${ISSUE}\" \\ - -d '{\"state\":\"closed\"}' - -# Signal done: -echo \"PHASE:done\" > \"${PHASE_FILE}\" -\`\`\` -If merge fails due to conflicts, rebase first then retry the merge. -If merge repeatedly fails, write PHASE:escalate with a reason. +The orchestrator handles merging and issue closure automatically via the bash +phase handler. You do not need to merge or close anything — stop and wait. **When you need human help (CI exhausted, merge blocked, stuck on a decision):** \`\`\`bash diff --git a/review/review-poll.sh b/review/review-poll.sh index 72114ba..8384b2b 100755 --- a/review/review-poll.sh +++ b/review/review-poll.sh @@ -139,24 +139,9 @@ inject_review_into_dev_session() { local inject_msg="" if [ "${verdict}" = "APPROVE" ]; then inject_msg="Approved! PR #${pr_num} has been approved by the reviewer. -Merge the PR and close the issue, then signal done: -curl -sf -X POST \\ - -H \"Authorization: token \$CODEBERG_TOKEN\" \\ - -H 'Content-Type: application/json' \\ - \"${API_BASE}/pulls/${pr_num}/merge\" \\ - -d '{\"Do\":\"merge\",\"delete_branch_after_merge\":true}' - -curl -sf -X PATCH \\ - -H \"Authorization: token \$CODEBERG_TOKEN\" \\ - -H 'Content-Type: application/json' \\ - \"${API_BASE}/issues/${issue_num}\" \\ - -d '{\"state\":\"closed\"}' - -echo \"PHASE:done\" > \"${phase_file}\" - -If merge fails due to conflicts, rebase first then retry. -If merge repeatedly fails, write PHASE:escalate with a reason." +The orchestrator will handle merging and closing the issue automatically. +You do not need to take any action — stop and wait." elif [ "${verdict}" = "REQUEST_CHANGES" ] || [ "${verdict}" = "DISCUSS" ]; then inject_msg="Review: ${verdict} on PR #${pr_num}: