Rename autopilot label 'auto' to 'autopilot'

This commit is contained in:
2026-07-04 19:16:47 +00:00
parent d4145d5462
commit f6867ccedb
2 changed files with 18 additions and 18 deletions
+13 -13
View File
@@ -104,7 +104,7 @@ jobs:
fi fi
fi fi
# --- Autopilot gate: read the `auto` label FRESH every run. --- # --- Autopilot gate: read the `autopilot` label FRESH every run. ---
# Presence of this label is the opt-in switch (and the kill switch: remove it mid-flight # Presence of this label is the opt-in switch (and the kill switch: remove it mid-flight
# and the next run reverts to normal human-approval behavior). When @qa is triggered on a # and the next run reverts to normal human-approval behavior). When @qa is triggered on a
# PR thread, the label lives on the ORIGIN issue (ai/issue-N), so resolve N from the branch. # PR thread, the label lives on the ORIGIN issue (ai/issue-N), so resolve N from the branch.
@@ -113,10 +113,10 @@ jobs:
[ -z "$issnum" ] && issnum="$NUM" [ -z "$issnum" ] && issnum="$NUM"
autopilot=false autopilot=false
if curl -sS -H "Authorization: token $GT" "$API/issues/$issnum/labels" 2>/dev/null \ if curl -sS -H "Authorization: token $GT" "$API/issues/$issnum/labels" 2>/dev/null \
| jq -e 'any(.[]?; .name=="auto")' >/dev/null 2>&1; then | jq -e 'any(.[]?; .name=="autopilot")' >/dev/null 2>&1; then
autopilot=true autopilot=true
fi fi
echo "autopilot (auto label on #$issnum)=$autopilot" echo "autopilot (autopilot label on #$issnum)=$autopilot"
{ echo "autopilot=$autopilot"; echo "issnum=$issnum"; } >> "$GITHUB_OUTPUT" { echo "autopilot=$autopilot"; echo "issnum=$issnum"; } >> "$GITHUB_OUTPUT"
- name: Install opencode + provider config (+ Playwright MCP for browser agents) - name: Install opencode + provider config (+ Playwright MCP for browser agents)
@@ -458,7 +458,7 @@ jobs:
does NOT auto-start any dev — the maintainer @mentions an agent on each sub-issue when ready." does NOT auto-start any dev — the maintainer @mentions an agent on each sub-issue when ready."
if [ "$AUTOPILOT" = "true" ]; then if [ "$AUTOPILOT" = "true" ]; then
ACTION="$ACTION ACTION="$ACTION
AUTOPILOT MODE IS ACTIVE (this issue carries the 'auto' label). This OVERRIDES the AUTOPILOT MODE IS ACTIVE (this issue carries the 'autopilot' label). This OVERRIDES the
two-phase approval gate above: do NOT ask '@ffaerber ready to start building?' and do NOT wait two-phase approval gate above: do NOT ask '@ffaerber ready to start building?' and do NOT wait
for a 'yes'. When the task is clear, present your SHORT plan naming the best teammate to build it for a 'yes'. When the task is clear, present your SHORT plan naming the best teammate to build it
AND end your reply with a 'DELEGATE: @<agent>' line in the SAME turn to hand off immediately. AND end your reply with a 'DELEGATE: @<agent>' line in the SAME turn to hand off immediately.
@@ -474,14 +474,14 @@ jobs:
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 'auto' label). This grants you a AUTOPILOT MODE IS ACTIVE (this issue/PR carries the 'autopilot' label). This grants you a
NARROW, one-time merge authority for THIS PR only: NARROW, one-time merge authority for THIS PR only:
- If, after verifying, the PR is correct and any CI checks are green, end your reply with EXACTLY - If, after verifying, the PR is correct and any CI checks are green, end your reply with EXACTLY
one line: 'MERGE_PR'. The automation will then merge the PR and close the linked issue for you. one line: 'MERGE_PR'. The automation will then merge the PR and close the linked issue for you.
Do NOT merge via any other means; only the MERGE_PR marker triggers the merge. Do NOT merge via any other means; only the MERGE_PR marker triggers the merge.
- If you find ANY bug, doubt, or the change is not clearly correct, do NOT merge. Instead describe - If you find ANY bug, doubt, or the change is not clearly correct, do NOT merge. Instead describe
the problem clearly and end your reply with EXACTLY one line: 'HALT_AUTOPILOT'. The automation the problem clearly and end your reply with EXACTLY one line: 'HALT_AUTOPILOT'. The automation
removes the 'auto' label (returning this issue to normal human control) and leaves removes the 'autopilot' label (returning this issue to normal human control) and leaves
it for @ffaerber to decide next steps. Never auto-bounce back to a dev. it for @ffaerber to decide next steps. Never auto-bounce back to a dev.
Emit AT MOST one of MERGE_PR or HALT_AUTOPILOT, and only after you have actually verified. When in Emit AT MOST one of MERGE_PR or HALT_AUTOPILOT, and only after you have actually verified. When in
doubt, prefer HALT_AUTOPILOT." doubt, prefer HALT_AUTOPILOT."
@@ -603,18 +603,18 @@ jobs:
hdr=(-H "Authorization: token $TOK" -H "Content-Type: application/json") hdr=(-H "Authorization: token $TOK" -H "Content-Type: application/json")
post() { curl -sS -w 'comment -> HTTP %{http_code}\n' -X POST "${hdr[@]}" \ post() { curl -sS -w 'comment -> HTTP %{http_code}\n' -X POST "${hdr[@]}" \
"$API/issues/$NUM/comments" -d "$(jq -nc --arg b "$1" '{body:$b}')"; } "$API/issues/$NUM/comments" -d "$(jq -nc --arg b "$1" '{body:$b}')"; }
# Remove the 'auto' label from an issue by resolving its ID first (Gitea's # Remove the 'autopilot' label from an issue by resolving its ID first (Gitea's
# DELETE label endpoint is by ID, not name). Arg $1 = issue number. # DELETE label endpoint is by ID, not name). Arg $1 = issue number.
del_autopilot_label() { del_autopilot_label() {
local iss="$1" local iss="$1"
local lid local lid
lid=$(curl -sS "${hdr[@]}" "$API/issues/$iss/labels" 2>/dev/null \ lid=$(curl -sS "${hdr[@]}" "$API/issues/$iss/labels" 2>/dev/null \
| jq -r 'if type=="array" then ([.[]|select(.name=="auto")][0].id // empty) else empty end') | jq -r 'if type=="array" then ([.[]|select(.name=="autopilot")][0].id // empty) else empty end')
if [ -n "$lid" ]; then if [ -n "$lid" ]; then
curl -sS -X DELETE "${hdr[@]}" "$API/issues/$iss/labels/$lid" \ curl -sS -X DELETE "${hdr[@]}" "$API/issues/$iss/labels/$lid" \
-w '\nunlabel -> HTTP %{http_code}\n' || true -w '\nunlabel -> HTTP %{http_code}\n' || true
else else
echo "no 'auto' label found on #$iss to remove" echo "no 'autopilot' label found on #$iss to remove"
fi fi
} }
@@ -651,7 +651,7 @@ jobs:
fi fi
# --- AUTOPILOT: @qa's narrow, label-gated merge / halt authority --- # --- AUTOPILOT: @qa's narrow, label-gated merge / halt authority ---
# Only @qa, only when 'auto' is set, and only on a PR thread. The MERGE_PR / # Only @qa, only when 'autopilot' is set, and only on a PR thread. The MERGE_PR /
# HALT_AUTOPILOT markers come from the QA prompt. Merge uses TOKEN_QA (the QA user's PAT, # HALT_AUTOPILOT markers come from the QA prompt. Merge uses TOKEN_QA (the QA user's PAT,
# which the maintainer must grant write+merge scope); label removal uses it too. # which the maintainer must grant write+merge scope); label removal uses it too.
if [ "$NAME" = "qa" ] && [ "$AUTOPILOT" = "true" ]; then if [ "$NAME" = "qa" ] && [ "$AUTOPILOT" = "true" ]; then
@@ -674,14 +674,14 @@ jobs:
# Merge failed (checks not green, conflicts, or TOKEN_QA lacks merge scope) — do # Merge failed (checks not green, conflicts, or TOKEN_QA lacks merge scope) — do
# NOT silently proceed: drop the label so it reverts to human control and report. # NOT silently proceed: drop the label so it reverts to human control and report.
del_autopilot_label "${ISSNUM:-$NUM}" del_autopilot_label "${ISSNUM:-$NUM}"
post "$(printf '🤖 **@qa** — ⚠️ tried to merge PR #%s but the API returned HTTP %s (checks not green, a conflict, or missing merge permission on TOKEN_QA). Removed the `auto` label — @ffaerber please take a look.' "$NUM" "$mc")" post "$(printf '🤖 **@qa** — ⚠️ tried to merge PR #%s but the API returned HTTP %s (checks not green, a conflict, or missing merge permission on TOKEN_QA). Removed the `autopilot` label — @ffaerber please take a look.' "$NUM" "$mc")"
;; ;;
esac esac
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 'auto' 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 `auto` label (back to human control). @ffaerber please decide next steps (details above).')" 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).')"
fi fi
fi fi
# BREAKDOWN: from a BEGIN_SUBTASKS block, create a milestone + one sub-issue per line # BREAKDOWN: from a BEGIN_SUBTASKS block, create a milestone + one sub-issue per line
+5 -5
View File
@@ -12,21 +12,21 @@ the loop guards.
- You may edit **any file**. **NEVER push to `main`, NEVER merge a PR** — all work goes on a branch - You may edit **any file**. **NEVER push to `main`, NEVER merge a PR** — all work goes on a branch
and becomes a PR a human reviews and merges. and becomes a PR a human reviews and merges.
- **Narrow exception — `@qa` autopilot merge:** `@qa` (and only `@qa`) MAY merge a single PR **only** - **Narrow exception — `@qa` autopilot merge:** `@qa` (and only `@qa`) MAY merge a single PR **only**
when the linked issue carries the `auto` label, the PR is clearly correct, and any CI when the linked issue carries the `autopilot` label, the PR is clearly correct, and any CI
checks are green. `@qa` triggers the merge by ending its reply with the `MERGE_PR` marker (the checks are green. `@qa` triggers the merge by ending its reply with the `MERGE_PR` marker (the
workflow performs the merge + closes the issue). On **any** doubt or bug, `@qa` must NOT merge: workflow performs the merge + closes the issue). On **any** doubt or bug, `@qa` must NOT merge:
it ends with `HALT_AUTOPILOT` instead, which removes the `auto` label and returns the it ends with `HALT_AUTOPILOT` instead, which removes the `autopilot` label and returns the
issue to human control. No other agent may merge, and `@qa` may not merge without the label. issue to human control. No other agent may merge, and `@qa` may not merge without the label.
- **Never print, exfiltrate, or invent secret values.** - **Never print, exfiltrate, or invent secret values.**
- Keep changes **minimal** and match the conventions already in the file you're editing. - Keep changes **minimal** and match the conventions already in the file you're editing.
- Do the work on a **branch** — never paste code or diffs into the issue thread. - Do the work on a **branch** — never paste code or diffs into the issue thread.
## Autopilot (`auto` label) ## Autopilot (`autopilot` label)
An issue labeled **`auto`** runs without the usual human checkpoints: An issue labeled **`autopilot`** runs without the usual human checkpoints:
- `@pm` plans **and** delegates in the same turn (skips the "ready to build? reply yes" gate). - `@pm` plans **and** delegates in the same turn (skips the "ready to build? reply yes" gate).
- After the dev's PR is opened, `@qa` is auto-triggered to verify it, and merges + closes on success - After the dev's PR is opened, `@qa` is auto-triggered to verify it, and merges + closes on success
(see the QA merge exception above). (see the QA merge exception above).
- **Kill switch:** remove the `auto` label at any time. The label is re-read fresh at the - **Kill switch:** remove the `autopilot` label at any time. The label is re-read fresh at the
start of every run, so the next agent turn reverts to normal human-approval behavior. `@qa` also start of every run, so the next agent turn reverts to normal human-approval behavior. `@qa` also
removes the label itself whenever it halts on a bug or a failed merge. removes the label itself whenever it halts on a bug or a failed merge.
No label (the default) = today's behavior, unchanged. No label (the default) = today's behavior, unchanged.