autopilot(qa): bounce to dev instead of halt; stop after 3 #51
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user