Merge pull request 'autopilot(qa): bounce to dev instead of halt; stop after 3' (#51) from fix/autopilot-bounce into main

This commit was merged in pull request #51.
This commit is contained in:
2026-07-04 22:21:51 +02:00
2 changed files with 55 additions and 13 deletions
+41 -2
View File
@@ -42,6 +42,7 @@ reply=$(awk '
/^[[:space:]]*CLOSE_ISSUE[[:space:]]*$/{next} /^[[:space:]]*CLOSE_ISSUE[[:space:]]*$/{next}
/^[[:space:]]*MERGE_PR[[:space:]]*$/{next} /^[[:space:]]*MERGE_PR[[:space:]]*$/{next}
/^[[:space:]]*HALT_AUTOPILOT[[:space:]]*$/{next} /^[[:space:]]*HALT_AUTOPILOT[[:space:]]*$/{next}
/^[[:space:]]*BOUNCE:[[:space:]]*@/{next}
s{ if(/^[[:space:]]*END_SUBTASKS/){s=0}; next } s{ if(/^[[:space:]]*END_SUBTASKS/){s=0}; next }
p{ if(/^[[:space:]]*END_PR_DESCRIPTION/){p=0}; next } p{ if(/^[[:space:]]*END_PR_DESCRIPTION/){p=0}; next }
{print} {print}
@@ -137,10 +138,36 @@ if [ "$MODE" != "pr" ]; then
;; ;;
esac esac
fi fi
elif grep -qiE '^[[:space:]]*BOUNCE:[[:space:]]*@(junior|senior|lead)' /tmp/agent_out.md; then
# @qa wants the dev to fix something. Send it back — never fix it ourselves. After 3 bounces,
# stop and hand to the human. QA's feedback is already posted (the reply comment above).
if [ -z "$IS_PR" ]; then
echo "BOUNCE marker but this run is not on a PR thread — skipping"
else
target=$(grep -oiE 'BOUNCE:[[:space:]]*@(junior|senior|lead)' /tmp/agent_out.md | head -1 \
| grep -oiE '(junior|senior|lead)' | tr '[:upper:]' '[:lower:]')
[ -z "$target" ] && target=$(curl -sS "${hdr[@]}" "$API/pulls/$NUM" | jq -r '.user.login // "junior"')
# Count how many times this PR has already been bounced (marker in the trigger comment).
prior=$(curl -sS "${hdr[@]}" "$API/issues/$NUM/comments?limit=100" \
| jq -r 'if type=="array" then [.[]|select(.body|test("autopilot fix attempt"))]|length else 0 end' 2>/dev/null)
prior=${prior:-0}
if [ "$prior" -ge 3 ]; then
echo "@qa autopilot: 3 bounces already — halting"
del_autopilot_label "${ISSNUM:-$NUM}"
post "$(printf '🤖 **@qa** — 🛑 still not right after 3 fix attempts. Stopping autopilot (removed the `autopilot` label). @ffaerber please take over — details in the comments above.')"
else
n=$((prior + 1))
echo "@qa autopilot: bounce $n/3 -> @$target"
curl -sS -X POST -H "Authorization: token $AGENT_TOKEN" -H "Content-Type: application/json" \
"$API/issues/$NUM/comments" \
-d "$(jq -nc --arg b "@$target please address @qa's feedback above and update this PR (autopilot fix attempt $n/3)." '{body:$b}')" \
-w '\nbounce -> HTTP %{http_code}\n' || true
fi
fi
elif grep -qiE '^[[:space:]]*HALT_AUTOPILOT[[:space:]]*$' /tmp/agent_out.md; then elif grep -qiE '^[[:space:]]*HALT_AUTOPILOT[[:space:]]*$' /tmp/agent_out.md; then
echo "@qa autopilot: HALT — removing 'autopilot' label from #${ISSNUM:-$NUM}" echo "@qa autopilot: HALT — removing 'autopilot' label from #${ISSNUM:-$NUM}"
del_autopilot_label "${ISSNUM:-$NUM}" del_autopilot_label "${ISSNUM:-$NUM}"
post "$(printf '🤖 **@qa** — 🛑 found a problem, so I did NOT merge. Removed the `autopilot` label (back to human control). @ffaerber please decide next steps (details above).')" post "$(printf '🤖 **@qa** — 🛑 this needs a human decision (not a dev fix). Removed the `autopilot` label (back to human control). @ffaerber please decide next steps (details above).')"
fi fi
exit 0 exit 0
fi fi
@@ -247,11 +274,23 @@ if [ "$NEW" = "true" ]; then
echo "autopilot: auto-triggering @qa to review PR #$prnum" echo "autopilot: auto-triggering @qa to review PR #$prnum"
curl -sS -X POST -H "Authorization: token $AGENT_TOKEN" -H "Content-Type: application/json" \ curl -sS -X POST -H "Authorization: token $AGENT_TOKEN" -H "Content-Type: application/json" \
"$API/issues/$prnum/comments" \ "$API/issues/$prnum/comments" \
-d "$(jq -nc --arg b "@qa please verify this PR (autopilot: issue #$NUM is labeled autopilot). Merge it if correct, or halt and remove the label if you find a problem." '{body:$b}')" \ -d "$(jq -nc --arg b "@qa please verify this PR (autopilot: issue #$NUM is labeled autopilot). Merge it if correct, or bounce it back to the dev with exactly what needs fixing." '{body:$b}')" \
-w '\ntrigger-qa -> HTTP %{http_code}\n' || true -w '\ntrigger-qa -> HTTP %{http_code}\n' || true
fi fi
else else
# Resume: just link the PR — its body and the diff already carry the description, so we don't # Resume: just link the PR — its body and the diff already carry the description, so we don't
# repeat the full write-up in the comment (the reasoning trail below shows what this run did). # repeat the full write-up in the comment (the reasoning trail below shows what this run did).
prpost "$prnum" "$(printf '🤖 **@%s** — pushed an update to the PR:\n- %s%s' "$NAME" "$url" "$activity")" prpost "$prnum" "$(printf '🤖 **@%s** — pushed an update to the PR:\n- %s%s' "$NAME" "$url" "$activity")"
# AUTOPILOT: after a dev pushes a fix (e.g. following a @qa bounce), hand back to @qa to re-verify.
if [ "$AUTOPILOT" = "true" ] && [ -n "$AGENT_TOKEN" ] && [ -n "$prnum" ]; then
case "$NAME" in
junior|senior|lead)
echo "autopilot: dev pushed a fix — re-triggering @qa to re-verify PR #$prnum"
curl -sS -X POST -H "Authorization: token $AGENT_TOKEN" -H "Content-Type: application/json" \
"$API/issues/$prnum/comments" \
-d "$(jq -nc --arg b "@qa please re-verify this PR (autopilot). Merge it if now correct, or bounce it back with exactly what still needs fixing." '{body:$b}')" \
-w '\ntrigger-qa -> HTTP %{http_code}\n' || true
;;
esac
fi
fi fi
+14 -11
View File
@@ -71,17 +71,20 @@ if [ "$MODE" = "comment" ]; then
a human does that." a human does that."
if [ "$AUTOPILOT" = "true" ]; then if [ "$AUTOPILOT" = "true" ]; then
ACTION="$ACTION ACTION="$ACTION
AUTOPILOT MODE IS ACTIVE (this issue/PR carries the 'autopilot' label). This grants you a AUTOPILOT MODE IS ACTIVE (this issue/PR carries the 'autopilot' label). You are the quality gate.
NARROW, one-time merge authority for THIS PR only: You do NOT edit code or fix anything yourself — you either accept the PR or send it back to the dev
- If, after verifying, the PR is correct and any CI checks are green, end your reply with EXACTLY with precise instructions. After actually verifying, end your reply with EXACTLY one of:
one line: 'MERGE_PR'. The automation will then merge the PR and close the linked issue for you. - 'MERGE_PR' — the change is correct and any CI is green. The automation merges the PR and closes
Do NOT merge via any other means; only the MERGE_PR marker triggers the merge. the linked issue. Do NOT merge by any other means; only this marker triggers the merge.
- If you find ANY bug, doubt, or the change is not clearly correct, do NOT merge. Instead describe - 'BOUNCE: @<dev>' — something needs changing. FIRST spell out, specifically and actionably, exactly
the problem clearly and end your reply with EXACTLY one line: 'HALT_AUTOPILOT'. The automation what the dev must change (name the file, label, value, hostname, etc.), THEN end with the BOUNCE
removes the 'autopilot' label (returning this issue to normal human control) and leaves line naming who should fix it (@junior / @senior / @lead — usually whoever built it; @senior or
it for @ffaerber to decide next steps. Never auto-bounce back to a dev. @lead for something harder). The automation sends the PR back to that dev and then re-verifies
Emit AT MOST one of MERGE_PR or HALT_AUTOPILOT, and only after you have actually verified. When in with you. After 3 bounces it stops automatically and hands to @ffaerber — so make each round
doubt, prefer HALT_AUTOPILOT." count and list ALL problems at once, not one at a time.
Use BOUNCE for anything a dev can fix. Only use 'HALT_AUTOPILOT' when the problem is NOT fixable by
a dev — the request itself is ambiguous or needs a human decision — to hand back to @ffaerber.
Emit AT MOST one of MERGE_PR / BOUNCE / HALT_AUTOPILOT, and only after you have actually verified."
fi fi
fi fi
else else