This is an automated email from the ASF dual-hosted git repository.

potiuk pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow-steward.git


The following commit(s) were added to refs/heads/main by this push:
     new 7b8ef76  feat(pr-management-triage): add Step 0.5 to promote 
bot-authored draft PRs (#221)
7b8ef76 is described below

commit 7b8ef7641e50a103da380b9f034914ee7ec5f247
Author: Jarek Potiuk <[email protected]>
AuthorDate: Mon May 18 22:21:37 2026 +0200

    feat(pr-management-triage): add Step 0.5 to promote bot-authored draft PRs 
(#221)
    
    Adds a once-per-session pre-pass that runs after pre-flight and before
    the main classify loop. Sweeps open draft PRs authored by the F2 bot
    logins (`dependabot`, `dependabot[bot]`, `renovate[bot]`,
    `github-actions`, `github-actions[bot]`, `*[bot]`), bundles
    `gh pr ready` + `ready for maintainer review` label-add as the new
    `promote-bot-draft` action, and presents the matches as a single
    interaction-loop group with `[A]ll` as the default keystroke.
    
    Inherits Golden rule 1b's workflow-approval guard — a bot draft with
    `action_required` workflow runs at its head SHA refuses promotion and
    re-routes to `pending_workflow_approval`. F2 still excludes the same
    logins from Steps 1–5, so the pre-pass is the only place bot drafts
    surface; a maintainer who skips the group leaves the PR untouched.
    
    Generated-by: Claude Code (Opus 4.7)
---
 .claude/skills/pr-management-triage/SKILL.md       | 56 ++++++++++++++++++++--
 .claude/skills/pr-management-triage/actions.md     | 48 +++++++++++++++++++
 .../pr-management-triage/classify-and-act.md       |  2 +-
 3 files changed, 102 insertions(+), 4 deletions(-)

diff --git a/.claude/skills/pr-management-triage/SKILL.md 
b/.claude/skills/pr-management-triage/SKILL.md
index 499a183..0c85ee8 100644
--- a/.claude/skills/pr-management-triage/SKILL.md
+++ b/.claude/skills/pr-management-triage/SKILL.md
@@ -9,8 +9,8 @@ description: |
   options per PR: draft / comment / close / rebase / CI-rerun
   / workflow-approve / ping-stale-reviewer / request author
   confirmation of readiness / mark `ready for maintainer
-  review`. Does **not** perform code review — that lives in
-  `pr-management-code-review`.
+  review` / promote bot-authored draft. Does **not** perform
+  code review — that lives in `pr-management-code-review`.
 when_to_use: |
   Invoke when a maintainer says "triage the PR queue", "go
   through new contributor PRs", "run the morning triage",
@@ -334,6 +334,55 @@ gracefully with warnings.
 
 ---
 
+## Step 0.5 — Promote bot-authored draft PRs
+
+Before the main triage loop, sweep for open *draft* PRs authored
+by the bot logins enumerated in
+[`classify-and-act.md#pre-filters`](classify-and-act.md), row F2
+(`dependabot`, `dependabot[bot]`, `renovate[bot]`,
+`github-actions`, `github-actions[bot]`, anything matching
+`*[bot]`). For each match the skill proposes two mutations —
+convert draft → non-draft (`gh pr ready`) **and** add the
+`ready for maintainer review` label — bundled as the single
+[`promote-bot-draft`](actions.md#promote-bot-draft--convert-a-bot-authored-draft-and-label-it-ready)
+action.
+
+This is a once-per-session pre-pass, not a per-page sweep — bot
+drafts are author-deterministic, low volume, and don't benefit
+from pagination. F2 still excludes the same logins from
+Steps 1–5, so a bot draft the maintainer skips here stays a
+draft and does not surface again in the main loop.
+
+Fetch query (one GraphQL call, no overlap with Step 1's page-1
+fetch):
+
+```text
+is:pr is:open draft:true repo:<repo>
+```
+
+then client-filter the returned authors to the F2 login pattern.
+If the result set is empty, log a one-line "no bot drafts open"
+and proceed to Step 1.
+
+Otherwise present every match as a single group via the
+[interaction loop](interaction-loop.md). Default keystroke is
+`[A]ll` — the action is deterministic and the bot authorship
+removes the contributor-conversation concern that motivates
+per-PR review elsewhere. The maintainer may still pick
+`[E]ach` / `[P]ick NN` / `[S]kip group` for individual review.
+
+**Golden rule 1b still applies.** The `promote-bot-draft` action
+adds the `ready for maintainer review` label, so its
+implementation MUST run the same `action_required` workflow-run
+check that 
[`mark-ready`](actions.md#mark-ready--add-ready-for-maintainer-review-label)
+does. A bot draft with workflow runs awaiting approval refuses
+promotion and is re-routed to `pending_workflow_approval` —
+unusual for trusted bots in practice, but defensive against the
+case where the head SHA picks up a first-time-contributor commit
+via a merge or a misconfigured bot account.
+
+---
+
 ## Step 1 — Resolve the selector and fetch page 1
 
 Translate the selector into the GraphQL PR-list query from
@@ -505,7 +554,8 @@ On exit, print a one-screen summary:
 
 - counts of PRs handled per action (drafted, commented, closed,
   rebased, reruns triggered, author-confirm requests posted,
-  marked ready, pinged, workflow approvals, suspicious flags)
+  marked ready, bot drafts promoted, pinged, workflow approvals,
+  suspicious flags)
 - counts of PRs skipped and per-reason breakdown (already
   triaged, inside grace window, bot, collaborator)
 - counts of PRs left pending (reached quit, didn't finish the
diff --git a/.claude/skills/pr-management-triage/actions.md 
b/.claude/skills/pr-management-triage/actions.md
index 864d2a7..9db69a9 100644
--- a/.claude/skills/pr-management-triage/actions.md
+++ b/.claude/skills/pr-management-triage/actions.md
@@ -220,6 +220,54 @@ error; this is the only action of the skill whose sole 
purpose
 
 ---
 
+## `promote-bot-draft` — convert a bot-authored draft and label it ready
+
+The action behind [Step 0.5 of 
`SKILL.md`](SKILL.md#step-05--promote-bot-authored-draft-prs).
+Two mutations bundled per PR: convert draft → non-draft
+(`gh pr ready`) and add the `ready for maintainer review`
+label.
+
+Inherits the workflow-approval guard from
+[`mark-ready`](#mark-ready--add-ready-for-maintainer-review-label)
+verbatim — Golden rule 1b in [`SKILL.md`](SKILL.md) applies
+to every code path that adds the label, including this one.
+
+```bash
+# Pre-check: same action_required index lookup as mark-ready.
+head_sha=$(gh api "repos/<owner>/<repo>/pulls/<N>" --jq '.head.sha')
+pending=$(gh api 
"repos/<owner>/<repo>/actions/runs?head_sha=${head_sha}&per_page=20" \
+  --jq '[.workflow_runs[] | select(.conclusion == "action_required")] | 
length')
+if [ "$pending" -gt 0 ]; then
+  echo "refuse promote-bot-draft: <N> has ${pending} workflow run(s) awaiting 
approval at ${head_sha}" >&2
+  # Reclassify the PR as pending_workflow_approval; the maintainer
+  # handles it via the approve-workflow flow rather than promoting blind.
+  exit 2
+fi
+
+# Mutation 1 — flip draft to ready-for-review.
+gh pr ready <N> --repo <repo>
+
+# Mutation 2 — add the ready-for-maintainer-review label.
+gh pr edit <N> --repo <repo> --add-label "ready for maintainer review"
+```
+
+Order matters: `gh pr ready` first, then the label add. If
+`gh pr ready` fails (PR is no longer a draft, was closed, the
+bot pushed a new commit and the head SHA moved) the action stops
+before labelling — the PR is no longer in the bot-draft
+category and should be re-classified by the normal flow on the
+next run. If the label step fails after a successful ready
+toggle, do **not** roll back: the ready toggle is still a
+maintainer-visible improvement; log the label-add failure for
+the session summary so the maintainer can retry next sweep.
+
+No comment is posted. The bot's own commit message plus the
+`ready for maintainer review` label are sufficient signal — a
+contributor-facing footer would be misdirected for a bot author
+that won't read it.
+
+---
+
 ## `request-author-confirmation` — ask the PR author whether feedback is 
addressed
 
 Single mutation. Used when the only `deterministic_flag` signal
diff --git a/.claude/skills/pr-management-triage/classify-and-act.md 
b/.claude/skills/pr-management-triage/classify-and-act.md
index a346bea..ca06f9b 100644
--- a/.claude/skills/pr-management-triage/classify-and-act.md
+++ b/.claude/skills/pr-management-triage/classify-and-act.md
@@ -42,7 +42,7 @@ filter is skipped silently from the main triage flow.
 | # | Filter | Match condition |
 |---|---|---|
 | F1 | Author is collaborator/member/owner | `authorAssociation ∈ {OWNER, 
MEMBER, COLLABORATOR}` (override: `authors:all` or `authors:collaborators`) |
-| F2 | Author is a known bot | login is `dependabot`, `dependabot[bot]`, 
`renovate[bot]`, `github-actions`, `github-actions[bot]`, or matches `*[bot]` |
+| F2 | Author is a known bot | login is `dependabot`, `dependabot[bot]`, 
`renovate[bot]`, `github-actions`, `github-actions[bot]`, or matches `*[bot]`. 
Bot-authored **draft** PRs are handled separately by [`SKILL.md` Step 
0.5](SKILL.md#step-05--promote-bot-authored-draft-prs) *before* this filter 
runs; F2 then drops the same logins from the main triage flow regardless of 
whether Step 0.5 promoted them. |
 | F3 | Draft and not stale | `isDraft == true` and any activity within the 
last 14 days. Stale-sweep classifications in 
[`stale-sweeps.md`](stale-sweeps.md) may still pull the PR back in. |
 | F4 | Already marked ready, no regression | `labels` contains `ready for 
maintainer review` AND CI green AND `mergeable != CONFLICTING` AND no 
unresolved threads. **Regression bypasses this filter** — any of: CI red, new 
conflict, or new unresolved thread whose triggering event (failing check 
`startedAt`, conflict detection, thread `createdAt`) is *after* the label-add 
timestamp. The typical case is a contributor pushing a rebase or fixup commit 
to a ready-for-review PR that re-introduc [...]
 | F5a | Recent collaborator comment (author cooldown) | Most recent comment 
from the **union of** general-issue comments (`comments(last:10)`) and 
**review-thread comments** (`reviewThreads.nodes.comments`) is by a 
`COLLABORATOR`/`MEMBER`/`OWNER`, `createdAt < 72h` ago, AND posted after 
`commits(last:1).committedDate`. The review-thread leg is essential — a 
maintainer asking a clarifying question in-thread is just as much an active 
conversation as a top-level comment, and treating only t [...]

Reply via email to